Nucleic: Windows Port 1
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
<Project>
|
||||
<!-- Thin shim: MSBuild only auto-imports Directory.Build.props from ancestor directories,
|
||||
and the repo layout (docs/WINDOWS_PORT.md §10) keeps the real shared properties in
|
||||
props/Directory.Build.props. -->
|
||||
<Import Project="$(MSBuildThisFileDirectory)props\Directory.Build.props" />
|
||||
</Project>
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucleicBroker", "NucleicBroker\NucleicBroker.csproj", "{9DFE1688-402D-4623-9F0F-B2F238F0AE78}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NucleicBroker.Tests", "NucleicBroker.Tests\NucleicBroker.Tests.csproj", "{513C933F-89FF-4918-87AB-E9B70625BE4B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9DFE1688-402D-4623-9F0F-B2F238F0AE78}.Release|x86.Build.0 = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{513C933F-89FF-4918-87AB-E9B70625BE4B}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,227 @@
|
||||
using System.Text.Json;
|
||||
using NucleicBroker;
|
||||
|
||||
namespace NucleicBroker.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Contract tests for the §3.3 RPC surface: each test drives BrokerService with raw NDJSON
|
||||
/// lines (exactly what hostd sends) and asserts on the emitted lines (exactly what hostd's
|
||||
/// WslcBrokerClient parses). The Swift side's fake-broker tests mirror these — together they
|
||||
/// pin the contract from both ends (docs/WINDOWS_PORT.md §14).
|
||||
/// </summary>
|
||||
public sealed class BrokerServiceTests
|
||||
{
|
||||
private readonly FakeWslc wslc = new();
|
||||
private readonly StringWriter captured = new();
|
||||
private readonly OutboundWriter outbound;
|
||||
private readonly BrokerService service;
|
||||
|
||||
public BrokerServiceTests()
|
||||
{
|
||||
outbound = new OutboundWriter(captured);
|
||||
service = new BrokerService(wslc, new UnavailableAiProvider(), outbound);
|
||||
}
|
||||
|
||||
/// <summary>Send one request line and return every line emitted once drained.</summary>
|
||||
private async Task<List<JsonElement>> RoundTrip(params string[] lines)
|
||||
{
|
||||
foreach (var line in lines)
|
||||
await service.HandleLineAsync(line);
|
||||
await outbound.CompleteAsync();
|
||||
return captured.ToString()
|
||||
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(l => JsonDocument.Parse(l).RootElement.Clone())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static JsonElement Result(JsonElement response)
|
||||
{
|
||||
Assert.Equal("2.0", response.GetProperty("jsonrpc").GetString());
|
||||
Assert.False(response.TryGetProperty("error", out var error), error.ToString());
|
||||
return response.GetProperty("result");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Hello_ReportsProtocolAndCapabilities()
|
||||
{
|
||||
var lines = await RoundTrip("""{"jsonrpc":"2.0","id":1,"method":"hello"}""");
|
||||
var result = Result(Assert.Single(lines));
|
||||
Assert.Equal(BrokerService.ProtocolVersion, result.GetProperty("protocol").GetInt32());
|
||||
Assert.Equal("9.9-test", result.GetProperty("wslcVersion").GetString());
|
||||
var caps = result.GetProperty("capabilities").EnumerateArray().Select(c => c.GetString()).ToList();
|
||||
Assert.Contains("proc", caps);
|
||||
Assert.DoesNotContain("ai", caps); // UnavailableAiProvider
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UnknownMethod_ReturnsMethodNotFound()
|
||||
{
|
||||
var lines = await RoundTrip("""{"jsonrpc":"2.0","id":7,"method":"nope.nothing"}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal(Rpc.MethodNotFound, error.GetProperty("code").GetInt32());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MalformedLine_ReturnsParseErrorWithNullId()
|
||||
{
|
||||
var lines = await RoundTrip("this is not json");
|
||||
var response = Assert.Single(lines);
|
||||
Assert.Equal(JsonValueKind.Null, response.GetProperty("id").ValueKind);
|
||||
Assert.Equal(Rpc.ParseError, response.GetProperty("error").GetProperty("code").GetInt32());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MissingParams_ReturnsInvalidParams()
|
||||
{
|
||||
var lines = await RoundTrip("""{"jsonrpc":"2.0","id":8,"method":"session.ensure"}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal(Rpc.InvalidParams, error.GetProperty("code").GetInt32());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SessionEnsure_ForwardsSpecAndReturnsGateway()
|
||||
{
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":2,"method":"session.ensure","params":{"name":"nucleic-dev","dataDir":"C:\\data","cpu":4,"memoryMB":8192}}""");
|
||||
Assert.Equal("172.28.0.1", Result(Assert.Single(lines)).GetProperty("gateway").GetString());
|
||||
Assert.Equal(new SessionSpec("nucleic-dev", @"C:\data", 4, 8192), wslc.LastSession);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ImagePull_EmitsProgressNotificationsBeforeResult()
|
||||
{
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":3,"method":"image.pull","params":{"ref":"ghcr.io/abkslm/naros-agent:26.07"}}""");
|
||||
Assert.Equal(3, lines.Count);
|
||||
Assert.Equal("image.pullProgress", lines[0].GetProperty("method").GetString());
|
||||
Assert.Equal("ghcr.io/abkslm/naros-agent:26.07",
|
||||
lines[0].GetProperty("params").GetProperty("ref").GetString());
|
||||
Assert.Equal("done", lines[1].GetProperty("params").GetProperty("status").GetString());
|
||||
Result(lines[2]); // the pull's own success response arrives after its progress
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainerLifecycle_CreateStartStateStopDelete()
|
||||
{
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"container.create","params":{"name":"nucleic-control-local","image":"img","volumes":[{"host":"C:\\repo","guest":"/work","ro":false}],"env":{"A":"1"},"initArgv":["/sbin/init"]}}""",
|
||||
"""{"jsonrpc":"2.0","id":2,"method":"container.start","params":{"name":"nucleic-control-local"}}""",
|
||||
"""{"jsonrpc":"2.0","id":3,"method":"container.state","params":{"name":"nucleic-control-local"}}""",
|
||||
"""{"jsonrpc":"2.0","id":4,"method":"container.stop","params":{"name":"nucleic-control-local","signal":15,"graceMs":2000}}""",
|
||||
"""{"jsonrpc":"2.0","id":5,"method":"container.delete","params":{"name":"nucleic-control-local"}}""",
|
||||
"""{"jsonrpc":"2.0","id":6,"method":"container.state","params":{"name":"nucleic-control-local"}}""");
|
||||
Assert.Equal(6, lines.Count);
|
||||
Assert.Equal("running", Result(lines[2]).GetProperty("state").GetString());
|
||||
Assert.Equal(("nucleic-control-local", 15, 2000), wslc.LastStop);
|
||||
Assert.Equal("absent", Result(lines[5]).GetProperty("state").GetString());
|
||||
var create = wslc.LastCreate!;
|
||||
Assert.Equal("/work", Assert.Single(create.Volumes!).Guest);
|
||||
Assert.False(Assert.Single(create.Volumes!).ReadOnly);
|
||||
Assert.Equal("/sbin/init", Assert.Single(create.InitArgv!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcExec_MintsIdAndRoutesStdioEventsInOrder()
|
||||
{
|
||||
wslc.ContainerStates["box"] = "running";
|
||||
await service.HandleLineAsync(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"proc.exec","params":{"container":"box","argv":["claude","-p"],"tty":false}}""");
|
||||
// The facade emits output then exit, from its own (non-broker) thread.
|
||||
wslc.Events!.ProcOutput(wslc.LastProcId, stderr: false, "hel"u8);
|
||||
wslc.Events!.ProcOutput(wslc.LastProcId, stderr: false, "lo\n"u8);
|
||||
wslc.Events!.ProcExited(wslc.LastProcId, 0);
|
||||
await outbound.CompleteAsync();
|
||||
|
||||
var lines = captured.ToString().Split('\n', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(l => JsonDocument.Parse(l).RootElement.Clone()).ToList();
|
||||
var procId = Result(lines[0]).GetProperty("procId").GetInt64();
|
||||
Assert.Equal(wslc.LastProcId, procId);
|
||||
|
||||
var stdout = lines.Where(l =>
|
||||
l.TryGetProperty("method", out var m) && m.GetString() == "proc.stdout").ToList();
|
||||
var decoded = string.Concat(stdout.Select(n =>
|
||||
System.Text.Encoding.UTF8.GetString(
|
||||
Convert.FromBase64String(n.GetProperty("params").GetProperty("b64").GetString()!))));
|
||||
Assert.Equal("hello\n", decoded);
|
||||
|
||||
// exit is last, and never precedes the output that came before it
|
||||
Assert.Equal("proc.exit", lines[^1].GetProperty("method").GetString());
|
||||
Assert.Equal(0, lines[^1].GetProperty("params").GetProperty("code").GetInt32());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcStdin_DecodesBase64AndSupportsSignalCloseResize()
|
||||
{
|
||||
wslc.ContainerStates["box"] = "running";
|
||||
await service.HandleLineAsync(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"proc.exec","params":{"container":"box","argv":["sh"],"tty":true}}""");
|
||||
var b64 = Convert.ToBase64String("{\"x\":1}\n"u8.ToArray());
|
||||
// The trailing literal `} }` pairs are spaced apart: inside a `$$"""…"""` string two
|
||||
// consecutive closing braces would read as an interpolation delimiter (CS9007), and
|
||||
// whitespace between JSON braces is insignificant.
|
||||
var lines = await RoundTrip(
|
||||
$$"""{"jsonrpc":"2.0","id":2,"method":"proc.stdin","params":{"procId":{{wslc.LastProcId}},"b64":"{{b64}}"} }""",
|
||||
$$"""{"jsonrpc":"2.0","id":3,"method":"proc.signal","params":{"procId":{{wslc.LastProcId}},"sig":2} }""",
|
||||
$$"""{"jsonrpc":"2.0","id":4,"method":"proc.resize","params":{"procId":{{wslc.LastProcId}},"cols":120,"rows":40} }""",
|
||||
$$"""{"jsonrpc":"2.0","id":5,"method":"proc.closeStdin","params":{"procId":{{wslc.LastProcId}} } }""");
|
||||
Assert.Equal(5, lines.Count); // exec response + 4 above
|
||||
var proc = wslc.LastProcess!;
|
||||
Assert.Equal("{\"x\":1}\n", System.Text.Encoding.UTF8.GetString(proc.Stdin.ToArray()));
|
||||
Assert.Equal([2], proc.Signals);
|
||||
Assert.Equal((120, 40), proc.LastResize);
|
||||
Assert.True(proc.StdinClosed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UnknownProcId_ReturnsFacadeErrorWithKind()
|
||||
{
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"proc.signal","params":{"procId":999,"sig":9}}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal(Rpc.FacadeError, error.GetProperty("code").GetInt32());
|
||||
Assert.Equal("not_found", error.GetProperty("data").GetProperty("kind").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FacadeError_SurfacesStructuredKind()
|
||||
{
|
||||
wslc.NextError = new WslcError(WslcError.PullFailed, "registry said no");
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"image.pull","params":{"ref":"ghcr.io/x/y:1"}}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal("image_pull_failed", error.GetProperty("data").GetProperty("kind").GetString());
|
||||
Assert.Equal("registry said no", error.GetProperty("message").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SessionDown_ForwardsAsNotification()
|
||||
{
|
||||
wslc.Events!.SessionDown("vm terminated");
|
||||
await outbound.CompleteAsync();
|
||||
var lines = await Task.FromResult(captured.ToString()
|
||||
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(l => JsonDocument.Parse(l).RootElement.Clone()).ToList());
|
||||
var note = Assert.Single(lines);
|
||||
Assert.Equal("session.down", note.GetProperty("method").GetString());
|
||||
Assert.Equal("vm terminated", note.GetProperty("params").GetProperty("reason").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AiGenerate_UnavailableProviderReturnsStructuredError()
|
||||
{
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"ai.generate","params":{"prompt":"hi"}}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal("ai_unavailable", error.GetProperty("data").GetProperty("kind").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecInStoppedContainer_ReturnsNotRunning()
|
||||
{
|
||||
wslc.ContainerStates["box"] = "stopped";
|
||||
var lines = await RoundTrip(
|
||||
"""{"jsonrpc":"2.0","id":1,"method":"proc.exec","params":{"container":"box","argv":["sh"]}}""");
|
||||
var error = Assert.Single(lines).GetProperty("error");
|
||||
Assert.Equal("not_running", error.GetProperty("data").GetProperty("kind").GetString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using NucleicBroker;
|
||||
|
||||
namespace NucleicBroker.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// In-memory IWslc for the broker contract tests (docs/WINDOWS_PORT.md §14): records calls,
|
||||
/// serves canned state, and exposes the event sink so tests can emit process output/exit and
|
||||
/// session-death exactly as the wslc facade would — from arbitrary threads, asynchronously.
|
||||
/// </summary>
|
||||
public sealed class FakeWslc : IWslc
|
||||
{
|
||||
public IBrokerEvents? Events;
|
||||
public List<string> Calls = [];
|
||||
public Dictionary<string, string> ContainerStates = [];
|
||||
public List<ImageInfo> Images = [];
|
||||
public List<string> MissingComponents = [];
|
||||
public string Gateway = "172.28.0.1";
|
||||
public SessionSpec? LastSession;
|
||||
public ContainerCreateSpec? LastCreate;
|
||||
public (string Name, int Signal, int GraceMs)? LastStop;
|
||||
public FakeProcess? LastProcess;
|
||||
public long LastProcId;
|
||||
public Exception? NextError;
|
||||
|
||||
public string? WslcVersion => "9.9-test";
|
||||
|
||||
public void SetEvents(IBrokerEvents events) => Events = events;
|
||||
|
||||
private void Record(string call)
|
||||
{
|
||||
Calls.Add(call);
|
||||
if (NextError is { } error)
|
||||
{
|
||||
NextError = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> MissingComponentsAsync(CancellationToken ct)
|
||||
{
|
||||
Record("components.missing");
|
||||
return Task.FromResult<IReadOnlyList<string>>(MissingComponents);
|
||||
}
|
||||
|
||||
public Task InstallComponentsAsync(CancellationToken ct)
|
||||
{
|
||||
Record("components.install");
|
||||
Events?.InstallProgress("installing", 50);
|
||||
Events?.InstallProgress("done", 100);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<string> EnsureSessionAsync(SessionSpec spec, CancellationToken ct)
|
||||
{
|
||||
Record("session.ensure");
|
||||
LastSession = spec;
|
||||
return Task.FromResult(Gateway);
|
||||
}
|
||||
|
||||
public Task TerminateSessionAsync(CancellationToken ct)
|
||||
{
|
||||
Record("session.terminate");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task PullImageAsync(string reference, RegistryAuth? auth, CancellationToken ct)
|
||||
{
|
||||
Record($"image.pull:{reference}");
|
||||
Events?.PullProgress(reference, "downloading", 10, 100);
|
||||
Events?.PullProgress(reference, "done", 100, 100);
|
||||
Images.Add(new ImageInfo(reference, "sha256:fake", 1234));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<ImageInfo>> ListImagesAsync(CancellationToken ct)
|
||||
{
|
||||
Record("image.list");
|
||||
return Task.FromResult<IReadOnlyList<ImageInfo>>(Images);
|
||||
}
|
||||
|
||||
public Task DeleteImageAsync(string reference, CancellationToken ct)
|
||||
{
|
||||
Record($"image.delete:{reference}");
|
||||
Images.RemoveAll(i => i.Ref == reference);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<ImageInfo?> InspectImageAsync(string reference, CancellationToken ct)
|
||||
{
|
||||
Record($"image.inspect:{reference}");
|
||||
return Task.FromResult(Images.FirstOrDefault(i => i.Ref == reference));
|
||||
}
|
||||
|
||||
public Task CreateContainerAsync(ContainerCreateSpec spec, CancellationToken ct)
|
||||
{
|
||||
Record($"container.create:{spec.Name}");
|
||||
LastCreate = spec;
|
||||
ContainerStates[spec.Name] = "stopped";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StartContainerAsync(string name, CancellationToken ct)
|
||||
{
|
||||
Record($"container.start:{name}");
|
||||
if (!ContainerStates.ContainsKey(name))
|
||||
throw new WslcError(WslcError.NotFound, $"no container named {name}");
|
||||
ContainerStates[name] = "running";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopContainerAsync(string name, int signal, int graceMs, CancellationToken ct)
|
||||
{
|
||||
Record($"container.stop:{name}");
|
||||
LastStop = (name, signal, graceMs);
|
||||
ContainerStates[name] = "stopped";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DeleteContainerAsync(string name, bool force, CancellationToken ct)
|
||||
{
|
||||
Record($"container.delete:{name}");
|
||||
ContainerStates.Remove(name);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<ContainerInfo>> ListContainersAsync(CancellationToken ct)
|
||||
{
|
||||
Record("container.list");
|
||||
return Task.FromResult<IReadOnlyList<ContainerInfo>>(
|
||||
ContainerStates.Select(kv => new ContainerInfo(kv.Key, "img", kv.Value)).ToList());
|
||||
}
|
||||
|
||||
public Task<string> ContainerStateAsync(string name, CancellationToken ct)
|
||||
{
|
||||
Record($"container.state:{name}");
|
||||
return Task.FromResult(ContainerStates.GetValueOrDefault(name, "absent"));
|
||||
}
|
||||
|
||||
public Task<ContainerStatsInfo?> ContainerStatsAsync(string name, CancellationToken ct)
|
||||
{
|
||||
Record($"container.stats:{name}");
|
||||
return Task.FromResult<ContainerStatsInfo?>(
|
||||
ContainerStates.GetValueOrDefault(name) == "running"
|
||||
? new ContainerStatsInfo(111, 222, 333, 0)
|
||||
: null);
|
||||
}
|
||||
|
||||
public Task<IWslcProcess> ExecAsync(long procId, ProcSpec spec, CancellationToken ct)
|
||||
{
|
||||
Record($"proc.exec:{spec.Container}:{string.Join(' ', spec.Argv)}");
|
||||
if (ContainerStates.GetValueOrDefault(spec.Container) != "running")
|
||||
throw new WslcError(WslcError.NotRunning, $"container {spec.Container} isn't running");
|
||||
LastProcId = procId;
|
||||
LastProcess = new FakeProcess();
|
||||
return Task.FromResult<IWslcProcess>(LastProcess);
|
||||
}
|
||||
|
||||
public sealed class FakeProcess : IWslcProcess
|
||||
{
|
||||
public MemoryStream Stdin = new();
|
||||
public bool StdinClosed;
|
||||
public List<int> Signals = [];
|
||||
public (int Cols, int Rows)? LastResize;
|
||||
|
||||
public Task WriteStdinAsync(ReadOnlyMemory<byte> data, CancellationToken ct)
|
||||
{
|
||||
Stdin.Write(data.Span);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task CloseStdinAsync(CancellationToken ct)
|
||||
{
|
||||
StdinClosed = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SignalAsync(int signal, CancellationToken ct)
|
||||
{
|
||||
Signals.Add(signal);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task ResizeAsync(int cols, int rows, CancellationToken ct)
|
||||
{
|
||||
LastResize = (cols, rows);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!-- Broker contract tests (docs/WINDOWS_PORT.md §14): drive BrokerService line-by-line
|
||||
against FakeWslc — no wslc, no Windows, runnable on any CI leg. -->
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../NucleicBroker/NucleicBroker.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,475 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v9.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v9.0": {
|
||||
"NucleicBroker.Tests/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NET.Test.Sdk": "17.12.0",
|
||||
"nucleic-brokerd": "1.0.0",
|
||||
"xunit": "2.9.2",
|
||||
"xunit.runner.visualstudio": "2.8.2",
|
||||
"nucleic-brokerd.Reference": "1.0.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"NucleicBroker.Tests.dll": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.CodeCoverage/17.12.0": {
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.1/Microsoft.VisualStudio.CodeCoverage.Shim.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.524.48002"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.NET.Test.Sdk/17.12.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.CodeCoverage": "17.12.0",
|
||||
"Microsoft.TestPlatform.TestHost": "17.12.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.TestPlatform.ObjectModel/17.12.0": {
|
||||
"dependencies": {
|
||||
"System.Reflection.Metadata": "1.6.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.1/Microsoft.TestPlatform.CoreUtilities.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/Microsoft.TestPlatform.PlatformAbstractions.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/Microsoft.VisualStudio.TestPlatform.ObjectModel.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"lib/netcoreapp3.1/cs/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "cs"
|
||||
},
|
||||
"lib/netcoreapp3.1/cs/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "cs"
|
||||
},
|
||||
"lib/netcoreapp3.1/de/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "de"
|
||||
},
|
||||
"lib/netcoreapp3.1/de/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "de"
|
||||
},
|
||||
"lib/netcoreapp3.1/es/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "es"
|
||||
},
|
||||
"lib/netcoreapp3.1/es/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "es"
|
||||
},
|
||||
"lib/netcoreapp3.1/fr/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "fr"
|
||||
},
|
||||
"lib/netcoreapp3.1/fr/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "fr"
|
||||
},
|
||||
"lib/netcoreapp3.1/it/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "it"
|
||||
},
|
||||
"lib/netcoreapp3.1/it/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "it"
|
||||
},
|
||||
"lib/netcoreapp3.1/ja/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "ja"
|
||||
},
|
||||
"lib/netcoreapp3.1/ja/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "ja"
|
||||
},
|
||||
"lib/netcoreapp3.1/ko/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "ko"
|
||||
},
|
||||
"lib/netcoreapp3.1/ko/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "ko"
|
||||
},
|
||||
"lib/netcoreapp3.1/pl/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "pl"
|
||||
},
|
||||
"lib/netcoreapp3.1/pl/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "pl"
|
||||
},
|
||||
"lib/netcoreapp3.1/pt-BR/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "pt-BR"
|
||||
},
|
||||
"lib/netcoreapp3.1/pt-BR/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "pt-BR"
|
||||
},
|
||||
"lib/netcoreapp3.1/ru/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "ru"
|
||||
},
|
||||
"lib/netcoreapp3.1/ru/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "ru"
|
||||
},
|
||||
"lib/netcoreapp3.1/tr/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "tr"
|
||||
},
|
||||
"lib/netcoreapp3.1/tr/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "tr"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hans/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "zh-Hans"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hans/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "zh-Hans"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hant/Microsoft.TestPlatform.CoreUtilities.resources.dll": {
|
||||
"locale": "zh-Hant"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hant/Microsoft.VisualStudio.TestPlatform.ObjectModel.resources.dll": {
|
||||
"locale": "zh-Hant"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.TestPlatform.TestHost/17.12.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.TestPlatform.ObjectModel": "17.12.0",
|
||||
"Newtonsoft.Json": "13.0.1"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.1/Microsoft.TestPlatform.CommunicationUtilities.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/Microsoft.TestPlatform.CrossPlatEngine.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/Microsoft.TestPlatform.Utilities.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/Microsoft.VisualStudio.TestPlatform.Common.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
},
|
||||
"lib/netcoreapp3.1/testhost.dll": {
|
||||
"assemblyVersion": "15.0.0.0",
|
||||
"fileVersion": "17.1200.24.56501"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"lib/netcoreapp3.1/cs/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "cs"
|
||||
},
|
||||
"lib/netcoreapp3.1/cs/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "cs"
|
||||
},
|
||||
"lib/netcoreapp3.1/cs/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "cs"
|
||||
},
|
||||
"lib/netcoreapp3.1/de/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "de"
|
||||
},
|
||||
"lib/netcoreapp3.1/de/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "de"
|
||||
},
|
||||
"lib/netcoreapp3.1/de/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "de"
|
||||
},
|
||||
"lib/netcoreapp3.1/es/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "es"
|
||||
},
|
||||
"lib/netcoreapp3.1/es/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "es"
|
||||
},
|
||||
"lib/netcoreapp3.1/es/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "es"
|
||||
},
|
||||
"lib/netcoreapp3.1/fr/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "fr"
|
||||
},
|
||||
"lib/netcoreapp3.1/fr/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "fr"
|
||||
},
|
||||
"lib/netcoreapp3.1/fr/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "fr"
|
||||
},
|
||||
"lib/netcoreapp3.1/it/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "it"
|
||||
},
|
||||
"lib/netcoreapp3.1/it/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "it"
|
||||
},
|
||||
"lib/netcoreapp3.1/it/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "it"
|
||||
},
|
||||
"lib/netcoreapp3.1/ja/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "ja"
|
||||
},
|
||||
"lib/netcoreapp3.1/ja/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "ja"
|
||||
},
|
||||
"lib/netcoreapp3.1/ja/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "ja"
|
||||
},
|
||||
"lib/netcoreapp3.1/ko/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "ko"
|
||||
},
|
||||
"lib/netcoreapp3.1/ko/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "ko"
|
||||
},
|
||||
"lib/netcoreapp3.1/ko/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "ko"
|
||||
},
|
||||
"lib/netcoreapp3.1/pl/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "pl"
|
||||
},
|
||||
"lib/netcoreapp3.1/pl/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "pl"
|
||||
},
|
||||
"lib/netcoreapp3.1/pl/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "pl"
|
||||
},
|
||||
"lib/netcoreapp3.1/pt-BR/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "pt-BR"
|
||||
},
|
||||
"lib/netcoreapp3.1/pt-BR/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "pt-BR"
|
||||
},
|
||||
"lib/netcoreapp3.1/pt-BR/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "pt-BR"
|
||||
},
|
||||
"lib/netcoreapp3.1/ru/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "ru"
|
||||
},
|
||||
"lib/netcoreapp3.1/ru/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "ru"
|
||||
},
|
||||
"lib/netcoreapp3.1/ru/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "ru"
|
||||
},
|
||||
"lib/netcoreapp3.1/tr/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "tr"
|
||||
},
|
||||
"lib/netcoreapp3.1/tr/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "tr"
|
||||
},
|
||||
"lib/netcoreapp3.1/tr/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "tr"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hans/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "zh-Hans"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hans/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "zh-Hans"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hans/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "zh-Hans"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hant/Microsoft.TestPlatform.CommunicationUtilities.resources.dll": {
|
||||
"locale": "zh-Hant"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hant/Microsoft.TestPlatform.CrossPlatEngine.resources.dll": {
|
||||
"locale": "zh-Hant"
|
||||
},
|
||||
"lib/netcoreapp3.1/zh-Hant/Microsoft.VisualStudio.TestPlatform.Common.resources.dll": {
|
||||
"locale": "zh-Hant"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Newtonsoft.Json/13.0.1": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "13.0.0.0",
|
||||
"fileVersion": "13.0.1.25517"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Reflection.Metadata/1.6.0": {},
|
||||
"xunit/2.9.2": {
|
||||
"dependencies": {
|
||||
"xunit.analyzers": "1.16.0",
|
||||
"xunit.assert": "2.9.2",
|
||||
"xunit.core": "2.9.2"
|
||||
}
|
||||
},
|
||||
"xunit.abstractions/2.0.3": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/xunit.abstractions.dll": {
|
||||
"assemblyVersion": "2.0.0.0",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"xunit.analyzers/1.16.0": {},
|
||||
"xunit.assert/2.9.2": {
|
||||
"runtime": {
|
||||
"lib/net6.0/xunit.assert.dll": {
|
||||
"assemblyVersion": "2.9.2.0",
|
||||
"fileVersion": "2.9.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"xunit.core/2.9.2": {
|
||||
"dependencies": {
|
||||
"xunit.extensibility.core": "2.9.2",
|
||||
"xunit.extensibility.execution": "2.9.2"
|
||||
}
|
||||
},
|
||||
"xunit.extensibility.core/2.9.2": {
|
||||
"dependencies": {
|
||||
"xunit.abstractions": "2.0.3"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.1/xunit.core.dll": {
|
||||
"assemblyVersion": "2.9.2.0",
|
||||
"fileVersion": "2.9.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"xunit.extensibility.execution/2.9.2": {
|
||||
"dependencies": {
|
||||
"xunit.extensibility.core": "2.9.2"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.1/xunit.execution.dotnet.dll": {
|
||||
"assemblyVersion": "2.9.2.0",
|
||||
"fileVersion": "2.9.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"xunit.runner.visualstudio/2.8.2": {},
|
||||
"nucleic-brokerd/1.0.0": {
|
||||
"runtime": {
|
||||
"nucleic-brokerd.dll": {
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nucleic-brokerd.Reference/1.0.0.0": {
|
||||
"runtime": {
|
||||
"nucleic-brokerd.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"NucleicBroker.Tests/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Microsoft.CodeCoverage/17.12.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4svMznBd5JM21JIG2xZKGNanAHNXplxf/kQDFfLHXQ3OnpJkayRK/TjacFjA+EYmoyuNXHo/sOETEfcYtAzIrA==",
|
||||
"path": "microsoft.codecoverage/17.12.0",
|
||||
"hashPath": "microsoft.codecoverage.17.12.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NET.Test.Sdk/17.12.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-kt/PKBZ91rFCWxVIJZSgVLk+YR+4KxTuHf799ho8WNiK5ZQpJNAEZCAWX86vcKrs+DiYjiibpYKdGZP6+/N17w==",
|
||||
"path": "microsoft.net.test.sdk/17.12.0",
|
||||
"hashPath": "microsoft.net.test.sdk.17.12.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.TestPlatform.ObjectModel/17.12.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==",
|
||||
"path": "microsoft.testplatform.objectmodel/17.12.0",
|
||||
"hashPath": "microsoft.testplatform.objectmodel.17.12.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.TestPlatform.TestHost/17.12.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-MiPEJQNyADfwZ4pJNpQex+t9/jOClBGMiCiVVFuELCMSX2nmNfvUor3uFVxNNCg30uxDP8JDYfPnMXQzsfzYyg==",
|
||||
"path": "microsoft.testplatform.testhost/17.12.0",
|
||||
"hashPath": "microsoft.testplatform.testhost.17.12.0.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/13.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
|
||||
"path": "newtonsoft.json/13.0.1",
|
||||
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
|
||||
},
|
||||
"System.Reflection.Metadata/1.6.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==",
|
||||
"path": "system.reflection.metadata/1.6.0",
|
||||
"hashPath": "system.reflection.metadata.1.6.0.nupkg.sha512"
|
||||
},
|
||||
"xunit/2.9.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-7LhFS2N9Z6Xgg8aE5lY95cneYivRMfRI8v+4PATa4S64D5Z/Plkg0qa8dTRHSiGRgVZ/CL2gEfJDE5AUhOX+2Q==",
|
||||
"path": "xunit/2.9.2",
|
||||
"hashPath": "xunit.2.9.2.nupkg.sha512"
|
||||
},
|
||||
"xunit.abstractions/2.0.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==",
|
||||
"path": "xunit.abstractions/2.0.3",
|
||||
"hashPath": "xunit.abstractions.2.0.3.nupkg.sha512"
|
||||
},
|
||||
"xunit.analyzers/1.16.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-hptYM7vGr46GUIgZt21YHO4rfuBAQS2eINbFo16CV/Dqq+24Tp+P5gDCACu1AbFfW4Sp/WRfDPSK8fmUUb8s0Q==",
|
||||
"path": "xunit.analyzers/1.16.0",
|
||||
"hashPath": "xunit.analyzers.1.16.0.nupkg.sha512"
|
||||
},
|
||||
"xunit.assert/2.9.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-QkNBAQG4pa66cholm28AxijBjrmki98/vsEh4Sx5iplzotvPgpiotcxqJQMRC8d7RV7nIT8ozh97957hDnZwsQ==",
|
||||
"path": "xunit.assert/2.9.2",
|
||||
"hashPath": "xunit.assert.2.9.2.nupkg.sha512"
|
||||
},
|
||||
"xunit.core/2.9.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-O6RrNSdmZ0xgEn5kT927PNwog5vxTtKrWMihhhrT0Sg9jQ7iBDciYOwzBgP2krBEk5/GBXI18R1lKvmnxGcb4w==",
|
||||
"path": "xunit.core/2.9.2",
|
||||
"hashPath": "xunit.core.2.9.2.nupkg.sha512"
|
||||
},
|
||||
"xunit.extensibility.core/2.9.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Ol+KlBJz1x8BrdnhN2DeOuLrr1I/cTwtHCggL9BvYqFuVd/TUSzxNT5O0NxCIXth30bsKxgMfdqLTcORtM52yQ==",
|
||||
"path": "xunit.extensibility.core/2.9.2",
|
||||
"hashPath": "xunit.extensibility.core.2.9.2.nupkg.sha512"
|
||||
},
|
||||
"xunit.extensibility.execution/2.9.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-rKMpq4GsIUIJibXuZoZ8lYp5EpROlnYaRpwu9Zr0sRZXE7JqJfEEbCsUriZqB+ByXCLFBJyjkTRULMdC+U566g==",
|
||||
"path": "xunit.extensibility.execution/2.9.2",
|
||||
"hashPath": "xunit.extensibility.execution.2.9.2.nupkg.sha512"
|
||||
},
|
||||
"xunit.runner.visualstudio/2.8.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-vm1tbfXhFmjFMUmS4M0J0ASXz3/U5XvXBa6DOQUL3fEz4Vt6YPhv+ESCarx6M6D+9kJkJYZKCNvJMas1+nVfmQ==",
|
||||
"path": "xunit.runner.visualstudio/2.8.2",
|
||||
"hashPath": "xunit.runner.visualstudio.2.8.2.nupkg.sha512"
|
||||
},
|
||||
"nucleic-brokerd/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"nucleic-brokerd.Reference/1.0.0.0": {
|
||||
"type": "reference",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net9.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "9.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Globalization.Invariant": true,
|
||||
"System.Globalization.PredefinedCulturesOnly": true,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v9.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v9.0": {
|
||||
"nucleic-brokerd/1.0.0": {
|
||||
"runtime": {
|
||||
"nucleic-brokerd.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"nucleic-brokerd/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net9.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "9.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Globalization.Invariant": true,
|
||||
"System.Globalization.PredefinedCulturesOnly": true,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user