Eve is deprecated; per thing2:ruling:eve-dashboards-quarantined the surface builders, EveSurfaceDocument publication, GameCult.Eve.Surface reference and EveRoot are gone. YmirOperatorStateDocument and its publication stay. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
92 lines
3.9 KiB
C#
92 lines
3.9 KiB
C#
using GameCult.Caching;
|
|
using GameCult.Caching.MessagePack;
|
|
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("Box3D-only isolated snapshot stepping", advertisement.Owns);
|
|
Assert.Contains("public in-process retained sessions with explicit mutation receipts", advertisement.Owns);
|
|
Assert.Contains("typed Begin, Hit, and End contact facts for retained steps", advertisement.Owns);
|
|
Assert.Contains("daemon-owned named session registry or CultMesh command lowering yet", advertisement.DoesNotOwn);
|
|
Assert.Empty(advertisement.CommandLowerings);
|
|
Assert.Contains("Box3D solver and collision semantics", advertisement.DoesNotOwn);
|
|
Assert.Equal("Box3D v0.1.0 (C17)", diagnostics.NumericSubstrate);
|
|
Assert.Contains("does not own physics algorithms", diagnostics.BatchKernel, StringComparison.Ordinal);
|
|
Assert.Contains("world_state.v2", diagnostics.Persistence, StringComparison.Ordinal);
|
|
Assert.Contains("replay checkpoint v1", diagnostics.Persistence, StringComparison.Ordinal);
|
|
Assert.Contains("host-owned private journal persistence", diagnostics.Persistence, StringComparison.Ordinal);
|
|
Assert.Equal("box3d-retained-session", diagnostics.Status);
|
|
}
|
|
|
|
[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
|
|
});
|
|
|
|
Assert.NotNull(cache.Get<YmirOperatorStateDocument>(new CultRecordKey("ymir:operator:ymir.physics")));
|
|
Assert.Single(cache.GetAll<YmirOperatorStateDocument>());
|
|
}
|
|
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<YmirOperatorStateDocument>(new CultRecordKey("ymir:operator:ymir.physics")));
|
|
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);
|
|
}
|
|
}
|