using System.Linq; using NUnit.Framework; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Definition; using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Serialization.Markdown.Value; using Robust.Shared.Utility; // ReSharper disable UnassignedGetOnlyAutoProperty // ReSharper disable UnusedAutoPropertyAccessor.Global namespace Robust.UnitTesting.Shared.Serialization { internal sealed partial class PropertyAndFieldDefinitionTest : OurSerializationTest { private const string GetOnlyPropertyName = "GetOnlyProperty"; private const string GetOnlyPropertyFieldTargetedName = "GetOnlyPropertyFieldTargeted"; private const string GetAndSetPropertyName = "GetAndSetProperty"; private const string FieldName = "Field"; private const string GetOnlyPropertyWithOtherAttributeFieldTargetedName = "GetOnlyPropertyWithOtherAttributeFieldTargeted"; private const string GetOnlyPropertyFieldTargetedAndOtherAttributeName = "GetOnlyPropertyFieldTargetedAndOtherAttribute"; [Test] public void ParityTest() { var mapping = new MappingDataNode(); mapping.Add(GetOnlyPropertyName, new ValueDataNode("5")); mapping.Add(GetOnlyPropertyFieldTargetedName, new ValueDataNode("10")); mapping.Add(GetAndSetPropertyName, new ValueDataNode("15")); mapping.Add(FieldName, new ValueDataNode("20")); mapping.Add(GetOnlyPropertyWithOtherAttributeFieldTargetedName, new ValueDataNode("25")); mapping.Add(GetOnlyPropertyFieldTargetedAndOtherAttributeName, new ValueDataNode("30")); var definition = Serialization.Read(mapping, notNullableOverride: true); Assert.That(definition, Is.Not.Null); // Get only property with backing field, property targeted Assert.That(definition!.GetOnlyProperty, Is.EqualTo(5)); var backingField = definition.GetType().GetBackingField(GetOnlyPropertyName); Assert.That(backingField, Is.Not.Null); var backingFieldValue = backingField!.GetValue(definition); Assert.That(backingFieldValue, Is.EqualTo(5)); // Get only property with backing field, field targeted Assert.That(definition.GetOnlyPropertyFieldTargeted, Is.EqualTo(10)); // Get and set property with backing field, property targeted Assert.That(definition.GetAndSetProperty, Is.EqualTo(15)); // Field Assert.That(definition.Field, Is.EqualTo(20)); // Get only property with backing field, property targeted with another attribute field targeted Assert.That(definition.GetOnlyPropertyWithOtherAttributeFieldTargeted, Is.EqualTo(25)); var property = definition.GetType().GetProperty(GetOnlyPropertyWithOtherAttributeFieldTargetedName); Assert.That(property, Is.Not.Null); var propertyInfo = new SpecificPropertyInfo(property!); Assert.That(propertyInfo.GetAttribute(), Is.Not.Null); Assert.That(propertyInfo.GetAttribute(), Is.Not.Null); // We check for the property info properly finding field targeted attributes as // well, otherwise we run the risk of the data field being targeted to the // property but an additional attribute like AlwaysPushInheritance being targeted // to the field, as was the case in EntityPrototype. // And I don't want to debug that ever again. Assert.That(propertyInfo.DeclaringType, Is.Not.Null); var dataDefinition = ((SerializationManager) Serialization).GetDefinition(propertyInfo.DeclaringType!); Assert.That(dataDefinition, Is.Not.Null); var propertyDefinition = dataDefinition!.BaseFieldDefinitions.Single(e => (e.Tag ?? e.CamelCasedName).Equals(GetOnlyPropertyWithOtherAttributeFieldTargetedName)); var inheritanceBehaviour = propertyDefinition.InheritanceBehavior; Assert.That(inheritanceBehaviour, Is.EqualTo(InheritanceBehavior.Always)); // Get only property with backing field, field targeted with another attribute property targeted Assert.That(definition.GetOnlyPropertyFieldTargetedAndOtherAttribute, Is.EqualTo(30)); property = definition.GetType().GetProperty(GetOnlyPropertyFieldTargetedAndOtherAttributeName); Assert.That(property, Is.Not.Null); propertyInfo = new SpecificPropertyInfo(property!); // Data field is targeted to the backing field Assert.That(propertyInfo.GetAttribute(), Is.Not.Null); Assert.That(propertyInfo.GetBackingField()!.GetAttribute(), Is.Null); Assert.That(propertyInfo.GetAttribute(true), Is.Not.Null); // NeverPushInheritanceAttribute is targeted to the property Assert.That(propertyInfo.GetAttribute(), Is.Not.Null); Assert.That(propertyInfo.GetBackingField()!.GetAttribute(), Is.Null); Assert.That(propertyInfo.GetAttribute(true), Is.Not.Null); propertyDefinition = dataDefinition!.BaseFieldDefinitions.Single(e => (e.Tag ?? e.CamelCasedName).Equals(GetOnlyPropertyFieldTargetedAndOtherAttributeName)); inheritanceBehaviour = propertyDefinition.InheritanceBehavior; dataDefinition = ((SerializationManager) Serialization).GetDefinition(property!.DeclaringType!); Assert.That(dataDefinition, Is.Not.Null); Assert.That(inheritanceBehaviour, Is.EqualTo(InheritanceBehavior.Never)); } [DataDefinition] internal sealed partial class PropertyAndFieldDefinitionTestDefinition { [DataField(GetOnlyPropertyName)] public int GetOnlyProperty { get; private set; } [DataField(GetOnlyPropertyFieldTargetedName)] public int GetOnlyPropertyFieldTargeted { get; private set; } [DataField(GetAndSetPropertyName)] public int GetAndSetProperty { get; set; } [DataField(FieldName)] // ReSharper disable once UnassignedField.Global public int Field; [DataField(GetOnlyPropertyWithOtherAttributeFieldTargetedName)] [AlwaysPushInheritance] public int GetOnlyPropertyWithOtherAttributeFieldTargeted { get; private set; } [DataField(GetOnlyPropertyFieldTargetedAndOtherAttributeName)] [NeverPushInheritance] public int GetOnlyPropertyFieldTargetedAndOtherAttribute { get; private set; } } } }