diff --git a/tests/OpenCode.Sdk.Tests/Hosting/BackgroundService/Contender/ServiceContenderSpawnerTests.cs b/tests/OpenCode.Sdk.Tests/Hosting/BackgroundService/Contender/ServiceContenderSpawnerTests.cs index d89a6318..910513da 100644 --- a/tests/OpenCode.Sdk.Tests/Hosting/BackgroundService/Contender/ServiceContenderSpawnerTests.cs +++ b/tests/OpenCode.Sdk.Tests/Hosting/BackgroundService/Contender/ServiceContenderSpawnerTests.cs @@ -639,6 +639,8 @@ public async Task TryGetFailure_Should_Report_A_Nonzero_Exit_With_The_Stderr_Tai await Assert.That(failure).IsNotNull(); await Assert.That(failure!.Message).Contains("exited with code 2"); await Assert.That(failure.Message).Contains("Usage: contender-probe"); + await Assert.That(failure.Message).StartsWith( + "The background service contender (pid " + contender.ProcessId.ToString(CultureInfo.InvariantCulture) + ") exited with code 2.\n"); } finally { diff --git a/tests/OpenCode.Sdk.Tests/Hosting/OpenCodeServerContractTests.cs b/tests/OpenCode.Sdk.Tests/Hosting/OpenCodeServerContractTests.cs index cc07bb60..a3544cfd 100644 --- a/tests/OpenCode.Sdk.Tests/Hosting/OpenCodeServerContractTests.cs +++ b/tests/OpenCode.Sdk.Tests/Hosting/OpenCodeServerContractTests.cs @@ -205,6 +205,41 @@ public async Task StartAsync_Should_Refuse_A_Blank_Command_Entry() new OpenCodeServerOptions { Command = ["bun", " "] })).Throws(); } + [Test] + [Arguments(false, "OpenCodeServerOptions.Command needs the executable and its leading arguments.")] + [Arguments(true, "OpenCodeServerOptions.Command entries cannot be blank.")] + public Task StartAsync_Should_Name_The_Refused_Command_And_Its_Options(bool blankEntry, string text) => + AssertOptionsRefusalAsync( + async () => await OpenCodeServer.StartAsync(new OpenCodeServerOptions { Command = RefusedCommand(blankEntry) }), + text); + + [Test] + [Arguments(false, "OpenCodeServerEnsureOptions.Command needs the executable and its leading arguments.")] + [Arguments(true, "OpenCodeServerEnsureOptions.Command entries cannot be blank.")] + public Task EnsureAsync_Should_Name_The_Refused_Command_And_Its_Options(bool blankEntry, string text) => + AssertOptionsRefusalAsync( + async () => await OpenCodeServer.EnsureAsync(new OpenCodeServerEnsureOptions { Command = RefusedCommand(blankEntry) }), + text); + + private static string[] RefusedCommand(bool blankEntry) => blankEntry ? ["bun", " "] : []; + + /// + /// The door refuses with exactly for its public options parameter, in the + /// message renders on each runtime. + /// + private static async Task AssertOptionsRefusalAsync(Func door, string text) + { + var failure = await Assert.That(door).Throws(); + + await Assert.That(failure!.Message).IsEqualTo( +#if NET + text + " (Parameter 'options')"); +#else + text + Environment.NewLine + "Parameter name: options"); +#endif + await Assert.That(failure.ParamName).IsEqualTo("options"); + } + [Test] public async Task Endpoint_Should_Throw_The_Mock_Seam_Failure_On_A_Bare_Mock() {