615b487a77
Adds missing <summary>/<param> XML docs across 99 server, worker, and test files so CommentChecker reports zero issues (TreatWarningsAsErrors needs the analyzer clean). Bundles in WIP dashboard work: NavSection extraction, MainLayout/site.css/js styling alignment, and DashboardOptions/Auth tweaks.
212 lines
9.2 KiB
C#
212 lines
9.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using ZB.MOM.WW.MxGateway.Worker.MxAccess;
|
|
|
|
namespace ZB.MOM.WW.MxGateway.Worker.Tests.MxAccess;
|
|
|
|
/// <summary>
|
|
/// Worker-007 regression tests for <see cref="MxAccessComServer"/>. The
|
|
/// adapter no longer falls back to late-bound <c>Type.InvokeMember</c>
|
|
/// reflection: a COM object must implement either the typed
|
|
/// <c>ILMXProxyServer</c> COM interface family (production) or
|
|
/// <see cref="IMxAccessServer"/> directly (test fakes).
|
|
/// </summary>
|
|
public sealed class MxAccessComServerTests
|
|
{
|
|
/// <summary>
|
|
/// A COM object implementing <see cref="IMxAccessServer"/> is routed
|
|
/// through the typed interface — no reflection — preserving arguments
|
|
/// and return values.
|
|
/// </summary>
|
|
[Fact]
|
|
public void Methods_WithTypedServer_RouteThroughTypedInterface()
|
|
{
|
|
RecordingMxAccessServer typed = new(registerHandle: 77);
|
|
MxAccessComServer adapter = new(typed);
|
|
|
|
int serverHandle = adapter.Register("client-a");
|
|
adapter.Advise(serverHandle, itemHandle: 9);
|
|
adapter.Unregister(serverHandle);
|
|
|
|
Assert.Equal(77, serverHandle);
|
|
Assert.Equal("client-a", typed.RegisteredClientName);
|
|
Assert.Equal(new[] { "Register:client-a", "Advise:77:9", "Unregister:77" }, typed.Calls);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A COM object that implements neither the typed COM interface family
|
|
/// nor <see cref="IMxAccessServer"/> fails fast with a clear
|
|
/// <see cref="InvalidOperationException"/> instead of a late-bound
|
|
/// reflection call.
|
|
/// </summary>
|
|
[Fact]
|
|
public void Methods_WithUntypedObject_ThrowInvalidOperation()
|
|
{
|
|
MxAccessComServer adapter = new(new object());
|
|
|
|
InvalidOperationException exception =
|
|
Assert.Throws<InvalidOperationException>(() => adapter.Register("client"));
|
|
|
|
Assert.Contains("does not implement", exception.Message, StringComparison.Ordinal);
|
|
Assert.Contains(nameof(IMxAccessServer), exception.Message, StringComparison.Ordinal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Exceptions thrown by the typed server propagate unchanged — no
|
|
/// <c>TargetInvocationException</c> wrapping (reflection is gone).
|
|
/// </summary>
|
|
[Fact]
|
|
public void Methods_WhenTypedServerThrows_PropagateOriginalException()
|
|
{
|
|
RecordingMxAccessServer typed = new(registerHandle: 1)
|
|
{
|
|
ThrowOnRegister = new InvalidOperationException("register failed"),
|
|
};
|
|
MxAccessComServer adapter = new(typed);
|
|
|
|
InvalidOperationException exception =
|
|
Assert.Throws<InvalidOperationException>(() => adapter.Register("client"));
|
|
|
|
Assert.Equal("register failed", exception.Message);
|
|
}
|
|
|
|
private sealed class RecordingMxAccessServer : IMxAccessServer
|
|
{
|
|
private readonly int registerHandle;
|
|
private readonly List<string> calls = new();
|
|
|
|
/// <summary>Initializes a new instance with the specified register handle.</summary>
|
|
/// <param name="registerHandle">The initial server handle value to return from Register.</param>
|
|
public RecordingMxAccessServer(int registerHandle)
|
|
{
|
|
this.registerHandle = registerHandle;
|
|
}
|
|
|
|
/// <summary>Gets the client name passed to the most recent Register call.</summary>
|
|
public string? RegisteredClientName { get; private set; }
|
|
|
|
/// <summary>Gets or sets an exception to throw from the Register method.</summary>
|
|
public Exception? ThrowOnRegister { get; set; }
|
|
|
|
/// <summary>Gets the recorded method calls as strings.</summary>
|
|
public IReadOnlyList<string> Calls => calls.ToArray();
|
|
|
|
/// <summary>Records a Register call and returns the configured handle.</summary>
|
|
/// <param name="clientName">The client name to record.</param>
|
|
public int Register(string clientName)
|
|
{
|
|
calls.Add($"Register:{clientName}");
|
|
RegisteredClientName = clientName;
|
|
if (ThrowOnRegister is not null)
|
|
{
|
|
throw ThrowOnRegister;
|
|
}
|
|
|
|
return registerHandle;
|
|
}
|
|
|
|
/// <summary>Records an Unregister call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
public void Unregister(int serverHandle)
|
|
{
|
|
calls.Add($"Unregister:{serverHandle}");
|
|
}
|
|
|
|
/// <summary>Records an AddItem call and returns zero.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemDefinition">The item definition string to record.</param>
|
|
public int AddItem(int serverHandle, string itemDefinition)
|
|
{
|
|
calls.Add($"AddItem:{serverHandle}:{itemDefinition}");
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>Records an AddItem2 call and returns zero.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemDefinition">The item definition string to record.</param>
|
|
/// <param name="itemContext">The item context string to record.</param>
|
|
public int AddItem2(int serverHandle, string itemDefinition, string itemContext)
|
|
{
|
|
calls.Add($"AddItem2:{serverHandle}:{itemDefinition}:{itemContext}");
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>Records a RemoveItem call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
public void RemoveItem(int serverHandle, int itemHandle)
|
|
{
|
|
calls.Add($"RemoveItem:{serverHandle}:{itemHandle}");
|
|
}
|
|
|
|
/// <summary>Records an Advise call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
public void Advise(int serverHandle, int itemHandle)
|
|
{
|
|
calls.Add($"Advise:{serverHandle}:{itemHandle}");
|
|
}
|
|
|
|
/// <summary>Records an UnAdvise call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
public void UnAdvise(int serverHandle, int itemHandle)
|
|
{
|
|
calls.Add($"UnAdvise:{serverHandle}:{itemHandle}");
|
|
}
|
|
|
|
/// <summary>Records an AdviseSupervisory call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
public void AdviseSupervisory(int serverHandle, int itemHandle)
|
|
{
|
|
calls.Add($"AdviseSupervisory:{serverHandle}:{itemHandle}");
|
|
}
|
|
|
|
/// <summary>Records a Write call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
/// <param name="value">The value to write.</param>
|
|
/// <param name="userId">The user identifier.</param>
|
|
public void Write(int serverHandle, int itemHandle, object? value, int userId)
|
|
{
|
|
calls.Add($"Write:{serverHandle}:{itemHandle}:{value}:{userId}");
|
|
}
|
|
|
|
/// <summary>Records a Write2 call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
/// <param name="value">The value to write.</param>
|
|
/// <param name="timestamp">The timestamp value.</param>
|
|
/// <param name="userId">The user identifier.</param>
|
|
public void Write2(int serverHandle, int itemHandle, object? value, object? timestamp, int userId)
|
|
{
|
|
calls.Add($"Write2:{serverHandle}:{itemHandle}:{value}:{timestamp}:{userId}");
|
|
}
|
|
|
|
/// <summary>Records a WriteSecured call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
/// <param name="currentUserId">The current user identifier.</param>
|
|
/// <param name="verifierUserId">The verifier user identifier.</param>
|
|
/// <param name="value">The value to write.</param>
|
|
public void WriteSecured(int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value)
|
|
{
|
|
calls.Add($"WriteSecured:{serverHandle}:{itemHandle}:{currentUserId}:{verifierUserId}:{value}");
|
|
}
|
|
|
|
/// <summary>Records a WriteSecured2 call.</summary>
|
|
/// <param name="serverHandle">The MXAccess server handle.</param>
|
|
/// <param name="itemHandle">The MXAccess item handle.</param>
|
|
/// <param name="currentUserId">The current user identifier.</param>
|
|
/// <param name="verifierUserId">The verifier user identifier.</param>
|
|
/// <param name="value">The value to write.</param>
|
|
/// <param name="timestamp">The timestamp value.</param>
|
|
public void WriteSecured2(
|
|
int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value, object? timestamp)
|
|
{
|
|
calls.Add($"WriteSecured2:{serverHandle}:{itemHandle}:{currentUserId}:{verifierUserId}:{value}:{timestamp}");
|
|
}
|
|
}
|
|
}
|