Skip to content

Commit

Permalink
Merge pull request #588 from mpostol/SemanticData-6.1.3
Browse files Browse the repository at this point in the history
Semantic data 6.1.3 update
  • Loading branch information
mpostol committed May 1, 2021
2 parents 38be6a7 + e7bc8e1 commit af10296
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 115 deletions.
8 changes: 8 additions & 0 deletions SemanticData/BuildingErrorsHandling/BuildErrors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ public partial class BuildError
Identifier = "P6-0F03000000",
Descriptor = "SymbolicName contains characters that are not allowed. Only letters, digits or the underscore (‘_’) are permitted." }; } }
/// <summary>
/// Error: P6-0F02000000; Focus: XML; The required model is missing.
/// </summary>
/// <value>An instance of <see cref="BuildError"/> describing the error P6-0F02000000.</value>
public static BuildError LackOfRequiredModel { get { return new BuildError()
{ Focus = Focus.XML,
Identifier = "P6-0F02000000",
Descriptor = "The required model is missing." }; } }
/// <summary>
/// Error: P3-XXXXX00000; Focus: DataType; Abstract DataType of the field of a concrete structure is not permitted.
/// </summary>
/// <value>An instance of <see cref="BuildError"/> describing the error P3-XXXXX00000.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@
<ns1:Descriptor>SymbolicName contains characters that are not allowed. Only letters, digits or the underscore (‘_’) are permitted.</ns1:Descriptor>
<ns1:Name>WrongSymbolicName</ns1:Name>
</ns1:NamedBuildError>
<ns1:NamedBuildError>
<ns1:Focus>XML</ns1:Focus>
<ns1:Identifier>P6-0F02000000</ns1:Identifier>
<ns1:Descriptor>The required model is missing.</ns1:Descriptor>
<ns1:Name>LackOfRequiredModel</ns1:Name>
</ns1:NamedBuildError>
<ns1:NamedBuildError>
<ns1:Focus>DataType</ns1:Focus>
<ns1:Identifier>P3-XXXXX00000</ns1:Identifier>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,18 @@ public void ConstructorTest()
List<IModelTableEntry> listOfExportedNamespaceTable = models.ToList<IModelTableEntry>();
Assert.AreEqual<int>(1, listOfExportedNamespaceTable.Count);
Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/"), listOfExportedNamespaceTable[0].ModelUri);
Assert.IsNull(listOfExportedNamespaceTable[0].RequiredModel);
}

[TestMethod]
public void GetURIatIndexTest()
{
NamespaceTable instance = new NamespaceTable();
Assert.AreEqual<Uri>(new Uri(Namespaces.OpcUa), instance.GetModelTableEntry(0).ModelUri);
Assert.ThrowsException<ArgumentOutOfRangeException>(() => instance.GetModelTableEntry(1));
Assert.AreEqual<Uri>(new Uri(Namespaces.OpcUa), instance.GetModelTableEntry(0));
Assert.IsNull(instance.GetModelTableEntry(1));
Assert.AreEqual(1, ((INamespaceTable)instance).GetURIIndexOrAppend(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest1")));
Assert.AreEqual(2, ((INamespaceTable)instance).GetURIIndexOrAppend(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest2")));
Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest2"), instance.GetModelTableEntry(2).ModelUri);
Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest1"), instance.GetModelTableEntry(1).ModelUri);
Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest2"), instance.GetModelTableEntry(2));
Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/GetURIatIndexTest1"), instance.GetModelTableEntry(1));
}

[TestMethod]
Expand All @@ -60,29 +59,57 @@ public void GetURIIndexIndexTest()
public void UpadateModelOrAppendTest()
{
NamespaceTable instance = new NamespaceTable();
IModelTableEntry model1 = ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1");
IModelTableEntry model1 = GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1");
((INamespaceTable)instance).RegisterModel(model1);
IModelTableEntry model2 = ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1");
IModelTableEntry model2 = GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1");
((INamespaceTable)instance).RegisterModel(model2);
IModelTableEntry model3 = instance.GetModelTableEntry(1);
Assert.IsNotNull(model3);
Assert.AreSame(model2, model3);
Assert.AreNotSame(model1, model3);
Assert.IsNotNull(instance.GetModelTableEntry(1));
Assert.IsNull(instance.GetModelTableEntry(2));
Assert.IsNull(instance.GetModelTableEntry(3));
}

[TestMethod]
public void ModelsTest()
{
NamespaceTable instance = new NamespaceTable();
((INamespaceTable)instance).RegisterModel(ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1"));
((INamespaceTable)instance).RegisterModel(ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest3"));
((INamespaceTable)instance).RegisterModel(ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest2"));
((INamespaceTable)instance).RegisterModel(ModelTableEntry.GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1"));
((INamespaceTable)instance).RegisterModel(GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1"));
((INamespaceTable)instance).RegisterModel(GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest3"));
((INamespaceTable)instance).RegisterModel(GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest2"));
((INamespaceTable)instance).RegisterModel(GetDefaultModelTableEntry("http://opcfoundation.org/UA/GetURIatIndexTest1"));
Assert.AreEqual<int>(4, instance.Models.Count<IModelTableEntry>());
}

#region instrumentation
[TestMethod]
public void ValidateNamesapceTableTestMethod()
{
NamespaceTable instance = new NamespaceTable();
Assert.IsFalse(instance.ValidateNamesapceTable(y => Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/"), y)));
instance.RegisterModel(GetDefaultModelTableEntry("http://opcfoundation.org/UA/"));
Assert.IsTrue(instance.ValidateNamesapceTable(y => Assert.Fail()));
instance.RegisterDependency(GetDefaultModelTableEntry("http://opcfoundation.org/UA/RandomName"));
Assert.IsFalse(instance.ValidateNamesapceTable(y => Assert.AreEqual<Uri>(new Uri("http://opcfoundation.org/UA/RandomName"), y)));
}

#region fixtures

/// <summary>
/// Gets a default model table entry.
/// </summary>
/// <param name="modelUri">The model URI.</param>
/// <returns>IModelTableEntry.</returns>
private static IModelTableEntry GetDefaultModelTableEntry(string modelUri)
{
return new ModelTableEntry
{
AccessRestrictions = 0xC,
ModelUri = modelUri,
PublicationDate = DateTime.UtcNow.Date,
RequiredModel = null,
RolePermissions = new XML.RolePermission[] { new XML.RolePermission() },
Version = new Version(1, 0).ToString()
};
}

#endregion instrumentation
#endregion fixtures
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,19 @@ public void ParseUANodeSetModelHeaderTest()
{
UANodeSet nodeSet = TestData.CreateNodeSetModel();
Assert.IsNotNull(nodeSet);
Mock<INamespaceTable> asMock = new Mock<INamespaceTable>();
Mock<INamespaceTable> nsMock = new Mock<INamespaceTable>();
List<TraceMessage> trace = new List<TraceMessage>();
Action<TraceMessage> logMock = z => trace.Add(z);
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(null, asMock.Object, logMock));
Assert.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(null, nsMock.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.ThrowsException<ArgumentNullException>(() => UAModelContext.ParseUANodeSetModelHeader(nodeSet, nsMock.Object, null));
Assert.AreEqual<int>(0, trace.Count);
UAModelContext modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
UAModelContext modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, nsMock.Object, logMock);
Assert.IsNotNull(modelContext);
Assert.AreEqual<int>(1, trace.Count);
Assert.AreEqual<string>("P0-0001030000", trace[0].BuildError.Identifier);
//TODO Import all dependencies for the model #575
//Assert.IsTrue(modelContext.ModelUri.ToString().StartsWith(@"http://cas.eu/UA/Demo/"));
}

[TestMethod]
Expand Down Expand Up @@ -129,6 +127,7 @@ public void ImportQualifiedNameWrongNamespaceIndexTest()
Assert.AreEqual<TraceEventType>(TraceEventType.Information, trace[0].TraceLevel);
}

//TODO AddressSpacePrototyping - IMNamespace must be required in case of export #584 - this UT look useless
[TestMethod]
public void ModelUriTest()
{
Expand All @@ -141,7 +140,6 @@ public void ModelUriTest()
Mock<INamespaceTable> asMock = new Mock<INamespaceTable>();
asMock.Setup<ushort>(x => x.GetURIIndexOrAppend(It.IsAny<Uri>())).Returns(10);
Action<TraceMessage> logMock = z => Assert.Fail();
//TODO Import all dependencies for the model #575
UAModelContext _modelContext = UAModelContext.ParseUANodeSetModelHeader(nodeSet, asMock.Object, logMock);
//Assert.AreEqual<string>(nodeSet.Models[0].ModelUri, _modelContext.ModelUri.ToString());
}
Expand Down Expand Up @@ -248,13 +246,6 @@ public void RecalculateNodeIdsTest()
Assert.AreEqual<string>("The BrowseName of a ReferenceType shall be unique.", trace[0].BuildError.Descriptor);
Assert.AreEqual<string>("The UAReferenceType duplicated BrowseName=10:QualifiedName. It is not allowed that two different ReferenceTypes have the same BrowseName", trace[0].Message);
Debug.WriteLine(trace[0].ToString());
//TODO Import all dependencies for the model #575
trace.Clear();
_modelContext.RegisterUAReferenceType(new QualifiedName("QualifiedName", 11));
//Assert.AreEqual<int>(1, trace.Count);
//Assert.AreEqual<string>(BuildError.BrowseNameReferenceTypeScope.Identifier, trace[0].BuildError.Identifier);
//Assert.AreEqual<string>("The BrowseName of a ReferenceType is defined outside of the model.", trace[0].BuildError.Descriptor);
//Assert.AreEqual<string>("Wrong NamespaceIndex of the 11:QualifiedName. The UAReferenceType should be defined by the default model 10", trace[0].Message);
}

[TestMethod]
Expand All @@ -278,5 +269,23 @@ public void ParseUANodeSetModelHeaderCallBack()
asMock.Verify(x => x.RegisterModel(It.IsAny<IModelTableEntry>()), Times.Once);
Assert.AreEqual<int>(0, trace.Count);
}

/// <summary>
/// Gets the default model table entry.
/// </summary>
/// <param name="modelUri">The model URI.</param>
/// <returns>IModelTableEntry.</returns>
private static IModelTableEntry GetDefaultModelTableEntry(string modelUri)
{
return new ModelTableEntry
{
AccessRestrictions = 0xC,
ModelUri = modelUri,
PublicationDate = DateTime.UtcNow.Date,
RequiredModel = null,
RolePermissions = new XML.RolePermission[] { new XML.RolePermission() },
Version = new Version(1, 0).ToString()
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public void ADITest()
using (TracedAddressSpaceContext traceContext = new TracedAddressSpaceContext())
{
IAddressSpaceContext addressSpace = traceContext.CreateAddressSpaceContext();
//TODO Import all dependencies for the model #575 - DI model must be imported as well
addressSpace.ImportUANodeSet(_testDataFileInfo);
Assert.AreEqual<int>(1, traceContext.TraceList.Count);
Assert.AreEqual<string>(BuildError.ModelsCannotBeNull.Identifier, traceContext.TraceList[0].BuildError.Identifier);
Expand All @@ -41,14 +40,14 @@ public void ADITest()
Assert.AreEqual<int>(24, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Focus == Focus.NodeClass).Count<TraceMessage>());
Assert.AreEqual<int>(0, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Focus == Focus.NonCategorized).Count<TraceMessage>());
Assert.AreEqual<int>(23, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Focus == Focus.Reference).Count<TraceMessage>());
Assert.AreEqual<int>(1, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Focus == Focus.XML).Count<TraceMessage>());
Assert.AreEqual<int>(2, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Focus == Focus.XML).Count<TraceMessage>());
//errors
Assert.AreEqual<int>(48, traceContext.TraceList.Count);
Assert.AreEqual<int>(49, traceContext.TraceList.Count);
Assert.AreEqual<int>(3, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Identifier == BuildError.NodeIdNotDefined.Identifier).Count<TraceMessage>());
Assert.AreEqual<int>(5, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Identifier == BuildError.UndefinedHasSubtypeTarget.Identifier).Count<TraceMessage>());
Assert.AreEqual<int>(18, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Identifier == BuildError.UndefinedHasTypeDefinition.Identifier).Count<TraceMessage>());
Assert.AreEqual<int>(1, traceContext.TraceList.Where<TraceMessage>(x => x.BuildError.Identifier == BuildError.ModelContainsErrors.Identifier).Count<TraceMessage>());
Assert.AreEqual<string>(BuildError.ModelContainsErrors.Identifier, traceContext.TraceList[47].BuildError.Identifier);
Assert.AreEqual<string>(BuildError.ModelContainsErrors.Identifier, traceContext.TraceList[48].BuildError.Identifier);
}
}

Expand Down
8 changes: 6 additions & 2 deletions SemanticData/UANodeSetValidation/AddressSpaceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,12 @@ void IAddressSpaceContext.ValidateAndExportModel()
void IAddressSpaceContext.ValidateAndExportModel(Uri targetNamespace)
{
m_TraceEvent.TraceEvent(TraceMessage.DiagnosticTraceMessage(string.Format("Entering IAddressSpaceContext.ValidateAndExportModel - starting for the {0} namespace.", targetNamespace)));
List<Uri> undefinedUriLists = new List<Uri>();
if (!m_NamespaceTable.ValidateNamesapceTable(x => undefinedUriLists.Add(x)))
foreach (Uri item in undefinedUriLists)
m_TraceEvent.TraceEvent(TraceMessage.BuildErrorTraceMessage(BuildError.LackOfRequiredModel, $"I cannot find definition of the required model {item}"));
int _nsIndex = m_NamespaceTable.GetURIIndex(targetNamespace);
//TODO This example doesn't work #583
//TODO This example doesn't work #583 - handle this exception
if (_nsIndex == -1)
throw new ArgumentOutOfRangeException("targetNamespace", $"Cannot find this {targetNamespace} namespace");
ValidateAndExportModel(_nsIndex);
Expand Down Expand Up @@ -189,7 +193,7 @@ public IUANodeContext GetOrCreateNodeContext(NodeId nodeId, Func<NodeId, IUANode
/// <param name="namespaceIndex">Index of the namespace.</param>
public string GetNamespace(ushort namespaceIndex)
{
return m_NamespaceTable.GetModelTableEntry(namespaceIndex).ModelUri.ToString();
return m_NamespaceTable.GetModelTableEntry(namespaceIndex).ToString();
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//___________________________________________________________________________________
//__________________________________________________________________________________________________
//
// Copyright (C) 2021, Mariusz Postol LODZ POLAND.
//
// To be in touch join the community at GITTER: https://gitter.im/mpostol/OPC-UA-OOI
//___________________________________________________________________________________
// To be in touch join the community at GitHub: https://github.com/mpostol/OPC-UA-OOI/discussions
//__________________________________________________________________________________________________

using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -499,8 +499,8 @@ internal static ExpandedNodeId Parse(string text, INamespaceTable currentNamespa
// lookup the namespace uri.
string uri = nodeId.m_namespaceUri;
if (nodeId.m_nodeId.NamespaceIndex != 0)
uri = currentNamespaces.GetModelTableEntry(nodeId.m_nodeId.NamespaceIndex).ModelUri.ToString();
// translate the namespace uri.
uri = currentNamespaces.GetModelTableEntry(nodeId.m_nodeId.NamespaceIndex).ToString();
// translate the namespace Uri.
ushort namespaceIndex = 0;
if (!String.IsNullOrEmpty(uri))
{
Expand Down Expand Up @@ -608,7 +608,7 @@ internal static void UnescapeUri(string text, int start, int index, StringBuilde
}
}

#endregion statioc Parse
#endregion static Parse

#region IComparable Members

Expand Down
1 change: 1 addition & 0 deletions SemanticData/UANodeSetValidation/IAddressSpaceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public interface IAddressSpaceContext
/// <value>The information model factory.</value>
IModelFactory InformationModelFactory { set; }

//TODO AddressSpacePrototyping - IMNamespace must be required in case of export #584
/// <summary>
/// Validates and exports the selected model for the default namespace at index 1 if defined or standard OPC UA.
/// </summary>
Expand Down
Loading

0 comments on commit af10296

Please sign in to comment.