review(Driver.OpcUaClient.Browser): AttributesAsync updates LastUsedUtc
Review at HEAD 7286d320. -001: AttributesAsync now updates LastUsedUtc (IBrowseSession
contract) + test (InternalsVisibleTo+Moq added). -002 (continuation-point cancel leak)
deferred cross-cutting w/ runtime Driver.OpcUaClient.
This commit is contained in:
+39
@@ -1,5 +1,9 @@
|
||||
using Moq;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.Tests;
|
||||
@@ -49,4 +53,39 @@ public sealed class OpcUaClientDriverBrowserTests
|
||||
() => _sut.OpenAsync(json, TestContext.Current.CancellationToken));
|
||||
ex.Message.ShouldContain("Certificate");
|
||||
}
|
||||
|
||||
// ---- Driver.OpcUaClient.Browser-001: AttributesAsync must refresh LastUsedUtc ----
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IBrowseSession.LastUsedUtc"/> must be updated on every call
|
||||
/// including <see cref="OpcUaClientBrowseSession.AttributesAsync"/>, which the
|
||||
/// <see cref="BrowseSessionReaper"/> uses for idle eviction. Before the fix
|
||||
/// the method returned immediately without touching the property, causing a
|
||||
/// session that only received <c>AttributesAsync</c> calls to be evicted early.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task AttributesAsync_updates_LastUsedUtc()
|
||||
{
|
||||
var ct = TestContext.Current.CancellationToken;
|
||||
|
||||
// Arrange: build a minimal OpcUaClientBrowseSession without a live server.
|
||||
// AttributesAsync does not call ISession — MockBehavior.Loose is safe.
|
||||
var mockSession = new Mock<ISession>(MockBehavior.Loose);
|
||||
var nsMap = NamespaceMap.FromTable(new NamespaceTable());
|
||||
var sut = new OpcUaClientBrowseSession(mockSession.Object, nsMap, ObjectIds.ObjectsFolder);
|
||||
|
||||
var before = sut.LastUsedUtc;
|
||||
|
||||
// Introduce a small delay so clock advances at least one tick.
|
||||
await Task.Delay(5, ct);
|
||||
|
||||
// Act
|
||||
var attrs = await sut.AttributesAsync("nsu=http://opcfoundation.org/UA/;i=85", ct);
|
||||
|
||||
// Assert: LastUsedUtc must have been refreshed, and the result must be empty
|
||||
// (OPC UA picker treats variables as leaves, no attribute side-panel).
|
||||
attrs.ShouldBeEmpty();
|
||||
sut.LastUsedUtc.ShouldBeGreaterThan(before,
|
||||
"AttributesAsync must refresh LastUsedUtc to satisfy the IBrowseSession contract");
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -12,6 +12,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit.v3"/>
|
||||
<PackageReference Include="Shouldly"/>
|
||||
<PackageReference Include="Moq"/>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
Reference in New Issue
Block a user