2026-09-29 17:05:14 +02:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
2026-09-30 14:59:50 +02:00
|
|
|
using System.Linq;
|
2026-09-29 17:05:14 +02:00
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
// Assertions over collections of entities and shots. xunit formats a collection's contents into its failure
|
|
|
|
|
// message, and an Entity, a PendingShot or a ShotOutcome drags the whole zone graph in with it: the formatter
|
|
|
|
|
// recurses until the test host dies of a stack overflow, which a mutation tool scores as a kill of every test
|
|
|
|
|
// that was running. A failure here must be an ordinary red naming the test, so these compare counts and
|
|
|
|
|
// identities and never hand xunit an entity.
|
|
|
|
|
internal static class SafeAssert
|
|
|
|
|
{
|
|
|
|
|
public static void NoShots(Zone zone) =>
|
|
|
|
|
Assert.True(zone.PendingShots.Count == 0, $"{zone.PendingShots.Count} shot(s) still pending");
|
|
|
|
|
|
|
|
|
|
public static PendingShot OnlyShot(Zone zone)
|
|
|
|
|
{
|
|
|
|
|
Assert.True(zone.PendingShots.Count == 1, $"expected exactly one pending shot, found {zone.PendingShots.Count}");
|
|
|
|
|
return zone.PendingShots[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static T Only<T>(List<T> list)
|
|
|
|
|
{
|
|
|
|
|
Assert.True(list.Count == 1, $"expected exactly one {typeof(T).Name}, found {list.Count}");
|
|
|
|
|
return list[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Empty<T>(List<T> list) => Assert.True(list.Count == 0, $"expected no {typeof(T).Name}, found {list.Count}");
|
|
|
|
|
|
|
|
|
|
public static void In(Zone zone, Entity entity, string why = "entity should be in the zone") =>
|
|
|
|
|
Assert.True(zone.Entities.Contains(entity), why);
|
|
|
|
|
|
|
|
|
|
public static void NotIn(Zone zone, Entity entity, string why = "entity should have left the zone") =>
|
|
|
|
|
Assert.False(zone.Entities.Contains(entity), why);
|
2026-09-30 14:59:50 +02:00
|
|
|
|
|
|
|
|
// The zone holds exactly the entities and agents it held before, in the same order: nothing admitted, nothing
|
|
|
|
|
// lost. A failure names what changed by hull name.
|
|
|
|
|
public static void Unchanged(Zone zone, List<Entity> entities, List<Agent> agents)
|
|
|
|
|
{
|
|
|
|
|
Same(entities, zone.Entities.ToList(), entity => entity.Name, "entities");
|
|
|
|
|
Same(agents, zone.Agents, agent => agent.Ship.Name, "agents");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void Same<T>(List<T> before, List<T> now, System.Func<T, string> name, string what) where T : class
|
|
|
|
|
{
|
|
|
|
|
var added = now.Where(x => !before.Contains(x)).Select(name).ToList();
|
|
|
|
|
var lost = before.Where(x => !now.Contains(x)).Select(name).ToList();
|
|
|
|
|
var inOrder = now.Count == before.Count && now.Zip(before, ReferenceEquals).All(same => same);
|
|
|
|
|
Assert.True(inOrder, $"the zone's {what} changed, {before.Count} -> {now.Count}: added [{string.Join(", ", added)}], lost [{string.Join(", ", lost)}]");
|
|
|
|
|
}
|
2026-09-29 17:05:14 +02:00
|
|
|
}
|