Refactor construction tests (#43155)

Introduce 2681 more tests.
This commit is contained in:
Moony 2026-03-10 20:56:23 +01:00 committed by Coryler
parent 43f8a9d395
commit 79590e2a69
1 changed files with 45 additions and 108 deletions

View File

@ -1,9 +1,7 @@
using System.Numerics;
using Content.IntegrationTests.Utility;
using Content.Server.Construction.Components;
using Content.Shared.Construction.Prototypes;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Construction
@ -15,109 +13,40 @@ namespace Content.IntegrationTests.Tests.Construction
// TODO: Create serialization validators for these?
// Top test definitely can be but writing a serializer takes ages.
private static string[] _constructablePrototypes = GameDataScrounger.EntitiesWithComponent("Construction");
private static string[] _constructions = GameDataScrounger.PrototypesOfKind<ConstructionPrototype>();
/// <summary>
/// Checks every entity prototype with a construction component has a valid start node.
/// </summary>
[Test]
public async Task TestStartNodeValid()
[TestOf(typeof(ConstructionComponent))]
[TestCaseSource(nameof(_constructablePrototypes))]
[Description("Tests that a given entity specifies a valid node for construction, and optionally a valid one for deconstruction.")]
public async Task ConstructionComponentValid(string protoKey)
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var entMan = server.ResolveDependency<IEntityManager>();
var protoMan = server.ResolveDependency<IPrototypeManager>();
var map = await pair.CreateTestMap();
await server.WaitAssertion(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())
var proto = protoMan.Index(protoKey);
var construction = (ConstructionComponent)proto.Components["Construction"].Component;
var graph = protoMan.Index<ConstructionGraphPrototype>(construction.Graph);
using (Assert.EnterMultipleScope())
{
if (!proto.Components.ContainsKey("Construction"))
continue;
var ent = entMan.SpawnEntity(proto.ID, new MapCoordinates(Vector2.Zero, map.MapId));
var construction = entMan.GetComponent<ConstructionComponent>(ent);
var graph = protoMan.Index<ConstructionGraphPrototype>(construction.Graph);
entMan.DeleteEntity(ent);
Assert.That(graph.Nodes.ContainsKey(construction.Node),
$"Found no startNode \"{construction.Node}\" on graph \"{graph.ID}\" for entity \"{proto.ID}\"!");
}
});
$"Found no node \"{construction.Node}\" on graph \"{graph.ID}\" for entity \"{proto.ID}\"!");
await pair.CleanReturnAsync();
}
[Test]
public async Task TestStartIsValid()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
await server.WaitAssertion(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
{
var start = proto.StartNode;
var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
Assert.That(graph.Nodes.ContainsKey(start),
$"Found no startNode \"{start}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!");
}
});
await pair.CleanReturnAsync();
}
[Test]
public async Task TestTargetIsValid()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
await server.WaitAssertion(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
{
var target = proto.TargetNode;
var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
if (construction.DeconstructionNode is not { } target)
return;
Assert.That(graph.Nodes.ContainsKey(target),
$"Found no targetNode \"{target}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!");
}
});
await pair.CleanReturnAsync();
}
[Test]
public async Task DeconstructionIsValid()
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
var protoMan = server.ResolveDependency<IPrototypeManager>();
var compFact = server.ResolveDependency<IComponentFactory>();
var name = compFact.GetComponentName<ConstructionComponent>();
Assert.Multiple(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())
{
if (proto.Abstract || pair.IsTestPrototype(proto) || !proto.Components.TryGetValue(name, out var reg))
continue;
var comp = (ConstructionComponent) reg.Component;
var target = comp.DeconstructionNode;
if (target == null)
continue;
var graph = protoMan.Index<ConstructionGraphPrototype>(comp.Graph);
Assert.That(graph.Nodes.ContainsKey(target), $"Invalid deconstruction node \"{target}\" on graph \"{graph.ID}\" for construction entity \"{proto.ID}\"!");
$"Invalid deconstruction node \"{target}\" on graph \"{graph.ID}\" for construction entity \"{proto.ID}\"!");
}
});
@ -125,7 +54,10 @@ namespace Content.IntegrationTests.Tests.Construction
}
[Test]
public async Task TestStartReachesValidTarget()
[TestOf(typeof(ConstructionPrototype))]
[TestCaseSource(nameof(_constructions))]
[Description("Tests that a given construction prototype has a valid starting and target node, and a valid path between them.")]
public async Task ConstructionFormsValidGraph(string protoKey)
{
await using var pair = await PoolManager.GetServerClient();
var server = pair.Server;
@ -135,29 +67,34 @@ namespace Content.IntegrationTests.Tests.Construction
await server.WaitAssertion(() =>
{
foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
var proto = protoMan.Index<ConstructionPrototype>(protoKey);
var start = proto.StartNode;
var target = proto.TargetNode;
var graph = protoMan.Index(proto.Graph);
using (Assert.EnterMultipleScope())
{
var start = proto.StartNode;
var target = proto.TargetNode;
var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
Assert.That(graph.Nodes.ContainsKey(start),
$"Found no startNode \"{start}\" on graph \"{graph.ID}\"!");
Assert.That(graph.Nodes.ContainsKey(target),
$"Found no targetNode \"{target}\" on graph \"{graph.ID}\"!");
}
#pragma warning disable NUnit2045 // Interdependent assertions.
Assert.That(graph.TryPath(start, target, out var path),
$"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\"");
Assert.That(path, Has.Length.GreaterThanOrEqualTo(1),
$"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\".");
var next = path[0];
var nextId = next.Entity.GetId(null, null, new(entMan));
Assert.That(nextId, Is.Not.Null,
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) must specify an entity! Graph: {graph.ID}");
Assert.That(protoMan.TryIndex(nextId, out EntityPrototype entity),
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an invalid entity prototype ({nextId} [{next.Entity}])");
Assert.That(entity.Components.ContainsKey("Construction"),
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an entity prototype ({next.Entity}) without a ConstructionComponent.");
Assert.That(graph.TryPath(start, target, out var path),
$"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\"");
Assert.That(path, Has.Length.GreaterThanOrEqualTo(1),
$"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\".");
var next = path![0];
var nextId = next.Entity.GetId(null, null, new(entMan));
Assert.That(nextId, Is.Not.Null,
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) must specify an entity! Graph: {graph.ID}");
Assert.That(protoMan.TryIndex(nextId, out EntityPrototype entity),
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an invalid entity prototype ({nextId} [{next.Entity}])");
Assert.That(entity!.Components.ContainsKey("Construction"),
$"The next node ({next.Name}) in the path from the start node ({start}) to the target node ({target}) specified an entity prototype ({next.Entity}) without a ConstructionComponent.");
#pragma warning restore NUnit2045
}
});
await pair.CleanReturnAsync();
}
}