79 lines
3.4 KiB
C#
79 lines
3.4 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using FluentAssertions;
|
|
using GameCult.Caching;
|
|
using GameCult.Caching.MessagePack;
|
|
using GameCult.Networking;
|
|
using NUnit.Framework;
|
|
|
|
namespace GameCult.Mesh.Tests;
|
|
|
|
// The mesh's typed reads of a raw record decode the payload through the one-value rule: a tail is refused, never ignored.
|
|
public class BytesAfterPathTests
|
|
{
|
|
private const string Clause = "bytes after its first MessagePack value";
|
|
|
|
private static CultNetRawDocumentRecord WithTail(CultMeshCdnArtifactManifest manifest)
|
|
{
|
|
var payload = CultDocumentMessagePackSerialization.SerializeUntyped(manifest, typeof(CultMeshCdnArtifactManifest)).Concat(new byte[] { 0xc0 }).ToArray();
|
|
return new CultNetRawDocumentRecord
|
|
{
|
|
SchemaId = CultDocumentRegistry.Shared.GetRequired<CultMeshCdnArtifactManifest>().SchemaId,
|
|
RecordKey = "k",
|
|
StoredAt = "1970-01-01T00:00:00.000Z",
|
|
Payload = payload,
|
|
};
|
|
}
|
|
|
|
private static CultMeshCdnArtifactManifest Manifest() => new() { ArtifactId = "a", Version = "1", ContentHash = "h" };
|
|
|
|
private static string Refusal(Action read)
|
|
{
|
|
var thrown = Assert.Catch(read)!;
|
|
return thrown is TargetInvocationException { InnerException: { } inner } ? inner.ToString() : thrown.ToString();
|
|
}
|
|
|
|
[Test]
|
|
public void ASnapshotDecodeThroughABindingRefusesATail()
|
|
{
|
|
var registry = CultMeshCdn.CreateDocumentRegistry();
|
|
var snapshot = new CultNetSnapshotResponseRawMessage { Documents = new[] { WithTail(Manifest()) } };
|
|
Refusal(() => CultMesh.DecodeSnapshotDocuments<CultMeshCdnArtifactManifest>(snapshot, registry)).Should().Contain(Clause);
|
|
}
|
|
|
|
[Test]
|
|
public void ASnapshotDecodeWithNoBindingRefusesATail()
|
|
{
|
|
var snapshot = new CultNetSnapshotResponseRawMessage { Documents = new[] { WithTail(Manifest()) } };
|
|
Refusal(() => CultMesh.DecodeSnapshotDocuments<CultMeshCdnArtifactManifest>(snapshot, new CultNetDocumentRegistry())).Should().Contain(Clause);
|
|
}
|
|
|
|
[Test]
|
|
public void ATypedReadOfOneSnapshotRecordRefusesATail()
|
|
{
|
|
var record = WithTail(Manifest());
|
|
var snapshot = new CultNetSnapshotResponseRawMessage { MessageId = "m", Documents = new[] { record } };
|
|
var read = typeof(CultMesh).GetMethod("ReadDocumentFromSnapshotResponse", BindingFlags.NonPublic | BindingFlags.Static)!
|
|
.MakeGenericMethod(typeof(CultMeshCdnArtifactManifest));
|
|
Refusal(() => read.Invoke(null, new object[] { snapshot, record.SchemaId, record.RecordKey })).Should().Contain(Clause);
|
|
}
|
|
|
|
[Test]
|
|
public void ASingleFileDocumentReadRefusesATail()
|
|
{
|
|
var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"cultlib-bytesafter-mesh-{Guid.NewGuid():N}.cc");
|
|
try
|
|
{
|
|
var descriptor = CultDocumentRegistry.Shared.GetRequired<CultMeshCdnArtifactManifest>();
|
|
var schema = new CultMeshSingleFileDocumentSchema(descriptor.SchemaId, descriptor.SchemaName, descriptor.SchemaVersion);
|
|
var payload = WithTail(Manifest()).Payload;
|
|
CultMesh.WriteSingleFileDocumentPayload(path, new CultRecordKey("k"), schema, null, payload);
|
|
Refusal(() => CultMesh.ReadSingleFileDocument<CultMeshCdnArtifactManifest>(path, new CultRecordKey("k"))).Should().Contain(Clause);
|
|
}
|
|
finally
|
|
{
|
|
System.IO.File.Delete(path);
|
|
}
|
|
}
|
|
}
|