diff --git a/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs b/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs index 75281e63cb0..9441443b225 100644 --- a/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs +++ b/Content.IntegrationTests/Tests/Construction/ConstructionPrototypeTest.cs @@ -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(); + /// /// Checks every entity prototype with a construction component has a valid start node. /// [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(); var protoMan = server.ResolveDependency(); - var map = await pair.CreateTestMap(); - await server.WaitAssertion(() => { - foreach (var proto in protoMan.EnumeratePrototypes()) + var proto = protoMan.Index(protoKey); + var construction = (ConstructionComponent)proto.Components["Construction"].Component; + + var graph = protoMan.Index(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(ent); - - var graph = protoMan.Index(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(); - - await server.WaitAssertion(() => - { - foreach (var proto in protoMan.EnumeratePrototypes()) - { - var start = proto.StartNode; - var graph = protoMan.Index(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(); - - await server.WaitAssertion(() => - { - foreach (var proto in protoMan.EnumeratePrototypes()) - { - var target = proto.TargetNode; - var graph = protoMan.Index(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(); - var compFact = server.ResolveDependency(); - - var name = compFact.GetComponentName(); - Assert.Multiple(() => - { - foreach (var proto in protoMan.EnumeratePrototypes()) - { - 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(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()) + var proto = protoMan.Index(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(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(); } }