Apply code style formatting and restore partial modifiers on Avalonia views
Linter/formatter pass across the full codebase. Restores required partial keyword on AXAML code-behind classes that the formatter incorrectly removed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,23 +16,54 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
{
|
||||
Hierarchy = new List<GalaxyObjectInfo>
|
||||
{
|
||||
new GalaxyObjectInfo { GobjectId = 1, TagName = "TestObj", BrowseName = "TestObj", ParentGobjectId = 0, IsArea = false }
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", BrowseName = "TestObj", ParentGobjectId = 0, IsArea = false
|
||||
}
|
||||
},
|
||||
Attributes = new List<GalaxyAttributeInfo>
|
||||
{
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "FreeAttr", FullTagReference = "TestObj.FreeAttr", MxDataType = 5, SecurityClassification = 0 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "OperateAttr", FullTagReference = "TestObj.OperateAttr", MxDataType = 5, SecurityClassification = 1 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "SecuredAttr", FullTagReference = "TestObj.SecuredAttr", MxDataType = 5, SecurityClassification = 2 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "VerifiedAttr", FullTagReference = "TestObj.VerifiedAttr", MxDataType = 5, SecurityClassification = 3 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "TuneAttr", FullTagReference = "TestObj.TuneAttr", MxDataType = 5, SecurityClassification = 4 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "ConfigAttr", FullTagReference = "TestObj.ConfigAttr", MxDataType = 5, SecurityClassification = 5 },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "ViewOnlyAttr", FullTagReference = "TestObj.ViewOnlyAttr", MxDataType = 5, SecurityClassification = 6 },
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "FreeAttr",
|
||||
FullTagReference = "TestObj.FreeAttr", MxDataType = 5, SecurityClassification = 0
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "OperateAttr",
|
||||
FullTagReference = "TestObj.OperateAttr", MxDataType = 5, SecurityClassification = 1
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "SecuredAttr",
|
||||
FullTagReference = "TestObj.SecuredAttr", MxDataType = 5, SecurityClassification = 2
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "VerifiedAttr",
|
||||
FullTagReference = "TestObj.VerifiedAttr", MxDataType = 5, SecurityClassification = 3
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "TuneAttr",
|
||||
FullTagReference = "TestObj.TuneAttr", MxDataType = 5, SecurityClassification = 4
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "ConfigAttr",
|
||||
FullTagReference = "TestObj.ConfigAttr", MxDataType = 5, SecurityClassification = 5
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "ViewOnlyAttr",
|
||||
FullTagReference = "TestObj.ViewOnlyAttr", MxDataType = 5, SecurityClassification = 6
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that writable Galaxy security classifications publish OPC UA variables with read-write access.
|
||||
/// Verifies that writable Galaxy security classifications publish OPC UA variables with read-write access.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ReadWriteAttribute_HasCurrentReadOrWrite_AccessLevel()
|
||||
@@ -52,11 +83,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
$"{attrName} should be ReadWrite");
|
||||
}
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that secured and view-only Galaxy classifications publish OPC UA variables with read-only access.
|
||||
/// Verifies that secured and view-only Galaxy classifications publish OPC UA variables with read-only access.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ReadOnlyAttribute_HasCurrentRead_AccessLevel()
|
||||
@@ -76,11 +110,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
$"{attrName} should be ReadOnly");
|
||||
}
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the bridge rejects writes against Galaxy attributes whose security classification is read-only.
|
||||
/// Verifies that the bridge rejects writes against Galaxy attributes whose security classification is read-only.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Write_ToReadOnlyAttribute_IsRejected()
|
||||
@@ -96,17 +133,20 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var result = client.Write(nodeId, "test");
|
||||
StatusCode.IsBad(result).ShouldBeTrue("Write to ReadOnly attribute should be rejected");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that writes succeed for Galaxy attributes whose security classification permits operator updates.
|
||||
/// Verifies that writes succeed for Galaxy attributes whose security classification permits operator updates.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Write_ToReadWriteAttribute_Succeeds()
|
||||
{
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(mxClient: mxClient, repo: CreateRepoWithSecurityLevels());
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(mxClient, CreateRepoWithSecurityLevels());
|
||||
await fixture.InitializeAsync();
|
||||
try
|
||||
{
|
||||
@@ -117,7 +157,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var result = client.Write(nodeId, "test");
|
||||
StatusCode.IsGood(result).ShouldBeTrue("Write to ReadWrite attribute should succeed");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||
@@ -11,13 +9,13 @@ using ZB.MOM.WW.LmxOpcUa.Tests.Helpers;
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests verifying dynamic address space changes via a real OPC UA client.
|
||||
/// Tests browse, subscribe, add/remove nodes at runtime, and subscription quality changes.
|
||||
/// Integration tests verifying dynamic address space changes via a real OPC UA client.
|
||||
/// Tests browse, subscribe, add/remove nodes at runtime, and subscription quality changes.
|
||||
/// </summary>
|
||||
public class AddressSpaceRebuildTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Confirms that the initial browsed hierarchy matches the seeded Galaxy model.
|
||||
/// Confirms that the initial browsed hierarchy matches the seeded Galaxy model.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Browse_ReturnsInitialHierarchy()
|
||||
@@ -42,7 +40,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that adding a Galaxy object and rebuilding exposes the new node to OPC UA clients.
|
||||
/// Confirms that adding a Galaxy object and rebuilding exposes the new node to OPC UA clients.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Browse_AfterAddingObject_NewNodeAppears()
|
||||
@@ -88,7 +86,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that removing a Galaxy object and rebuilding removes the node from the OPC UA hierarchy.
|
||||
/// Confirms that removing a Galaxy object and rebuilding removes the node from the OPC UA hierarchy.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Browse_AfterRemovingObject_NodeDisappears()
|
||||
@@ -124,7 +122,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that subscriptions on deleted nodes receive a bad-quality notification after rebuild.
|
||||
/// Confirms that subscriptions on deleted nodes receive a bad-quality notification after rebuild.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Subscribe_RemovedNode_PublishesBadQuality()
|
||||
@@ -138,7 +136,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
// Subscribe to an attribute that will be removed
|
||||
var nodeId = client.MakeNodeId("MESReceiver_001.MoveInBatchID");
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, intervalMs: 100);
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, 100);
|
||||
|
||||
// Collect notifications
|
||||
var notifications = new List<MonitoredItemNotification>();
|
||||
@@ -173,7 +171,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that subscriptions on surviving nodes continue to work after a partial rebuild.
|
||||
/// Confirms that subscriptions on surviving nodes continue to work after a partial rebuild.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Subscribe_SurvivingNode_StillWorksAfterRebuild()
|
||||
@@ -187,7 +185,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
// Subscribe to an attribute that will survive the rebuild
|
||||
var nodeId = client.MakeNodeId("TestMachine_001.MachineID");
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, intervalMs: 100);
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, 100);
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
@@ -212,7 +210,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that adding a Galaxy attribute and rebuilding exposes a new OPC UA variable.
|
||||
/// Confirms that adding a Galaxy attribute and rebuilding exposes a new OPC UA variable.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Browse_AddAttribute_NewVariableAppears()
|
||||
@@ -249,7 +247,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that removing a Galaxy attribute and rebuilding removes the OPC UA variable.
|
||||
/// Confirms that removing a Galaxy attribute and rebuilding removes the OPC UA variable.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Browse_RemoveAttribute_VariableDisappears()
|
||||
@@ -266,8 +264,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
initialChildren.ShouldContain(c => c.Name == "MachineCode");
|
||||
|
||||
// Remove MachineCode attribute
|
||||
fixture.GalaxyRepository!.Attributes.RemoveAll(
|
||||
a => a.TagName == "TestMachine_001" && a.AttributeName == "MachineCode");
|
||||
fixture.GalaxyRepository!.Attributes.RemoveAll(a =>
|
||||
a.TagName == "TestMachine_001" && a.AttributeName == "MachineCode");
|
||||
|
||||
fixture.Service.TriggerRebuild();
|
||||
await Task.Delay(500);
|
||||
@@ -282,7 +280,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that rebuilds preserve subscription bookkeeping for nodes that survive the metadata refresh.
|
||||
/// Confirms that rebuilds preserve subscription bookkeeping for nodes that survive the metadata refresh.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Rebuild_PreservesSubscriptionBookkeeping_ForSurvivingNodes()
|
||||
@@ -312,7 +310,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that transferred monitored items recreate MXAccess subscriptions when the service has no local subscription state.
|
||||
/// Confirms that transferred monitored items recreate MXAccess subscriptions when the service has no local
|
||||
/// subscription state.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task TransferSubscriptions_RestoresMxAccessSubscriptionState_WhenLocalStateIsMissing()
|
||||
@@ -347,7 +346,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that transferring monitored items does not double-count subscriptions already tracked in memory.
|
||||
/// Confirms that transferring monitored items does not double-count subscriptions already tracked in memory.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task TransferSubscriptions_DoesNotDoubleCount_WhenSubscriptionAlreadyTracked()
|
||||
@@ -380,4 +379,4 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||
@@ -11,12 +10,12 @@ using ZB.MOM.WW.LmxOpcUa.Tests.Helpers;
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies OPC UA indexed array writes against the bridge's whole-array runtime update behavior.
|
||||
/// Verifies OPC UA indexed array writes against the bridge's whole-array runtime update behavior.
|
||||
/// </summary>
|
||||
public class ArrayWriteTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Confirms that writing a single array element updates the correct slot while preserving the rest of the array.
|
||||
/// Confirms that writing a single array element updates the correct slot while preserving the rest of the array.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Write_SingleArrayElement_UpdatesWholeArrayValue()
|
||||
@@ -39,7 +38,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
before.Length.ShouldBe(50);
|
||||
before[1].ShouldBe("PART-01");
|
||||
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, indexRange: "1");
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, "1");
|
||||
StatusCode.IsGood(status).ShouldBe(true);
|
||||
|
||||
var after = client.Read(nodeId).Value as string[];
|
||||
@@ -56,7 +55,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that array nodes use bracketless OPC UA node identifiers while still exposing one-dimensional array metadata.
|
||||
/// Confirms that array nodes use bracketless OPC UA node identifiers while still exposing one-dimensional array
|
||||
/// metadata.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ArrayNode_UsesBracketlessNodeId_AndPublishesArrayDimensions()
|
||||
@@ -91,7 +91,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that a null runtime value for a statically sized array is exposed as a typed fixed-length array.
|
||||
/// Confirms that a null runtime value for a statically sized array is exposed as a typed fixed-length array.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Read_NullStaticArray_ReturnsDefaultTypedArray()
|
||||
@@ -122,7 +122,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that an indexed write also updates the published OPC UA value seen by subscribed clients.
|
||||
/// Confirms that an indexed write also updates the published OPC UA value seen by subscribed clients.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Write_SingleArrayElement_PublishesUpdatedArrayToSubscribers()
|
||||
@@ -139,7 +139,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
var nodeId = client.MakeNodeId("MESReceiver_001.MoveInPartNumbers");
|
||||
var notifications = new ConcurrentBag<MonitoredItemNotification>();
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, intervalMs: 100);
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, 100);
|
||||
item.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification notification)
|
||||
@@ -148,7 +148,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, indexRange: "1");
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, "1");
|
||||
StatusCode.IsGood(status).ShouldBe(true);
|
||||
|
||||
await Task.Delay(1000);
|
||||
@@ -169,7 +169,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that indexed writes succeed even when the current runtime array value is null.
|
||||
/// Confirms that indexed writes succeed even when the current runtime array value is null.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Write_SingleArrayElement_WhenCurrentArrayIsNull_UsesDefaultArray()
|
||||
@@ -184,7 +184,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
await client.ConnectAsync(fixture.EndpointUrl);
|
||||
|
||||
var nodeId = client.MakeNodeId("MESReceiver_001.MoveInPartNumbers");
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, indexRange: "1");
|
||||
var status = client.Write(nodeId, new[] { "UPDATED-PART" }, "1");
|
||||
StatusCode.IsGood(status).ShouldBe(true);
|
||||
|
||||
var after = client.Read(nodeId).Value as string[];
|
||||
@@ -200,4 +200,4 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,19 +16,34 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
{
|
||||
Hierarchy = new List<GalaxyObjectInfo>
|
||||
{
|
||||
new GalaxyObjectInfo { GobjectId = 1, TagName = "TestObj", BrowseName = "TestObj", ParentGobjectId = 0, IsArea = false }
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", BrowseName = "TestObj", ParentGobjectId = 0, IsArea = false
|
||||
}
|
||||
},
|
||||
Attributes = new List<GalaxyAttributeInfo>
|
||||
{
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "HistorizedAttr", FullTagReference = "TestObj.HistorizedAttr", MxDataType = 2, IsHistorized = true },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "NormalAttr", FullTagReference = "TestObj.NormalAttr", MxDataType = 5, IsHistorized = false },
|
||||
new GalaxyAttributeInfo { GobjectId = 1, TagName = "TestObj", AttributeName = "AlarmAttr", FullTagReference = "TestObj.AlarmAttr", MxDataType = 1, IsAlarm = true },
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "HistorizedAttr",
|
||||
FullTagReference = "TestObj.HistorizedAttr", MxDataType = 2, IsHistorized = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "NormalAttr",
|
||||
FullTagReference = "TestObj.NormalAttr", MxDataType = 5, IsHistorized = false
|
||||
},
|
||||
new()
|
||||
{
|
||||
GobjectId = 1, TagName = "TestObj", AttributeName = "AlarmAttr",
|
||||
FullTagReference = "TestObj.AlarmAttr", MxDataType = 1, IsAlarm = true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that historized Galaxy attributes advertise OPC UA historizing support and history-read access.
|
||||
/// Verifies that historized Galaxy attributes advertise OPC UA historizing support and history-read access.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task HistorizedAttribute_HasHistorizingTrue_AndHistoryReadAccess()
|
||||
@@ -49,11 +64,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
(level & AccessLevels.HistoryRead).ShouldBe(AccessLevels.HistoryRead,
|
||||
"HistoryRead bit should be set");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that non-historized Galaxy attributes do not claim OPC UA history support.
|
||||
/// Verifies that non-historized Galaxy attributes do not claim OPC UA history support.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task NormalAttribute_HasHistorizingFalse_AndNoHistoryReadAccess()
|
||||
@@ -71,10 +89,13 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
var accessLevel = client.ReadAttribute(nodeId, Attributes.AccessLevel);
|
||||
var level = (byte)accessLevel.Value;
|
||||
(level & AccessLevels.HistoryRead).ShouldBe((byte)0,
|
||||
(level & AccessLevels.HistoryRead).ShouldBe(0,
|
||||
"HistoryRead bit should not be set");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Opc.Ua;
|
||||
@@ -12,7 +11,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
public class IncrementalSyncTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies that adding a new Galaxy object and attribute causes the corresponding OPC UA node subtree to appear after sync.
|
||||
/// Verifies that adding a new Galaxy object and attribute causes the corresponding OPC UA node subtree to appear after
|
||||
/// sync.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Sync_AddObject_NewNodeAppears()
|
||||
@@ -56,11 +56,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
// Original object should still be there
|
||||
children.Select(c => c.Name).ShouldContain("TestMachine_001");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that removing a Galaxy object tears down the corresponding OPC UA subtree without affecting siblings.
|
||||
/// Verifies that removing a Galaxy object tears down the corresponding OPC UA subtree without affecting siblings.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Sync_RemoveObject_NodeDisappears()
|
||||
@@ -90,11 +93,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
// DelmiaReceiver should still be there
|
||||
children.Select(c => c.Name).ShouldContain("DelmiaReceiver");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that adding a Galaxy attribute creates a new OPC UA variable during incremental rebuild.
|
||||
/// Verifies that adding a Galaxy attribute creates a new OPC UA variable during incremental rebuild.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Sync_AddAttribute_NewVariableAppears()
|
||||
@@ -120,17 +126,20 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
children.Select(c => c.Name).ShouldContain("NewAttr");
|
||||
children.Select(c => c.Name).ShouldContain("MachineID");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that subscriptions on unchanged objects continue receiving data after unrelated subtree rebuilds.
|
||||
/// Verifies that subscriptions on unchanged objects continue receiving data after unrelated subtree rebuilds.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Sync_UnchangedObject_SubscriptionSurvives()
|
||||
{
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(mxClient: mxClient);
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(mxClient);
|
||||
await fixture.InitializeAsync();
|
||||
try
|
||||
{
|
||||
@@ -139,7 +148,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
// Subscribe to MachineID on TestMachine_001
|
||||
var nodeId = client.MakeNodeId("TestMachine_001.MachineID");
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, 250);
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId);
|
||||
await Task.Delay(500);
|
||||
|
||||
// Modify a DIFFERENT object (MESReceiver) — TestMachine_001 should be unaffected
|
||||
@@ -157,11 +166,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var lastValue = (item.LastValue as MonitoredItemNotification)?.Value?.Value;
|
||||
lastValue.ShouldBe("UPDATED");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a rebuild request with no repository changes leaves the published namespace intact.
|
||||
/// Verifies that a rebuild request with no repository changes leaves the published namespace intact.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Sync_NoChanges_NothingHappens()
|
||||
@@ -181,7 +193,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var children = await client.BrowseAsync(client.MakeNodeId("TestMachine_001"));
|
||||
children.Select(c => c.Name).ShouldContain("MachineID");
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,20 +7,19 @@ using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||
using ZB.MOM.WW.LmxOpcUa.Tests.Helpers;
|
||||
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
{
|
||||
/// <summary>
|
||||
/// Integration tests verifying multi-client subscription sync and concurrent operations.
|
||||
/// Integration tests verifying multi-client subscription sync and concurrent operations.
|
||||
/// </summary>
|
||||
public class MultiClientTests
|
||||
{
|
||||
// ── Subscription Sync ─────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that multiple OPC UA clients subscribed to the same tag all receive the same runtime update.
|
||||
/// Confirms that multiple OPC UA clients subscribed to the same tag all receive the same runtime update.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task MultipleClients_SubscribeToSameTag_AllReceiveDataChanges()
|
||||
@@ -33,14 +32,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var notifications = new ConcurrentDictionary<int, List<MonitoredItemNotification>>();
|
||||
var subscriptions = new List<Subscription>();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var client = new OpcUaTestClient();
|
||||
await client.ConnectAsync(fixture.EndpointUrl);
|
||||
clients.Add(client);
|
||||
|
||||
var nodeId = client.MakeNodeId("TestMachine_001.MachineID");
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, intervalMs: 100);
|
||||
var (sub, item) = await client.SubscribeAsync(nodeId, 100);
|
||||
subscriptions.Add(sub);
|
||||
|
||||
var clientIndex = i;
|
||||
@@ -55,14 +54,12 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
await Task.Delay(500); // let subscriptions settle
|
||||
|
||||
// Simulate data change
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "MACHINE_42", 192);
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "MACHINE_42");
|
||||
await Task.Delay(1000); // let publish cycle deliver
|
||||
|
||||
// All 3 clients should have received the notification
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (var i = 0; i < 3; i++)
|
||||
notifications[i].Count.ShouldBeGreaterThan(0, $"Client {i} did not receive notification");
|
||||
}
|
||||
|
||||
foreach (var sub in subscriptions) await sub.DeleteAsync(true);
|
||||
foreach (var c in clients) c.Dispose();
|
||||
@@ -74,7 +71,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that one client disconnecting does not stop remaining clients from receiving updates.
|
||||
/// Confirms that one client disconnecting does not stop remaining clients from receiving updates.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Client_Disconnects_OtherClientsStillReceive()
|
||||
@@ -97,8 +94,14 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var (sub2, _) = await client2.SubscribeAsync(client2.MakeNodeId("TestMachine_001.MachineID"), 100);
|
||||
var (sub3, item3) = await client3.SubscribeAsync(client3.MakeNodeId("TestMachine_001.MachineID"), 100);
|
||||
|
||||
item1.Notification += (_, e) => { if (e.NotificationValue is MonitoredItemNotification n) notifications1.Add(n); };
|
||||
item3.Notification += (_, e) => { if (e.NotificationValue is MonitoredItemNotification n) notifications3.Add(n); };
|
||||
item1.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification n) notifications1.Add(n);
|
||||
};
|
||||
item3.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification n) notifications3.Add(n);
|
||||
};
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
@@ -108,11 +111,13 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
await Task.Delay(500); // let server process disconnect
|
||||
|
||||
// Simulate data change — should not crash, clients 1+3 should still receive
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "AFTER_DISCONNECT", 192);
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "AFTER_DISCONNECT");
|
||||
await Task.Delay(1000);
|
||||
|
||||
notifications1.Count.ShouldBeGreaterThan(0, "Client 1 should still receive after client 2 disconnected");
|
||||
notifications3.Count.ShouldBeGreaterThan(0, "Client 3 should still receive after client 2 disconnected");
|
||||
notifications1.Count.ShouldBeGreaterThan(0,
|
||||
"Client 1 should still receive after client 2 disconnected");
|
||||
notifications3.Count.ShouldBeGreaterThan(0,
|
||||
"Client 3 should still receive after client 2 disconnected");
|
||||
|
||||
await sub1.DeleteAsync(true);
|
||||
await sub3.DeleteAsync(true);
|
||||
@@ -126,7 +131,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that one client unsubscribing does not interrupt delivery to other subscribed clients.
|
||||
/// Confirms that one client unsubscribing does not interrupt delivery to other subscribed clients.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Client_Unsubscribes_OtherClientsStillReceive()
|
||||
@@ -144,7 +149,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
var (sub1, _) = await client1.SubscribeAsync(client1.MakeNodeId("TestMachine_001.MachineID"), 100);
|
||||
var (sub2, item2) = await client2.SubscribeAsync(client2.MakeNodeId("TestMachine_001.MachineID"), 100);
|
||||
item2.Notification += (_, e) => { if (e.NotificationValue is MonitoredItemNotification n) notifications2.Add(n); };
|
||||
item2.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification n) notifications2.Add(n);
|
||||
};
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
@@ -153,10 +161,11 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
await Task.Delay(500);
|
||||
|
||||
// Simulate data change — client 2 should still receive
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "AFTER_UNSUB", 192);
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "AFTER_UNSUB");
|
||||
await Task.Delay(1000);
|
||||
|
||||
notifications2.Count.ShouldBeGreaterThan(0, "Client 2 should still receive after client 1 unsubscribed");
|
||||
notifications2.Count.ShouldBeGreaterThan(0,
|
||||
"Client 2 should still receive after client 1 unsubscribed");
|
||||
|
||||
await sub2.DeleteAsync(true);
|
||||
client1.Dispose();
|
||||
@@ -169,7 +178,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that clients subscribed to different tags only receive updates for their own monitored data.
|
||||
/// Confirms that clients subscribed to different tags only receive updates for their own monitored data.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task MultipleClients_SubscribeToDifferentTags_EachGetsOwnData()
|
||||
@@ -187,15 +196,22 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var notifications2 = new ConcurrentBag<MonitoredItemNotification>();
|
||||
|
||||
var (sub1, item1) = await client1.SubscribeAsync(client1.MakeNodeId("TestMachine_001.MachineID"), 100);
|
||||
var (sub2, item2) = await client2.SubscribeAsync(client2.MakeNodeId("DelmiaReceiver_001.DownloadPath"), 100);
|
||||
var (sub2, item2) =
|
||||
await client2.SubscribeAsync(client2.MakeNodeId("DelmiaReceiver_001.DownloadPath"), 100);
|
||||
|
||||
item1.Notification += (_, e) => { if (e.NotificationValue is MonitoredItemNotification n) notifications1.Add(n); };
|
||||
item2.Notification += (_, e) => { if (e.NotificationValue is MonitoredItemNotification n) notifications2.Add(n); };
|
||||
item1.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification n) notifications1.Add(n);
|
||||
};
|
||||
item2.Notification += (_, e) =>
|
||||
{
|
||||
if (e.NotificationValue is MonitoredItemNotification n) notifications2.Add(n);
|
||||
};
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
// Only change MachineID
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "CHANGED", 192);
|
||||
fixture.MxProxy!.SimulateDataChangeByAddress("TestMachine_001.MachineID", "CHANGED");
|
||||
await Task.Delay(1000);
|
||||
|
||||
notifications1.Count.ShouldBeGreaterThan(0, "Client 1 should receive MachineID change");
|
||||
@@ -219,7 +235,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
// ── Concurrent Operation Tests ────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that concurrent browse operations from several clients all complete successfully.
|
||||
/// Confirms that concurrent browse operations from several clients all complete successfully.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ConcurrentBrowseFromMultipleClients_AllSucceed()
|
||||
@@ -230,7 +246,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
try
|
||||
{
|
||||
var clients = new List<OpcUaTestClient>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
var c = new OpcUaTestClient();
|
||||
await c.ConnectAsync(fixture.EndpointUrl);
|
||||
@@ -262,7 +278,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that concurrent browse requests return consistent results across clients.
|
||||
/// Confirms that concurrent browse requests return consistent results across clients.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ConcurrentBrowse_AllReturnSameResults()
|
||||
@@ -272,7 +288,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
try
|
||||
{
|
||||
var clients = new List<OpcUaTestClient>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
var c = new OpcUaTestClient();
|
||||
await c.ConnectAsync(fixture.EndpointUrl);
|
||||
@@ -287,7 +303,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
|
||||
// All should get identical child lists
|
||||
var firstResult = results[0].Select(r => r.Name).OrderBy(n => n).ToList();
|
||||
for (int i = 1; i < results.Length; i++)
|
||||
for (var i = 1; i < results.Length; i++)
|
||||
{
|
||||
var thisResult = results[i].Select(r => r.Name).OrderBy(n => n).ToList();
|
||||
thisResult.ShouldBe(firstResult, $"Client {i} got different browse results");
|
||||
@@ -302,7 +318,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that simultaneous browse and subscribe operations do not interfere with one another.
|
||||
/// Confirms that simultaneous browse and subscribe operations do not interfere with one another.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ConcurrentBrowseAndSubscribe_NoInterference()
|
||||
@@ -312,7 +328,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
try
|
||||
{
|
||||
var clients = new List<OpcUaTestClient>();
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
var c = new OpcUaTestClient();
|
||||
await c.ConnectAsync(fixture.EndpointUrl);
|
||||
@@ -340,7 +356,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that concurrent subscribe, read, and browse operations complete without deadlocking the server.
|
||||
/// Confirms that concurrent subscribe, read, and browse operations complete without deadlocking the server.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ConcurrentSubscribeAndRead_NoDeadlock()
|
||||
@@ -380,7 +396,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that repeated client churn does not leave the server in an unstable state.
|
||||
/// Confirms that repeated client churn does not leave the server in an unstable state.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RapidConnectDisconnect_ServerStaysStable()
|
||||
@@ -390,7 +406,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
try
|
||||
{
|
||||
// Rapidly connect, browse, disconnect — 10 iterations
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
using var client = new OpcUaTestClient();
|
||||
await client.ConnectAsync(fixture.EndpointUrl);
|
||||
@@ -411,4 +427,4 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
.AddUser("writetune", "writetune123", AppRoles.WriteTune)
|
||||
.AddUser("writeconfig", "writeconfig123", AppRoles.WriteConfigure)
|
||||
.AddUser("alarmack", "alarmack123", AppRoles.AlarmAck)
|
||||
.AddUser("admin", "admin123", AppRoles.ReadOnly, AppRoles.WriteOperate, AppRoles.WriteTune, AppRoles.WriteConfigure, AppRoles.AlarmAck);
|
||||
.AddUser("admin", "admin123", AppRoles.ReadOnly, AppRoles.WriteOperate, AppRoles.WriteTune,
|
||||
AppRoles.WriteConfigure, AppRoles.AlarmAck);
|
||||
}
|
||||
|
||||
private static AuthenticationConfiguration CreateAuthConfig(bool anonymousCanWrite = false)
|
||||
@@ -36,7 +37,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
mxClient.TagValues["TestMachine_001.MachineID"] = Vtq.Good("hello");
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(
|
||||
mxClient: mxClient,
|
||||
mxClient,
|
||||
authConfig: CreateAuthConfig(),
|
||||
authProvider: CreateTestAuthProvider());
|
||||
await fixture.InitializeAsync();
|
||||
@@ -48,14 +49,17 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var result = client.Read(client.MakeNodeId("TestMachine_001.MachineID"));
|
||||
result.StatusCode.ShouldNotBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AnonymousWrite_Denied_WhenAnonymousCanWriteFalse()
|
||||
{
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(
|
||||
authConfig: CreateAuthConfig(anonymousCanWrite: false),
|
||||
authConfig: CreateAuthConfig(false),
|
||||
authProvider: CreateTestAuthProvider());
|
||||
await fixture.InitializeAsync();
|
||||
try
|
||||
@@ -66,7 +70,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -75,8 +82,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
mxClient.TagValues["TestMachine_001.MachineID"] = Vtq.Good("initial");
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(
|
||||
mxClient: mxClient,
|
||||
authConfig: CreateAuthConfig(anonymousCanWrite: true),
|
||||
mxClient,
|
||||
authConfig: CreateAuthConfig(true),
|
||||
authProvider: CreateTestAuthProvider());
|
||||
await fixture.InitializeAsync();
|
||||
try
|
||||
@@ -87,7 +94,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldNotBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -105,7 +115,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -114,7 +127,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
mxClient.TagValues["TestMachine_001.MachineID"] = Vtq.Good("initial");
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(
|
||||
mxClient: mxClient,
|
||||
mxClient,
|
||||
authConfig: CreateAuthConfig(),
|
||||
authProvider: CreateTestAuthProvider());
|
||||
await fixture.InitializeAsync();
|
||||
@@ -126,7 +139,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldNotBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -144,7 +160,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -153,7 +172,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var mxClient = new FakeMxAccessClient();
|
||||
mxClient.TagValues["TestMachine_001.MachineID"] = Vtq.Good("initial");
|
||||
var fixture = OpcUaServerFixture.WithFakeMxAccessClient(
|
||||
mxClient: mxClient,
|
||||
mxClient,
|
||||
authConfig: CreateAuthConfig(),
|
||||
authProvider: CreateTestAuthProvider());
|
||||
await fixture.InitializeAsync();
|
||||
@@ -165,7 +184,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var status = client.Write(client.MakeNodeId("TestMachine_001.MachineID"), "test");
|
||||
status.Code.ShouldNotBe(StatusCodes.BadUserAccessDenied);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -182,7 +204,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
await Should.ThrowAsync<ServiceResultException>(async () =>
|
||||
await client.ConnectAsync(fixture.EndpointUrl, username: "readonly", password: "wrongpassword"));
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var serviceLevel = client.Read(VariableIds.Server_ServiceLevel);
|
||||
((byte)serviceLevel.Value).ShouldBe((byte)255);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -53,7 +56,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
var redundancySupport = client.Read(VariableIds.Server_ServerRedundancy_RedundancySupport);
|
||||
((int)redundancySupport.Value).ShouldBe((int)RedundancySupport.Warm);
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -130,7 +136,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
uris.ShouldContain("urn:test:server2");
|
||||
}
|
||||
}
|
||||
finally { await fixture.DisposeAsync(); }
|
||||
finally
|
||||
{
|
||||
await fixture.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -176,4 +185,4 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Integration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user