Files
UA-.NETStandard/tests/Opc.Ua.SourceGeneration.Core.Tests/Schema/NodeDesignTests.cs
romanett 9b034f8291 Enable nullable reference types centrally; migrate all unset and annotations-only projects (#4700)
# Description

Nullable reference types are now enabled once, in `common.props`, and
every project in the repository builds warning-clean with them.

**Configuration**
- `<Nullable>enable</Nullable>` lives in `common.props`. All per-project
`<Nullable>` settings are removed: 178 project files (enable,
annotations, and the `disable` in the three Aot test projects).
- 419 per-file `#nullable enable`/`restore` directives and the 4
`#nullable disable` directives are removed.
- Kept on purpose:
- The 5 `<auto-generated>` schema files (`UANodeSet.cs`, `UA Type
Dictionary.cs`, `OPCBinarySchema.cs`, `SecuredApplication.cs`,
`PInvokeHelper.cs`) keep `#nullable enable`. The compiler ignores the
project setting in generated code, so the directive is required there.
- `tests/Opc.Ua.Interop.LegacyPeer` keeps `disable`. It builds against
the 1.5.378 packages and does not import the repository props.
- `docs/DeveloperGuide.md` and `.github/copilot-instructions.md` now
describe the central setting.

**Migration** (the 43 unset and 13 annotations-only projects, roughly
10k diagnostics)
- **Production code: annotated at the declarations.** Covers
`tools/Opc.Ua.SourceGeneration.Core`, `src/Opc.Ua.Lds.Server` and the
LDS sample.
- Members, parameters and returns are nullable where null actually
flows.
- Null-check helpers carry `[NotNullWhen]` (`IsNull`, `IsValidXmlName`,
`IsMethodTypeDesign`).
- `CoreUtils.Format`, `Utils.Format`, `ITemplateWriter.WriteLine` take
`params object?[]`. `Template.AddReplacement` takes `string?` (rendering
already skips null replacements).
- `IRegisteredServerStore.RegisterAsync` returns
`Task<RegistrationEntry?>`: it returns null when a registration is
removed.
- Dereferences backed by an invariant (for example, the validated model)
use `!`, so runtime behaviour is unchanged.
- **Behavioural changes in production code** (small, deliberate):
- `NodeSetToModelDesign` throws `InvalidOperationException` when the
file is not a NodeSet. Before, it threw a NullReferenceException on the
next line.
- `ModelDesignValidator` starts its lookup tables empty instead of null.
A redundant `if (m_nodes == null) return;` guard is gone.
- **Test code: minimal annotations.**
  - `?` on values that can be null, `!` where the test asserts non-null.
  - `= null!` for fixture members assigned in SetUp.
- `TryGetStructure<T>(out T? x)` where the inferred `T?` broke the
`IEncodeable` constraint.
- A few redundant `== null` checks on structs (`NodeId`, `ArrayOf<T>`)
folded into the adjacent `IsNull`/`Count` checks.

**Notes for reviewers**
- The diff is large (~1,500 files) but almost entirely mechanical: `?`,
`!` and directive removal. The non-annotation changes are listed above.
- Known follow-up, not done here:
`IModelDesign.Namespaces/TargetNamespace/NamespaceUris` stay
non-nullable even though the validator returns null before it loads a
dictionary. Making them nullable would ripple through every generator
call site.

## Related Issues

- Fixes #4439

## Checklist

- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [ ] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.

The "no new warnings" box covers net10.0 and net48: full non-incremental
builds of `UA.slnx`, `tools/SourceGeneration.slnx`,
`tools/MigrationAnalyzer.slnx` and the Aot test projects finished with 0
warnings and 0 errors under the repository's warnings-as-errors
settings. net9.0 and net8.0 also had no nullable diagnostics, but they
were not rebuilt after the final fixes. Tests have not been run locally
yet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:48:13 +02:00

2750 lines
92 KiB
C#

/* ========================================================================
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Globalization;
using System.Xml;
using NUnit.Framework;
namespace Opc.Ua.Schema.Model.Tests
{
/// <summary>
/// Unit tests for the NodeDesign class Equals(object) method.
/// </summary>
[TestFixture]
[Category("ModelDesign")]
[SetCulture("en-us")]
[SetUICulture("en-us")]
[Parallelizable]
public class NodeDesignTests
{
/// <summary>
/// Tests that Equals returns false when comparing with null.
/// </summary>
[Test]
public void Equals_NullObject_ReturnsFalse()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
// Act
#pragma warning disable CA1508 // Avoid dead conditional code
bool result = nodeDesign.Equals((object)null!);
#pragma warning restore CA1508 // Avoid dead conditional code
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when comparing an instance with itself.
/// </summary>
[Test]
public void Equals_SameReference_ReturnsTrue()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
// Act
bool result = nodeDesign.Equals((object)nodeDesign);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when comparing with an object of a different type.
/// </summary>
[Test]
public void Equals_DifferentType_ReturnsFalse()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
object otherObject = new();
// Act
bool result = nodeDesign.Equals(otherObject);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when comparing with a string object.
/// </summary>
[Test]
public void Equals_StringObject_ReturnsFalse()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
object otherObject = "TestNode";
// Act
bool result = nodeDesign.Equals(otherObject);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when comparing two NodeDesign instances with identical properties.
/// </summary>
[Test]
public void Equals_IdenticalNodeDesigns_ReturnsTrue()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
IsDeclaration = true,
NumericId = 12345,
NumericIdSpecified = true,
StringId = "TestStringId"
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
IsDeclaration = true,
NumericId = 12345,
NumericIdSpecified = true,
StringId = "TestStringId"
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different BrowseName.
/// </summary>
[Test]
public void Equals_DifferentBrowseName_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign { BrowseName = "TestNode1" };
var nodeDesign2 = new NodeDesign { BrowseName = "TestNode2" };
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different NumericId.
/// </summary>
[Test]
public void Equals_DifferentNumericId_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = 123,
NumericIdSpecified = true
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = 456,
NumericIdSpecified = true
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different IsDeclaration flag.
/// </summary>
[Test]
public void Equals_DifferentIsDeclaration_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
IsDeclaration = true
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
IsDeclaration = false
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different SymbolicId.
/// </summary>
[Test]
public void Equals_DifferentSymbolicId_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
SymbolicId = new XmlQualifiedName("Id1", "http://test.org")
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
SymbolicId = new XmlQualifiedName("Id2", "http://test.org")
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when both NodeDesign instances have null properties.
/// </summary>
[Test]
public void Equals_BothWithNullProperties_ReturnsTrue()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = null,
StringId = null,
SymbolicId = null
};
var nodeDesign2 = new NodeDesign
{
BrowseName = null,
StringId = null,
SymbolicId = null
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when one NodeDesign has null property and other does not.
/// </summary>
[Test]
public void Equals_OneNullStringIdOneNot_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
StringId = "TestId"
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
StringId = null
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals handles boundary values for NumericId (uint.MaxValue).
/// </summary>
[Test]
public void Equals_MaxNumericId_ReturnsTrue()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = uint.MaxValue,
NumericIdSpecified = true
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = uint.MaxValue,
NumericIdSpecified = true
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals handles boundary values for NumericId (uint.MinValue/0).
/// </summary>
[Test]
public void Equals_MinNumericId_ReturnsTrue()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = uint.MinValue,
NumericIdSpecified = true
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
NumericId = 0,
NumericIdSpecified = true
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when comparing with derived type object
/// cast to object.
/// </summary>
[Test]
public void Equals_DerivedTypeObjectDesign_ReturnsFalseWhenDifferent()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
var objectDesign = new ObjectDesign { BrowseName = "ObjectNode" };
// Act
bool result = nodeDesign.Equals((object)objectDesign);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when comparing with derived type
/// </summary>
[Test]
public void Equals_DerivedTypeObjectDesign_ReturnsTrueWhenSameBaseProperties()
{
// Arrange
var nodeDesign = new NodeDesign { BrowseName = "TestNode" };
var objectDesign = new ObjectDesign { BrowseName = "TestNode" };
// Act
bool result = nodeDesign.Equals((object)objectDesign);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when comparing with empty string BrowseName.
/// </summary>
[Test]
public void Equals_EmptyStringBrowseName_ReturnsTrue()
{
// Arrange
var nodeDesign1 = new NodeDesign { BrowseName = string.Empty };
var nodeDesign2 = new NodeDesign { BrowseName = string.Empty };
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different WriteAccess values.
/// </summary>
[Test]
public void Equals_DifferentWriteAccess_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
WriteAccess = 1
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
WriteAccess = 2
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when comparing NodeDesign instances with different Category.
/// </summary>
[Test]
public void Equals_DifferentCategory_ReturnsFalse()
{
// Arrange
var nodeDesign1 = new NodeDesign
{
BrowseName = "TestNode",
Category = "Category1"
};
var nodeDesign2 = new NodeDesign
{
BrowseName = "TestNode",
Category = "Category2"
};
// Act
bool result = nodeDesign1.Equals((object)nodeDesign2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that CreateSymbolicId returns parentId when childName is null.
/// </summary>
[Test]
public void CreateSymbolicId_ChildNameNull_ReturnsParentId()
{
// Arrange
const string parentId = "Parent";
const string? childName = null;
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName!);
// Assert
Assert.That(result, Is.EqualTo(parentId));
}
/// <summary>
/// Tests that CreateSymbolicId returns parentId when childName is empty.
/// </summary>
[Test]
public void CreateSymbolicId_ChildNameEmpty_ReturnsParentId()
{
// Arrange
const string parentId = "Parent";
const string childName = "";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(parentId));
}
/// <summary>
/// Tests that CreateSymbolicId returns childName when parentId is null.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdNull_ReturnsChildName()
{
// Arrange
const string? parentId = null;
const string childName = "Child";
// Act
string result = NodeDesign.CreateSymbolicId(parentId!, childName);
// Assert
Assert.That(result, Is.EqualTo(childName));
}
/// <summary>
/// Tests that CreateSymbolicId returns childName when parentId is empty.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdEmpty_ReturnsChildName()
{
// Arrange
const string parentId = "";
const string childName = "Child";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(childName));
}
/// <summary>
/// Tests that CreateSymbolicId returns null when both parentId and childName are null.
/// </summary>
[Test]
public void CreateSymbolicId_BothNull_ReturnsNull()
{
// Arrange
const string? parentId = null;
const string? childName = null;
// Act
string result = NodeDesign.CreateSymbolicId(parentId!, childName!);
// Assert
Assert.That(result, Is.Null);
}
/// <summary>
/// Tests that CreateSymbolicId returns empty string when both parentId and childName are empty.
/// </summary>
[Test]
public void CreateSymbolicId_BothEmpty_ReturnsEmpty()
{
// Arrange
const string parentId = "";
const string childName = "";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(string.Empty));
}
/// <summary>
/// Tests that CreateSymbolicId correctly combines valid parentId and childName with underscore separator.
/// </summary>
[TestCase("Parent", "Child", "Parent_Child")]
[TestCase("Root", "Node", "Root_Node")]
[TestCase("A", "B", "A_B")]
public void CreateSymbolicId_BothValid_ReturnsCombinedWithUnderscore(string parentId, string childName, string expected)
{
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(expected));
}
/// <summary>
/// Tests that CreateSymbolicId handles whitespace-only childName by treating it as non-empty.
/// Whitespace-only strings are not considered empty by string.IsNullOrEmpty.
/// </summary>
[Test]
public void CreateSymbolicId_ChildNameWhitespaceOnly_CombinesWithParent()
{
// Arrange
const string parentId = "Parent";
const string childName = " ";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo("Parent_ "));
}
/// <summary>
/// Tests that CreateSymbolicId handles whitespace-only parentId by treating it as non-empty.
/// Whitespace-only strings are not considered empty by string.IsNullOrEmpty.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdWhitespaceOnly_CombinesWithChild()
{
// Arrange
const string parentId = " ";
const string childName = "Child";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(" _Child"));
}
/// <summary>
/// Tests that CreateSymbolicId returns whitespace when parentId is whitespace and childName is null.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdWhitespaceChildNameNull_ReturnsParentId()
{
// Arrange
const string parentId = " ";
const string? childName = null;
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName!);
// Assert
Assert.That(result, Is.EqualTo(parentId));
}
/// <summary>
/// Tests that CreateSymbolicId handles special characters in both parameters.
/// </summary>
[TestCase("Parent-1", "Child#2", "Parent-1_Child#2")]
[TestCase("Namespace.Type", "Property", "Namespace.Type_Property")]
[TestCase("Parent@123", "Child$456", "Parent@123_Child$456")]
public void CreateSymbolicId_SpecialCharacters_ReturnsCombined(string parentId, string childName, string expected)
{
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(expected));
}
/// <summary>
/// Tests that CreateSymbolicId handles parameters containing underscore characters.
/// </summary>
[Test]
public void CreateSymbolicId_ContainsUnderscore_ReturnsCombined()
{
// Arrange
const string parentId = "Parent_Node";
const string childName = "Child_Property";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo("Parent_Node_Child_Property"));
}
/// <summary>
/// Tests that CreateSymbolicId handles very long strings for both parameters.
/// </summary>
[Test]
public void CreateSymbolicId_VeryLongStrings_ReturnsCombined()
{
// Arrange
string parentId = new('P', 1000);
string childName = new('C', 1000);
string expected = parentId + "_" + childName;
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(expected));
Assert.That(result, Has.Length.EqualTo(2001));
}
/// <summary>
/// Tests that CreateSymbolicId handles strings with unicode characters.
/// </summary>
[TestCase("親", "子", "親_子")]
[TestCase("Родитель", "Ребенок", "Родитель_Ребенок")]
[TestCase("🔧", "🔨", "🔧_🔨")]
public void CreateSymbolicId_UnicodeCharacters_ReturnsCombined(string parentId, string childName, string expected)
{
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(expected));
}
/// <summary>
/// Tests that CreateSymbolicId handles strings with control characters.
/// </summary>
[Test]
public void CreateSymbolicId_ControlCharacters_ReturnsCombined()
{
// Arrange
const string parentId = "Parent\t\n";
const string childName = "Child\r\n";
const string expected = "Parent\t\n_Child\r\n";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(expected));
}
/// <summary>
/// Tests that CreateSymbolicId handles single character strings.
/// </summary>
[Test]
public void CreateSymbolicId_SingleCharacterStrings_ReturnsCombined()
{
// Arrange
const string parentId = "A";
const string childName = "B";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo("A_B"));
}
/// <summary>
/// Tests that CreateSymbolicId returns parentId when it's null and childName is empty.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdNullChildNameEmpty_ReturnsNull()
{
// Arrange
const string? parentId = null;
const string childName = "";
// Act
string result = NodeDesign.CreateSymbolicId(parentId!, childName);
// Assert
Assert.That(result, Is.Null);
}
/// <summary>
/// Tests that CreateSymbolicId returns parentId when it's empty and childName is also empty.
/// Edge case testing precedence of checks.
/// </summary>
[Test]
public void CreateSymbolicId_ParentIdEmptyChildNameEmpty_ReturnsEmpty()
{
// Arrange
const string parentId = "";
const string childName = "";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(string.Empty));
}
/// <summary>
/// Tests that ToString() with no parameters returns the type name when SymbolicName is null.
/// </summary>
[Test]
public void ToString_NoParameters_SymbolicNameNull_ReturnsTypeName()
{
// Arrange
var nodeDesign = new NodeDesign();
// Act
string result = nodeDesign.ToString();
// Assert
Assert.That(result, Is.EqualTo("NodeDesign"));
}
/// <summary>
/// Tests that ToString() with no parameters returns the SymbolicName when it is set.
/// </summary>
[Test]
public void ToString_NoParameters_SymbolicNameSet_ReturnsSymbolicName()
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName("TestNode", "http://test.org")
};
// Act
string result = nodeDesign.ToString();
// Assert
Assert.That(result, Is.EqualTo("TestNode"));
}
/// <summary>
/// Tests that ToString with null format and null SymbolicName returns the type name.
/// </summary>
[Test]
public void ToString_NullFormat_SymbolicNameNull_ReturnsTypeName()
{
// Arrange
var nodeDesign = new NodeDesign();
// Act
string result = nodeDesign.ToString(null!, null!);
// Assert
Assert.That(result, Is.EqualTo("NodeDesign"));
}
/// <summary>
/// Tests that ToString with null format and set SymbolicName returns the SymbolicName.Name.
/// </summary>
[Test]
public void ToString_NullFormat_SymbolicNameSet_ReturnsSymbolicName()
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName("MyNode", "http://example.com")
};
// Act
string result = nodeDesign.ToString(null!, null!);
// Assert
Assert.That(result, Is.EqualTo("MyNode"));
}
/// <summary>
/// Tests that ToString with null format and SymbolicName with empty Name returns empty string.
/// </summary>
[Test]
public void ToString_NullFormat_SymbolicNameEmptyName_ReturnsEmptyString()
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName(string.Empty, "http://example.com")
};
// Act
string result = nodeDesign.ToString(null!, null!);
// Assert
Assert.That(result, Is.EqualTo(string.Empty));
}
/// <summary>
/// Tests that ToString with null format and InvariantCulture formatProvider formats correctly.
/// </summary>
[Test]
public void ToString_NullFormat_InvariantCultureProvider_FormatsCorrectly()
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName("TestNode", "http://test.org")
};
// Act
string result = nodeDesign.ToString(null!, CultureInfo.InvariantCulture);
// Assert
Assert.That(result, Is.EqualTo("TestNode"));
}
/// <summary>
/// Tests that ToString with null format and specific culture formatProvider formats correctly.
/// </summary>
[Test]
public void ToString_NullFormat_SpecificCultureProvider_FormatsCorrectly()
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName("TestNode", "http://test.org")
};
// Act
string result = nodeDesign.ToString(null!, CultureInfo.GetCultureInfo("en-US"));
// Assert
Assert.That(result, Is.EqualTo("TestNode"));
}
/// <summary>
/// Tests that ToString throws FormatException when format is an empty string.
/// </summary>
[Test]
public void ToString_EmptyStringFormat_ThrowsFormatException()
{
// Arrange
var nodeDesign = new NodeDesign();
// Act & Assert
FormatException ex = Assert.Throws<FormatException>(() => nodeDesign.ToString(string.Empty, null!));
Assert.That(ex.Message, Does.Contain("Invalid format string"));
Assert.That(ex.Message, Does.Contain("''"));
}
/// <summary>
/// Tests that ToString throws FormatException when format is a non-null string.
/// Input format strings: "G", "D", "X", "custom"
/// Expected result: FormatException with appropriate message.
/// </summary>
[TestCase("G")]
[TestCase("D")]
[TestCase("X")]
[TestCase("custom")]
[TestCase("anyFormat")]
public void ToString_NonNullFormat_ThrowsFormatException(string format)
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName("TestNode", "http://test.org")
};
// Act & Assert
FormatException ex = Assert.Throws<FormatException>(() => nodeDesign.ToString(format, null!));
Assert.That(ex.Message, Does.Contain("Invalid format string"));
Assert.That(ex.Message, Does.Contain(format));
}
/// <summary>
/// Tests that ToString throws FormatException when format is whitespace.
/// </summary>
[TestCase(" ")]
[TestCase(" ")]
[TestCase("\t")]
[TestCase("\n")]
public void ToString_WhitespaceFormat_ThrowsFormatException(string format)
{
// Arrange
var nodeDesign = new NodeDesign();
// Act & Assert
FormatException ex = Assert.Throws<FormatException>(() => nodeDesign.ToString(format, null!));
Assert.That(ex.Message, Does.Contain("Invalid format string"));
}
/// <summary>
/// Tests that ToString throws FormatException with formatProvider when format is non-null.
/// </summary>
[Test]
public void ToString_NonNullFormat_WithFormatProvider_ThrowsFormatException()
{
// Arrange
var nodeDesign = new NodeDesign();
// Act & Assert
FormatException ex = Assert.Throws<FormatException>(() => nodeDesign.ToString("G", CultureInfo.InvariantCulture));
Assert.That(ex.Message, Does.Contain("Invalid format string"));
Assert.That(ex.Message, Does.Contain("G"));
}
/// <summary>
/// Tests that ToString handles SymbolicName with special characters in Name correctly.
/// </summary>
[TestCase("Node_With_Underscores")]
[TestCase("Node-With-Dashes")]
[TestCase("Node.With.Dots")]
[TestCase("Node$With$Special")]
public void ToString_SymbolicNameWithSpecialCharacters_ReturnsName(string name)
{
// Arrange
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName(name, "http://test.org")
};
// Act
string result = nodeDesign.ToString(null!, null!);
// Assert
Assert.That(result, Is.EqualTo(name));
}
/// <summary>
/// Tests that ToString handles very long SymbolicName correctly.
/// </summary>
[Test]
public void ToString_VeryLongSymbolicName_ReturnsFullName()
{
// Arrange
string longName = new('A', 1000);
var nodeDesign = new NodeDesign
{
SymbolicName = new XmlQualifiedName(longName, "http://test.org")
};
// Act
string result = nodeDesign.ToString(null!, null!);
// Assert
Assert.That(result, Is.EqualTo(longName));
Assert.That(result, Has.Length.EqualTo(1000));
}
/// <summary>
/// Tests CreateSymbolicId method with null parentId parameter.
/// Should return childName directly when parentId is null.
/// </summary>
[TestCase(null, ExpectedResult = null)]
[TestCase("", ExpectedResult = "")]
[TestCase("ChildNode", ExpectedResult = "ChildNode")]
[TestCase(" ", ExpectedResult = " ")]
[TestCase("Child_With_Underscores", ExpectedResult = "Child_With_Underscores")]
public string? CreateSymbolicId_NullParentId_ReturnsChildName(string? childName)
{
// Arrange
XmlQualifiedName? parentId = null;
// Act
return NodeDesign.CreateSymbolicId(parentId!, childName!);
}
/// <summary>
/// Tests CreateSymbolicId method with non-null parentId and null childName.
/// Should delegate to string overload which returns parentId.Name when childName is null.
/// </summary>
[TestCase("ParentNode", null, ExpectedResult = "ParentNode")]
[TestCase("ParentNode", "", ExpectedResult = "ParentNode")]
[TestCase("", null, ExpectedResult = "")]
[TestCase("", "", ExpectedResult = "")]
public string CreateSymbolicId_NonNullParentId_NullOrEmptyChildName_ReturnsParentName(string parentName, string? childName)
{
// Arrange
var parentId = new XmlQualifiedName(parentName);
// Act
return NodeDesign.CreateSymbolicId(parentId, childName!);
}
/// <summary>
/// Tests CreateSymbolicId method with non-null parentId and non-empty childName.
/// Should delegate to string overload which combines parent and child with PathChar separator.
/// </summary>
[TestCase("Parent", "Child", ExpectedResult = "Parent_Child")]
[TestCase("Root", "Node", ExpectedResult = "Root_Node")]
[TestCase("Parent_Node", "Child_Node", ExpectedResult = "Parent_Node_Child_Node")]
public string CreateSymbolicId_NonNullParentId_NonEmptyChildName_ReturnsCombinedId(string parentName, string childName)
{
// Arrange
var parentId = new XmlQualifiedName(parentName);
// Act
return NodeDesign.CreateSymbolicId(parentId, childName);
}
/// <summary>
/// Tests CreateSymbolicId method with null or empty parent name in XmlQualifiedName.
/// Should delegate to string overload which returns childName when parentId.Name is null or empty.
/// </summary>
[TestCase(null, "ChildNode", ExpectedResult = "ChildNode")]
[TestCase("", "ChildNode", ExpectedResult = "ChildNode")]
public string CreateSymbolicId_NullOrEmptyParentName_NonEmptyChildName_ReturnsChildName(string? parentName, string childName)
{
// Arrange
var parentId = new XmlQualifiedName(parentName ?? string.Empty);
// Act
return NodeDesign.CreateSymbolicId(parentId, childName);
}
/// <summary>
/// Tests CreateSymbolicId method with whitespace-only strings.
/// Should handle whitespace strings according to string overload behavior.
/// </summary>
[TestCase(" ", "Child", ExpectedResult = " _Child")]
[TestCase("Parent", " ", ExpectedResult = "Parent_ ")]
[TestCase(" ", " ", ExpectedResult = " _ ")]
public string CreateSymbolicId_WhitespaceStrings_HandlesCorrectly(string parentName, string childName)
{
// Arrange
var parentId = new XmlQualifiedName(parentName);
// Act
return NodeDesign.CreateSymbolicId(parentId, childName);
}
/// <summary>
/// Tests CreateSymbolicId method with special characters in names.
/// Should handle special characters without validation or transformation.
/// </summary>
[TestCase("Parent@Node", "Child#Node", ExpectedResult = "Parent@Node_Child#Node")]
[TestCase("Parent.Node", "Child.Node", ExpectedResult = "Parent.Node_Child.Node")]
[TestCase("Parent/Node", "Child\\Node", ExpectedResult = "Parent/Node_Child\\Node")]
public string CreateSymbolicId_SpecialCharacters_HandlesCorrectly(string parentName, string childName)
{
// Arrange
var parentId = new XmlQualifiedName(parentName);
// Act
return NodeDesign.CreateSymbolicId(parentId, childName);
}
/// <summary>
/// Tests CreateSymbolicId method with very long strings.
/// Should handle long strings without truncation or errors.
/// </summary>
[Test]
public void CreateSymbolicId_VeryLongStrings_HandlesCorrectly()
{
// Arrange
string longParentName = new('A', 10000);
string longChildName = new('B', 10000);
var parentId = new XmlQualifiedName(longParentName);
// Act
string result = NodeDesign.CreateSymbolicId(parentId, longChildName);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result, Has.Length.EqualTo(20001)); // 10000 + 1 (PathChar) + 10000
Assert.That(result, Does.StartWith(longParentName));
Assert.That(result, Does.Contain("_"));
Assert.That(result, Does.EndWith(longChildName));
}
/// <summary>
/// Tests CreateSymbolicId method with XmlQualifiedName that has namespace.
/// Should only use the Name property, ignoring the namespace.
/// </summary>
[Test]
public void CreateSymbolicId_XmlQualifiedNameWithNamespace_UsesOnlyName()
{
// Arrange
var parentId = new XmlQualifiedName("ParentNode", "http://example.com/namespace");
const string childName = "ChildNode";
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo("ParentNode_ChildNode"));
}
/// <summary>
/// Tests CreateSymbolicId method with empty strings for both parent and child names.
/// Should return empty string when both names are empty.
/// </summary>
[Test]
public void CreateSymbolicId_BothEmptyStrings_ReturnsEmptyString()
{
// Arrange
var parentId = new XmlQualifiedName(string.Empty);
string childName = string.Empty;
// Act
string result = NodeDesign.CreateSymbolicId(parentId, childName);
// Assert
Assert.That(result, Is.EqualTo(string.Empty));
}
/// <summary>
/// Tests that GetHashCode returns the same value for two identical objects.
/// Verifies that objects with identical property values produce consistent hash codes.
/// Expected result: Both objects produce the same hash code.
/// </summary>
[Test]
public void GetHashCode_IdenticalObjects_ReturnsSameHashCode()
{
// Arrange
var node1 = new NodeDesign
{
BrowseName = "TestNode",
StringId = "TestId",
IsDeclaration = true,
WriteAccess = 5,
PartNo = 10,
Category = "TestCategory",
NotInAddressSpace = false,
ReleaseStatus = ReleaseStatus.Released,
Purpose = DataTypePurpose.Normal,
IsDynamic = false
};
var node2 = new NodeDesign
{
BrowseName = "TestNode",
StringId = "TestId",
IsDeclaration = true,
WriteAccess = 5,
PartNo = 10,
Category = "TestCategory",
NotInAddressSpace = false,
ReleaseStatus = ReleaseStatus.Released,
Purpose = DataTypePurpose.Normal,
IsDynamic = false
};
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when BrowseName differs.
/// Verifies that changes to the BrowseName property affect the hash code.
/// Expected result: Different hash codes for different BrowseNames.
/// </summary>
[Test]
public void GetHashCode_DifferentBrowseName_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { BrowseName = "Node1" };
var node2 = new NodeDesign { BrowseName = "Node2" };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null BrowseName correctly.
/// Verifies that null values for BrowseName produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullBrowseName_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { BrowseName = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles empty string BrowseName correctly.
/// Verifies that empty string values for BrowseName produce a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_EmptyBrowseName_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { BrowseName = string.Empty };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when NumericId differs.
/// Verifies that changes to the NumericId property affect the hash code.
/// Expected result: Different hash codes for different NumericIds.
/// </summary>
[Test]
public void GetHashCode_DifferentNumericId_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { NumericId = 100, NumericIdSpecified = true };
var node2 = new NodeDesign { NumericId = 200, NumericIdSpecified = true };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles extreme NumericId values correctly.
/// Verifies that boundary values (min, max) for NumericId produce valid hash codes.
/// Expected result: Hash codes are computed successfully for boundary values.
/// </summary>
[TestCase(uint.MinValue)]
[TestCase(uint.MaxValue)]
[TestCase(0u)]
public void GetHashCode_ExtremeNumericId_ReturnsValidHashCode(uint numericId)
{
// Arrange
var node = new NodeDesign { NumericId = numericId, NumericIdSpecified = true };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when IsDeclaration differs.
/// Verifies that changes to the IsDeclaration property affect the hash code.
/// Expected result: Different hash codes for different IsDeclaration values.
/// </summary>
[Test]
public void GetHashCode_DifferentIsDeclaration_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { IsDeclaration = true };
var node2 = new NodeDesign { IsDeclaration = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when WriteAccess differs.
/// Verifies that changes to the WriteAccess property affect the hash code.
/// Expected result: Different hash codes for different WriteAccess values.
/// </summary>
[Test]
public void GetHashCode_DifferentWriteAccess_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { WriteAccess = 0 };
var node2 = new NodeDesign { WriteAccess = 100 };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles extreme WriteAccess values correctly.
/// Verifies that boundary values (min, max) for WriteAccess produce valid hash codes.
/// Expected result: Hash codes are computed successfully for boundary values.
/// </summary>
[TestCase(uint.MinValue)]
[TestCase(uint.MaxValue)]
public void GetHashCode_ExtremeWriteAccess_ReturnsValidHashCode(uint writeAccess)
{
// Arrange
var node = new NodeDesign { WriteAccess = writeAccess };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when PartNo differs.
/// Verifies that changes to the PartNo property affect the hash code.
/// Expected result: Different hash codes for different PartNo values.
/// </summary>
[Test]
public void GetHashCode_DifferentPartNo_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { PartNo = 1 };
var node2 = new NodeDesign { PartNo = 2 };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when Category differs.
/// Verifies that changes to the Category property affect the hash code.
/// Expected result: Different hash codes for different Category values.
/// </summary>
[Test]
public void GetHashCode_DifferentCategory_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { Category = "Category1" };
var node2 = new NodeDesign { Category = "Category2" };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null Category correctly.
/// Verifies that null values for Category produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullCategory_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { Category = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when NotInAddressSpace differs.
/// Verifies that changes to the NotInAddressSpace property affect the hash code.
/// Expected result: Different hash codes for different NotInAddressSpace values.
/// </summary>
[Test]
public void GetHashCode_DifferentNotInAddressSpace_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { NotInAddressSpace = true };
var node2 = new NodeDesign { NotInAddressSpace = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when ReleaseStatus differs.
/// Verifies that changes to the ReleaseStatus property affect the hash code.
/// Expected result: Different hash codes for different ReleaseStatus values.
/// </summary>
[Test]
public void GetHashCode_DifferentReleaseStatus_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { ReleaseStatus = ReleaseStatus.Released };
var node2 = new NodeDesign { ReleaseStatus = ReleaseStatus.Draft };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when Purpose differs.
/// Verifies that changes to the Purpose property affect the hash code.
/// Expected result: Different hash codes for different Purpose values.
/// </summary>
[Test]
public void GetHashCode_DifferentPurpose_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { Purpose = DataTypePurpose.Normal };
var node2 = new NodeDesign { Purpose = DataTypePurpose.ServicesOnly };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when IsDynamic differs.
/// Verifies that changes to the IsDynamic property affect the hash code.
/// Expected result: Different hash codes for different IsDynamic values.
/// </summary>
[Test]
public void GetHashCode_DifferentIsDynamic_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { IsDynamic = true };
var node2 = new NodeDesign { IsDynamic = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when StringId differs.
/// Verifies that changes to the StringId property affect the hash code.
/// Expected result: Different hash codes for different StringId values.
/// </summary>
[Test]
public void GetHashCode_DifferentStringId_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { StringId = "Id1" };
var node2 = new NodeDesign { StringId = "Id2" };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null StringId correctly.
/// Verifies that null values for StringId produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullStringId_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { StringId = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles very long StringId correctly.
/// Verifies that long string values for StringId produce a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_VeryLongStringId_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { StringId = new string('A', 10000) };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when SymbolicName differs.
/// Verifies that changes to the SymbolicName property affect the hash code.
/// Expected result: Different hash codes for different SymbolicName values.
/// </summary>
[Test]
public void GetHashCode_DifferentSymbolicName_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { SymbolicName = new XmlQualifiedName("Name1", "http://test1.com") };
var node2 = new NodeDesign { SymbolicName = new XmlQualifiedName("Name2", "http://test2.com") };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null SymbolicName correctly.
/// Verifies that null values for SymbolicName produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullSymbolicName_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { SymbolicName = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when SymbolicId differs.
/// Verifies that changes to the SymbolicId property affect the hash code.
/// Expected result: Different hash codes for different SymbolicId values.
/// </summary>
[Test]
public void GetHashCode_DifferentSymbolicId_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { SymbolicId = new XmlQualifiedName("Id1", "http://test1.com") };
var node2 = new NodeDesign { SymbolicId = new XmlQualifiedName("Id2", "http://test2.com") };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null SymbolicId correctly.
/// Verifies that null values for SymbolicId produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullSymbolicId_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { SymbolicId = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when DisplayName differs.
/// Verifies that changes to the DisplayName property affect the hash code.
/// Expected result: Different hash codes for different DisplayName values.
/// </summary>
[Test]
public void GetHashCode_DifferentDisplayName_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { DisplayName = new LocalizedText { Key = "key1", Value = "Display1" } };
var node2 = new NodeDesign { DisplayName = new LocalizedText { Key = "key2", Value = "Display2" } };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null DisplayName correctly.
/// Verifies that null values for DisplayName produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullDisplayName_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { DisplayName = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when Description differs.
/// Verifies that changes to the Description property affect the hash code.
/// Expected result: Different hash codes for different Description values.
/// </summary>
[Test]
public void GetHashCode_DifferentDescription_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { Description = new LocalizedText { Key = "key1", Value = "Desc1" } };
var node2 = new NodeDesign { Description = new LocalizedText { Key = "key2", Value = "Desc2" } };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null Description correctly.
/// Verifies that null values for Description produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullDescription_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { Description = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles null References array correctly.
/// Verifies that null values for References produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullReferences_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { References = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles empty References array correctly.
/// Verifies that empty array values for References produce a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_EmptyReferences_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { References = [] };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when References differs.
/// Verifies that changes to the References array affect the hash code.
/// Expected result: Different hash codes for different References arrays.
/// </summary>
[Test]
public void GetHashCode_DifferentReferences_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign
{
References =
[
new Reference { ReferenceType = new XmlQualifiedName("RefType1") }
]
};
var node2 = new NodeDesign
{
References =
[
new Reference { ReferenceType = new XmlQualifiedName("RefType2") }
]
};
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null Extensions array correctly.
/// Verifies that null values for Extensions produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullExtensions_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { Extensions = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles empty Extensions array correctly.
/// Verifies that empty array values for Extensions produce a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_EmptyExtensions_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { Extensions = [] };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles null Children correctly.
/// Verifies that null values for Children produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullChildren_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { Children = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when Children differs.
/// Verifies that changes to the Children property affect the hash code.
/// Expected result: Different hash codes for different Children values.
/// </summary>
[Test]
public void GetHashCode_DifferentChildren_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { Children = new ListOfChildren { Items = [new ObjectDesign()] } };
var node2 = new NodeDesign { Children = new ListOfChildren() };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when Children differs.
/// Verifies that changes to the Children property affect the hash code.
/// Expected result: Different hash codes for different Children values.
/// </summary>
[Test]
public void GetHashCode_NoChildren_ReturnsSameHashCode()
{
// Arrange
var node1 = new NodeDesign { Children = null };
var node2 = new NodeDesign { Children = new ListOfChildren() };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode handles null RolePermissions correctly.
/// Verifies that null values for RolePermissions produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullRolePermissions_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { RolePermissions = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles null DefaultRolePermissions correctly.
/// Verifies that null values for DefaultRolePermissions produce a valid hash code without exceptions.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_NullDefaultRolePermissions_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign { DefaultRolePermissions = null };
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode returns different values when AccessRestrictionsSpecified differs.
/// Verifies that changes to the AccessRestrictionsSpecified property affect the hash code.
/// Expected result: Different hash codes for different AccessRestrictionsSpecified values.
/// </summary>
[Test]
public void GetHashCode_DifferentAccessRestrictionsSpecified_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { AccessRestrictionsSpecified = true };
var node2 = new NodeDesign { AccessRestrictionsSpecified = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when DefaultAccessRestrictionsSpecified differs.
/// Verifies that changes to the DefaultAccessRestrictionsSpecified property affect the hash code.
/// Expected result: Different hash codes for different DefaultAccessRestrictionsSpecified values.
/// </summary>
[Test]
public void GetHashCode_DifferentDefaultAccessRestrictionsSpecified_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { DefaultAccessRestrictionsSpecified = true };
var node2 = new NodeDesign { DefaultAccessRestrictionsSpecified = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode returns different values when NumericIdSpecified differs.
/// Verifies that changes to the NumericIdSpecified property affect the hash code.
/// Expected result: Different hash codes for different NumericIdSpecified values.
/// </summary>
[Test]
public void GetHashCode_DifferentNumericIdSpecified_ReturnsDifferentHashCode()
{
// Arrange
var node1 = new NodeDesign { NumericIdSpecified = true };
var node2 = new NodeDesign { NumericIdSpecified = false };
// Act
int hashCode1 = node1.GetHashCode();
int hashCode2 = node2.GetHashCode();
// Assert
Assert.That(hashCode1, Is.Not.EqualTo(hashCode2));
}
/// <summary>
/// Tests that GetHashCode produces consistent results when called multiple times.
/// Verifies that the hash code is deterministic and stable.
/// Expected result: Same hash code is returned on multiple invocations.
/// </summary>
[Test]
public void GetHashCode_MultipleInvocations_ReturnsConsistentHashCode()
{
// Arrange
var node = new NodeDesign
{
BrowseName = "TestNode",
StringId = "TestId",
IsDeclaration = true,
WriteAccess = 5
};
// Act
int hashCode1 = node.GetHashCode();
int hashCode2 = node.GetHashCode();
int hashCode3 = node.GetHashCode();
// Assert
Assert.That(hashCode1, Is.EqualTo(hashCode2));
Assert.That(hashCode2, Is.EqualTo(hashCode3));
}
/// <summary>
/// Tests that GetHashCode handles all properties set to default values.
/// Verifies that a default-initialized object produces a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_AllDefaultValues_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign();
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that GetHashCode handles all properties set to non-default values.
/// Verifies that a fully populated object produces a valid hash code.
/// Expected result: Hash code is computed successfully.
/// </summary>
[Test]
public void GetHashCode_AllNonDefaultValues_ReturnsValidHashCode()
{
// Arrange
var node = new NodeDesign
{
BrowseName = "TestBrowseName",
DisplayName = new LocalizedText { Key = "DisplayKey", Value = "DisplayValue" },
Description = new LocalizedText { Key = "DescKey", Value = "DescValue" },
Children = new ListOfChildren(),
References = [new Reference { ReferenceType = new XmlQualifiedName("RefType") }],
RolePermissions = new RolePermissionSet(),
DefaultRolePermissions = new RolePermissionSet(),
AccessRestrictions = AccessRestrictions.EncryptionRequired,
AccessRestrictionsSpecified = true,
DefaultAccessRestrictions = AccessRestrictions.SigningRequired,
DefaultAccessRestrictionsSpecified = true,
SymbolicName = new XmlQualifiedName("SymName", "http://test.com"),
SymbolicId = new XmlQualifiedName("SymId", "http://test.com"),
IsDeclaration = true,
NumericId = 12345,
NumericIdSpecified = true,
StringId = "StringIdValue",
WriteAccess = 100,
PartNo = 200,
Category = "TestCategory",
NotInAddressSpace = true,
ReleaseStatus = ReleaseStatus.Deprecated,
Purpose = DataTypePurpose.CodeGenerator,
IsDynamic = true
};
// Act
int hashCode = node.GetHashCode();
// Assert
Assert.That(hashCode, Is.Not.Zero.Or.Zero);
}
/// <summary>
/// Tests that Equals returns false when comparing with null.
/// </summary>
[Test]
public void Equals_NullParameter_ReturnsFalse()
{
// Arrange
var node = new NodeDesign();
// Act
#pragma warning disable CA1508 // Avoid dead conditional code
bool result = node.Equals(null!);
#pragma warning restore CA1508 // Avoid dead conditional code
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when comparing the same instance.
/// </summary>
[Test]
public void Equals_SameInstance_ReturnsTrue()
{
// Arrange
var node = new NodeDesign { BrowseName = "TestNode" };
// Act
bool result = node.Equals(node);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when all properties of two different instances are equal.
/// </summary>
[Test]
public void Equals_AllPropertiesEqual_ReturnsTrue()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when DisplayName differs.
/// </summary>
[Test]
public void Equals_DifferentDisplayName_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.DisplayName = new LocalizedText { Value = "DifferentDisplayName" };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when Description differs.
/// </summary>
[Test]
public void Equals_DifferentDescription_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.Description = new LocalizedText { Value = "DifferentDescription" };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when Children differs.
/// </summary>
[Test]
public void Equals_DifferentChildren_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.Children = new ListOfChildren();
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when References array differs.
/// </summary>
[Test]
public void Equals_DifferentReferences_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.References = [new Reference()];
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when RolePermissions differs.
/// </summary>
[Test]
public void Equals_DifferentRolePermissions_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.RolePermissions = new RolePermissionSet();
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when DefaultRolePermissions differs.
/// </summary>
[Test]
public void Equals_DifferentDefaultRolePermissions_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.DefaultRolePermissions = new RolePermissionSet();
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when AccessRestrictions differs.
/// </summary>
[Test]
public void Equals_DifferentAccessRestrictions_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.AccessRestrictions = AccessRestrictions.EncryptionRequired;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when AccessRestrictionsSpecified differs.
/// </summary>
[Test]
public void Equals_DifferentAccessRestrictionsSpecified_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.AccessRestrictionsSpecified = true;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when DefaultAccessRestrictions differs.
/// </summary>
[Test]
public void Equals_DifferentDefaultAccessRestrictions_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.DefaultAccessRestrictions = AccessRestrictions.SessionRequired;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when DefaultAccessRestrictionsSpecified differs.
/// </summary>
[Test]
public void Equals_DifferentDefaultAccessRestrictionsSpecified_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.DefaultAccessRestrictionsSpecified = true;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when Extensions array differs.
/// </summary>
[Test]
public void Equals_DifferentExtensions_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
var doc = new XmlDocument();
node2.Extensions = [doc.CreateElement("Extension")];
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when SymbolicName differs.
/// </summary>
[Test]
public void Equals_DifferentSymbolicName_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.SymbolicName = new XmlQualifiedName("DifferentName", "http://example.com");
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when NumericIdSpecified differs.
/// </summary>
[Test]
public void Equals_DifferentNumericIdSpecified_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.NumericIdSpecified = true;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when StringId differs.
/// </summary>
[Test]
public void Equals_DifferentStringId_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.StringId = "DifferentStringId";
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when PartNo differs.
/// </summary>
[Test]
public void Equals_DifferentPartNo_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.PartNo = 5;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when NotInAddressSpace differs.
/// </summary>
[Test]
public void Equals_DifferentNotInAddressSpace_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.NotInAddressSpace = true;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when ReleaseStatus differs.
/// </summary>
[Test]
public void Equals_DifferentReleaseStatus_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.ReleaseStatus = ReleaseStatus.Draft;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when Purpose differs.
/// </summary>
[Test]
public void Equals_DifferentPurpose_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.Purpose = DataTypePurpose.ServicesOnly;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns false when IsDynamic differs.
/// </summary>
[Test]
public void Equals_DifferentIsDynamic_ReturnsFalse()
{
// Arrange
NodeDesign node1 = CreateTestNodeDesign();
NodeDesign node2 = CreateTestNodeDesign();
node2.IsDynamic = true;
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals returns true when both instances have null BrowseName.
/// </summary>
[Test]
public void Equals_BothBrowseNameNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { BrowseName = null };
var node2 = new NodeDesign { BrowseName = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns false when one BrowseName is null and the other is not.
/// </summary>
[Test]
public void Equals_OneBrowseNameNull_ReturnsFalse()
{
// Arrange
var node1 = new NodeDesign { BrowseName = "TestName" };
var node2 = new NodeDesign { BrowseName = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.False);
}
/// <summary>
/// Tests that Equals handles empty string BrowseName correctly.
/// </summary>
[Test]
public void Equals_EmptyBrowseName_HandlesCorrectly()
{
// Arrange
var node1 = new NodeDesign { BrowseName = string.Empty };
var node2 = new NodeDesign { BrowseName = string.Empty };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals handles extreme values for NumericId.
/// </summary>
[Test]
public void Equals_ExtremeNumericId_HandlesCorrectly()
{
// Arrange
var node1 = new NodeDesign { NumericId = uint.MaxValue };
var node2 = new NodeDesign { NumericId = uint.MaxValue };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals handles extreme values for WriteAccess.
/// </summary>
[Test]
public void Equals_ExtremeWriteAccess_HandlesCorrectly()
{
// Arrange
var node1 = new NodeDesign { WriteAccess = uint.MaxValue };
var node2 = new NodeDesign { WriteAccess = uint.MaxValue };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals handles extreme values for PartNo.
/// </summary>
[Test]
public void Equals_ExtremePartNo_HandlesCorrectly()
{
// Arrange
var node1 = new NodeDesign { PartNo = uint.MaxValue };
var node2 = new NodeDesign { PartNo = uint.MaxValue };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null DisplayName.
/// </summary>
[Test]
public void Equals_BothDisplayNameNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { DisplayName = null };
var node2 = new NodeDesign { DisplayName = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null Description.
/// </summary>
[Test]
public void Equals_BothDescriptionNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { Description = null };
var node2 = new NodeDesign { Description = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null References.
/// </summary>
[Test]
public void Equals_BothReferencesNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { References = null };
var node2 = new NodeDesign { References = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have empty References arrays.
/// </summary>
[Test]
public void Equals_BothReferencesEmpty_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { References = [] };
var node2 = new NodeDesign { References = [] };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null Extensions.
/// </summary>
[Test]
public void Equals_BothExtensionsNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { Extensions = null };
var node2 = new NodeDesign { Extensions = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null SymbolicName.
/// </summary>
[Test]
public void Equals_BothSymbolicNameNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { SymbolicName = null };
var node2 = new NodeDesign { SymbolicName = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null SymbolicId.
/// </summary>
[Test]
public void Equals_BothSymbolicIdNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { SymbolicId = null };
var node2 = new NodeDesign { SymbolicId = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have null StringId.
/// </summary>
[Test]
public void Equals_BothStringIdNull_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign { StringId = null };
var node2 = new NodeDesign { StringId = null };
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Tests that Equals returns true when both instances have all enum values set to their valid extremes.
/// </summary>
[Test]
public void Equals_AllEnumExtremes_ReturnsTrue()
{
// Arrange
var node1 = new NodeDesign
{
ReleaseStatus = ReleaseStatus.Deprecated,
Purpose = DataTypePurpose.Testing,
AccessRestrictions = AccessRestrictions.SessionWithEncryptionAndApplyToBrowseRequired
};
var node2 = new NodeDesign
{
ReleaseStatus = ReleaseStatus.Deprecated,
Purpose = DataTypePurpose.Testing,
AccessRestrictions = AccessRestrictions.SessionWithEncryptionAndApplyToBrowseRequired
};
// Act
bool result = node1.Equals(node2);
// Assert
Assert.That(result, Is.True);
}
/// <summary>
/// Helper method to create a test NodeDesign with all properties set.
/// </summary>
private static NodeDesign CreateTestNodeDesign()
{
return new NodeDesign
{
BrowseName = "TestNode",
DisplayName = new LocalizedText { Value = "Test Display Name" },
Description = new LocalizedText { Value = "Test Description" },
Children = null,
References = null,
RolePermissions = null,
DefaultRolePermissions = null,
AccessRestrictions = AccessRestrictions.SigningRequired,
AccessRestrictionsSpecified = false,
DefaultAccessRestrictions = AccessRestrictions.SigningRequired,
DefaultAccessRestrictionsSpecified = false,
Extensions = null,
SymbolicName = new XmlQualifiedName("SymbolicName", "http://test.com"),
SymbolicId = new XmlQualifiedName("SymbolicId", "http://test.com"),
IsDeclaration = false,
NumericId = 100,
NumericIdSpecified = false,
StringId = "TestStringId",
WriteAccess = 0,
PartNo = 0,
Category = string.Empty,
NotInAddressSpace = false,
ReleaseStatus = ReleaseStatus.Released,
Purpose = DataTypePurpose.Normal,
IsDynamic = false
};
}
}
}