/* ======================================================================== * 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 Microsoft.Extensions.DependencyInjection; using NUnit.Framework; using Opc.Ua.Schema.Json; namespace Opc.Ua.Schema.Tests { /// /// Tests for the schema generation dependency injection registration. /// [TestFixture] [Category("Schema")] public class SchemaServiceCollectionExtensionsTests { [Test] public void AddSchemaGenerationResolvesProviderAndResolvesRegisteredType() { var services = new ServiceCollection(); services.AddOpcUa().AddSchemaGeneration(); using ServiceProvider serviceProvider = services.BuildServiceProvider(); DataTypeDefinitionRegistry registry = serviceProvider.GetRequiredService(); UaTypeDescription type = SchemaTestData.Structure( 3001, "SampleType", SchemaTestData.Field("Id", SchemaTestData.BuiltIn(BuiltInType.Int32))); registry.Add(type); ISchemaProvider provider = serviceProvider.GetRequiredService(); bool resolved = provider.TryGetSchema( type.TypeId, UaSchemaFormat.JsonCompact, UaSchemaScope.Type, out IUaSchema? schema); Assert.Multiple(() => { Assert.That(resolved, Is.True); Assert.That(schema, Is.Not.Null); Assert.That(schema!.Format, Is.EqualTo(UaSchemaFormat.JsonCompact)); }); } [Test] public void AddSchemaGenerationResolvesUriFormRegisteredNode() { var services = new ServiceCollection(); services.AddOpcUa().AddSchemaGeneration(); using ServiceProvider serviceProvider = services.BuildServiceProvider(); var namespaceUris = new NamespaceTable(); namespaceUris.Append(SchemaTestData.TestNamespace); var node = new DataTypeNode { NodeId = new NodeId(3002, SchemaTestData.TestNamespaceIndex), BrowseName = new QualifiedName("RegisteredNode", SchemaTestData.TestNamespaceIndex), DataTypeDefinition = new ExtensionObject(new StructureDefinition { BaseDataType = DataTypeIds.Structure, StructureType = StructureType.Structure, Fields = [ SchemaTestData.Field("Value", SchemaTestData.BuiltIn(BuiltInType.Int32)) ] }) }; DataTypeDefinitionRegistry registry = serviceProvider.GetRequiredService(); bool added = registry.TryAddDataType(node, namespaceUris); ISchemaProvider provider = serviceProvider.GetRequiredService(); bool resolved = provider.TryGetSchema( NodeId.ToExpandedNodeId(node.NodeId, namespaceUris), UaSchemaFormat.JsonCompact, UaSchemaScope.Type, out IUaSchema? schema); Assert.Multiple(() => { Assert.That(added, Is.True); Assert.That(resolved, Is.True); Assert.That(schema, Is.Not.Null); }); } [TestCaseSource(typeof(SchemaTestData), nameof(SchemaTestData.TypeIdentifierCases))] public void RegisteredIdentifierResolvesWithoutUsingBrowseNameNamespace(NodeId nodeId) { var services = new ServiceCollection(); services.AddOpcUa().AddSchemaGeneration(); using ServiceProvider serviceProvider = services.BuildServiceProvider(); var namespaceUris = new NamespaceTable(); namespaceUris.Append(SchemaTestData.TestNamespace); namespaceUris.Append(SchemaTestData.OtherNamespace); var node = new DataTypeNode { NodeId = nodeId, BrowseName = new QualifiedName("RegisteredEnum", SchemaTestData.OtherNamespaceIndex), DataTypeDefinition = new ExtensionObject(new EnumDefinition { Fields = [new EnumField { Name = "Running", Value = 2 }] }) }; DataTypeDefinitionRegistry registry = serviceProvider.GetRequiredService(); ISchemaProvider provider = serviceProvider.GetRequiredService(); Assert.That(registry.TryAddDataType(node, namespaceUris), Is.True); Assert.That( provider.TryGetSchema( NodeId.ToExpandedNodeId(nodeId, namespaceUris), UaSchemaFormat.JsonCompact, UaSchemaScope.Type, out IUaSchema? uriSchema), Is.True); Assert.That( provider.TryGetSchema( new ExpandedNodeId(nodeId), UaSchemaFormat.JsonCompact, UaSchemaScope.Type, out IUaSchema? indexSchema), Is.True); Assert.That(uriSchema, Is.TypeOf()); var document = (JsonSchemaDocument)uriSchema!; Assert.That(document.Root["title"]!.GetValue(), Is.EqualTo("RegisteredEnum")); Assert.That(uriSchema.ToSchemaString(), Does.Contain("Running")); Assert.That(indexSchema!.ToSchemaString(), Is.EqualTo(uriSchema.ToSchemaString())); } [Test] public void AddSchemaGenerationThrowsForNullBuilder() { Assert.That( () => SchemaServiceCollectionExtensions.AddSchemaGeneration(null!), Throws.ArgumentNullException.With.Property(nameof(ArgumentNullException.ParamName)).EqualTo("builder")); } [Test] public void TryGetSchemaReturnsFalseForUnknownType() { var services = new ServiceCollection(); services.AddOpcUa().AddSchemaGeneration(); using ServiceProvider serviceProvider = services.BuildServiceProvider(); ISchemaProvider provider = serviceProvider.GetRequiredService(); bool resolved = provider.TryGetSchema( new ExpandedNodeId(new NodeId(9999, 1)), UaSchemaFormat.JsonCompact, UaSchemaScope.Type, out IUaSchema? schema); Assert.Multiple(() => { Assert.That(resolved, Is.False); Assert.That(schema, Is.Null); }); } } }