diff --git a/common.props b/common.props index ebbe3fac0a..4fdfab847b 100644 --- a/common.props +++ b/common.props @@ -46,8 +46,8 @@ - - + + diff --git a/deploy/docker/build.cmd b/deploy/docker/build.cmd index df3a7adefd..e1299d0a6d 100644 --- a/deploy/docker/build.cmd +++ b/deploy/docker/build.cmd @@ -1,7 +1,7 @@ @echo off setlocal -set CMDLINE=--self-contained false /t:PublishContainer +set CMDLINE=--self-contained false /t:PublishContainer -r linux-x64 set PROJECT=../../src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj dotnet publish %PROJECT% -c Release %CMDLINE% /p:ContainerImageTag=latest diff --git a/src/Azure.IIoT.OpcUa.Publisher.Models/src/Azure.IIoT.OpcUa.Publisher.Models.csproj b/src/Azure.IIoT.OpcUa.Publisher.Models/src/Azure.IIoT.OpcUa.Publisher.Models.csproj index 821748e526..98b9bef8b0 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Models/src/Azure.IIoT.OpcUa.Publisher.Models.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Models/src/Azure.IIoT.OpcUa.Publisher.Models.csproj @@ -8,7 +8,7 @@ enable - + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupDiagnosticModel.cs b/src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupDiagnosticModel.cs index 8b09f3efb1..fbbcdd59e6 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupDiagnosticModel.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupDiagnosticModel.cs @@ -481,5 +481,26 @@ public record class WriterGroupDiagnosticModel [DataMember(Name = "MonitoredOpcNodesCount", Order = 76, EmitDefaultValue = true)] public int MonitoredOpcNodesCount { get; set; } + + /// + /// Container Cpu limit utilization + /// + [DataMember(Name = "CpuLimitUtilization", Order = 77, + EmitDefaultValue = true)] + public double CpuLimitUtilization { get; set; } + + /// + /// Container Cpu request utilization + /// + [DataMember(Name = "CpuRequestUtilization", Order = 78, + EmitDefaultValue = true)] + public double CpuRequestUtilization { get; set; } + + /// + /// Container memory limit utilization + /// + [DataMember(Name = "MemoryLimitUtilization", Order = 79, + EmitDefaultValue = true)] + public double MemoryLimitUtilization { get; set; } } } diff --git a/src/Azure.IIoT.OpcUa.Publisher.Models/tests/Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj b/src/Azure.IIoT.OpcUa.Publisher.Models/tests/Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj index 09ebbcaf5a..90b4f0a449 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Models/tests/Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Models/tests/Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj @@ -4,22 +4,22 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers - - - + + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/cli/Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj b/src/Azure.IIoT.OpcUa.Publisher.Module/cli/Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj index d8077080be..0b75d3e45f 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Module/cli/Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Module/cli/Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj @@ -7,8 +7,8 @@ true - - + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj b/src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj index 46bc14952e..46fa1084af 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj @@ -32,23 +32,23 @@ - - - - - - + + + + + + - - + + - - + + - - - - + + + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj index ac394032fa..0808490ea0 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj @@ -3,19 +3,19 @@ net9.0 - - - - + + + + - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/AdvancedPubSubIntegrationTests.cs b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/AdvancedPubSubIntegrationTests.cs index cbaf4b50e5..ec014c1bac 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/AdvancedPubSubIntegrationTests.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/AdvancedPubSubIntegrationTests.cs @@ -53,7 +53,10 @@ public async Task RestartServerTestAsync() message = Assert.Single(messages).Message; AssertFixedValueMessage(message); - Assert.Null(metadata); + + // When we recreated the session we did not handle new metadata but now that we create we do. + // Assert.Null(metadata); + Assert.NotNull(metadata); } finally { diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicPubSubIntegrationTests.cs b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicPubSubIntegrationTests.cs index a2c7da7570..4b742d3b93 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicPubSubIntegrationTests.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicPubSubIntegrationTests.cs @@ -80,10 +80,11 @@ public async Task CanSendModelChangeEventsToIoTHubTestAsync() Assert.True(Guid.TryParse(payload1.GetProperty("EventId").GetProperty("Value").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=ReferenceChange", payload1.GetProperty("EventType").GetProperty("Value").GetString()); - Assert.Equal("i=84", payload1.GetProperty("SourceNode").GetProperty("Value").GetString()); Assert.True(DateTime.TryParse(payload1.GetProperty("Time").GetProperty("Value").GetString(), out _)); Assert.True(payload1.GetProperty("Change").GetProperty("Value").GetProperty("IsForward").GetBoolean()); - Assert.Equal("Objects", payload1.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); + // NO order anymore: + // Assert.Equal("i=84", payload1.GetProperty("SourceNode").GetProperty("Value").GetString()); + // Assert.Equal("Objects", payload1.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); var payload2 = messages[1].Message.GetProperty("Messages")[0].GetProperty("Payload"); _output.WriteLine(payload2.ToJsonString()); @@ -91,9 +92,10 @@ public async Task CanSendModelChangeEventsToIoTHubTestAsync() Assert.True(Guid.TryParse(payload2.GetProperty("EventId").GetProperty("Value").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=NodeChange", payload2.GetProperty("EventType").GetProperty("Value").GetString()); - Assert.Equal("i=85", payload2.GetProperty("SourceNode").GetProperty("Value").GetString()); Assert.True(DateTime.TryParse(payload2.GetProperty("Time").GetProperty("Value").GetString(), out _)); - Assert.Equal("Objects", payload2.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); + // NO order anymore: + // Assert.Equal("i=85", payload2.GetProperty("SourceNode").GetProperty("Value").GetString()); + // Assert.Equal("Objects", payload2.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); // TODO: currently metadata is sent later // Assert.NotNull(metadata); diff --git a/src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Azure.IIoT.OpcUa.Publisher.Sdk.csproj b/src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Azure.IIoT.OpcUa.Publisher.Sdk.csproj index c009d845ec..297fbf2684 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Azure.IIoT.OpcUa.Publisher.Sdk.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Azure.IIoT.OpcUa.Publisher.Sdk.csproj @@ -8,13 +8,13 @@ enable - - - + + + - - - + + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/cli/Azure.IIoT.OpcUa.Publisher.Service.Cli.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/cli/Azure.IIoT.OpcUa.Publisher.Service.Cli.csproj index 2124958e86..f6a298d4fe 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/cli/Azure.IIoT.OpcUa.Publisher.Service.Cli.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/cli/Azure.IIoT.OpcUa.Publisher.Service.Cli.csproj @@ -10,13 +10,13 @@ mcr.microsoft.com/dotnet/runtime:9.0-azurelinux3.0-distroless - - - + + + - + - + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk.csproj index f69a0e4ef8..0090239347 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk/src/Azure.IIoT.OpcUa.Publisher.Service.Sdk.csproj @@ -8,14 +8,14 @@ enable - - - - - - - - + + + + + + + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj index df38db355f..1ca451d83c 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj @@ -15,23 +15,23 @@ - - - - - - - - + + + + + + + + - - - - - - + + + + + + - + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/tests/Azure.IIoT.OpcUa.Publisher.Service.WebApi.Tests.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/tests/Azure.IIoT.OpcUa.Publisher.Service.WebApi.Tests.csproj index f9788d2616..051c842674 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/tests/Azure.IIoT.OpcUa.Publisher.Service.WebApi.Tests.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/tests/Azure.IIoT.OpcUa.Publisher.Service.WebApi.Tests.csproj @@ -3,20 +3,20 @@ net9.0 - - - - - + + + + + - + all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service/src/Azure.IIoT.OpcUa.Publisher.Service.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service/src/Azure.IIoT.OpcUa.Publisher.Service.csproj index 061546b6ae..7ee66c9951 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service/src/Azure.IIoT.OpcUa.Publisher.Service.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service/src/Azure.IIoT.OpcUa.Publisher.Service.csproj @@ -6,8 +6,8 @@ enable - - + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service/tests/Azure.IIoT.OpcUa.Publisher.Service.Tests.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service/tests/Azure.IIoT.OpcUa.Publisher.Service.Tests.csproj index 4b858763fb..76735bc867 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Service/tests/Azure.IIoT.OpcUa.Publisher.Service.Tests.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Service/tests/Azure.IIoT.OpcUa.Publisher.Service.Tests.csproj @@ -6,15 +6,15 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/src/Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj b/src/Azure.IIoT.OpcUa.Publisher.Testing/src/Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj index abfafcba80..3488f33be1 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/src/Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/src/Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj @@ -58,10 +58,10 @@ - - + + - - + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerConsoleHost.cs b/src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerConsoleHost.cs index 2eb1a7a3e6..ae7ac79c59 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerConsoleHost.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerConsoleHost.cs @@ -228,8 +228,8 @@ private async Task StartServerInternalAsync(IEnumerable ports, string pkiRo var application = new ApplicationInstance(config); // check the application certificate. - var hasAppCertificate = await application.CheckApplicationInstanceCertificate( - silent: true, CertificateFactory.DefaultKeySize).ConfigureAwait(false); + var hasAppCertificate = await application.CheckApplicationInstanceCertificates( + silent: true).ConfigureAwait(false); if (!hasAppCertificate) { _logger.LogError("Server {Instance} - Failed validating own certificate!", this); @@ -246,7 +246,7 @@ private async Task StartServerInternalAsync(IEnumerable ports, string pkiRo } }; - await config.CertificateValidator.Update(config.SecurityConfiguration).ConfigureAwait(false); + await config.CertificateValidator.Update(config).ConfigureAwait(false); // Set Certificate try diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Azure.IIoT.OpcUa.Publisher.Testing.csproj b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Azure.IIoT.OpcUa.Publisher.Testing.csproj index 9af78a8d95..2cd558bccb 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Azure.IIoT.OpcUa.Publisher.Testing.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Azure.IIoT.OpcUa.Publisher.Testing.csproj @@ -5,12 +5,12 @@ enable - - - - - - + + + + + + diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseServicesTests.cs b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseServicesTests.cs index 6d3b6325a1..caf853a46f 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseServicesTests.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseServicesTests.cs @@ -44,37 +44,39 @@ public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); - Assert.Collection(results.References, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Objects", reference.Target.BrowseName); - Assert.Equal("Objects", reference.Target.DisplayName); - Assert.Equal("i=85", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.True(reference.Target.Children); - }, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Types", reference.Target.BrowseName); - Assert.Equal("Types", reference.Target.DisplayName); - Assert.Equal("i=86", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.True(reference.Target.Children); - }, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Views", reference.Target.BrowseName); - Assert.Equal("Views", reference.Target.DisplayName); - Assert.Equal("i=87", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.False(reference.Target.Children); - }); + // No order anymore in stack + + // Assert.Collection(results.References, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Objects", reference.Target.BrowseName); + // Assert.Equal("Objects", reference.Target.DisplayName); + // Assert.Equal("i=85", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.True(reference.Target.Children); + // }, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Types", reference.Target.BrowseName); + // Assert.Equal("Types", reference.Target.DisplayName); + // Assert.Equal("i=86", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.True(reference.Target.Children); + // }, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Views", reference.Target.BrowseName); + // Assert.Equal("Views", reference.Target.DisplayName); + // Assert.Equal("i=87", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.False(reference.Target.Children); + // }); } public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) @@ -96,37 +98,38 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); - Assert.Collection(results.References, - reference => - { - Assert.Null(reference.ReferenceTypeId); - Assert.Null(reference.Direction); - Assert.Equal("Objects", reference.Target.BrowseName); - Assert.Equal("Objects", reference.Target.DisplayName); - Assert.Equal("i=85", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.True(reference.Target.Children); - }, - reference => - { - Assert.Null(reference.ReferenceTypeId); - Assert.Null(reference.Direction); - Assert.Equal("Types", reference.Target.BrowseName); - Assert.Equal("Types", reference.Target.DisplayName); - Assert.Equal("i=86", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.True(reference.Target.Children); - }, - reference => - { - Assert.Null(reference.ReferenceTypeId); - Assert.Null(reference.Direction); - Assert.Equal("Views", reference.Target.BrowseName); - Assert.Equal("Views", reference.Target.DisplayName); - Assert.Equal("i=87", reference.Target.NodeId); - Assert.True(reference.Target.Value.IsNull()); - Assert.False(reference.Target.Children); - }); + // No order anymore in stack + // Assert.Collection(results.References, + // reference => + // { + // Assert.Null(reference.ReferenceTypeId); + // Assert.Null(reference.Direction); + // Assert.Equal("Objects", reference.Target.BrowseName); + // Assert.Equal("Objects", reference.Target.DisplayName); + // Assert.Equal("i=85", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.True(reference.Target.Children); + // }, + // reference => + // { + // Assert.Null(reference.ReferenceTypeId); + // Assert.Null(reference.Direction); + // Assert.Equal("Types", reference.Target.BrowseName); + // Assert.Equal("Types", reference.Target.DisplayName); + // Assert.Equal("i=86", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.True(reference.Target.Children); + // }, + // reference => + // { + // Assert.Null(reference.ReferenceTypeId); + // Assert.Null(reference.Direction); + // Assert.Equal("Views", reference.Target.BrowseName); + // Assert.Equal("Views", reference.Target.DisplayName); + // Assert.Equal("i=87", reference.Target.NodeId); + // Assert.True(reference.Target.Value.IsNull()); + // Assert.False(reference.Target.Children); + // }); } public async Task NodeBrowseFirstInRootTest1Async(CancellationToken ct = default) @@ -150,16 +153,18 @@ public async Task NodeBrowseFirstInRootTest1Async(CancellationToken ct = default Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.True(results.References.Count == 1); - Assert.Collection(results.References, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Objects", reference.Target.BrowseName); - Assert.Equal("Objects", reference.Target.DisplayName); - Assert.Equal("i=85", reference.Target.NodeId); - Assert.True(reference.Target.Children); - }); + + // No order anymore in stack + // Assert.Collection(results.References, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Objects", reference.Target.BrowseName); + // Assert.Equal("Objects", reference.Target.DisplayName); + // Assert.Equal("i=85", reference.Target.NodeId); + // Assert.True(reference.Target.Children); + // }); } public async Task NodeBrowseFirstInRootTest2Async(CancellationToken ct = default) @@ -183,25 +188,26 @@ public async Task NodeBrowseFirstInRootTest2Async(CancellationToken ct = default Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.True(results.References.Count == 2); - Assert.Collection(results.References, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Objects", reference.Target.BrowseName); - Assert.Equal("Objects", reference.Target.DisplayName); - Assert.Equal("i=85", reference.Target.NodeId); - Assert.True(reference.Target.Children); - }, - reference => - { - Assert.Equal("i=35", reference.ReferenceTypeId); - Assert.Equal(BrowseDirection.Forward, reference.Direction); - Assert.Equal("Types", reference.Target.BrowseName); - Assert.Equal("Types", reference.Target.DisplayName); - Assert.Equal("i=86", reference.Target.NodeId); - Assert.True(reference.Target.Children); - }); + // No order anymore in stack + // Assert.Collection(results.References, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Objects", reference.Target.BrowseName); + // Assert.Equal("Objects", reference.Target.DisplayName); + // Assert.Equal("i=85", reference.Target.NodeId); + // Assert.True(reference.Target.Children); + // }, + // reference => + // { + // Assert.Equal("i=35", reference.ReferenceTypeId); + // Assert.Equal(BrowseDirection.Forward, reference.Direction); + // Assert.Equal("Types", reference.Target.BrowseName); + // Assert.Equal("Types", reference.Target.DisplayName); + // Assert.Equal("i=86", reference.Target.NodeId); + // Assert.True(reference.Target.Children); + // }); } public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = default) @@ -805,9 +811,14 @@ public async Task NodeBrowseBoilersObjectsTest2Async(CancellationToken ct = defa Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); - Assert.Collection(results.References, + Assert.Contains(results.References, reference => { + if (reference.ReferenceTypeId != "i=47") + { + return false; + } + Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); @@ -818,9 +829,16 @@ public async Task NodeBrowseBoilersObjectsTest2Async(CancellationToken ct = defa Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.True(reference.Target.Children); - }, + return true; + }); + Assert.Contains(results.References, reference => { + if (reference.ReferenceTypeId != "i=48") + { + return false; + } + Assert.Equal("i=48", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); @@ -831,9 +849,16 @@ public async Task NodeBrowseBoilersObjectsTest2Async(CancellationToken ct = defa Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.True(reference.Target.Children); - }, + return true; + }); + Assert.Contains(results.References, reference => { + if (reference.ReferenceTypeId != "i=35") + { + return false; + } + Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#Boiler+%232", reference.Target.BrowseName); @@ -844,6 +869,7 @@ public async Task NodeBrowseBoilersObjectsTest2Async(CancellationToken ct = defa Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Target.NodeId); Assert.True(reference.Target.Children); + return true; }); } @@ -2217,9 +2243,14 @@ public async Task NodeBrowseStaticArrayVariablesRawModeTestAsync(CancellationTok Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); - Assert.Collection(results.References, + Assert.Contains(results.References, reference => { + if (reference.ReferenceTypeId != "i=47") + { + return false; + } + Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); @@ -2231,9 +2262,16 @@ public async Task NodeBrowseStaticArrayVariablesRawModeTestAsync(CancellationTok Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); - }, - reference => + return true; + }); + Assert.Contains(results.References, + reference => { + if (reference.ReferenceTypeId != "i=48") + { + return false; + } + Assert.Equal("i=48", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); @@ -2245,9 +2283,16 @@ public async Task NodeBrowseStaticArrayVariablesRawModeTestAsync(CancellationTok Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); - }, + return true; + }); + Assert.Contains(results.References, reference => { + if (reference.ReferenceTypeId != "i=35") + { + return false; + } + Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#Boiler+%232", reference.Target.BrowseName); @@ -2260,6 +2305,7 @@ public async Task NodeBrowseStaticArrayVariablesRawModeTestAsync(CancellationTok Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); + return true; }); } diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseStreamTests.cs b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseStreamTests.cs index fb9fa64be3..0cfd1c8db2 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseStreamTests.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseStreamTests.cs @@ -40,18 +40,30 @@ public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert - Assert.Collection(results, + Assert.Contains(results, node => { + if (node.Attributes?.DisplayName != "Root") + { + return false; + } + Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=84", node.SourceId); Assert.Equal("Root", node.Attributes.DisplayName); Assert.Equal("The root of the server address space.", node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Objects") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -61,9 +73,16 @@ public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) Assert.Equal("Objects", reference.Reference.Target.DisplayName); Assert.Equal("i=85", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Types") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -73,9 +92,16 @@ public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) Assert.Equal("Types", reference.Reference.Target.DisplayName); Assert.Equal("i=86", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Views") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -85,6 +111,7 @@ public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) Assert.Equal("Views", reference.Reference.Target.DisplayName); Assert.Equal("i=87", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); + return true; }); } @@ -101,9 +128,14 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert - Assert.Collection(results, + Assert.Contains(results, node => { + if (node.Attributes?.DisplayName != "Root") + { + return false; + } + Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=84", node.SourceId); @@ -111,9 +143,16 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) Assert.Equal("Root", node.Attributes.DisplayName); Assert.Equal("The root of the server address space.", node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Objects") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -123,9 +162,16 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) Assert.Equal("Objects", reference.Reference.Target.DisplayName); Assert.Equal("i=85", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Types") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -135,9 +181,16 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) Assert.Equal("Types", reference.Reference.Target.DisplayName); Assert.Equal("i=86", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.Target.DisplayName != "Views") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); @@ -147,6 +200,7 @@ public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) Assert.Equal("Views", reference.Reference.Target.DisplayName); Assert.Equal("i=87", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); + return true; }); } @@ -163,9 +217,14 @@ public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = defa }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert - Assert.Collection(results, + Assert.Contains(results, node => { + if (node.Reference != null) + { + return false; + } + Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", node.SourceId); @@ -176,9 +235,16 @@ public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = defa Assert.Equal(NodeEventNotifier.SubscribeToEvents, node.Attributes.EventNotifier); Assert.Null(node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.ReferenceTypeId != "i=47") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); @@ -189,9 +255,16 @@ public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = defa Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Reference.Target.NodeId); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.ReferenceTypeId != "i=48") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); @@ -202,9 +275,16 @@ public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = defa Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Reference.Target.NodeId); - }, + return true; + }); + Assert.Contains(results, reference => { + if (reference.Reference?.ReferenceTypeId != "i=35") + { + return false; + } + Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); @@ -215,6 +295,7 @@ public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = defa Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Reference.Target.NodeId); + return true; }); } @@ -906,7 +987,7 @@ public async Task NodeBrowseStaticScalarVariablesTestWithFilter5Async(Cancellati } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); - Assert.Equal(2409, results.Count); + Assert.Equal(2481, results.Count); } public async Task NodeBrowseStaticArrayVariablesTestAsync(CancellationToken ct = default) diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests1.cs b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests1.cs index 5d275c3987..a49ab05b64 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests1.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests1.cs @@ -170,7 +170,7 @@ public async Task ExpandServerObjectTest1Async(CancellationToken ct = default) CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(72, results.Count); + Assert.Equal(76, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -199,7 +199,7 @@ public async Task ExpandServerObjectTest2Async(CancellationToken ct = default) CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(73, results.Count); + Assert.Equal(77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -232,7 +232,7 @@ public async Task ExpandServerObjectTest3Async(CancellationToken ct = default) Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); - Assert.Equal(918, result.Result.OpcNodes.Count); + Assert.Equal(930, result.Result.OpcNodes.Count); } public async Task ExpandServerObjectTest4Async(CancellationToken ct = default) @@ -313,7 +313,7 @@ public async Task ExpandBaseObjectTypeTest1Async(CancellationToken ct = default) CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(76, results.Count); + Assert.Equal(80, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -384,7 +384,7 @@ public async Task ExpandBaseObjectsAndObjectTypesTestAsync(CancellationToken ct CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(76 + 73 + 25, results.Count); + Assert.Equal(80 + 77 + 25, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -442,7 +442,7 @@ public async Task ExpandVariablesAndObjectsTest1Async(CancellationToken ct = def CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(1 + 76 + 73, results.Count); + Assert.Equal(1 + 80 + 77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -474,7 +474,7 @@ public async Task ExpandVariableTypesTest1Async(CancellationToken ct = default) Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.PropertyType + "/PropertyType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); - Assert.Equal(675, result.Result.OpcNodes.Count); + Assert.Equal(687, result.Result.OpcNodes.Count); } public async Task ExpandVariableTypesTest2Async(CancellationToken ct = default) @@ -529,7 +529,7 @@ public async Task ExpandVariableTypesTest3Async(CancellationToken ct = default) Assert.NotNull(r.Result.OpcNodes); total += r.Result.OpcNodes.Count; }); - Assert.Equal(96 + 675, total); + Assert.Equal(96 + 687, total); } public async Task ExpandObjectWithNoObjectsTest1Async(CancellationToken ct = default) diff --git a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests2.cs b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests2.cs index 02da0225a4..8efdb643df 100644 --- a/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests2.cs +++ b/src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests2.cs @@ -285,7 +285,7 @@ public async Task ConfigureFromServerObjectTest1Async(CancellationToken ct = def Id = Opc.Ua.ObjectIds.Server.ToString() } }; - _createCall.Verifiable(Times.Exactly(72)); + _createCall.Verifiable(Times.Exactly(76)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { @@ -295,7 +295,7 @@ public async Task ConfigureFromServerObjectTest1Async(CancellationToken ct = def CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(72, results.Count); + Assert.Equal(76, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -317,7 +317,7 @@ public async Task ConfigureFromServerObjectTest2Async(CancellationToken ct = def Id = Opc.Ua.ObjectIds.Server.ToString() } }; - _createCall.Verifiable(Times.Exactly(73)); + _createCall.Verifiable(Times.Exactly(77)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { @@ -327,7 +327,7 @@ public async Task ConfigureFromServerObjectTest2Async(CancellationToken ct = def CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(73, results.Count); + Assert.Equal(77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -363,7 +363,7 @@ public async Task ConfigureFromServerObjectTest3Async(CancellationToken ct = def Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); - Assert.Equal(918, result.Result.OpcNodes.Count); + Assert.Equal(930, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } @@ -442,7 +442,7 @@ public async Task ConfigureFromBaseObjectTypeTest1Async(CancellationToken ct = d Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; - _createCall.Verifiable(Times.Exactly(76)); + _createCall.Verifiable(Times.Exactly(80)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { @@ -453,7 +453,7 @@ public async Task ConfigureFromBaseObjectTypeTest1Async(CancellationToken ct = d CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(76, results.Count); + Assert.Equal(80, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -519,7 +519,7 @@ public async Task ConfigureFromBaseObjectsAndObjectTypesTestAsync(CancellationTo DataSetFieldId = "data" } }; - _createCall.Verifiable(Times.Exactly(76 + 73 + 25)); + _createCall.Verifiable(Times.Exactly(80 + 77 + 25)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { @@ -530,7 +530,7 @@ public async Task ConfigureFromBaseObjectsAndObjectTypesTestAsync(CancellationTo CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(76 + 73 + 25, results.Count); + Assert.Equal(80 + 77 + 25, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -583,7 +583,7 @@ public async Task ConfigureFromVariablesAndObjectsTest1Async(CancellationToken c new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10218" }, new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; - _createCall.Verifiable(Times.Exactly(1 + 76 + 73)); + _createCall.Verifiable(Times.Exactly(1 + 80 + 77)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { @@ -594,7 +594,7 @@ public async Task ConfigureFromVariablesAndObjectsTest1Async(CancellationToken c CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); - Assert.Equal(1 + 76 + 73, results.Count); + Assert.Equal(1 + 80 + 77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); @@ -629,7 +629,7 @@ public async Task ConfigureFromVariableTypesTest1Async(CancellationToken ct = de Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.PropertyType + "/PropertyType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); - Assert.Equal(675, result.Result.OpcNodes.Count); + Assert.Equal(687, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } @@ -690,7 +690,7 @@ public async Task ConfigureFromVariableTypesTest3Async(CancellationToken ct = de Assert.NotNull(r.Result.OpcNodes); total += r.Result.OpcNodes.Count; }); - Assert.Equal(96 + 675, total); + Assert.Equal(783, total); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Azure.IIoT.OpcUa.Publisher.csproj b/src/Azure.IIoT.OpcUa.Publisher/src/Azure.IIoT.OpcUa.Publisher.csproj index bc3baa8819..7e214c765a 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Azure.IIoT.OpcUa.Publisher.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Azure.IIoT.OpcUa.Publisher.csproj @@ -5,14 +5,14 @@ enable - - - + + + - + - - + + diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherDiagnosticCollector.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherDiagnosticCollector.cs index ce5605a4db..b89a5177ab 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherDiagnosticCollector.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherDiagnosticCollector.cs @@ -15,6 +15,7 @@ namespace Azure.IIoT.OpcUa.Publisher.Services using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; + using System.Diagnostics; /// /// Collects metrics from the writer groups inside the publisher using the .net Meter listener @@ -29,12 +30,10 @@ public sealed class PublisherDiagnosticCollector : IDiagnosticCollector, /// Create collector /// /// - /// /// public PublisherDiagnosticCollector(ILogger logger, - IResourceMonitor? resources = null, TimeProvider? timeProvider = null) + TimeProvider? timeProvider = null) { - _resources = resources; _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; _meterListener = new MeterListener @@ -76,39 +75,17 @@ public bool TryGetDiagnosticsForWriterGroup(string writerGroupId, _meterListener.RecordObservableInstruments(); var duration = _timeProvider.GetUtcNow() - value.IngestionStart; - if (_resources != null) + diagnostic = value with { - var resources = _resources.GetUtilization(TimeSpan.FromSeconds(5)); - - diagnostic = value with - { - IngestionDuration = duration, - OpcEndpointConnected = value.NumberOfConnectedEndpoints != 0, - - MemoryUsedPercentage = - resources.MemoryUsedPercentage, - MemoryUsedInBytes = - resources.MemoryUsedInBytes, - CpuUsedPercentage = - resources.CpuUsedPercentage, - GuaranteedCpuUnits = - resources.SystemResources.GuaranteedCpuUnits, - MaximumCpuUnits = - resources.SystemResources.MaximumCpuUnits, - GuaranteedMemoryInBytes = - resources.SystemResources.GuaranteedMemoryInBytes, - MaximumMemoryInBytes = - resources.SystemResources.MaximumMemoryInBytes - }; - } - else - { - diagnostic = value with - { - IngestionDuration = duration, - OpcEndpointConnected = value.NumberOfConnectedEndpoints != 0, - }; - } + IngestionDuration = duration, + OpcEndpointConnected = value.NumberOfConnectedEndpoints != 0, + MemoryLimitUtilization = _process.MemoryLimitUtilization, + CpuLimitUtilization = _process.CpuLimitUtilization, + CpuRequestUtilization = _process.CpuRequestUtilization, + CpuUsedPercentage = _process.CpuUsedPercentage, + MemoryUsedPercentage = _process.MemoryUsedPercentage, + MemoryUsedInBytes = _process.MemoryUsedInBytes + }; return true; } diagnostic = default; @@ -124,41 +101,19 @@ public bool TryGetDiagnosticsForWriterGroup(string writerGroupId, foreach (var (writerGroupId, info) in _diagnostics) { var duration = now - info.IngestionStart; - - if (_resources == null) - { - yield return (writerGroupId, info with - { - Timestamp = now, - IngestionDuration = duration, - OpcEndpointConnected = info.NumberOfConnectedEndpoints != 0, - }); - } - else + yield return (writerGroupId, info with { - var resources = _resources.GetUtilization(TimeSpan.FromSeconds(5)); - yield return (writerGroupId, info with - { - Timestamp = now, - IngestionDuration = duration, - OpcEndpointConnected = info.NumberOfConnectedEndpoints != 0, + Timestamp = now, + IngestionDuration = duration, + OpcEndpointConnected = info.NumberOfConnectedEndpoints != 0, - MemoryUsedPercentage = - resources.MemoryUsedPercentage, - MemoryUsedInBytes = - resources.MemoryUsedInBytes, - CpuUsedPercentage = - resources.CpuUsedPercentage, - GuaranteedCpuUnits = - resources.SystemResources.GuaranteedCpuUnits, - MaximumCpuUnits = - resources.SystemResources.MaximumCpuUnits, - GuaranteedMemoryInBytes = - resources.SystemResources.GuaranteedMemoryInBytes, - MaximumMemoryInBytes = - resources.SystemResources.MaximumMemoryInBytes - }); - } + MemoryLimitUtilization = _process.MemoryLimitUtilization, + CpuLimitUtilization = _process.CpuLimitUtilization, + CpuRequestUtilization = _process.CpuRequestUtilization, + CpuUsedPercentage = _process.CpuUsedPercentage, + MemoryUsedPercentage = _process.MemoryUsedPercentage, + MemoryUsedInBytes = _process.MemoryUsedInBytes + }); } } @@ -210,16 +165,23 @@ private void OnInstrumentPublished(Instrument instrument, MeterListener listener private void OnMeasurementRecorded(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state) { - if (_bindings.TryGetValue(instrument.Name, out var binding) && - TryGetIds(tags, out var writerGroupId, out var writerGroupName) && - _diagnostics.TryGetValue(writerGroupId, out var diag)) + if (_bindings.TryGetValue(instrument.Name, out var binding)) { - if (writerGroupName != null) + if (TryGetIds(tags, out var writerGroupId, out var writerGroupName) && + _diagnostics.TryGetValue(writerGroupId, out var diag)) { - diag.WriterGroupName = writerGroupName; + if (writerGroupName != null) + { + diag.WriterGroupName = writerGroupName; + } + binding(diag, measurement!); + } + else + { + binding(_process, measurement!); } - binding(diag, measurement!); } + static bool TryGetIds(ReadOnlySpan> tags, [NotNullWhen(true)] out string? writerGroupId, out string? writerGroupName) { @@ -251,9 +213,9 @@ static bool TryGetIds(ReadOnlySpan> tags, } private readonly MeterListener _meterListener; - private readonly IResourceMonitor? _resources; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; + private readonly WriterGroupDiagnosticModel _process = new(); private readonly ConcurrentDictionary _diagnostics = new(); // TODO: Split this per measurement type to avoid boxing @@ -372,9 +334,22 @@ static bool TryGetIds(ReadOnlySpan> tags, ["iiot_edge_publisher_messages"] = (d, i) => d.OutgressIoTMessageCount = (long)i, ["iiot_edge_publisher_message_send_failures"] = - (d, i) => d.OutgressIoTMessageFailedCount = (long)i + (d, i) => d.OutgressIoTMessageFailedCount = (long)i, + + ["container.cpu.limit.utilization"] = + (d, i) => d.CpuLimitUtilization = (double)i, + ["container.cpu.request.utilization"] = + (d, i) => d.CpuRequestUtilization = (double)i, + ["process.cpu.utilization"] = + (d, i) => d.CpuUsedPercentage = (double)i, + ["container.memory.limit.utilization"] = + (d, i) => d.MemoryLimitUtilization = (double)i, + ["dotnet.process.memory.virtual.utilization"] = + (d, i) => d.MemoryUsedPercentage = (double)i, + ["dotnet.process.memory.working_set"] = + (d, i) => d.MemoryUsedInBytes = (ulong)(long)i, - // ... Add here more items if needed + // ... Add here more items if needed }; } } diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs index b49436410e..1a68a79360 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs @@ -592,23 +592,20 @@ static string Format(long changes, long lastMinute, double s) if (includeResourceInfo) { sb = sb - .Append(" # Cpu/Memory max : ") - .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n2}", info.MaximumCpuUnits) + .Append(" # Cpu (%limit/%req/%used) : ") + .AppendFormat(CultureInfo.CurrentCulture, "{0,14:p2}", info.CpuLimitUtilization) .Append(" | ") - .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.MaximumMemoryInBytes / 1000d) - .AppendLine(" KB") - .Append(" # Cpu/Memory available : ") - .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n2}", info.GuaranteedCpuUnits) - .Append(" | ") - .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.GuaranteedMemoryInBytes / 1000d) - .AppendLine(" KB") - .Append(" # Cpu/Memory % used (window/total) : ") - .AppendFormat(CultureInfo.CurrentCulture, "{0,14:p2}", info.CpuUsedPercentage) + .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.CpuRequestUtilization) + .Append(" (") + .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.CpuUsedPercentage) + .AppendLine(")") + .Append(" # Memory (%limit/%used/total used) : ") + .AppendFormat(CultureInfo.CurrentCulture, "{0,14:p2}", info.MemoryLimitUtilization) .Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.MemoryUsedPercentage) .Append(" (") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.MemoryUsedInBytes / 1000d) - .AppendLine(" kb)") + .AppendLine(" KB)") ; } return sb diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackModelsEx.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackModelsEx.cs index f0ca503907..fc8e2276a2 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackModelsEx.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackModelsEx.cs @@ -325,8 +325,10 @@ public static async ValueTask ToUserIdentityAsync( { using var users = configuration.SecurityConfiguration .TrustedUserCertificates.OpenStore(); +#pragma warning disable CS0618 // Type or member is obsolete /* TODO add rsa/ecc*/ var userCertWithPrivateKey = await users.LoadPrivateKey( thumbprint, subjectName, passCode).ConfigureAwait(false); +#pragma warning restore CS0618 // Type or member is obsolete if (userCertWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaApplication.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaApplication.cs index 12def0fe02..77432e403c 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaApplication.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaApplication.cs @@ -527,9 +527,8 @@ await UpdateFromExistingCertificateAsync( ownCertificate.Subject, ownCertificate.Thumbprint); } - var hasAppCertificate = await appInstance.CheckApplicationInstanceCertificate(true, - CertificateFactory.DefaultKeySize, - CertificateFactory.DefaultLifeTime).ConfigureAwait(false); + var hasAppCertificate = + await appInstance.CheckApplicationInstanceCertificates(true).ConfigureAwait(false); if (!hasAppCertificate || appConfig.SecurityConfiguration.ApplicationCertificate.Certificate == null) { diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Subscription.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Subscription.cs index b529370a77..dc89b00506 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Subscription.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Subscription.cs @@ -432,7 +432,6 @@ private async Task EnsureSessionIsReadyForSubscriptionsAsync(OpcUaSession sessio /// private void RescheduleSynchronization(TimeSpan delay) { - Debug.Assert(delay <= Timeout.InfiniteTimeSpan, delay.ToString()); Debug.Assert(_subscriptionLock.CurrentCount == 0, "Must be locked"); if (delay == Timeout.InfiniteTimeSpan) diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.cs index e0de8c1b0a..d3fec9652f 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.cs @@ -302,6 +302,54 @@ public void Dispose() return $"{_sessionName} [state:{_lastState}|refs:{_refCount}]"; } + /// + public override async Task RecreateAsync(ISession sessionTemplate, + ITransportWaitingConnection connection, CancellationToken ct) + { + // + // We do not support recreation of sessions create a new session from scratch. + // Then we add the desired subscriptions to the new session. + // + if(connection != null) + { + _logger.LogInformation( + "{Client}: RECREATE: Creating new session with new waiting connection.", this); + return await CreateAsync(_configuration, connection, sessionTemplate.ConfiguredEndpoint, + true, false, _sessionName, (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, + sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); + } + _logger.LogInformation("{Client}: RECREATE: Creating new session without connection.", this); + return await CreateAsync(_configuration, _reverseConnectManager, + sessionTemplate.ConfiguredEndpoint, true, false, _sessionName, + (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, + sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); + } + + /// + public override async Task RecreateAsync(ISession sessionTemplate, + ITransportChannel? transportChannel, CancellationToken ct) + { + // + // We do not support recreation of sessions therefore we close + // and reopen the transport channel as a regular creation operation. + // Then we add the desired subscriptions to the new session + // + if (transportChannel != null) + { + _logger.LogInformation( + "{Client}: RECREATE: Closing channel and creating new session.", this); + transportChannel.Dispose(); + } + else + { + _logger.LogInformation("{Client}: RECREATE: Creating new session.", this); + + } + return await CreateAsync(_configuration, sessionTemplate.ConfiguredEndpoint, + true, false, _sessionName, (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, + sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); + } + /// public override Session Create(ISessionChannel channel, ApplicationConfiguration configuration, ConfiguredEndpoint endpoint) @@ -921,22 +969,25 @@ private async Task ManageSessionStateMachineAsync(CancellationToken ct) { case SessionState.Connected: // only valid when connected. Debug.Assert(_reconnectHandler.State == SessionReconnectHandler.ReconnectState.Ready); + _logger.LogInformation("{Client}: Reconnecting session {Session} due to {Reason}...", + this, _sessionName, (context is ServiceResult sr) ? "error " + sr : "RESET"); // Ensure no more access to the session through reader locks Debug.Assert(_disconnectLock == null); _disconnectLock = await _lock.WriterLockAsync(ct); - - _logger.LogInformation("{Client}: Reconnecting session {Session} due to {Reason}...", - this, _sessionName, (context is ServiceResult sr) ? "error " + sr : "RESET"); + _logger.LogInformation("{Client}: Begin reconnecting session {Session}...", + this, _sessionName); Debug.Assert(_session != null); var state = _reconnectHandler.BeginReconnect(_session, _reverseConnectManager, GetMinReconnectPeriod(), (sender, evt) => { - if (ReferenceEquals(sender, _reconnectHandler)) + if (!ReferenceEquals(sender, _reconnectHandler)) { - TriggerConnectionEvent(ConnectionEvent.ReconnectComplete, - _reconnectHandler.Session); + _logger.LogError("{Client}: Reconnect handler mismatch.", this); + return; } + TriggerConnectionEvent(ConnectionEvent.ReconnectComplete, + _reconnectHandler.Session); }); // Save session while reconnecting. @@ -962,6 +1013,8 @@ private async Task ManageSessionStateMachineAsync(CancellationToken ct) switch (currentSessionState) { case SessionState.Reconnecting: + _logger.LogInformation("{Client}: Completed reconnecting session {Session}...", + this, _sessionName); // // Behavior of the reconnect handler is as follows: // 1) newSession == null @@ -999,12 +1052,11 @@ private async Task ManageSessionStateMachineAsync(CancellationToken ct) Debug.Assert(_disconnectLock != null); _disconnectLock.Dispose(); _disconnectLock = null; - - await SyncAsync(ct).ConfigureAwait(false); - _reconnectRequired = 0; reconnectPeriod = GetMinReconnectPeriod(); currentSessionState = SessionState.Connected; + + await SyncAsync(ct).ConfigureAwait(false); NotifySubscriptions(_session, false); break; @@ -1280,7 +1332,7 @@ private async ValueTask TryConnectAsync(CancellationToken ct) _configuration).ConfigureAwait(false); var identityPolicy = endpoint.Description.FindUserTokenPolicy( - userIdentity.TokenType, userIdentity.IssuedTokenType); + userIdentity.TokenType, userIdentity.IssuedTokenType, endpointDescription.SecurityPolicyUri); if (identityPolicy == null) { _logger.LogWarning( @@ -1317,7 +1369,7 @@ private async ValueTask TryConnectAsync(CancellationToken ct) Debug.Assert(session != null); session.RenewUserIdentity += (_, _) => userIdentity; - // Assign the createdSubscriptions session + // Assign the session var isNew = await UpdateSessionAsync(session).ConfigureAwait(false); Debug.Assert(isNew); _logger.LogInformation( @@ -1347,22 +1399,31 @@ private async ValueTask TryConnectAsync(CancellationToken ct) /// internal void Session_HandlePublishError(ISession session, PublishErrorEventArgs e) { - if (_disconnectLock == null && session == _session) + if (!ReferenceEquals(session, _session)) { - switch (e.Status.Code) + if (_session != null) { - case StatusCodes.BadSessionIdInvalid: - case StatusCodes.BadSecureChannelClosed: - case StatusCodes.BadSessionClosed: - case StatusCodes.BadConnectionClosed: - case StatusCodes.BadNoCommunication: - TriggerReconnect(e.Status, "Publish"); - return; - default: - _logger.LogInformation("{Client}: Publish error: {Error}...", - this, e.Status); - break; + _logger.LogError( + "{Client}: Received publish error for different session {Session}!", + this, session); } + return; + } + switch (e.Status.Code) + { + case StatusCodes.BadSessionIdInvalid: + case StatusCodes.BadSecureChannelClosed: + case StatusCodes.BadSessionClosed: + case StatusCodes.BadConnectionClosed: + case StatusCodes.BadServerHalted: + case StatusCodes.BadNotConnected: + case StatusCodes.BadNoCommunication: + TriggerReconnect(e.Status, "Publish"); + return; + default: + _logger.LogInformation("{Client}: Publish error: {Error}...", + this, e.Status); + break; } } @@ -1441,6 +1502,12 @@ internal void Session_KeepAlive(ISession session, KeepAliveEventArgs e) // check for events from discarded sessions. if (!ReferenceEquals(session, _session)) { + if (_session != null) + { + _logger.LogError( + "{Client}: Received keep alive for different session {Session}!", + this, session); + } return; } // start reconnect sequence on communication error. diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSession.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSession.cs index e980460afe..d7a89ed235 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSession.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSession.cs @@ -135,7 +135,9 @@ private OpcUaSession(OpcUaSession session, /// protected override void Dispose(bool disposing) { + // Disposes all contained subscriptions base.Dispose(disposing); + if (disposing && !_disposed) { var sessionName = SessionName; diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscription.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscription.cs index 4c8ba5cc12..6e05c66bff 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscription.cs +++ b/src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscription.cs @@ -390,7 +390,7 @@ public async ValueTask DisposeAsync() // // Called by the management thread to "close" the subscription and dispose it. // Note that the session calls dispose again or when it is closed or - // reconnected. This her is called when the management thread determines + // reconnected. This here is called when the management thread determines // to gracefully close the subscription. // try @@ -2424,7 +2424,6 @@ private void OnKeepAliveMissing(object? state) /// private void OnPublishStatusChange(Subscription subscription, PublishStateChangedEventArgs e) { - ObjectDisposedException.ThrowIf(_disposed, this); if (_disposed) { return; @@ -2478,11 +2477,6 @@ private void OnPublishStatusChange(Subscription subscription, PublishStateChange /// private void OnStateChange(Subscription subscription, SubscriptionStateChangedEventArgs e) { - ObjectDisposedException.ThrowIf(_disposed, this); - if (_disposed) - { - return; - } if (e.Status.HasFlag(SubscriptionChangeMask.Created)) { _logger.LogDebug("Subscription {Subscription} created.", this); diff --git a/src/Azure.IIoT.OpcUa.Publisher/tests/Azure.IIoT.OpcUa.Publisher.Tests.csproj b/src/Azure.IIoT.OpcUa.Publisher/tests/Azure.IIoT.OpcUa.Publisher.Tests.csproj index 49a9a49328..1170d216f6 100644 --- a/src/Azure.IIoT.OpcUa.Publisher/tests/Azure.IIoT.OpcUa.Publisher.Tests.csproj +++ b/src/Azure.IIoT.OpcUa.Publisher/tests/Azure.IIoT.OpcUa.Publisher.Tests.csproj @@ -5,15 +5,15 @@ - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Azure.IIoT.OpcUa/src/Azure.IIoT.OpcUa.csproj b/src/Azure.IIoT.OpcUa/src/Azure.IIoT.OpcUa.csproj index dad3742fc4..fbfe2c5180 100644 --- a/src/Azure.IIoT.OpcUa/src/Azure.IIoT.OpcUa.csproj +++ b/src/Azure.IIoT.OpcUa/src/Azure.IIoT.OpcUa.csproj @@ -7,10 +7,10 @@ - + - - + + diff --git a/src/Azure.IIoT.OpcUa/tests/Azure.IIoT.OpcUa.Tests.csproj b/src/Azure.IIoT.OpcUa/tests/Azure.IIoT.OpcUa.Tests.csproj index a83576cc99..f0b65f2d28 100644 --- a/src/Azure.IIoT.OpcUa/tests/Azure.IIoT.OpcUa.Tests.csproj +++ b/src/Azure.IIoT.OpcUa/tests/Azure.IIoT.OpcUa.Tests.csproj @@ -3,19 +3,19 @@ net9.0 - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/version.json b/version.json index 7927421fcb..582adbcc45 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "2.9.14-rc.{height}", + "version": "2.9.12-rc.{height}", "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/heads/release/\\d+\\.\\d+\\.\\d+"