Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UAModelContext must provide default namespaceIndex #517 #522

Merged
merged 2 commits into from
Feb 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace UAOOI.SemanticData.UANodeSetValidation
{
//TODO NamespaceUrisCannotBeNull - is reported for UADefinedTypes #520
[TestClass]
public class NamespaceTableUnitTest
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Moq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using UAOOI.SemanticData.BuildingErrorsHandling;
using UAOOI.SemanticData.UANodeSetValidation.UAInformationModel;
using UAOOI.SemanticData.UANodeSetValidation.UnitTest.Helpers;
Expand All @@ -21,95 +22,148 @@ namespace UAOOI.SemanticData.UANodeSetValidation.UnitTest
public class UAModelContextUnitTest
{
[TestMethod]
public void ConstructorTest()
public void ParseUANodeSetModelHeaderTest()
{
IUANodeSetModelHeader _tm = TestData.CreateNodeSetModel();
Mock<IAddressSpaceURIRecalculate> _asMock = new Mock<IAddressSpaceURIRecalculate>();
int logCount = 0;
Action<TraceMessage> _logMock = z => logCount++;
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(null, _asMock.Object, _logMock));
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(_tm, _asMock.Object, null));
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(_tm, null, _logMock));
UAModelContext _mc = UAModelContext.ParseUANodeSetModelHeader(_tm, _asMock.Object, _logMock);
Assert.IsNotNull(_mc);
}

[TestMethod]
public void ModeltUriTest()
{
UANodeSet _tm = TestData.CreateNodeSetModel();
Mock<IAddressSpaceURIRecalculate> _asMock = new Mock<IAddressSpaceURIRecalculate>();
UANodeSet nodeSet = TestData.CreateNodeSetModel();
Assert.IsNotNull(nodeSet);
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
List<TraceMessage> trace = new List<TraceMessage>();
Action<TraceMessage> _logMock = z => trace.Add(z);
UAModelContext _mc = null;
_mc = UAModelContext.ParseUANodeSetModelHeader(_tm, _asMock.Object, _logMock);
Assert.IsTrue(_mc.ModeltUri.ToString().StartsWith(@"http://cas.eu/UA/Demo/"));
Action<TraceMessage> logMock = z => trace.Add(z);
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(null, asMock.Object, logMock));
Assert.AreEqual<int>(0, trace.Count);
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(nodeSet, null, logMock));
Assert.AreEqual<int>(0, trace.Count);
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, null));
Assert.AreEqual<int>(0, trace.Count);
UAModelContext modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
Assert.IsNotNull(modelContext);
Assert.AreEqual<int>(1, trace.Count);
Assert.AreEqual<string>("P0-0001030000", trace[0].BuildError.Identifier);
Assert.IsTrue(modelContext.ModelUri.ToString().StartsWith(@"http://cas.eu/UA/Demo/"));
}

