/* ========================================================================
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
#nullable enable
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
namespace Opc.Ua.Client.Subscriptions.Fakes
{
///
/// Hand-rolled fake for .
/// Records every invocation and lets tests override return behaviour
/// via callback fields. Replaces
/// Mock<ISubscriptionManagerContext>.
///
internal sealed class FakeSubscriptionManagerContext : ISubscriptionManagerContext
{
/// Recorded calls to .
public List CreateSubscriptionCalls { get; } = [];
/// Recorded calls to .
public List PublishCalls { get; } = [];
/// Recorded calls to .
public List TransferCalls { get; } = [];
/// Recorded calls to .
public List DeleteCalls { get; } = [];
///
/// Required factory for . Tests must
/// assign this before invoking the manager.
///
public Func, IMessageAckQueue,
IManagedSubscription> CreateSubscriptionFactory
{ get; set; }
= (_, _, _) => throw new InvalidOperationException(
"CreateSubscriptionFactory not set on FakeSubscriptionManagerContext.");
///
/// Optional override for . If null,
/// returns a default .
///
public Func,
CancellationToken, ValueTask>? OnPublishAsync
{ get; set; }
///
/// Optional override for .
///
public Func, bool, CancellationToken,
ValueTask>? OnTransferSubscriptionsAsync
{ get; set; }
///
/// Optional override for .
///
public Func, CancellationToken,
ValueTask>? OnDeleteSubscriptionsAsync
{ get; set; }
public IManagedSubscription CreateSubscription(
ISubscriptionNotificationHandler handler,
IOptionsMonitor options,
IMessageAckQueue queue,
SubscriptionLoadState? loadState = null)
{
CreateSubscriptionCalls.Add(
new CreateSubscriptionCall(handler, options, queue, loadState));
return CreateSubscriptionFactory(handler, options, queue);
}
public ValueTask PublishAsync(
RequestHeader? requestHeader,
ArrayOf subscriptionAcknowledgements,
CancellationToken ct = default)
{
PublishCalls.Add(new PublishCall(requestHeader,
subscriptionAcknowledgements));
return OnPublishAsync?.Invoke(requestHeader,
subscriptionAcknowledgements, ct)
?? new ValueTask(new PublishResponse());
}
public ValueTask TransferSubscriptionsAsync(
RequestHeader? requestHeader, ArrayOf subscriptionIds,
bool sendInitialValues, CancellationToken ct = default)
{
TransferCalls.Add(new TransferCall(requestHeader, subscriptionIds,
sendInitialValues));
return OnTransferSubscriptionsAsync?.Invoke(requestHeader,
subscriptionIds, sendInitialValues, ct)
?? new ValueTask(
new TransferSubscriptionsResponse());
}
public ValueTask DeleteSubscriptionsAsync(
RequestHeader? requestHeader, ArrayOf subscriptionIds,
CancellationToken ct = default)
{
DeleteCalls.Add(new DeleteCall(requestHeader, subscriptionIds));
return OnDeleteSubscriptionsAsync?.Invoke(requestHeader,
subscriptionIds, ct)
?? new ValueTask(
new DeleteSubscriptionsResponse());
}
internal readonly record struct CreateSubscriptionCall(
ISubscriptionNotificationHandler Handler,
IOptionsMonitor Options,
IMessageAckQueue Queue,
SubscriptionLoadState? LoadState);
internal readonly record struct PublishCall(
RequestHeader? RequestHeader,
ArrayOf Acknowledgements);
internal readonly record struct TransferCall(
RequestHeader? RequestHeader, ArrayOf SubscriptionIds,
bool SendInitialValues);
internal readonly record struct DeleteCall(
RequestHeader? RequestHeader, ArrayOf SubscriptionIds);
}
}