ConstructionPrototypeTest.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System.Numerics;
  2. using Content.Server.Construction.Components;
  3. using Content.Shared.Construction.Prototypes;
  4. using Robust.Shared.GameObjects;
  5. using Robust.Shared.Map;
  6. using Robust.Shared.Maths;
  7. using Robust.Shared.Prototypes;
  8. namespace Content.IntegrationTests.Tests.Construction
  9. {
  10. [TestFixture]
  11. public sealed class ConstructionPrototypeTest
  12. {
  13. // discount linter for construction graphs
  14. // TODO: Create serialization validators for these?
  15. // Top test definitely can be but writing a serializer takes ages.
  16. /// <summary>
  17. /// Checks every entity prototype with a construction component has a valid start node.
  18. /// </summary>
  19. [Test]
  20. public async Task TestStartNodeValid()
  21. {
  22. await using var pair = await PoolManager.GetServerClient();
  23. var server = pair.Server;
  24. var entMan = server.ResolveDependency<IEntityManager>();
  25. var protoMan = server.ResolveDependency<IPrototypeManager>();
  26. var map = await pair.CreateTestMap();
  27. await server.WaitAssertion(() =>
  28. {
  29. foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())
  30. {
  31. if (!proto.Components.ContainsKey("Construction"))
  32. continue;
  33. var ent = entMan.SpawnEntity(proto.ID, new MapCoordinates(Vector2.Zero, map.MapId));
  34. var construction = entMan.GetComponent<ConstructionComponent>(ent);
  35. var graph = protoMan.Index<ConstructionGraphPrototype>(construction.Graph);
  36. entMan.DeleteEntity(ent);
  37. Assert.That(graph.Nodes.ContainsKey(construction.Node),
  38. $"Found no startNode \"{construction.Node}\" on graph \"{graph.ID}\" for entity \"{proto.ID}\"!");
  39. }
  40. });
  41. await pair.CleanReturnAsync();
  42. }
  43. [Test]
  44. public async Task TestStartIsValid()
  45. {
  46. await using var pair = await PoolManager.GetServerClient();
  47. var server = pair.Server;
  48. var protoMan = server.ResolveDependency<IPrototypeManager>();
  49. await server.WaitAssertion(() =>
  50. {
  51. foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
  52. {
  53. var start = proto.StartNode;
  54. var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
  55. Assert.That(graph.Nodes.ContainsKey(start),
  56. $"Found no startNode \"{start}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!");
  57. }
  58. });
  59. await pair.CleanReturnAsync();
  60. }
  61. [Test]
  62. public async Task TestTargetIsValid()
  63. {
  64. await using var pair = await PoolManager.GetServerClient();
  65. var server = pair.Server;
  66. var protoMan = server.ResolveDependency<IPrototypeManager>();
  67. await server.WaitAssertion(() =>
  68. {
  69. foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
  70. {
  71. var target = proto.TargetNode;
  72. var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
  73. Assert.That(graph.Nodes.ContainsKey(target),
  74. $"Found no targetNode \"{target}\" on graph \"{graph.ID}\" for construction prototype \"{proto.ID}\"!");
  75. }
  76. });
  77. await pair.CleanReturnAsync();
  78. }
  79. [Test]
  80. public async Task DeconstructionIsValid()
  81. {
  82. await using var pair = await PoolManager.GetServerClient();
  83. var server = pair.Server;
  84. var protoMan = server.ResolveDependency<IPrototypeManager>();
  85. var compFact = server.ResolveDependency<IComponentFactory>();
  86. var name = compFact.GetComponentName(typeof(ConstructionComponent));
  87. Assert.Multiple(() =>
  88. {
  89. foreach (var proto in protoMan.EnumeratePrototypes<EntityPrototype>())
  90. {
  91. if (proto.Abstract || pair.IsTestPrototype(proto) || !proto.Components.TryGetValue(name, out var reg))
  92. continue;
  93. var comp = (ConstructionComponent) reg.Component;
  94. var target = comp.DeconstructionNode;
  95. if (target == null)
  96. continue;
  97. var graph = protoMan.Index<ConstructionGraphPrototype>(comp.Graph);
  98. Assert.That(graph.Nodes.ContainsKey(target), $"Invalid deconstruction node \"{target}\" on graph \"{graph.ID}\" for construction entity \"{proto.ID}\"!");
  99. }
  100. });
  101. await pair.CleanReturnAsync();
  102. }
  103. [Test]
  104. public async Task TestStartReachesValidTarget()
  105. {
  106. await using var pair = await PoolManager.GetServerClient();
  107. var server = pair.Server;
  108. var protoMan = server.ResolveDependency<IPrototypeManager>();
  109. var entMan = server.ResolveDependency<IEntityManager>();
  110. await server.WaitAssertion(() =>
  111. {
  112. foreach (var proto in protoMan.EnumeratePrototypes<ConstructionPrototype>())
  113. {
  114. var start = proto.StartNode;
  115. var target = proto.TargetNode;
  116. var graph = protoMan.Index<ConstructionGraphPrototype>(proto.Graph);
  117. #pragma warning disable NUnit2045 // Interdependent assertions.
  118. Assert.That(graph.TryPath(start, target, out var path),
  119. $"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\"");
  120. Assert.That(path, Has.Length.GreaterThanOrEqualTo(1),
  121. $"Unable to find path from \"{start}\" to \"{target}\" on graph \"{graph.ID}\".");
  122. var next = path[0];
  123. var nextId = next.Entity.GetId(null, null, new(entMan));
  124. Assert.That(nextId, Is.Not.Null,
  125. $"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}");
  126. Assert.That(protoMan.TryIndex(nextId, out EntityPrototype entity),
  127. $"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}])");
  128. Assert.That(entity.Components.ContainsKey("Construction"),
  129. $"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.");
  130. #pragma warning restore NUnit2045
  131. }
  132. });
  133. await pair.CleanReturnAsync();
  134. }
  135. }
  136. }