From 95b3ec4fa5ca6dbee1d3d7d18cea8d203bc3131e Mon Sep 17 00:00:00 2001 From: Timothy Nunnink <46979634+tnunnink@users.noreply.github.com> Date: Sat, 3 Feb 2024 14:20:36 -0600 Subject: [PATCH] Added IsEquivalent method to both LogixElement.cs and LogixType.cs to allow check of the underlying XML structure between two objects. Also some other clean up, documenting, and testing --- src/.idea/.idea.L5Sharp/.idea/workspace.xml | 18 ++- .../Components/AddOnInstruction.cs | 2 + src/L5Sharp.Core/Components/Controller.cs | 2 + src/L5Sharp.Core/Components/DataType.cs | 2 + src/L5Sharp.Core/Components/Module.cs | 1 + src/L5Sharp.Core/Components/Program.cs | 2 + src/L5Sharp.Core/Components/Routine.cs | 2 + src/L5Sharp.Core/Components/Tag.cs | 8 +- src/L5Sharp.Core/L5Sharp.Core.csproj | 18 +-- src/L5Sharp.Core/LogixElement.cs | 16 +++ src/L5Sharp.Core/LogixParser.cs | 4 - src/L5Sharp.Core/LogixType.cs | 24 +++- tests/L5Sharp.Tests/Elements/RungTests.cs | 22 ++++ tests/L5Sharp.Tests/LogixElementTests.cs | 111 ++++++++++++++++-- .../L5Sharp.Tests/Types/Atomics/BoolTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/DintTests.cs | 22 ++++ tests/L5Sharp.Tests/Types/Atomics/IntTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/LintTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/LrealTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/RealTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/SintTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/UDintTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/UIntTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/ULintTests.cs | 22 ++++ .../L5Sharp.Tests/Types/Atomics/USintTests.cs | 22 ++++ tests/L5Sharp.Tests/Types/ComplexTypeTests.cs | 84 ++++++++++++- 26 files changed, 522 insertions(+), 36 deletions(-) diff --git a/src/.idea/.idea.L5Sharp/.idea/workspace.xml b/src/.idea/.idea.L5Sharp/.idea/workspace.xml index 32618e6f..c2361e9b 100644 --- a/src/.idea/.idea.L5Sharp/.idea/workspace.xml +++ b/src/.idea/.idea.L5Sharp/.idea/workspace.xml @@ -10,9 +10,15 @@ + + + + + + + + - - @@ -755,7 +761,6 @@ diff --git a/src/L5Sharp.Core/Components/AddOnInstruction.cs b/src/L5Sharp.Core/Components/AddOnInstruction.cs index 7768b1bc..0f41d70c 100644 --- a/src/L5Sharp.Core/Components/AddOnInstruction.cs +++ b/src/L5Sharp.Core/Components/AddOnInstruction.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text.RegularExpressions; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -14,6 +15,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] [L5XType(L5XName.AddOnInstructionDefinition)] public class AddOnInstruction : LogixComponent { diff --git a/src/L5Sharp.Core/Components/Controller.cs b/src/L5Sharp.Core/Components/Controller.cs index 86d51b24..93ae8fb5 100644 --- a/src/L5Sharp.Core/Components/Controller.cs +++ b/src/L5Sharp.Core/Components/Controller.cs @@ -1,5 +1,6 @@ using System; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -26,6 +27,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] public class Controller : LogixComponent { private const string DateTimeFormat = "ddd MMM d HH:mm:ss yyyy"; diff --git a/src/L5Sharp.Core/Components/DataType.cs b/src/L5Sharp.Core/Components/DataType.cs index f4ae11b7..ce404f2c 100644 --- a/src/L5Sharp.Core/Components/DataType.cs +++ b/src/L5Sharp.Core/Components/DataType.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -23,6 +24,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] public class DataType : LogixComponent { /// diff --git a/src/L5Sharp.Core/Components/Module.cs b/src/L5Sharp.Core/Components/Module.cs index c6b74035..125a1dd5 100644 --- a/src/L5Sharp.Core/Components/Module.cs +++ b/src/L5Sharp.Core/Components/Module.cs @@ -14,6 +14,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] public class Module : LogixComponent { /// diff --git a/src/L5Sharp.Core/Components/Program.cs b/src/L5Sharp.Core/Components/Program.cs index 3688428d..282eb003 100644 --- a/src/L5Sharp.Core/Components/Program.cs +++ b/src/L5Sharp.Core/Components/Program.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -12,6 +13,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] public class Program : LogixComponent { /// diff --git a/src/L5Sharp.Core/Components/Routine.cs b/src/L5Sharp.Core/Components/Routine.cs index eed62049..ce762e42 100644 --- a/src/L5Sharp.Core/Components/Routine.cs +++ b/src/L5Sharp.Core/Components/Routine.cs @@ -1,5 +1,6 @@ using System; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -11,6 +12,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] public class Routine : LogixComponent { /// diff --git a/src/L5Sharp.Core/Components/Tag.cs b/src/L5Sharp.Core/Components/Tag.cs index 2ec12ed8..a3fc71e6 100644 --- a/src/L5Sharp.Core/Components/Tag.cs +++ b/src/L5Sharp.Core/Components/Tag.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using JetBrains.Annotations; namespace L5Sharp.Core; @@ -12,6 +13,7 @@ namespace L5Sharp.Core; /// See /// `Logix 5000 Controllers Import/Export` for more information. /// +[PublicAPI] [L5XType(L5XName.Tag)] [L5XType(L5XName.LocalTag)] [L5XType(L5XName.ConfigTag)] @@ -384,7 +386,7 @@ public void Add(string name, LogixType value) /// public IEnumerable Members() { - var members = Parent is null ? new List {this} : new List(); + var members = Parent is null ? [this] : new List(); foreach (var member in Value.Members) { @@ -409,7 +411,7 @@ public IEnumerable Members(Predicate predicate) { if (predicate is null) throw new ArgumentNullException(nameof(predicate)); - var members = Parent is null && predicate.Invoke(TagName) ? new List {this} : new List(); + var members = Parent is null && predicate.Invoke(TagName) ? [this] : new List(); foreach (var member in Value.Members) { @@ -437,7 +439,7 @@ public IEnumerable Members(Predicate predicate) { if (predicate is null) throw new ArgumentNullException(nameof(predicate)); - var members = Parent is null && predicate.Invoke(this) ? new List {this} : new List(); + var members = Parent is null && predicate.Invoke(this) ? [this] : new List(); foreach (var member in Value.Members) { diff --git a/src/L5Sharp.Core/L5Sharp.Core.csproj b/src/L5Sharp.Core/L5Sharp.Core.csproj index bdedbe4f..7372643d 100644 --- a/src/L5Sharp.Core/L5Sharp.Core.csproj +++ b/src/L5Sharp.Core/L5Sharp.Core.csproj @@ -7,9 +7,9 @@ true L5Sharp Timothy Nunnink - 0.19.1 - 0.19.1 - 0.19.1.0 + 0.19.2 + 0.19.3 + 0.19.3.0 A library for intuitively interacting with Rockwell's L5X import/export files. https://github.com/tnunnink/L5Sharp csharp allen-bradely l5x logix plc-programming rockwell-automation logix5000 @@ -17,7 +17,7 @@ MIT git - Upgraded to .NET7. Reworked LogixParser.cs. Added new ILogixParsable.cs. Fixed tests and documentation. + Added some equivalency methods to the LogixElement.cs and LogixType.cs to allow checks against entire XML structure.. Copyright (c) Timothy Nunnink 2022 README.md L5Sharp @@ -27,16 +27,16 @@ - - - + + + - + - + diff --git a/src/L5Sharp.Core/LogixElement.cs b/src/L5Sharp.Core/LogixElement.cs index 9e831d6f..e0fb9e6d 100644 --- a/src/L5Sharp.Core/LogixElement.cs +++ b/src/L5Sharp.Core/LogixElement.cs @@ -332,6 +332,22 @@ public void Replace(LogixElement element) /// public virtual XElement Serialize() => Element; + /// + /// Determines if the provided is equivalent to this element in terms of both type and + /// state, including all child elements and values. + /// + /// The to compare. + /// ture if the elements are equivalent; Otherwise, false. + /// + /// This internally compares the underlying XML nodes of the two elements to determine if all their + /// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it + /// compares the entire XML structure). + /// + public bool IsEquivalent(LogixElement other) + { + return XNode.DeepEquals(Element, other.Element); + } + /// /// Gets the value of the specified attribute name from the element parsed as the specified generic type parameter if it exists. /// If the attribute does not exist, returns default value of the generic type parameter. diff --git a/src/L5Sharp.Core/LogixParser.cs b/src/L5Sharp.Core/LogixParser.cs index 070b1478..0d04ffe4 100644 --- a/src/L5Sharp.Core/LogixParser.cs +++ b/src/L5Sharp.Core/LogixParser.cs @@ -141,10 +141,6 @@ private static IEnumerable> GetParsers() foreach (var type in types) { - if (!type.IsPublic) - { - Console.WriteLine(type.Name); - } var parse = BuildParseFunction(type); var tryParse = BuildTryParseFunction(type); var parsers = new Parsers(parse, tryParse); diff --git a/src/L5Sharp.Core/LogixType.cs b/src/L5Sharp.Core/LogixType.cs index 55004c97..e00ff2fc 100644 --- a/src/L5Sharp.Core/LogixType.cs +++ b/src/L5Sharp.Core/LogixType.cs @@ -92,6 +92,22 @@ public override bool Equals(object? obj) /// public override int GetHashCode() => Name.GetHashCode(); + + /// + /// Determines if the provided is equivalent to this type in terms of the underlying XML + /// data that comprise the complex object. + /// + /// The to compare. + /// ture if the types are equivalent; Otherwise, false. + /// + /// This internally compares the underlying XML nodes of the two types to determine if all their + /// elements, attributes, and values are equal. This includes all nested or descendant elements (i.e. it + /// compares the entire XML structure). + /// + public bool IsEquivalent(LogixType other) + { + return XNode.DeepEquals(Serialize(), other.Serialize()); + } /// /// Gets a with the specified name if it exists for the ; @@ -284,7 +300,7 @@ public override bool Equals(object? obj) /// /// The value to convert. /// A representing the converted value. - public static implicit operator LogixType(LogixType[,] value) =>ToArrayType(value); + public static implicit operator LogixType(LogixType[,] value) => ToArrayType(value); /// /// Converts the provided to a . @@ -300,7 +316,7 @@ public override bool Equals(object? obj) /// A representing the converted value. public static implicit operator LogixType(Dictionary value) => new ComplexType(nameof(ComplexType), value.Select(m => new LogixMember(m.Key, m.Value))); - + /// /// Converts the current array object to a of the concrete logix type by /// inspecting the first element's type in the array. @@ -321,7 +337,7 @@ private static ArrayType ToArrayType(Array array) var type = array.Cast().First().GetType(); var arrayType = typeof(ArrayType<>).MakeGenericType(type); var parameterType = typeof(Array); - var constructor = arrayType.GetConstructor(new[] { parameterType })!; + var constructor = arrayType.GetConstructor([parameterType])!; var parameter = Expression.Parameter(parameterType, "array"); var creator = Expression.New(constructor, parameter); var lambda = Expression.Lambda>(creator, parameter); @@ -360,4 +376,4 @@ public static ArrayType ToArrayType(this IEnumerable { - new() { SomeValue = "Child_1"}, - new() { SomeValue = "Child_2"}, - new() { SomeValue = "Child_3"} + new() { SomeValue = "Child_1" }, + new() { SomeValue = "Child_2" }, + new() { SomeValue = "Child_3" } }; return Verify(element.Serialize().ToString()); @@ -550,9 +550,9 @@ public Task SetContainer_HasValueDifferentValue_ShouldBeVerified() element.ChildElements = new LogixContainer { - new() { SomeValue = "Child_3"}, - new() { SomeValue = "Child_2"}, - new() { SomeValue = "Child_1"} + new() { SomeValue = "Child_3" }, + new() { SomeValue = "Child_2" }, + new() { SomeValue = "Child_1" } }; return Verify(element.Serialize().ToString()); @@ -573,7 +573,7 @@ public Task SetContainer_HasValueToNull_ShouldBeVerified() return Verify(element.Serialize().ToString()); } - + [Test] public void GetDateTime_HasValue_ShouldBeExpectedValue() { @@ -628,7 +628,7 @@ public Task SetDateTime_HasValueToNull_ShouldBeVerified() return Verify(element.Serialize().ToString()); } - + [Test] public Task SetDescription_NoValueToValue_ShouldBeVerified() { @@ -955,6 +955,99 @@ public void Convert_AsTypeDefaultType_ShouldHaveExpectedTypeAndBeSameInstance() converted.Should().BeOfType(); converted.Should().BeSameAs(element); } + + [Test] + public void IsEquivalent_AreEquivalent_ShouldBeTrue() + { + var first = new TestElement(); + var second = new TestElement(); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreEquivalentWithSetProperties_ShouldBeTrue() + { + var first = new TestElement + { + OptionalValue = "Testing", + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var second = new TestElement + { + OptionalValue = "Testing", + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEquivalentWithOneDifferent_ShouldBeFalse() + { + var first = new TestElement + { + OptionalValue = "Testing", + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var second = new TestElement + { + OptionalValue = "Testing", + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } + + [Test] + public void IsEquivalent_AreNotEquivalentOneUnsetProperty_ShouldBeFalse() + { + var first = new TestElement + { + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var second = new TestElement + { + OptionalValue = "Testing", + Property = "SomeValue", + Description = "This is a test", + Date = new DateTime(2024, 1, 1) + }; + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } + + [Test] + public void IsEquivalent_DifferentType_ShouldBeFalse() + { + var first = new TestElement(); + var second = new ChildElement(); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } } [L5XType("Test", "Container")] diff --git a/tests/L5Sharp.Tests/Types/Atomics/BoolTests.cs b/tests/L5Sharp.Tests/Types/Atomics/BoolTests.cs index bd119a81..3266aa57 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/BoolTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/BoolTests.cs @@ -796,6 +796,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new BOOL(1); + var second = new BOOL(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new BOOL(1); + var second = new BOOL(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } + [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() { diff --git a/tests/L5Sharp.Tests/Types/Atomics/DintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/DintTests.cs index d6d92662..998b9b7e 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/DintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/DintTests.cs @@ -882,6 +882,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new DINT(1); + var second = new DINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new DINT(1); + var second = new DINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/IntTests.cs b/tests/L5Sharp.Tests/Types/Atomics/IntTests.cs index a3999ec7..a057d1e0 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/IntTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/IntTests.cs @@ -869,6 +869,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new INT(1); + var second = new INT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new INT(1); + var second = new INT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/LintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/LintTests.cs index 1b058078..4e0379a1 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/LintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/LintTests.cs @@ -875,6 +875,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new LINT(1); + var second = new LINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new LINT(1); + var second = new LINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/LrealTests.cs b/tests/L5Sharp.Tests/Types/Atomics/LrealTests.cs index d3bad282..4725c8cb 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/LrealTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/LrealTests.cs @@ -806,6 +806,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new LREAL(1.23); + var second = new LREAL(1.23); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new LREAL(1.23); + var second = new LREAL(1.32); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/RealTests.cs b/tests/L5Sharp.Tests/Types/Atomics/RealTests.cs index c1f911a9..8315f31c 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/RealTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/RealTests.cs @@ -806,6 +806,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new REAL(1.23f); + var second = new REAL(1.23f); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new REAL(1.23f); + var second = new REAL(1.32f); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/SintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/SintTests.cs index 51ab7276..d477c571 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/SintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/SintTests.cs @@ -568,6 +568,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new SINT(1); + var second = new SINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new SINT(1); + var second = new SINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/UDintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/UDintTests.cs index 7bbf1bdb..2219db51 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/UDintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/UDintTests.cs @@ -867,6 +867,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new UDINT(1); + var second = new UDINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new UDINT(1); + var second = new UDINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/UIntTests.cs b/tests/L5Sharp.Tests/Types/Atomics/UIntTests.cs index 1bb050f5..8a7015ad 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/UIntTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/UIntTests.cs @@ -267,6 +267,28 @@ public void Equals_InvalidType_ShouldBeFalse() result.Should().BeFalse(); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new UINT(1); + var second = new UINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new UINT(1); + var second = new UINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void OperatorEquals_AreEqual_ShouldBeTrue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/ULintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/ULintTests.cs index 14b23b8e..81e61a4a 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/ULintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/ULintTests.cs @@ -867,6 +867,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new ULINT(1); + var second = new ULINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new ULINT(1); + var second = new ULINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/Atomics/USintTests.cs b/tests/L5Sharp.Tests/Types/Atomics/USintTests.cs index 73592e87..9a941007 100644 --- a/tests/L5Sharp.Tests/Types/Atomics/USintTests.cs +++ b/tests/L5Sharp.Tests/Types/Atomics/USintTests.cs @@ -868,6 +868,28 @@ public void Equals_OverLargeCollection_ShouldWorkFairlyFast(int capacity) result.Count.Should().Be(capacity); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new USINT(1); + var second = new USINT(1); + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqual_ShouldBeFalse() + { + var first = new USINT(1); + var second = new USINT(0); + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } [Test] public void GetHashCode_RandomValue_ShouldBeHashOfValue() diff --git a/tests/L5Sharp.Tests/Types/ComplexTypeTests.cs b/tests/L5Sharp.Tests/Types/ComplexTypeTests.cs index 3e6ea0c3..9c7b61a1 100644 --- a/tests/L5Sharp.Tests/Types/ComplexTypeTests.cs +++ b/tests/L5Sharp.Tests/Types/ComplexTypeTests.cs @@ -1,4 +1,5 @@ -using System.Xml.Linq; +using System.Runtime.InteropServices; +using System.Xml.Linq; using FluentAssertions; namespace L5Sharp.Tests.Types; @@ -573,4 +574,85 @@ public Task Serialize_Test_ShouldBeVerified() return Verify(xml); } + + [Test] + public void IsEquivalent_AreEqual_ShouldBeTrue() + { + var first = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.5f), + new("Member5", new TIMER()) + }); + + var second = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.5f), + new("Member5", new TIMER()) + }); + + + var result = first.IsEquivalent(second); + + result.Should().BeTrue(); + } + + [Test] + public void IsEquivalent_AreNotEqualByValue_ShouldBeFalse() + { + var first = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.5f), + new("Member5", new TIMER()) + }); + + var second = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.45f), + new("Member5", new TIMER()) + }); + + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } + + [Test] + public void IsEquivalent_AreNotEqualByName_ShouldBeFalse() + { + var first = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.5f), + new("Member5", new TIMER()) + }); + + var second = new ComplexType("Test", new List + { + new("Member1", true), + new("Member2", (byte)255), + new("Member3", 1000), + new("Member4", 4.5f), + new("Member6", new TIMER()) + }); + + + var result = first.IsEquivalent(second); + + result.Should().BeFalse(); + } } \ No newline at end of file