Files

69 lines
2.7 KiB
C#

using System.Text.Json;
using NucleicBroker;
namespace NucleicBroker.Tests;
public sealed class OutboundWriterTests
{
[Fact]
public async Task PreservesEnqueueOrderAcrossKinds()
{
var captured = new StringWriter();
var writer = new OutboundWriter(captured);
writer.EnqueueJson("""{"a":1}""");
writer.EnqueueProcOutput(1, stderr: false, "one"u8);
writer.EnqueueProcOutput(1, stderr: false, "two"u8);
writer.EnqueueJson("""{"b":2}""");
await writer.CompleteAsync();
var lines = captured.ToString().Split('\n', StringSplitOptions.RemoveEmptyEntries);
Assert.Equal("""{"a":1}""", lines[0]);
Assert.Equal("""{"b":2}""", lines[^1]);
// The two same-stream chunks arrive between the json lines, concatenated in order —
// as ONE notification when the drain saw both queued, as two otherwise. Either way
// the decoded byte stream is identical.
var decoded = string.Concat(lines[1..^1].Select(l =>
{
var note = JsonDocument.Parse(l).RootElement;
Assert.Equal("proc.stdout", note.GetProperty("method").GetString());
return System.Text.Encoding.UTF8.GetString(
Convert.FromBase64String(note.GetProperty("params").GetProperty("b64").GetString()!));
}));
Assert.Equal("onetwo", decoded);
}
[Fact]
public async Task FramesLinesWithBareLineFeed()
{
// The wire is LF-framed on every host (docs/WINDOWS_PORT.md §3.3). TextWriter.NewLine
// would otherwise be CRLF on Windows, hiding a stray \r inside every line hostd parses.
// Forcing CRLF on the sink reproduces the Windows default on any platform, so this
// pins the framing even when CI runs the suite on Linux.
var captured = new StringWriter { NewLine = "\r\n" };
var writer = new OutboundWriter(captured);
writer.EnqueueJson("""{"a":1}""");
writer.EnqueueProcOutput(1, stderr: false, "one"u8);
await writer.CompleteAsync();
var text = captured.ToString();
Assert.DoesNotContain('\r', text);
Assert.EndsWith("\n", text);
}
[Fact]
public async Task StderrAndStdoutChunksNeverMerge()
{
var captured = new StringWriter();
var writer = new OutboundWriter(captured);
writer.EnqueueProcOutput(1, stderr: false, "out"u8);
writer.EnqueueProcOutput(1, stderr: true, "err"u8);
await writer.CompleteAsync();
var methods = captured.ToString().Split('\n', StringSplitOptions.RemoveEmptyEntries)
.Select(l => JsonDocument.Parse(l).RootElement.GetProperty("method").GetString())
.ToList();
Assert.Equal(["proc.stdout", "proc.stderr"], methods);
}
}