using JetBrains.Annotations; using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager.Attributes; namespace Robust.UnitTesting.Shared.Prototypes; /// /// Tests the HasComp family of methods as well as serialization. /// [UsedImplicitly] [TestOf(typeof(EntityPrototype))] [Description($"Tests the {nameof(EntityPrototype)} HasComp family of methods")] internal sealed class PrototypeHasCompTest : OurRobustUnitTest { private IComponentFactory _factory = default!; private IPrototypeManager _proto = default!; protected override Type[] ExtraComponents => [ typeof(TestDefinedComponent), typeof(TestInheritedComponent), typeof(TestMissingComponent), typeof(TestCompNameComponent) ]; // TestEntity is expected to have TestDefinedComponent, TestInheritedComponent but not TestMissingComponent const string TestEntity = "TestEntity"; // expected to have TestCompNameComponent const string TestInception = "TestInception"; [OneTimeSetUp] public void Setup() { IoCManager.Resolve().Initialize(); _factory = IoCManager.Resolve(); _proto = IoCManager.Resolve(); _proto.Initialize(); _proto.LoadString(TestPrototypes); _proto.ResolveResults(); } [Test] public void TestHasCompGeneric() { var proto = _proto.Index(TestEntity); Assert.That(proto.HasComp(_factory)); Assert.That(proto.HasComp(_factory)); Assert.That(!proto.HasComp(_factory)); // and with CompName separately Assert.That(proto.HasComp(_factory.CompName())); Assert.That(proto.HasComp(_factory.CompName())); Assert.That(!proto.HasComp(_factory.CompName())); } [Test] public void TestHasCompType() { var proto = _proto.Index(TestEntity); // first test with GetRegistration var defined = _factory.GetRegistration().Type; var inherited = _factory.GetRegistration().Type; var missing = _factory.GetRegistration().Type; void TestThem() { Assert.That(proto.HasComp(defined, _factory)); Assert.That(proto.HasComp(inherited, _factory)); Assert.That(!proto.HasComp(missing, _factory)); } TestThem(); // then test with typeof defined = typeof(TestDefinedComponent); inherited = typeof(TestInheritedComponent); missing = typeof(TestMissingComponent); TestThem(); } [Test] public void TestHasCompString() { var proto = _proto.Index(TestEntity); var defined = new CompName("TestDefined", _factory); var inherited = new CompName("TestInherited", _factory); var missing = new CompName("TestMissing", _factory); Assert.That(proto.HasComp(defined)); Assert.That(proto.HasComp(inherited)); Assert.That(!proto.HasComp(missing)); } [Test] public void TestCompNameSerialization() { var proto = _proto.Index(TestInception); Assert.That(proto.TryComp(out var inception, _factory)); var name = inception!.Comp; Assert.That(name, Is.EqualTo(_factory.CompName())); // inception Assert.That(proto.HasComp(name)); Assert.That(_factory.HasRegistration(name)); // gibberish component should prevent it from loading Assert.That(!_proto.HasIndex("TestFail")); } const string TestPrototypes = $@" - type: entity parent: TestEntityParent # making sure inheritance wouldn't break it id: {TestEntity} components: - type: TestDefined - type: entity abstract: true id: TestEntityParent components: - type: TestInherited - type: entity id: TestInception components: - type: TestCompName comp: TestCompName # inception - type: entity id: TestFail components: - type: TestCompName comp: Afnuaghdjngbjda # this prevents this prototype from loading, hopefully nobody adds this component to rt :godo: "; } internal sealed partial class TestDefinedComponent : Component; internal sealed partial class TestInheritedComponent : Component; internal sealed partial class TestMissingComponent : Component; internal sealed partial class TestCompNameComponent : Component { [DataField(required: true)] public CompName Comp; }