TDD: PakKeyTests + PakFormatTests written first (confirmed a compile failure against the not-yet-existing AcDream.Content.Pak namespace), then PakKey (64-bit type:u8|fileId:u32|reserved:u24 compose/decompose) and PakFormat (64-byte PakHeader, 24-byte PakTocEntry) implemented to the normative layout in the MP1b plan. 21 tests green, including a key- ordering test proving ascending numeric key order equals ascending (type, fileId) tuple order (the TOC binary-search precondition) and an explicit byte-offset test for both structs.
75 lines
3.1 KiB
C#
75 lines
3.1 KiB
C#
using AcDream.Content.Pak;
|
|
|
|
namespace AcDream.Content.Tests;
|
|
|
|
public class PakKeyTests {
|
|
[Theory]
|
|
[InlineData(PakAssetType.GfxObjMesh, 0u)]
|
|
[InlineData(PakAssetType.GfxObjMesh, 0x01000001u)]
|
|
[InlineData(PakAssetType.SetupMesh, 0x020019FFu)]
|
|
[InlineData(PakAssetType.EnvCellMesh, 0xA9B40100u)]
|
|
[InlineData(PakAssetType.GfxObjMesh, 0xFFFFFFFFu)] // max fileId
|
|
[InlineData(PakAssetType.EnvCellMesh, 0xFFFFFFFFu)]
|
|
public void ComposeDecompose_RoundTrips(PakAssetType type, uint fileId) {
|
|
ulong key = PakKey.Compose(type, fileId);
|
|
var (decodedType, decodedFileId) = PakKey.Decompose(key);
|
|
Assert.Equal(type, decodedType);
|
|
Assert.Equal(fileId, decodedFileId);
|
|
}
|
|
|
|
[Fact]
|
|
public void Compose_LowFourBytesReserved() {
|
|
// Low 24 bits are reserved (zero in v1) — fileId << 24 must not spill
|
|
// into them, and the reserved region must actually read back as zero.
|
|
ulong key = PakKey.Compose(PakAssetType.GfxObjMesh, 0xFFFFFFFFu);
|
|
Assert.Equal(0u, (uint)(key & 0xFFFFFFu));
|
|
}
|
|
|
|
[Fact]
|
|
public void Compose_TypeOccupiesTopByte() {
|
|
ulong key = PakKey.Compose(PakAssetType.SetupMesh, 0u);
|
|
Assert.Equal((byte)PakAssetType.SetupMesh, (byte)(key >> 56));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(PakAssetType.GfxObjMesh, 1)]
|
|
[InlineData(PakAssetType.SetupMesh, 2)]
|
|
[InlineData(PakAssetType.EnvCellMesh, 3)]
|
|
public void AssetType_NumericValuesAreStable(PakAssetType type, byte expected) {
|
|
// These values are a wire format — pin them so a future refactor can't
|
|
// silently renumber the enum and corrupt existing paks.
|
|
Assert.Equal(expected, (byte)type);
|
|
}
|
|
|
|
[Fact]
|
|
public void KeyOrdering_MatchesTypeThenFileIdOrdering() {
|
|
// Ascending key order must equal ascending (type, fileId) tuple order —
|
|
// this is what makes the TOC's binary search over raw u64 keys valid.
|
|
var pairs = new (PakAssetType Type, uint FileId)[] {
|
|
(PakAssetType.GfxObjMesh, 0u),
|
|
(PakAssetType.GfxObjMesh, 1u),
|
|
(PakAssetType.GfxObjMesh, 0xFFFFFFFFu),
|
|
(PakAssetType.SetupMesh, 0u),
|
|
(PakAssetType.SetupMesh, 0x020019FFu),
|
|
(PakAssetType.EnvCellMesh, 0u),
|
|
(PakAssetType.EnvCellMesh, 0xA9B40100u),
|
|
};
|
|
|
|
var keys = pairs.Select(p => PakKey.Compose(p.Type, p.FileId)).ToArray();
|
|
|
|
// keys[] as generated must already be strictly ascending since pairs[]
|
|
// is in ascending tuple order.
|
|
for (int i = 1; i < keys.Length; i++) {
|
|
Assert.True(keys[i] > keys[i - 1],
|
|
$"key[{i}]=0x{keys[i]:X16} should be > key[{i - 1}]=0x{keys[i - 1]:X16} " +
|
|
$"for tuple order ({pairs[i - 1]}) < ({pairs[i]})");
|
|
}
|
|
|
|
// Sorting the keys numerically must reproduce the same order as sorting
|
|
// the tuples lexicographically by (Type, FileId).
|
|
var numericSorted = keys.OrderBy(k => k).ToArray();
|
|
var tupleSorted = pairs.OrderBy(p => (byte)p.Type).ThenBy(p => p.FileId)
|
|
.Select(p => PakKey.Compose(p.Type, p.FileId)).ToArray();
|
|
Assert.Equal(tupleSorted, numericSorted);
|
|
}
|
|
}
|