diff --git a/Content.IntegrationTests/Tests/Lathe/LatheTest.cs b/Content.IntegrationTests/Tests/Lathe/LatheTest.cs new file mode 100644 index 000000000000..88aece967b75 --- /dev/null +++ b/Content.IntegrationTests/Tests/Lathe/LatheTest.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Linq; +using Content.Shared.Lathe; +using Content.Shared.Materials; +using Content.Shared.Prototypes; +using Content.Shared.Research.Prototypes; +using Content.Shared.Whitelist; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.Lathe; + +[TestFixture] +public sealed class LatheTest +{ + [Test] + public async Task TestLatheRecipeIngredientsFitLathe() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + + var mapData = await pair.CreateTestMap(); + + var entMan = server.EntMan; + var protoMan = server.ProtoMan; + var compFactory = server.ResolveDependency(); + var materialStorageSystem = server.System(); + var whitelistSystem = server.System(); + + await server.WaitAssertion(() => + { + // Find all the lathes + var latheProtos = protoMan.EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => p.HasComponent()); + + // Find every EntityPrototype that can be inserted into a MaterialStorage + var materialEntityProtos = protoMan.EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => p.HasComponent()); + + // Spawn all of the above material EntityPrototypes - we need actual entities to do whitelist checks + var materialEntities = new List(materialEntityProtos.Count()); + foreach (var materialEntityProto in materialEntityProtos) + { + materialEntities.Add(entMan.SpawnEntity(materialEntityProto.ID, mapData.GridCoords)); + } + + Assert.Multiple(() => + { + // Check each lathe individually + foreach (var latheProto in latheProtos) + { + if (!latheProto.TryGetComponent(out var latheComp, compFactory)) + continue; + + if (!latheProto.TryGetComponent(out var storageComp, compFactory)) + continue; + + // Test which material-containing entities are accepted by this lathe + var acceptedMaterials = new HashSet>(); + foreach (var materialEntity in materialEntities) + { + Assert.That(entMan.TryGetComponent(materialEntity, out var compositionComponent)); + if (whitelistSystem.IsWhitelistFail(storageComp.Whitelist, materialEntity)) + continue; + + // Mark the lathe as accepting each material in the entity + foreach (var (material, _) in compositionComponent.MaterialComposition) + { + acceptedMaterials.Add(material); + } + } + + // Collect all the recipes assigned to this lathe + var recipes = new List>(); + recipes.AddRange(latheComp.StaticRecipes); + recipes.AddRange(latheComp.DynamicRecipes); + if (latheProto.TryGetComponent(out var emagRecipesComp, compFactory)) + { + recipes.AddRange(emagRecipesComp.EmagStaticRecipes); + recipes.AddRange(emagRecipesComp.EmagDynamicRecipes); + } + + // Check each recipe assigned to this lathe + foreach (var recipeId in recipes) + { + Assert.That(protoMan.TryIndex(recipeId, out var recipeProto)); + + // Track the total material volume of the recipe + var totalQuantity = 0; + // Check each material called for by the recipe + foreach (var (materialId, quantity) in recipeProto.Materials) + { + Assert.That(protoMan.TryIndex(materialId, out var materialProto)); + // Make sure the material is accepted by the lathe + Assert.That(acceptedMaterials, Does.Contain(materialId), $"Lathe {latheProto.ID} has recipe {recipeId} but does not accept any materials containing {materialId}"); + totalQuantity += quantity; + } + // Make sure the recipe doesn't call for more material than the lathe can hold + if (storageComp.StorageLimit != null) + Assert.That(totalQuantity, Is.LessThanOrEqualTo(storageComp.StorageLimit), $"Lathe {latheProto.ID} has recipe {recipeId} which calls for {totalQuantity} units of materials but can only hold {storageComp.StorageLimit}"); + } + } + }); + }); + + await pair.CleanReturnAsync(); + } + + [Test] + public async Task AllLatheRecipesValidTest() + { + await using var pair = await PoolManager.GetServerClient(); + + var server = pair.Server; + var proto = server.ProtoMan; + + Assert.Multiple(() => + { + foreach (var recipe in proto.EnumeratePrototypes()) + { + if (recipe.Result == null) + Assert.That(recipe.ResultReagents, Is.Not.Null, $"Recipe '{recipe.ID}' has no result or result reagents."); + } + }); + + await pair.CleanReturnAsync(); + } +} diff --git a/Content.IntegrationTests/Tests/ResearchTest.cs b/Content.IntegrationTests/Tests/ResearchTest.cs index f50e6111da3f..7ae29a79ffd5 100644 --- a/Content.IntegrationTests/Tests/ResearchTest.cs +++ b/Content.IntegrationTests/Tests/ResearchTest.cs @@ -98,24 +98,4 @@ await server.WaitAssertion(() => await pair.CleanReturnAsync(); } - - [Test] - public async Task AllLatheRecipesValidTest() - { - await using var pair = await PoolManager.GetServerClient(); - - var server = pair.Server; - var proto = server.ResolveDependency(); - - Assert.Multiple(() => - { - foreach (var recipe in proto.EnumeratePrototypes()) - { - if (recipe.Result == null) - Assert.That(recipe.ResultReagents, Is.Not.Null, $"Recipe '{recipe.ID}' has no result or result reagents."); - } - }); - - await pair.CleanReturnAsync(); - } }