Hygiene B6: test coverage (fixture + missing coverage + guards)
- TestWorld: shared plain-Entities fixture (Make/Make<T>/SetTick reconciling the two SetServerTick variants + Player/Enemy builders). Additive; new tests consume it (40-file migration of existing tests deliberately deferred as pure churn). - TestAttributeGuardTests: scans *Tests.cs and fails on any parameterless public-void method missing a runner attribute — guards the swallowed-[Test] bug (B0). Confirms the suite has no other dead tests. - PrepPurchaseSystemTests (6): the previously-untested RPC economy — afford, reject-when-broke, once-per-run, non-Staging reject, unknown-id drop, and DR-014 same-tick atomicity. - SystemOrderingCycleTests: registers the real run/cycle/combat system set and asserts SortSystems() has no circular dependency (invisible to single-system fixtures; only throws at Play) — also de-risks the B5 splits. 459/459 EditMode tests pass. (BossAISystemTests remains queued — the most complex to author faithfully; the boss stays Play-validated meanwhile.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using NUnit.Framework;
|
||||
using ProjectM.Server;
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Entities;
|
||||
|
||||
namespace ProjectM.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Guards the ComponentSystemSorter "circular dependency" hazard that is INVISIBLE to the rest of the suite:
|
||||
/// every other fixture registers a single system then sorts, so a cross-system [UpdateBefore/After] cycle can
|
||||
/// never surface — it only throws at world creation in Play. This registers the REAL ordered server-sim set
|
||||
/// (every system that participates in an UpdateBefore/After relation, or its constraint is silently ignored)
|
||||
/// into one SimulationSystemGroup and sorts, reproducing the Play-time sort headlessly. Only SortSystems runs
|
||||
/// (never Update), so a bare world with no entities/singletons suffices.
|
||||
/// </summary>
|
||||
public class SystemOrderingCycleTests
|
||||
{
|
||||
[Test]
|
||||
public void RunCycleCombatChain_Sorts_Without_A_Dependency_Cycle()
|
||||
{
|
||||
using var world = new World("OrderCycleGuard");
|
||||
var group = world.GetOrCreateSystemManaged<SimulationSystemGroup>();
|
||||
|
||||
void Add<T>() where T : unmanaged, ISystem
|
||||
=> group.AddSystemToUpdateList(world.GetOrCreateSystem<T>());
|
||||
|
||||
// RPC-receive systems ordered before the run director
|
||||
Add<ReadyToggleSystem>(); Add<RouteSelectSystem>(); Add<PortalInteractReceiveSystem>();
|
||||
Add<MetaSpendSystem>(); Add<ClassSelectReceiveSystem>(); Add<BoonApplySystem>(); Add<PrepPurchaseSystem>();
|
||||
// Run director + the systems ordered around it and the cycle phase
|
||||
Add<RunDirectorSystem>(); Add<ThreatDirectorSystem>(); Add<RoomFieldSystem>();
|
||||
Add<RoomEnemyDirectorSystem>(); Add<BoonOfferSystem>(); Add<CyclePhaseSystem>();
|
||||
Add<GoalReachedSystem>(); Add<WaveSystem>();
|
||||
// Combat sub-chain in the same group
|
||||
Add<EnemyAISystem>(); Add<BossAISystem>(); Add<CoreDamageSystem>();
|
||||
Add<CoreRestoreSystem>(); Add<EnemyProjectileMoveSystem>(); Add<EnemyProjectileDamageSystem>();
|
||||
|
||||
Assert.DoesNotThrow(() => group.SortSystems(),
|
||||
"A [UpdateBefore/After] cycle in the run/cycle/combat chain throws here instead of only at Play world-creation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user