using NUnit.Framework; namespace InverseOfLife.Test; [TestFixture] public class CellTracerTests { private Board board; [SetUp] public void Setup() { board = new Board(5, 5, useTracer: true); } [Test] public void InitializeBoard_WithTracer_ShouldHaveNoCellsOrContributions() { var initialState = board.ToString(); Assert.IsNotNull(board.Tracer); Assert.That(board.Tracer!.Contribution, Is.Empty); } [Test] public void Toggle_ShouldNotAffectTracer() { board.Toggle(1, 1); board.Toggle(2, 2); Assert.That(board.Lives, Is.EquivalentTo(new[] { (1, 1), (2, 2) })); Assert.That(board.Tracer!.Contribution, Is.Empty); // Tracer not affected by Toggle } [Test] public void Evaluate_WithTracer_ShouldTrackNewCellContributions() { board.Toggle(1, 2, initialConfig: true); board.Toggle(2, 2, initialConfig: true); board.Toggle(3, 2, initialConfig: true); board.Evaluate(); Assert.That(board.Lives, Is.EquivalentTo(new[] { (2, 1), (2, 2), (2, 3) })); var tracer = board.Tracer!; Assert.That(tracer.Contribution.ContainsKey((2, 1)), Is.True); Assert.That(tracer.Contribution.ContainsKey((2, 3)), Is.True); var contributions = tracer.Contribution[(2, 1)]; Assert.That(contributions.Keys, Is.EquivalentTo(new[] { (1, 2), (2, 2), (3, 2) })); Assert.That(contributions[(1, 2)], Is.EqualTo(1.0 / 3.0)); Assert.That(contributions[(2, 2)], Is.EqualTo(1.0 / 3.0)); Assert.That(contributions[(3, 2)], Is.EqualTo(1.0 / 3.0)); } [Test] public void Evaluate_WithTracer_ShouldRemoveDeadCellContributions() { board.Toggle(1, 2, initialConfig: true); board.Toggle(2, 2, initialConfig: true); board.Toggle(3, 2, initialConfig: true); board.Evaluate(); board.Evaluate(); Assert.That(board.Lives, Is.EquivalentTo(new[] { (2, 2), (1, 2), (3, 2) })); var tracer = board.Tracer!; Assert.That(tracer.Contribution.ContainsKey((2, 2)), Is.True); Assert.That(tracer.Contribution.ContainsKey((2, 1)), Is.False); Assert.That(tracer.Contribution.ContainsKey((2, 3)), Is.False); } [Test] public void BatchProcess_ShouldApplyDeferredAddAndRemoveCorrectly() { board.Toggle(1, 2, initialConfig: true); board.Toggle(2, 2, initialConfig: true); board.Toggle(3, 2, initialConfig: true); board.Evaluate(); Assert.That(board.Lives, Does.Contain((2, 1))); Assert.That(board.Lives, Does.Not.Contain((1, 2))); Assert.That(board.Tracer!.Contribution.ContainsKey((1, 2)), Is.False); Assert.That(board.Tracer!.Contribution.ContainsKey((2, 1)), Is.True); } [Test] public void Play_ShouldRunGenerationsAndUpdateTracer() { board.Toggle(1, 2, initialConfig: true); board.Toggle(2, 2, initialConfig: true); board.Toggle(3, 2, initialConfig: true); board.Play(3, delay: 0); Assert.That(board.Lives, Is.EquivalentTo(new[] { (2, 1), (2, 2), (2, 3) })); var tracer = board.Tracer!; Assert.That(tracer.Contribution.ContainsKey((2, 2)), Is.True); } }