using ZB.MOM.WW.OtOpcUa.Driver.AbCip;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
///
/// Test fake for . Stores the mock PLC value in
/// + returns it from . Use
/// to simulate libplctag error codes,
/// / to simulate exceptions.
///
internal class FakeAbCipTag : IAbCipTagRuntime
{
public AbCipTagCreateParams CreationParams { get; }
public object? Value { get; set; }
public int Status { get; set; }
public bool ThrowOnInitialize { get; set; }
public bool ThrowOnRead { get; set; }
public Exception? Exception { get; set; }
public int InitializeCount { get; private set; }
public int ReadCount { get; private set; }
public int WriteCount { get; private set; }
public bool Disposed { get; private set; }
public FakeAbCipTag(AbCipTagCreateParams createParams) => CreationParams = createParams;
public virtual Task InitializeAsync(CancellationToken cancellationToken)
{
InitializeCount++;
if (ThrowOnInitialize) throw Exception ?? new InvalidOperationException("fake initialize failure");
return Task.CompletedTask;
}
public virtual Task ReadAsync(CancellationToken cancellationToken)
{
ReadCount++;
if (ThrowOnRead) throw Exception ?? new InvalidOperationException("fake read failure");
return Task.CompletedTask;
}
public virtual Task WriteAsync(CancellationToken cancellationToken)
{
WriteCount++;
return Task.CompletedTask;
}
public virtual int GetStatus() => Status;
public virtual object? DecodeValue(AbCipDataType type, int? bitIndex) => Value;
///
/// Task #194 whole-UDT read support. Tests drive multi-member decoding by setting
/// — keyed by member byte offset — before invoking
/// . Falls back to when the
/// offset is zero or unmapped so existing tests that never set the offset map keep
/// working unchanged.
///
public Dictionary ValuesByOffset { get; } = new();
public virtual object? DecodeValueAt(AbCipDataType type, int offset, int? bitIndex)
{
if (ValuesByOffset.TryGetValue(offset, out var v)) return v;
return offset == 0 ? Value : null;
}
public virtual void EncodeValue(AbCipDataType type, int? bitIndex, object? value) => Value = value;
public virtual void Dispose() => Disposed = true;
}
/// Test factory that produces s and indexes them for assertion.
internal sealed class FakeAbCipTagFactory : IAbCipTagFactory
{
public Dictionary Tags { get; } = new(StringComparer.OrdinalIgnoreCase);
public Func? Customise { get; set; }
public IAbCipTagRuntime Create(AbCipTagCreateParams createParams)
{
var fake = Customise?.Invoke(createParams) ?? new FakeAbCipTag(createParams);
Tags[createParams.TagName] = fake;
return fake;
}
}