Introduce the presentation-free RuntimeEntityDirectory and RuntimeEntityRecord as the sole owners of server GUIDs, INSTANCE_TS incarnations, accepted snapshots, authority versions, retryable tombstones, session epochs, and local-ID allocation. Convert LiveEntityRuntime into an App projection sidecar host resolved through canonical record identity without a second GUID map. Preserve the existing synchronous and reentrant projection lifecycle, including retryable registration/delete/session teardown. Add Runtime-only identity/lifetime tests and App ownership guards. Validated by the Release solution build and 8,441 complete Release tests with five existing skips. Co-authored-by: Codex <codex@openai.com>
76 lines
2.9 KiB
C#
76 lines
2.9 KiB
C#
using System.Reflection;
|
|
using AcDream.App.World;
|
|
using AcDream.Runtime.Entities;
|
|
|
|
namespace AcDream.App.Tests.World;
|
|
|
|
public sealed class RuntimeEntityOwnershipTests
|
|
{
|
|
[Fact]
|
|
public void LiveEntityRuntime_ComposesCanonicalRuntimeDirectory()
|
|
{
|
|
FieldInfo directory = typeof(LiveEntityRuntime).GetField(
|
|
"_directory",
|
|
BindingFlags.Instance | BindingFlags.NonPublic)
|
|
?? throw new InvalidOperationException("Missing canonical entity directory.");
|
|
FieldInfo sidecars = typeof(LiveEntityRuntime).GetField(
|
|
"_activeRecords",
|
|
BindingFlags.Instance | BindingFlags.NonPublic)
|
|
?? throw new InvalidOperationException("Missing App projection sidecar store.");
|
|
|
|
Assert.Equal(typeof(RuntimeEntityDirectory), directory.FieldType);
|
|
Assert.Equal(typeof(RuntimeEntityRecord), sidecars.FieldType.GetGenericArguments()[0]);
|
|
Assert.Equal(typeof(LiveEntityRecord), sidecars.FieldType.GetGenericArguments()[1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void AppCompatibilityLookup_IsNotASecondGuidDictionary()
|
|
{
|
|
FieldInfo compatibilityView = typeof(LiveEntityRuntime).GetField(
|
|
"_recordsByGuid",
|
|
BindingFlags.Instance | BindingFlags.NonPublic)
|
|
?? throw new InvalidOperationException("Missing migration compatibility view.");
|
|
|
|
Assert.False(compatibilityView.FieldType.IsGenericType);
|
|
Assert.DoesNotContain(
|
|
compatibilityView.FieldType.GetInterfaces(),
|
|
type => type.IsGenericType
|
|
&& type.GetGenericTypeDefinition() == typeof(IDictionary<,>));
|
|
}
|
|
|
|
[Fact]
|
|
public void CanonicalRuntimeRecord_HasNoProjectionOrBackendSurface()
|
|
{
|
|
string[] forbiddenPropertyNames =
|
|
[
|
|
"WorldEntity",
|
|
"AnimationRuntime",
|
|
"RemoteMotionRuntime",
|
|
"ProjectileRuntime",
|
|
"EffectProfile",
|
|
"ResourcesRegistered",
|
|
"IsSpatiallyProjected",
|
|
"IsSpatiallyVisible",
|
|
];
|
|
PropertyInfo[] properties = typeof(RuntimeEntityRecord).GetProperties(
|
|
BindingFlags.Instance | BindingFlags.Public);
|
|
|
|
Assert.DoesNotContain(
|
|
properties,
|
|
property => forbiddenPropertyNames.Contains(
|
|
property.Name,
|
|
StringComparer.Ordinal));
|
|
Assert.DoesNotContain(
|
|
properties,
|
|
property => IsPresentationType(property.PropertyType));
|
|
}
|
|
|
|
private static bool IsPresentationType(Type type)
|
|
{
|
|
string? ns = type.Namespace;
|
|
return ns?.StartsWith("AcDream.App", StringComparison.Ordinal) == true
|
|
|| ns?.StartsWith("AcDream.UI", StringComparison.Ordinal) == true
|
|
|| ns?.StartsWith("Silk.NET", StringComparison.Ordinal) == true
|
|
|| ns?.StartsWith("ImGuiNET", StringComparison.Ordinal) == true;
|
|
}
|
|
}
|