diff --git a/TrayApp.Test/StatusReportTests.cs b/TrayApp.Test/StatusReportTests.cs index bac994a..c8c756c 100644 --- a/TrayApp.Test/StatusReportTests.cs +++ b/TrayApp.Test/StatusReportTests.cs @@ -47,6 +47,28 @@ public void Build_WithAStatusAndDetails_AppendsThemInOrder() Assert.Contains("systemd-inhibit", report, StringComparison.Ordinal); } + [TestMethod] + public void Build_WithAThrowingDetail_ReportsTheErrorInItsRowAndKeepsTheRest() + { + string report = StatusReport.Build( + "demo", + "holding", + [ + new StatusDetail("Inhibitor", () => throw new InvalidOperationException("systemd-inhibit was not found on PATH")), + new StatusDetail("Helper", () => "present"), + ]); + + Assert.Contains("Platform:", report, StringComparison.Ordinal); + Assert.Contains("Tray icon:", report, StringComparison.Ordinal); + Assert.Contains("Inhibitor: error: systemd-inhibit was not found on PATH", report, StringComparison.Ordinal); + Assert.Contains("Helper:", report, StringComparison.Ordinal); + Assert.Contains("present", report, StringComparison.Ordinal); + } + + [TestMethod] + public void Read_WithAThrowingGetter_ReturnsTheError() => + Assert.AreEqual("error: boom", StatusReport.Read(() => throw new InvalidOperationException("boom"))); + [TestMethod] public void Build_EndsWithoutATrailingNewline() { diff --git a/TrayApp.Test/TrayAppBuilderTests.cs b/TrayApp.Test/TrayAppBuilderTests.cs index 44607aa..d0a875a 100644 --- a/TrayApp.Test/TrayAppBuilderTests.cs +++ b/TrayApp.Test/TrayAppBuilderTests.cs @@ -4,6 +4,7 @@ namespace ktsu.TrayApp.Test; using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using ktsu.Essentials.PersistenceProviders.InMemory; using ktsu.TrayApp; @@ -351,6 +352,36 @@ public async Task RunAsync_WithStatus_ReportsWithoutStarting() Assert.IsFalse(started); } + [TestMethod] + [DoNotParallelize] + public async Task RunAsync_WithStatusAndThrowingGetters_PrintsEveryRowAndExitsZero() + { + TextWriter original = Console.Out; + using StringWriter output = new(); + Console.SetOut(output); + int exitCode; + try + { + exitCode = await TrayAppBuilder.Create("demo") + .Status(() => throw new InvalidOperationException("state unknown")) + .Status("Inhibitor", () => throw new InvalidOperationException("systemd-inhibit was not found on PATH")) + .Status("Helper", () => "present") + .RunAsync(["--no-tray", "--status"]) + .ConfigureAwait(false); + } + finally + { + Console.SetOut(original); + } + + string report = output.ToString(); + Assert.AreEqual(0, exitCode); + Assert.Contains("Platform:", report, StringComparison.Ordinal); + Assert.Contains("State: error: state unknown", report, StringComparison.Ordinal); + Assert.Contains("Inhibitor: error: systemd-inhibit was not found on PATH", report, StringComparison.Ordinal); + Assert.Contains("Helper:", report, StringComparison.Ordinal); + } + [TestMethod] public async Task RunAsync_WithStatusAndARememberedToggle_RunsNoSetterAndReportsTheLiveState() { diff --git a/TrayApp/StatusReport.cs b/TrayApp/StatusReport.cs index 039d9d5..c34a138 100644 --- a/TrayApp/StatusReport.cs +++ b/TrayApp/StatusReport.cs @@ -45,7 +45,7 @@ public static string Build(string name, string? status, IReadOnlyList + /// Reads one of the tool's status getters for the report. + /// + /// + /// The report exists to explain a tool that cannot do its job, and a getter is likely to throw for the + /// same reason (a missing helper, say), so a throwing getter becomes its own row's text rather than + /// losing every row the library and the other getters would have printed. + /// + /// The tool's getter. + /// What the getter returned, or error: and the message of what it threw. + internal static string Read(Func getter) + { + try + { + return getter(); + } + catch (Exception ex) when (FatalError.IsNotFatal(ex)) + { + return "error: " + ex.Message; + } + } + private static void AppendRow(StringBuilder report, string label, string value) => report.AppendLine($"{(label + ':').PadRight(LabelWidth)}{value}"); } diff --git a/TrayApp/TrayAppBuilder.cs b/TrayApp/TrayAppBuilder.cs index 73cf5ca..e7a293c 100644 --- a/TrayApp/TrayAppBuilder.cs +++ b/TrayApp/TrayAppBuilder.cs @@ -437,7 +437,7 @@ public Task RunAsync(string[] args) if (options.ShowStatus) { - Console.WriteLine(StatusReport.Build(app.Name, app.Status?.Invoke(), app.StatusDetails)); + Console.WriteLine(StatusReport.Build(app.Name, app.Status is null ? null : StatusReport.Read(app.Status), app.StatusDetails)); return Task.FromResult(ExitSuccess); }