Test that capability events route only to their own kind's subscribers
CapabilityEventsTests.EachEventKindReachesOnlyItsOwnSubscribers publishes one of each event kind and asserts every subscriber list holds exactly its own event -- a subscriber to Absorb must never see a Grab/Melee/Thrust event. Mutation entry in tests/mutation_tests.py kills a mutant that makes PublishAbsorb also notify the Thrust stream, plus a no-op control proving the mutation script's own read/replace/restore path is transparent for this file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
807c4fab7e
commit
88bcbc94b0
2 changed files with 68 additions and 0 deletions
50
tests/Aetheria.Shared.Tests/CapabilityEventsTests.cs
Normal file
50
tests/Aetheria.Shared.Tests/CapabilityEventsTests.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System.Collections.Generic;
|
||||
using CultMath;
|
||||
using UniRx;
|
||||
using Xunit;
|
||||
using static CultMath.math;
|
||||
|
||||
// Pins the routing invariant of CapabilityEvents (Assets/Scripts/ServerShared/CapabilityEvents.cs,
|
||||
// docs/headless-playground-cut.md fork L): a publish of one capability event kind reaches only the
|
||||
// subscribers of that kind. A subscriber to Absorb must never see a Grab (or Melee, or Thrust) event,
|
||||
// and vice versa for every other kind.
|
||||
public sealed class CapabilityEventsTests
|
||||
{
|
||||
[Fact]
|
||||
public void EachEventKindReachesOnlyItsOwnSubscribers()
|
||||
{
|
||||
var events = new CapabilityEvents();
|
||||
|
||||
var absorbed = new List<AbsorbEvent>();
|
||||
var grabbed = new List<GrabEvent>();
|
||||
var meleed = new List<MeleeEvent>();
|
||||
var thrust = new List<ThrustEvent>();
|
||||
|
||||
events.Absorb.Subscribe(absorbed.Add);
|
||||
events.Grab.Subscribe(grabbed.Add);
|
||||
events.Melee.Subscribe(meleed.Add);
|
||||
events.Thrust.Subscribe(thrust.Add);
|
||||
|
||||
var absorbEvent = new AbsorbEvent(float3(1, 2, 3), float3(0, 0, 1), 5f, DamageType.Corrosive);
|
||||
var grabEvent = new GrabEvent(7, GrabPhase.Started, float3(1, 0, 0), 1.5f);
|
||||
var meleeEvent = new MeleeEvent(float3(0, 0, 1), 10f, 90f, 0.5f);
|
||||
var thrustEvent = new ThrustEvent(float2(1, 0), 0.5f, float2(0.2f, -0.2f));
|
||||
|
||||
events.PublishAbsorb(absorbEvent);
|
||||
events.PublishGrab(grabEvent);
|
||||
events.PublishMelee(meleeEvent);
|
||||
events.PublishThrust(thrustEvent);
|
||||
|
||||
// Each stream received exactly one event: its own.
|
||||
Assert.Equal(new[] { absorbEvent }, absorbed);
|
||||
Assert.Equal(new[] { grabEvent }, grabbed);
|
||||
Assert.Equal(new[] { meleeEvent }, meleed);
|
||||
Assert.Equal(new[] { thrustEvent }, thrust);
|
||||
|
||||
// And nothing extra leaked across kinds: every list has exactly one entry, not more.
|
||||
Assert.Single(absorbed);
|
||||
Assert.Single(grabbed);
|
||||
Assert.Single(meleed);
|
||||
Assert.Single(thrust);
|
||||
}
|
||||
}
|
||||
|
|
@ -416,6 +416,24 @@ MUTATIONS: list[Mutation] = [
|
|||
test="IffAndCombatTests.EligibleWandererFactionsExcludesOwnerAndNearest",
|
||||
expect="red",
|
||||
),
|
||||
# --- Capability event contract (docs/headless-playground-cut.md fork L, 2026-09-17): each event
|
||||
# kind must reach only its own subscribers. ---
|
||||
Mutation(
|
||||
rule="control (no-op round trip) for the capability event routing test",
|
||||
file="Assets/Scripts/ServerShared/CapabilityEvents.cs",
|
||||
anchor=" public void PublishAbsorb(AbsorbEvent e) => _absorb.OnNext(e);",
|
||||
mutated=" public void PublishAbsorb(AbsorbEvent e) => _absorb.OnNext(e);",
|
||||
test="CapabilityEventsTests.EachEventKindReachesOnlyItsOwnSubscribers",
|
||||
expect="green",
|
||||
),
|
||||
Mutation(
|
||||
rule="PublishAbsorb notifies only the Absorb stream, not Thrust as well",
|
||||
file="Assets/Scripts/ServerShared/CapabilityEvents.cs",
|
||||
anchor=" public void PublishAbsorb(AbsorbEvent e) => _absorb.OnNext(e);",
|
||||
mutated=" public void PublishAbsorb(AbsorbEvent e) { _absorb.OnNext(e); _thrust.OnNext(default); }",
|
||||
test="CapabilityEventsTests.EachEventKindReachesOnlyItsOwnSubscribers",
|
||||
expect="red",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue