test(battlenode): harness stub fails loud + non-parallelizable (M-HC-0 review)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-06 19:42:55 -04:00
parent ca91fca028
commit 50294c10b1
2 changed files with 20 additions and 8 deletions

View File

@@ -12,6 +12,7 @@ namespace SVSim.UnitTests.BattleNode.Integration;
/// SVSim.UnitTests process.
/// </summary>
[TestFixture]
[NonParallelizable]
public class HeadlessConductorTests
{
[Test]

View File

@@ -39,14 +39,20 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public const long DefaultSeatAViewerId = 1001;
public const long DefaultSeatBViewerId = 1002;
/// <summary>Spellboost cost-reducer card (looking ahead to M-HC-3). Present in cards.json.</summary>
/// <summary>Spellboost cost-reducer card (looking ahead to M-HC-3). Known id present in cards.json
/// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
/// it will produce a traceable failure here.</summary>
public const long SpellboostCardId = 101314020;
/// <summary>A second spellboost card seen in the tk2 capture; present in cards.json.</summary>
/// <summary>A second spellboost card seen in the tk2 capture. Known id present in cards.json
/// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
/// it will produce a traceable failure here.</summary>
public const long SpellboostCardIdAlt = 100314020;
/// <summary>A plain vanilla follower the engine resolution path proved out
/// (HeadlessFixture.FollowerId). The bulk of the deterministic deck.</summary>
/// (HeadlessFixture.FollowerId). The bulk of the deterministic deck. Known id present in cards.json
/// (sourced from tk2 battle capture / existing engine tests); a cards.json regeneration that drops
/// it will produce a traceable failure here.</summary>
public const long VanillaFollowerId = 100011010;
public BattleSessionState State { get; }
@@ -135,8 +141,10 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public void Dispose() { /* engine holds no unmanaged resources; nothing to release. */ }
/// <summary>Minimal test-only <see cref="IBattleParticipant"/> exposing only the
/// <see cref="ViewerId"/> + <see cref="Context"/> that the harness reads. All broker members are
/// no-ops — the harness drives the engine directly, never the session relay.</summary>
/// <see cref="ViewerId"/> + <see cref="Context"/> that the harness reads. Broker members
/// (<c>PushAsync</c>, <c>RunAsync</c>, <c>TerminateAsync</c>) throw <see cref="NotSupportedException"/>
/// — the harness drives the engine directly, so a frame must never reach the participant relay.
/// Silent no-ops would let a misrouted push pass undetected.</summary>
internal sealed class StubParticipant : IBattleParticipant
{
public long ViewerId { get; }
@@ -152,9 +160,12 @@ internal sealed class NodeNativeBattleHarness : IDisposable
public event Func<MsgEnvelope, CancellationToken, Task>? FrameEmitted;
#pragma warning restore CS0067
public Task PushAsync(MsgEnvelope envelope, Stock stock, CancellationToken ct) => Task.CompletedTask;
public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
public Task PushAsync(MsgEnvelope envelope, Stock stock, CancellationToken ct) =>
throw new NotSupportedException("StubParticipant.PushAsync — harness drives the engine directly; a frame must not reach the participant relay.");
public Task RunAsync(CancellationToken ct) =>
throw new NotSupportedException("StubParticipant.RunAsync should not be called in harness tests.");
public Task TerminateAsync(BattleFinishReason reason) =>
throw new NotSupportedException("StubParticipant.TerminateAsync should not be called in harness tests.");
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
}