[TestMethod]
public void AliasesConversionTest()
public void ImportNodeIdTest()
{
IUANodeSetModelHeader _nodeSet = new UANodeSet
IUANodeSetModelHeader nodeSet = new UANodeSet
{
Aliases = new NodeIdAlias[] {
new NodeIdAlias() { Alias = "HasSubtype", Value = "i=45" },
new NodeIdAlias() { Alias = "Boolean", Value = "ns=1;i=1" } },
NamespaceUris = new string[] { "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" },
};
Mock<IAddressSpaceURIRecalculate> _asMock = new Mock<IAddressSpaceURIRecalculate>();
_asMock.Setup(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest")).Returns(10);
string uri = string.Empty;
_asMock.Setup(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown")))).Returns<string>(x => { uri = x; return 20; });
List<TraceMessage> _logsCache = new List<TraceMessage>();
Action<TraceMessage> _logMock = z => _logsCache.Add(z);
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(_nodeSet, _asMock.Object, _logMock);
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
asMock.Setup(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest")).Returns(10);
string randomURI = string.Empty;
asMock.Setup(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown")))).Returns<string>(x => { randomURI = x; return 20; });
List<TraceMessage> trace = new List<TraceMessage>();
Action<TraceMessage> logMock = z => trace.Add(z);
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
//start testing
Assert.AreEqual<string>("ns=10;i=1", _modelContext.ImportNodeId("Boolean"));
Assert.AreEqual<string>("i=45", _modelContext.ImportNodeId("HasSubtype"));
Assert.AreEqual<string>("ns=20;i=2", _modelContext.ImportNodeId("ns=2;i=2"));
_asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Once);
_asMock.Verify(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown"))), Times.Once);
asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Once);
asMock.Verify(x => x.GetIndexOrAppend(randomURI), Times.Once);
Assert.AreEqual<string>("ns=20;i=3", _modelContext.ImportNodeId("ns=2;i=3"));
_asMock.Verify(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown"))), Times.Exactly(2));
asMock.Verify(x => x.GetIndexOrAppend(randomURI), Times.Exactly(2));
Assert.AreEqual<string>("ns=20;i=4", _modelContext.ImportNodeId("ns=2;i=4"));
_asMock.Verify(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown"))), Times.Exactly(3));
Assert.AreEqual<int>(2, _logsCache.Count);
Assert.IsTrue(_logsCache[0].Message.Contains("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"));
Assert.IsTrue(_logsCache[1].Message.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown"));
asMock.Verify(x => x.GetIndexOrAppend(randomURI), Times.Exactly(3));
asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Once);
Assert.AreEqual<int>(2, trace.Count);
Assert.IsTrue(trace[0].Message.Contains("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"));
Assert.AreEqual<string>("P0-0001030000", trace[0].BuildError.Identifier);
Assert.AreEqual<TraceEventType>(TraceEventType.Information, trace[0].TraceLevel);
Assert.IsTrue(trace[1].Message.Contains(randomURI));
Assert.AreEqual<string>("P3-0802020000", trace[1].BuildError.Identifier);
Assert.AreEqual<TraceEventType>(TraceEventType.Information, trace[1].TraceLevel);
}

[TestMethod]
public void ImportQualifiedNameTest()
{
IUANodeSetModelHeader _nodeSet = new UANodeSet
IUANodeSetModelHeader nodeSet = new UANodeSet
{
Aliases = new NodeIdAlias[] { new NodeIdAlias() { Alias = "HasSubtype", Value = "i=45" }, new NodeIdAlias() { Alias = "Boolean", Value = "ns=1;i=1" } },
NamespaceUris = new string[] { "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" },
Models = new ModelTableEntry[] { new ModelTableEntry() { ModelUri = "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" } }
};
Mock<IAddressSpaceURIRecalculate> _asMock = new Mock<IAddressSpaceURIRecalculate>();
_asMock.Setup(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest")).Returns(10);
List<TraceMessage> _logsCache = new List<TraceMessage>();
Action<TraceMessage> _logMock = z => _logsCache.Add(z);
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(_nodeSet, _asMock.Object, _logMock);
Assert.AreEqual<string>("10:Boolean", _modelContext.ImportQualifiedName("1:Boolean"));
Assert.AreEqual<string>("HasSubtype", _modelContext.ImportQualifiedName("HasSubtype"));
_asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Once);
Assert.AreEqual<int>(0, _logsCache.Count);
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
asMock.Setup(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest")).Returns(10);
Action<TraceMessage> logMock = z => Assert.Fail();
UAModelContext modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
Assert.AreEqual<string>("10:Boolean", modelContext.ImportQualifiedName("1:Boolean"));
Assert.AreEqual<string>("10:AnyText", modelContext.ImportQualifiedName("1:AnyText"));
Assert.AreEqual<string>("HasSubtype", modelContext.ImportQualifiedName("HasSubtype"));
Assert.AreEqual<string>("ns=10;i=232323", modelContext.ImportNodeId("ns=1;i=232323"));
asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Exactly(3));
}

[TestMethod]
public void ImportQualifiedNameWrongNamespaceIndexTest()
{
IUANodeSetModelHeader nodeSet = new UANodeSet
{
Aliases = new NodeIdAlias[] { new NodeIdAlias() { Alias = "HasSubtype", Value = "i=45" }, new NodeIdAlias() { Alias = "Boolean", Value = "ns=1;i=1" } },
NamespaceUris = new string[] { "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" },
Models = new ModelTableEntry[] { new ModelTableEntry() { ModelUri = "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" } }
};
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
asMock.Setup(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest")).Returns(10);
string randomURI = string.Empty;
asMock.Setup(x => x.GetIndexOrAppend(It.Is<string>(z => z.Contains("github.com/mpostol/OPC-UA-OOI/NameUnknown")))).Returns<string>(x => { randomURI = x; return 20; });
List<TraceMessage> trace = new List<TraceMessage>();
Action<TraceMessage> logMock = z => trace.Add(z);
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
Assert.AreEqual<string>("ns=20;i=232323", _modelContext.ImportNodeId("ns=2;i=232323"));
asMock.Verify(x => x.GetIndexOrAppend("http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest"), Times.Never);
asMock.Verify(x => x.GetIndexOrAppend(randomURI), Times.Once);
Assert.AreEqual<int>(1, trace.Count);
Assert.IsTrue(trace[0].Message.Contains(randomURI));
Assert.AreEqual<string>("P3-0802020000", trace[0].BuildError.Identifier);
Assert.AreEqual<TraceEventType>(TraceEventType.Information, trace[0].TraceLevel);
}

[TestMethod]
public void ModelUriTest()
{
IUANodeSetModelHeader nodeSet = new UANodeSet
{
Aliases = new NodeIdAlias[] { new NodeIdAlias() { Alias = "HasSubtype", Value = "i=45" }, new NodeIdAlias() { Alias = "Boolean", Value = "ns=1;i=1" } },
NamespaceUris = new string[] { "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" },
Models = new ModelTableEntry[] { new ModelTableEntry() { ModelUri = "http://cas.eu/UA/CommServer/UnitTests/ObjectTypeTest" } }
};
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
asMock.Setup(x => x.GetIndexOrAppend(It.IsAny<string>())).Returns(10);
Action<TraceMessage> logMock = z => Assert.Fail();
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
Assert.AreEqual<string>(nodeSet.Models[0].ModelUri, _modelContext.ModelUri.ToString());
}

[TestMethod]
public void ImportNamespaceIndexTest()
public void ModelUriModelsIsEmptyTest()
{
Assert.Inconclusive("Not implemented");
IUANodeSetModelHeader nodeSet = new UANodeSet
{
Aliases = new NodeIdAlias[] { new NodeIdAlias() { Alias = "HasSubtype", Value = "i=45" }, new NodeIdAlias() { Alias = "Boolean", Value = "ns=1;i=1" } },
NamespaceUris = new string[] { "http://opcfoundation.org/UA/ADI/", "http://opcfoundation.org/UA/DI/" },
};
Mock<IAddressSpaceURIRecalculate> asMock = new Mock<IAddressSpaceURIRecalculate>();
asMock.Setup(x => x.GetIndexOrAppend(It.IsAny<string>())).Returns(10);
List<TraceMessage> trace = new List<TraceMessage>();
Action<TraceMessage> logMock = z => trace.Add(z);
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
Assert.IsNull(nodeSet.Models);
Assert.AreEqual<string>("http://opcfoundation.org/UA/ADI/", _modelContext.ModelUri.ToString());
Assert.AreEqual<int>(1, trace.Count);
Assert.AreEqual<string>("P0-0001030000", trace[0].BuildError.Identifier);
Assert.AreEqual<TraceEventType>(TraceEventType.Information, trace[0].TraceLevel);
}

[TestMethod]
public void RecalculateNodeIdsUANodeSetTest()
{
UANodeSet _toTest = new UANodeSet()
UANodeSet nodeSet = new UANodeSet()
{
NamespaceUris = new string[] { @"http://cas.eu/UA/Demo/" },
Aliases = new NodeIdAlias[] { new NodeIdAlias() { Alias = "Alias name", Value = "ns=1;i=24" } },
Expand Down Expand Up @@ -143,15 +197,15 @@ public void RecalculateNodeIdsUANodeSetTest()
addressSpaceMock.Setup(x => x.GetIndexOrAppend(@"http://cas.eu/UA/Demo/")).Returns<string>(x => 2);
List<TraceMessage> _logsCache = new List<TraceMessage>();
Action<TraceMessage> _logMock = z => _logsCache.Add(z);
IUAModelContext model = _toTest.ParseUAModelContext(addressSpaceMock.Object, _logMock);
IUAModelContext model = nodeSet.ParseUAModelContext(addressSpaceMock.Object, _logMock);
Assert.IsNotNull(model);
addressSpaceMock.Verify(x => x.GetIndexOrAppend(@"http://cas.eu/UA/Demo/"), Times.AtLeastOnce());
Assert.AreEqual<string>("ns=2;i=24", _toTest.Aliases[0].Value);
Assert.AreEqual<string>("Alias name", _toTest.Aliases[0].Alias);
Assert.AreEqual<string>("ns=2;i=24", _toTest.Items[0].NodeId);
Assert.AreEqual<string>("ns=2;i=2", ((UAVariableType)_toTest.Items[1]).DataType);
Assert.AreEqual<string>("2:BleBle", model.ImportQualifiedName("1:BleBle"));
Assert.AreEqual<string>("s=1:BleBle", model.ImportNodeId("1:BleBle"));
Assert.AreEqual<string>("ns=2;i=24", nodeSet.Aliases[0].Value);
Assert.AreEqual<string>("Alias name", nodeSet.Aliases[0].Alias);
Assert.AreEqual<string>("ns=2;i=24", nodeSet.Items[0].NodeId);
Assert.AreEqual<string>("2:NewUAObject", nodeSet.Items[0].BrowseName);
Assert.AreEqual<string>("ns=2;i=2", ((UAVariableType)nodeSet.Items[1]).DataType);
Assert.AreEqual<string>("2:NewUAObject", ((UAVariableType)nodeSet.Items[1]).BrowseName);
}
}
}
24 changes: 14 additions & 10 deletions SemanticData/UANodeSetValidation/AddressSpaceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ void IAddressSpaceContext.ValidateAndExportModel(string targetNamespace)

#endregion IAddressSpaceContext

#region IAddressSpaceURIRecalculate

/// <summary>
/// Gets the index or append.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>System.UInt16.</returns>
ushort IAddressSpaceURIRecalculate.GetIndexOrAppend(string value)
{
return m_NamespaceTable.GetURIIndexOrAppend(value);
}

#endregion IAddressSpaceURIRecalculate

#region IAddressSpaceBuildContext

/// <summary>
Expand Down Expand Up @@ -179,16 +193,6 @@ public IUANodeContext GetOrCreateNodeContext(NodeId nodeId, Func<NodeId, IUANode
return _ret;
}

/// <summary>
/// Gets the index or append.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>System.UInt16.</returns>
public ushort GetIndexOrAppend(string value)
{
return m_NamespaceTable.GetURIIndexOrAppend(value);
}

/// <summary>
/// Gets the namespace.
/// </summary>
Expand Down
18 changes: 9 additions & 9 deletions SemanticData/UANodeSetValidation/XML/UAModelContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal static UAModelContext ParseUANodeSetModelHeader(IUANodeSetModelHeader m
return context2Return;
}

internal Uri ModeltUri { get; private set; }
internal Uri ModelUri { get; private set; }

#endregion API

Expand Down Expand Up @@ -77,7 +77,7 @@ public string ImportNodeId(string nodeId)

//var

private readonly Action<TraceMessage> _log;
private readonly Action<TraceMessage> _logTraceMessage;
private readonly Dictionary<string, string> _aliasesDictionary = new Dictionary<string, string>();
private List<string> _namespaceUris = new List<string>();
private IAddressSpaceURIRecalculate _addressSpaceContext { get; }
Expand All @@ -86,14 +86,14 @@ public string ImportNodeId(string nodeId)
//methods
private UAModelContext(IAddressSpaceURIRecalculate addressSpaceContext, Action<TraceMessage> traceEvent)
{
_log = traceEvent ?? throw new ArgumentNullException(nameof(traceEvent));
_logTraceMessage = traceEvent ?? throw new ArgumentNullException(nameof(traceEvent));
_addressSpaceContext = addressSpaceContext ?? throw new ArgumentNullException(nameof(addressSpaceContext));
}

private void Parse(IUANodeSetModelHeader modelHeader)
{
_namespaceUris = Parse(modelHeader.NamespaceUris);
ModeltUri = Parse(modelHeader.Models);
ModelUri = Parse(modelHeader.Models);
Parse(modelHeader.Aliases);
}

Expand All @@ -111,7 +111,7 @@ private List<string> Parse(string[] namespaceUris)
if (namespaceUris is null || namespaceUris.Length == 0)
{
namespaceUris = new string[] { RandomUri().ToString() };
_log(TraceMessage.BuildErrorTraceMessage(BuildError.NamespaceUrisCannotBeNull, $"Added a random URI { namespaceUris[0] } to NamespaceUris."));
_logTraceMessage(TraceMessage.BuildErrorTraceMessage(BuildError.NamespaceUrisCannotBeNull, $"Added a random URI { namespaceUris[0] } to NamespaceUris."));
}
for (int i = 0; i < namespaceUris.Length; i++)
list2Return.Add(namespaceUris[i]);
Expand All @@ -126,17 +126,17 @@ private Uri Parse(ModelTableEntry[] models)
{
AccessRestrictions = 0,
ModelUri = _namespaceUris[0],
PublicationDate =DateTime.UtcNow,
PublicationDate = DateTime.UtcNow,
PublicationDateSpecified = true,
RequiredModel = new ModelTableEntry[]{ },
RolePermissions = new RolePermission[] { },
Version = new Version().ToString()
}
};
_log(TraceMessage.BuildErrorTraceMessage(BuildError.ModelsCannotBeNull, $"Added default model {models[0].ModelUri}"));
_logTraceMessage(TraceMessage.BuildErrorTraceMessage(BuildError.ModelsCannotBeNull, $"Added default model {models[0].ModelUri}"));
}
else if (models.Length > 1)
_log(TraceMessage.BuildErrorTraceMessage(BuildError.NotSupportedFeature, $"Multi-model is not supported, only first model {models[0].ModelUri }is processed."));
_logTraceMessage(TraceMessage.BuildErrorTraceMessage(BuildError.NotSupportedFeature, $"Multi-model is not supported, only first model {models[0].ModelUri} is processed."));
return new UriBuilder(models[0].ModelUri).Uri;
}

Expand All @@ -158,7 +158,7 @@ private ushort ImportNamespaceIndex(ushort namespaceIndex)
{
// return a random value if index is out of range.
uriString = RandomUri().ToString();
this._log(
this._logTraceMessage(
TraceMessage.BuildErrorTraceMessage(BuildError.UndefinedNamespaceIndex, $"ImportNamespaceIndex failed - namespace index {namespaceIndex - 1} is out of the NamespaceUris index. New namespace {uriString} is created instead."));
_namespaceUris.Add(uriString);
}
Expand Down
Loading