Ymir/tests/Ymir.Tests/YmirServicePublicationTests.cs
2026-07-15 00:51:54 +01:00

140 lines
5.6 KiB
C#

using GameCult.Caching;
using GameCult.Caching.MessagePack;
using GameCult.Eve.Surface;
using Ymir.Core;
namespace Ymir.Tests;
public sealed class YmirServicePublicationTests
{
[Fact]
public void PublicationAdvertisesBox3DOwnershipBoundary()
{
var now = DateTimeOffset.Parse("2026-07-14T12:00:00Z");
var advertisement = YmirServicePublication.ProviderAdvertisement(now);
var diagnostics = YmirServicePublication.OperatorState(now);
Assert.Contains("Box3D", advertisement.Description, StringComparison.Ordinal);
Assert.Contains("stateless managed step and query request handling", advertisement.Owns);
Assert.Contains("Box3D solver and collision semantics", advertisement.DoesNotOwn);
Assert.Contains("retained Box3D production sessions during cutover", advertisement.DoesNotOwn);
Assert.Contains("CultMesh provider sessions or discovery during cutover", advertisement.DoesNotOwn);
Assert.DoesNotContain("daemon", advertisement.Description, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain(advertisement.Owns, claim => claim.Contains("session", StringComparison.OrdinalIgnoreCase));
Assert.Equal("box3d-cutover", diagnostics.Status);
Assert.StartsWith("Active: CultMath managed solver", diagnostics.NumericSubstrate, StringComparison.Ordinal);
Assert.Contains("no retained Box3D session", diagnostics.BatchKernel, StringComparison.Ordinal);
Assert.Contains("world_state.v0", diagnostics.Persistence, StringComparison.Ordinal);
}
[Fact]
public void EveSurfaceUsesCanonicalDocumentAndOperatorMetrics()
{
var diagnostics = new YmirOperatorStateDocument
{
ProviderId = "ymir.physics",
Status = "ready",
StateOwner = "diagnostic-owner",
NumericSubstrate = "diagnostic-math",
BatchKernel = "diagnostic-batch",
Persistence = "diagnostic-persistence",
UpdatedAtUtc = "2026-07-13T12:00:00.0000000Z"
};
EveSurfaceDocument surface = YmirServicePublication.EveSurface(diagnostics);
Assert.Equal(EveSurfaceDocument.SchemaId, surface.Schema);
Assert.Equal("ymir.physics.operator", surface.Surface.Id);
Assert.Equal("partition", surface.Surface.Root.Kind);
Assert.Equal(diagnostics.UpdatedAtUtc, surface.UpdatedAtUtc);
Assert.Equal(
new[]
{
("Status", diagnostics.Status),
("State owner", diagnostics.StateOwner),
("Numeric substrate", diagnostics.NumericSubstrate),
("Batch kernel", diagnostics.BatchKernel),
("Persistence", diagnostics.Persistence)
},
surface.Surface.Root.Children
.Select(child => (child.GetProp("label"), child.GetProp("value")))
.ToArray());
}
[Fact]
public void CombinedRegistryContainsExactlyOneCanonicalSurfaceDescriptor()
{
var registry = new CultDocumentRegistry();
var descriptors = registry.AllDescriptors
.Where(descriptor => descriptor.SchemaVersion == EveSurfaceDocument.SchemaId)
.ToArray();
var descriptor = Assert.Single(descriptors);
Assert.Equal(typeof(EveSurfaceDocument), descriptor.DocumentType);
}
[Fact]
public async Task PublicationPersistsAndReopensWithCombinedRegistry()
{
var path = TemporaryStorePath();
try
{
await YmirServicePublicationStore.RegenerateDerivedStoreAsync(path, DateTimeOffset.UtcNow);
using var cache = await CultCacheMessagePack.OpenAsync(path, new CultCacheOpenOptions
{
Registry = new CultDocumentRegistry(),
UseDirectoryStore = true
});
var surface = cache.Get<EveSurfaceDocument>(new CultRecordKey(YmirServicePublicationStore.SurfaceRecordKey));
Assert.NotNull(surface);
Assert.Equal("ymir.physics.operator", surface.Surface.Id);
Assert.Single(cache.GetAll<EveSurfaceDocument>());
}
finally
{
DeleteStore(path);
}
}
[Fact]
public async Task RegenerationReplacesUnreadableLegacyDerivedStoreBeforeOpen()
{
var path = TemporaryStorePath();
var recordsPath = DirectoryMessagePackBackingStore.DefaultRecordDirectoryPath(path);
try
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
Directory.CreateDirectory(recordsPath);
await File.WriteAllBytesAsync(path, [0xc1]);
await File.WriteAllBytesAsync(Path.Combine(recordsPath, "legacy.msgpack"), [0xc1]);
await YmirServicePublicationStore.RegenerateDerivedStoreAsync(path, DateTimeOffset.UtcNow);
using var cache = await CultCacheMessagePack.OpenAsync(path, new CultCacheOpenOptions
{
Registry = new CultDocumentRegistry(),
UseDirectoryStore = true
});
Assert.NotNull(cache.Get<EveSurfaceDocument>(new CultRecordKey(YmirServicePublicationStore.SurfaceRecordKey)));
Assert.False(File.Exists(Path.Combine(recordsPath, "legacy.msgpack")));
}
finally
{
DeleteStore(path);
}
}
private static string TemporaryStorePath() =>
Path.Combine(Path.GetTempPath(), "ymir-tests", Guid.NewGuid().ToString("N"), "service.cc");
private static void DeleteStore(string path)
{
var directory = Path.GetDirectoryName(path);
if (directory is not null && Directory.Exists(directory))
Directory.Delete(directory, recursive: true);
}
}