Tests: the VerseGrammar global replaces TestCatalogGlobal as the catalog global fixtures author

TestCatalogGlobal existed only to give the test host one [CultGlobal] routed to the catalog. VerseGrammar is the
game's first, so the test-only type is deleted and every fixture authors a VerseGrammar instead (63 call sites; the
missing-global tests assert on aetheria.verse_grammar). Stale comments about the test type are rewritten.
Builds (not yet run when committed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-10 07:18:00 +02:00
commit 0b721d691f
40 changed files with 75 additions and 88 deletions

View file

@ -8,10 +8,6 @@ using GameCult.Caching.MessagePack;
using MessagePack;
using Xunit;
// A [CultGlobal] routed to the catalog (PersonalityAttribute is a catalog home). The game has none yet, so this is
// the only way to prove a read-only catalog refuses to open without one.
[CultDocument("aetheria.tests.catalogglobal", "1"), CultGlobal, MessagePackObject]
public class TestCatalogGlobal : PersonalityAttribute { }
// Each test gets its own temp directory holding a catalog built through Open(catalogWritable: true).
public sealed class AetheriaStoresTests : IDisposable
@ -25,7 +21,7 @@ public sealed class AetheriaStoresTests : IDisposable
{
Directory.CreateDirectory(_root);
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var faction = new Faction { Name = "Adrasteia", ShortName = "ADR", PrimaryColor = new float3(1, .5f, .25f) };
faction.Allegiance[cache.Upsert(faction)] = 1;
cache.Upsert(faction);
@ -118,7 +114,7 @@ public sealed class AetheriaStoresTests : IDisposable
var empty = Path.Combine(_root, "empty.cc");
using (AetheriaStores.Open(empty, catalogWritable: true)) { }
var error = Assert.Throws<InvalidOperationException>(() => AetheriaStores.Open(empty));
Assert.Contains("aetheria.tests.catalogglobal", error.Message);
Assert.Contains("aetheria.verse_grammar", error.Message);
using (AetheriaStores.Open(Catalog)) { }
}
@ -128,13 +124,13 @@ public sealed class AetheriaStoresTests : IDisposable
{
using (var cache = AetheriaStores.Open(Catalog, catalogWritable: true))
{
var global = cache.GetGlobal<TestCatalogGlobal>();
var global = cache.GetGlobal<VerseGrammar>();
var key = cache.RefOf(global).Key;
Assert.True(cache.Commit(batch => batch.Remove(key)));
}
var error = Assert.Throws<InvalidOperationException>(() => AetheriaStores.Open(Catalog, catalogWritable: true));
Assert.Contains("aetheria.tests.catalogglobal", error.Message);
Assert.Contains("aetheria.verse_grammar", error.Message);
}
// The game opens the catalog read-only with its run and player stores, in the editor as in a build: a populated
@ -143,10 +139,10 @@ public sealed class AetheriaStoresTests : IDisposable
public void GameShapedOpenMissingGlobalIsLoud()
{
using (var cache = AetheriaStores.Open(Catalog, catalogWritable: true))
Assert.True(cache.Commit(batch => batch.Remove(cache.RefOf(cache.GetGlobal<TestCatalogGlobal>()).Key)));
Assert.True(cache.Commit(batch => batch.Remove(cache.RefOf(cache.GetGlobal<VerseGrammar>()).Key)));
var error = Assert.Throws<InvalidOperationException>(() => AetheriaStores.Open(Catalog, Run, Player));
Assert.Contains("aetheria.tests.catalogglobal", error.Message);
Assert.Contains("aetheria.verse_grammar", error.Message);
}
// --- F7 (docs/stats-and-power-cut.md, Soul pass 2026-09-19): "there are at least four [write bypasses]."

View file

@ -76,7 +76,7 @@ public sealed class BrownoutTests : IDisposable
private CultCache OpenCatalog(BehaviorData consumer)
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -59,7 +59,7 @@ public sealed class ConditionRatioTests : IDisposable
private CultCache OpenCatalog(ThrusterData thruster, string catalogPath = null)
{
var cache = AetheriaStores.Open(catalogPath ?? Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -43,7 +43,7 @@ public sealed class ConsumableTests : IDisposable
{
var thrust = new PerformanceStat { Min = 10, Max = 10 };
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new Faction { Name = "Maker", ShortName = "MKR" });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;

View file

@ -94,7 +94,7 @@ public sealed class FireAuthorityTests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{

View file

@ -92,7 +92,7 @@ public sealed class FireControlCut11Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{

View file

@ -104,7 +104,7 @@ public sealed class FireControlCut123Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(shooterHullData);
cache.Upsert(new GearData

View file

@ -133,7 +133,7 @@ public sealed partial class FireControlCut124Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(shooterHullData);
cache.Upsert(new WeaponItemData

View file

@ -130,7 +130,7 @@ public sealed class FireControlCut12Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(shooterHullData);
cache.Upsert(new GearData

View file

@ -82,7 +82,7 @@ public sealed class FireControlCut4Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(MakeHullData());
cache.Upsert(new GearData
{
@ -205,7 +205,7 @@ public sealed class FireControlCut4Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(MakeHullData());
cache.Upsert(new GearData
{
@ -258,7 +258,7 @@ public sealed class FireControlCut4Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(MakeHullData(armor));
cache.FlushAsync().Wait();

View file

@ -97,7 +97,7 @@ public sealed class FireControlCut5Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{
@ -284,7 +284,7 @@ public sealed class FireControlCut5Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new HullData
{
Name = "Hull", HullType = HullType.Ship, Shape = SolidShape(5, 5), Durability = 1000, Mass = 1000,
@ -393,7 +393,7 @@ public sealed class FireControlCut5Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new HullData
{
Name = "Hull", HullType = HullType.Ship, Shape = SolidShape(3, 3), Durability = 1000, Mass = 1000,
@ -534,7 +534,7 @@ public sealed class FireControlCut5Tests : IDisposable
{
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new HullData
{
Name = "Hull", HullType = HullType.Ship, Shape = SolidShape(6, 4), Durability = 1000, Mass = 1000

View file

@ -89,7 +89,7 @@ public sealed class FireControlCut6Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
// Cut 6b, 6.2 (renamed 12.4(a)): a real WeaponItemData (not the bare GearData earlier cuts' fixtures
// use) -- it is the one catalog type carrying Fuse and BlastRadius. WeaponModifiers no longer decides

View file

@ -83,7 +83,7 @@ public sealed class FireControlCut6cTests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{
@ -198,7 +198,7 @@ public sealed class FireControlCut6cTests : IDisposable
CultRecordRef<Faction> maker, targetingMaker;
using (var seedCache = AetheriaStores.Open(Catalog, catalogWritable: true))
{
seedCache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
seedCache.Upsert(new VerseGrammar { Revision = 1 });
maker = seedCache.Upsert(new Faction { Name = "Maker", ShortName = "MKR" });
targetingMaker = seedCache.Upsert(new Faction { Name = "Targeting Maker", ShortName = "TGM" });

View file

@ -85,7 +85,7 @@ public sealed class FireControlCut6dTests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{

View file

@ -80,7 +80,7 @@ public sealed class FireControlCut7Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{
@ -239,20 +239,14 @@ public sealed class FireControlCut7Tests : IDisposable
throw new DirectoryNotFoundException("Run from inside the Aetheria repository -- built test output was not under a recognizable repo root.");
}
// AetheriaStores.Open (Assets/Scripts/ServerShared/AetheriaStores.cs) uses `new CultCache()`, whose
// default registry (CultDocumentRegistry.Shared) auto-discovers every [CultDocument] type loaded
// ANYWHERE in the current process by scanning the whole AppDomain -- including this very test
// assembly's own TestCatalogGlobal (AetheriaStoresTests.cs: [CultGlobal], routed to the catalog through
// PersonalityAttribute). The shipped catalog naturally carries no record of a test-only type it has
// never heard of, so opening it through the shared, process-wide registry throws "no
// aetheria.tests.catalogglobal record" -- a same-process, cross-assembly artifact of this test suite,
// not something the real game process (which never loads TestCatalogGlobal) can ever hit.
// AetheriaStores.Open uses `new CultCache()`, whose default registry (CultDocumentRegistry.Shared) discovers every
// [CultDocument] type loaded anywhere in the current process by scanning the whole AppDomain.
//
// This reproduces AetheriaStores.Open's own composition and validation exactly, scoped to a registry
// built only from the shipped assembly's own [CultDocument] types (CultDocumentRegistry.ForTypes does
// not re-scan the AppDomain the way the default constructor's Refresh() does), so this test still opens
// the catalog the same way the game does -- same backing store, same missing-global check, same R-heat
// validation loop -- without the test assembly's own fixture type poisoning it.
// validation loop -- without scanning the whole AppDomain.
private static CultCache OpenReadOnlyRealCatalog(string catalogPath)
{
var registry = CultDocumentRegistry.ForTypes(typeof(ItemData).Assembly.GetTypes()

View file

@ -83,7 +83,7 @@ public sealed class FireControlCut8Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{
@ -177,7 +177,7 @@ public sealed class FireControlCut8Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{

View file

@ -90,7 +90,7 @@ public sealed class FireControlCut9Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
// A bare, inert item -- not read by anything this test cares about, but Entity.Update's
// `foreach (var item in _orderedEquipment)` NREs if an entity was never equipped with anything at
@ -286,7 +286,7 @@ public sealed class FireControlCut9Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{
@ -527,7 +527,7 @@ public sealed class FireControlCut9Tests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(new GearData
{

View file

@ -145,7 +145,7 @@ public sealed class FireControlPerWeaponTests : IDisposable
var cache = AetheriaStores.Open(Catalog + Guid.NewGuid().ToString("N"), catalogWritable: true);
_openCaches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(hullData);
cache.Upsert(shooterHullData);
cache.Upsert(new WeaponItemData

View file

@ -57,7 +57,7 @@ public sealed class FireControlTests : IDisposable
using (var buildCache = AetheriaStores.Open(Catalog, catalogWritable: true))
{
buildCache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
buildCache.Upsert(new VerseGrammar { Revision = 1 });
buildCache.Upsert(hullData);
buildCache.Upsert(new GearData
{

View file

@ -50,7 +50,7 @@ public sealed class HeatResponseTests : IDisposable
private CultCache OpenCatalogWithThermalGear()
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new Faction { Name = "Maker", ShortName = "MKR" });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
@ -127,7 +127,7 @@ public sealed class HeatResponseTests : IDisposable
{
var catalog = Path.Combine(root, "Aetheria.cc");
using var cache = AetheriaStores.Open(catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var ex = Assert.Throws<InvalidOperationException>(() => cache.Upsert(new GearData
{
Name = "BadOptimum", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 1,
@ -148,7 +148,7 @@ public sealed class HeatResponseTests : IDisposable
{
var catalog = Path.Combine(root, "Aetheria.cc");
using var cache = AetheriaStores.Open(catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var ex = Assert.Throws<InvalidOperationException>(() => cache.Upsert(new GearData
{
Name = "BadPlateau", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 1,
@ -169,7 +169,7 @@ public sealed class HeatResponseTests : IDisposable
{
var catalog = Path.Combine(root, "Aetheria.cc");
using var cache = AetheriaStores.Open(catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var ex = Assert.Throws<InvalidOperationException>(() => cache.Upsert(new GearData
{
Name = "ZeroSpan", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 1,
@ -193,7 +193,7 @@ public sealed class HeatResponseTests : IDisposable
{
var catalog = Path.Combine(root, "Aetheria.cc");
using var cache = AetheriaStores.Open(catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var ex = Assert.Throws<InvalidOperationException>(() => cache.Upsert(new GearData
{
Name = "NaNHeat", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 1,
@ -216,7 +216,7 @@ public sealed class HeatResponseTests : IDisposable
{
var catalog = Path.Combine(root, "Aetheria.cc");
using var cache = AetheriaStores.Open(catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var ex = Assert.Throws<InvalidOperationException>(() => cache.Upsert(new GearData
{
Name = "PokingPlateau", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 1,

View file

@ -21,7 +21,7 @@ public sealed class IffAndCombatTests : IDisposable
{
Directory.CreateDirectory(_root);
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData

View file

@ -36,7 +36,7 @@ public sealed class InputCapacitorTests : IDisposable
private CultCache OpenCatalog()
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -23,7 +23,7 @@ public sealed class ItemTitleTests : IDisposable
{
Directory.CreateDirectory(_root);
_cache = AetheriaStores.Open(Path.Combine(_root, "Aetheria.cc"), catalogWritable: true);
_cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
_cache.Upsert(new VerseGrammar { Revision = 1 });
_array = new GearData { Name = "Array", Hardpoint = HardpointType.Sensors, Shape = new Shape(), Price = 10, Durability = 5 };
_cache.Upsert(_array);
_cache.Upsert(new SimpleCommodityData { Name = "Ore", Shape = new Shape(), Price = 7, MaxStack = 100 });

View file

@ -25,7 +25,7 @@ public sealed class LoadoutTests : IDisposable
{
Directory.CreateDirectory(_root);
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var maker = cache.Upsert(new Faction { Name = "Maker", ShortName = "MKR" });
var hullShape = new Shape(3, 3);

View file

@ -79,7 +79,7 @@ public sealed class MineTests : IDisposable
};
var cache = AetheriaStores.Open(Path.Combine(_root, Guid.NewGuid().ToString("N") + ".cc"), catalogWritable: true);
_caches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
HullData Hull(string name, Shape shape) => new HullData
{
Name = name, HullType = HullType.Ship, Shape = shape, Durability = 1000000, Mass = 1000, Armor = 0,

View file

@ -108,7 +108,7 @@ public sealed partial class MiningCut3Tests : IDisposable
Directory.CreateDirectory(dir);
var cache = AetheriaStores.Open(Path.Combine(dir, "Aetheria.cc"), Path.Combine(dir, "run.cc"), catalogWritable: true);
_caches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
var hull = new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 };
@ -1000,7 +1000,7 @@ public sealed partial class MiningCut3Tests : IDisposable
Directory.CreateDirectory(dir);
var cache = AetheriaStores.Open(Path.Combine(dir, "Aetheria.cc"), Path.Combine(dir, "run.cc"), catalogWritable: true);
_caches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var shape = new Shape(5, 5);
foreach (var cell in shape.AllCoordinates) shape[cell] = true;
var hull = new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = shape, Durability = 10, Mass = 1000 };

View file

@ -22,9 +22,8 @@ public sealed class PiratesFactionCommandTests : IDisposable
{
Directory.CreateDirectory(Path.Combine(_root, "GameData"));
File.Copy(Path.Combine(AetherDb.FindRoot(), "GameData", "Aetheria.cc"), CatalogPath);
// AetherDb.Open composes the process-wide registry, which in this test host also sees this assembly's TestCatalogGlobal
// (see FireControlCut7Tests). So the copy is stripped through a registry scoped to the shipped assembly and then given
// the record that registry's shared sibling demands, as AetheriaStoresTests does.
// AetherDb.Open composes the process-wide registry. So the copy is stripped through a registry scoped to the shipped
// assembly (see FireControlCut7Tests) and then given the grammar global every populated catalog must hold.
var registry = CultDocumentRegistry.ForTypes(typeof(ItemData).Assembly.GetTypes()
.Where(t => t is { IsAbstract: false, IsInterface: false })
.Where(t => t.GetCustomAttribute<CultDocumentAttribute>() != null));
@ -41,7 +40,7 @@ public sealed class PiratesFactionCommandTests : IDisposable
using (var cache = new CultCache())
{
cache.AddBackingStore(new SingleFileMessagePackBackingStore(CatalogPath), AetheriaStores.CatalogTypes);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.FlushAsync().Wait();
}
}

View file

@ -41,7 +41,7 @@ public sealed class PowerBusTests : IDisposable
private CultCache OpenCatalog()
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
// Mass must be nonzero: HullData.SpecificHeat defaults to 1 but Mass defaults to 0, and Entity.MapEntity

View file

@ -64,7 +64,7 @@ public sealed class PowerCurveTests : IDisposable
private CultCache OpenCatalog(PerformanceStat curveStat)
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });
@ -274,7 +274,7 @@ public sealed class PowerCurveTests : IDisposable
var goodEnergy = new PerformanceStat { Min = 1, Max = 1, Terms = { new StatTerm { Source = StatSource.PowerSupply, Exponent = 1 } } };
using (var cache = AetheriaStores.Open(Catalog, catalogWritable: true))
{
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.UpsertAsync(new GearData
{
Name = "CurvedThruster", Hardpoint = HardpointType.Tool, Shape = new Shape(), Durability = 10,
@ -294,7 +294,7 @@ public sealed class PowerCurveTests : IDisposable
{
var goodEnergy = new PerformanceStat { Min = 1, Max = 1, Terms = { new StatTerm { Source = StatSource.PowerSupply, Exponent = 1 } } };
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new GearData
{
@ -318,7 +318,7 @@ public sealed class PowerCurveTests : IDisposable
{
var curvedPumpedHeat = new PerformanceStat { Min = 1000, Max = 4000, Terms = { new StatTerm { Source = StatSource.PowerSupply, Exponent = 1 } } };
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new GearData
{
@ -342,7 +342,7 @@ public sealed class PowerCurveTests : IDisposable
{
var curvedRefillDuration = new PerformanceStat { Min = 2, Max = 2, Terms = { new StatTerm { Source = StatSource.PowerSupply, Exponent = 1 } } };
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new GearData
{
@ -376,7 +376,7 @@ public sealed class PowerCurveTests : IDisposable
};
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData

View file

@ -36,7 +36,7 @@ public sealed class PowerTierTests : IDisposable
private CultCache OpenCatalog()
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -88,7 +88,7 @@ public sealed class RolesBackfillCommandTests : IDisposable
using (var plain = new CultCache())
{
plain.AddBackingStore(new SingleFileMessagePackBackingStore(CatalogPath), AetheriaStores.CatalogTypes);
plain.Upsert(new TestCatalogGlobal { Name = "Temperament" });
plain.Upsert(new VerseGrammar { Revision = 1 });
plain.FlushAsync().Wait();
}
}

View file

@ -23,7 +23,7 @@ public sealed class RunSaveTests : IDisposable
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Commit(batch =>
{
batch.Upsert(new TestCatalogGlobal { Name = "Temperament" });
batch.Upsert(new VerseGrammar { Revision = 1 });
batch.Upsert(new Faction { Name = "Adrasteia", ShortName = "ADR" });
});
}

View file

@ -46,7 +46,7 @@ public sealed class ShieldReserveTests : IDisposable
private CultCache OpenCatalog()
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -21,8 +21,8 @@ public sealed class ShipModCatalogTests : IDisposable
{
Directory.CreateDirectory(Mods);
using var cache = AetheriaStores.Open(Shipped, catalogWritable: true);
// The test assembly registers TestCatalogGlobal (AetheriaStoresTests), so any populated catalog must hold one.
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
// A populated catalog must hold the VerseGrammar global.
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new HullData { Name = "Wasp", Shape = ShipAuthoringTests.Fixture().Hull.Shape });
cache.Upsert(new GearData { Name = "Widget" });
cache.FlushAsync().Wait();

View file

@ -33,7 +33,7 @@ public sealed class StatResolverTests : IDisposable
private CultCache OpenCatalog(CapacitorData capacitor, StatModifierData modifier = null)
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData
@ -267,7 +267,7 @@ public sealed class StatResolverTests : IDisposable
Type = StatModifierType.Constant
};
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(3, 3);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData

View file

@ -19,7 +19,7 @@ public sealed class StationServicesTests : IDisposable
{
Directory.CreateDirectory(_root);
_cache = AetheriaStores.Open(Path.Combine(_root, "Aetheria.cc"), catalogWritable: true);
_cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
_cache.Upsert(new VerseGrammar { Revision = 1 });
var shape = new Shape(5, 5);
foreach (var cell in shape.AllCoordinates) shape[cell] = true;
var hardpoint = new HardpointData { Type = HardpointType.Sensors, Position = new int2(0, 0), Shape = new Shape() };

View file

@ -69,7 +69,7 @@ public sealed class TargetingSystemTests : IDisposable
using (var buildCache = AetheriaStores.Open(Catalog, catalogWritable: true))
{
buildCache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
buildCache.Upsert(new VerseGrammar { Revision = 1 });
buildCache.Upsert(hullData);
buildCache.Upsert(new GearData
{
@ -303,7 +303,7 @@ public sealed class TargetingSystemTests : IDisposable
public void StarvedTargetingRollsWorse()
{
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });
@ -378,7 +378,7 @@ public sealed class TargetingSystemTests : IDisposable
public void EveryArmedLoadoutGetsATargetingSystem()
{
using var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var maker = cache.Upsert(new Faction { Name = "Maker", ShortName = "MKR" });
var hullShape = new Shape(5, 5);

View file

@ -57,7 +57,7 @@ public sealed class ThrottleLockTests : IDisposable
private Fixture Build(float lockDuration)
{
var cache = AetheriaStores.Open(Catalog, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
var hullShape = new Shape(5, 5);
foreach (var cell in hullShape.AllCoordinates) hullShape[cell] = true;
cache.Upsert(new HullData { Name = "Skiff", HullType = HullType.Ship, Shape = hullShape, Durability = 10, Mass = 1000 });

View file

@ -69,7 +69,7 @@ public sealed class VapourCloudTests : IDisposable
};
var cache = AetheriaStores.Open(Path.Combine(_root, Guid.NewGuid().ToString("N") + ".cc"), catalogWritable: true);
_caches.Add(cache);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
cache.Upsert(new VerseGrammar { Revision = 1 });
cache.Upsert(new HullData
{
Name = "Hull", HullType = HullType.Ship, Shape = Solid(5, 5), Durability = 1000000, Mass = 1000,

View file

@ -36,13 +36,11 @@ public sealed class VerseGrammarTests : IDisposable
Roles = new[] { new VerseRole { Name = "site", Binds = VerseReferentKind.Place }, new VerseRole { Name = "load", Binds = VerseReferentKind.Cargo } },
};
// A catalog authored through AetheriaStores.Open; TestCatalogGlobal is the record the shared registry in this test host
// demands (see AetheriaStoresTests).
// A catalog authored through AetheriaStores.Open; a null grammar leaves the catalog without its global.
private string Author(string name, VerseGrammar grammar, params VerseVerb[] verbs)
{
var path = PathOf(name);
using var cache = AetheriaStores.Open(path, catalogWritable: true);
cache.Upsert(new TestCatalogGlobal { Name = "Temperament" });
if (grammar != null) cache.Upsert(grammar);
foreach (var verb in verbs) cache.Upsert(verb);
cache.FlushAsync().Wait();
@ -143,7 +141,7 @@ public sealed class VerseGrammarTests : IDisposable
// A scratch root holding a copy of the shipped catalog with its verse grammar removed: the catalog as it was before the
// command ran. The catalog is stripped and read through a registry scoped to the shipped assembly, as
// PiratesFactionCommandTests does, so the test assembly's TestCatalogGlobal does not poison it.
// PiratesFactionCommandTests does.
private string RootWithoutGrammar(params VerseVerb[] preexisting)
{
var gameData = Path.Combine(_root, "cmd", "GameData");