mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-09-08 10:10:49 +00:00
RegisterDynamicTypeDef fall back
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"fixtureVersion": 1,
|
||||
"protocolVersion": "3.1",
|
||||
"producer": "esiur-ts",
|
||||
"encoding": "indexed-TypeDefInfo",
|
||||
"payloadBase64": "iaSIolEDAckWCAAIAQgCCAMIBAggCCEIIggjCCQIJcmFCQMIEUkEUHVtcEkTQnVpbGRpbmcuQXV0b21hdGlvbggASRxDb250cm9scyBhIGNpcmN1bGF0aW9uIHB1bXAuSQ9QdW1wIGNvbnRyb2xsZXJJDGVuYWJsZWQ9dHJ1ZUkESFZBQ0kDMy4xiBpREhLJB0kFb3duZXLJDEkKb3BlcmF0aW9ucw==",
|
||||
"expected": {
|
||||
"id": 17,
|
||||
"kind": "Resource",
|
||||
"version": 3,
|
||||
"name": "Building.Automation.Pump",
|
||||
"namespace": "Building.Automation",
|
||||
"usage": "Controls a circulation pump.",
|
||||
"description": "Pump controller",
|
||||
"example": "enabled=true",
|
||||
"category": "HVAC",
|
||||
"since": "3.1",
|
||||
"annotations": {
|
||||
"owner": "operations"
|
||||
},
|
||||
"properties": [],
|
||||
"functions": [],
|
||||
"events": [],
|
||||
"constants": []
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="ConformanceFixtures\**\*.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Reference Esiur both as a runtime assembly and as the source generator (analyzer),
|
||||
mirroring Tests/Features/Functional so [Resource]/[Export] test types get generated code. -->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Text.Json;
|
||||
using Esiur.Data;
|
||||
using Esiur.Data.Types;
|
||||
using Esiur.Resource;
|
||||
|
||||
namespace Esiur.Tests.Unit;
|
||||
|
||||
public class TypeDefConformanceFixtureTests
|
||||
{
|
||||
[Fact]
|
||||
public void DotnetEncoder_MatchesCanonicalTypeScriptFixture()
|
||||
{
|
||||
var root = ReadFixture();
|
||||
var info = new TypeDefInfo
|
||||
{
|
||||
Version = 3,
|
||||
Id = 17,
|
||||
Name = "Pump",
|
||||
Namespace = "Building.Automation",
|
||||
Kind = TypeDefKind.Resource,
|
||||
Usage = "Controls a circulation pump.",
|
||||
Description = "Pump controller",
|
||||
Example = "enabled=true",
|
||||
Category = "HVAC",
|
||||
Since = "3.1",
|
||||
Annotations = new Map<string, string> { ["owner"] = "operations" },
|
||||
};
|
||||
|
||||
var encoded = Codec.Compose(info, Warehouse.Default, null);
|
||||
Assert.Equal(root.GetProperty("payloadBase64").GetString(), Convert.ToBase64String(encoded));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TypeScriptIndexedTypeDefInfoFixture_DecodesWithExpectedSemantics()
|
||||
{
|
||||
var root = ReadFixture();
|
||||
var expected = root.GetProperty("expected");
|
||||
var payload = Convert.FromBase64String(root.GetProperty("payloadBase64").GetString()!);
|
||||
|
||||
var (size, info) = Codec.ParseIndexedType<TypeDefInfo>(payload, 0, Warehouse.Default);
|
||||
|
||||
Assert.Equal((uint)payload.Length, size);
|
||||
Assert.Equal(expected.GetProperty("id").GetUInt64(), info.Id);
|
||||
Assert.Equal(expected.GetProperty("version").GetInt32(), info.Version);
|
||||
Assert.Equal("Pump", info.Name);
|
||||
Assert.Equal(expected.GetProperty("namespace").GetString(), info.Namespace);
|
||||
Assert.Equal(expected.GetProperty("usage").GetString(), info.Usage);
|
||||
Assert.Equal(expected.GetProperty("description").GetString(), info.Description);
|
||||
Assert.Equal(expected.GetProperty("example").GetString(), info.Example);
|
||||
Assert.Equal(expected.GetProperty("category").GetString(), info.Category);
|
||||
Assert.Equal(expected.GetProperty("since").GetString(), info.Since);
|
||||
Assert.Equal(
|
||||
expected.GetProperty("annotations").GetProperty("owner").GetString(),
|
||||
info.Annotations!["owner"]);
|
||||
}
|
||||
|
||||
private static JsonElement ReadFixture()
|
||||
{
|
||||
var location = Path.Combine(
|
||||
AppContext.BaseDirectory,
|
||||
"ConformanceFixtures",
|
||||
"typedef-info-v3-flat.json");
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(location));
|
||||
return document.RootElement.Clone();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Esiur.Core;
|
||||
using Esiur.Data.Types;
|
||||
using Esiur.Resource;
|
||||
using Esiur.Stores;
|
||||
|
||||
@@ -6,6 +7,25 @@ namespace Esiur.Tests.Unit;
|
||||
|
||||
public sealed class WarehouseLifecycleTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReparsedRemoteTypeDef_ReusesWarehouseLocalId()
|
||||
{
|
||||
var warehouse = new Warehouse();
|
||||
_ = new LocalTypeDef(typeof(LocalCollisionMarker), warehouse);
|
||||
|
||||
var first = new TestRemoteTypeDef(1, "Remote.ReportingService");
|
||||
Assert.True(warehouse.TryRegisterRemoteTypeDef("flow.example", first));
|
||||
Assert.NotEqual(0u, first.LocalTypeDefId);
|
||||
|
||||
var reparsed = new TestRemoteTypeDef(1, "Remote.ReportingService");
|
||||
Assert.False(warehouse.TryRegisterRemoteTypeDef("flow.example", reparsed));
|
||||
Assert.Equal(first.LocalTypeDefId, reparsed.LocalTypeDefId);
|
||||
|
||||
// Dynamic EpResource construction registers the definition again.
|
||||
// This must use the reused local id, not the colliding wire id 1.
|
||||
warehouse.RegisterDynamicTypeDef(reparsed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Close_AllowsWarehouseToBeOpenedAgain()
|
||||
{
|
||||
@@ -176,6 +196,21 @@ public sealed class WarehouseLifecycleTests
|
||||
|
||||
private static async Task<bool> Observe(AsyncReply<bool> reply) => await reply;
|
||||
|
||||
private enum LocalCollisionMarker
|
||||
{
|
||||
Value,
|
||||
}
|
||||
|
||||
private sealed class TestRemoteTypeDef : RemoteTypeDef
|
||||
{
|
||||
public TestRemoteTypeDef(ulong id, string name)
|
||||
{
|
||||
_typeId = id;
|
||||
_typeName = name;
|
||||
_typeDefKind = TypeDefKind.Resource;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ControlledLifecycleResource : IResource
|
||||
{
|
||||
private readonly AsyncReply<bool>? terminateReply;
|
||||
|
||||
Reference in New Issue
Block a user