Files
ulapp/tests/FieldLogger.Sync.Tests/FakeMqttTransport.cs

62 lines
2.2 KiB
C#

using FieldLogger.Sync;
namespace FieldLogger.Sync.Tests;
/// <summary>
/// In-memory stand-in for the broker. Records published payloads, lets a test toggle
/// connectivity, force publish failures, and inject application-level acks — so the engine's
/// durability/ack/backoff behaviour is exercised without MQTTnet or a live broker.
/// </summary>
public sealed class FakeMqttTransport : IMqttTransport
{
public bool IsConnected { get; set; } = true;
public bool FailNextPublish { get; set; }
public List<(string Topic, byte[] Payload)> Published { get; } = new();
public event Func<AckBatch, Task>? AckReceived;
public Task ConnectAsync(string ackTopic, CancellationToken ct = default)
{
IsConnected = true;
return Task.CompletedTask;
}
public Task DisconnectAsync()
{
IsConnected = false;
return Task.CompletedTask;
}
public Task PublishAsync(string topic, byte[] payload, string schemaVersion, CancellationToken ct = default)
{
if (!IsConnected) throw new InvalidOperationException("not connected");
if (FailNextPublish)
{
FailNextPublish = false;
throw new InvalidOperationException("simulated broker publish failure");
}
Published.Add((topic, payload));
return Task.CompletedTask;
}
/// <summary>Simulate the cloud emitting an application-level ack for these pointIds.</summary>
public async Task InjectAckAsync(params AckItem[] items)
{
if (AckReceived is { } handlers)
{
var batch = new AckBatch { Results = items.ToList() };
foreach (Func<AckBatch, Task> handler in handlers.GetInvocationList())
await handler(batch);
}
}
public Task InjectAcceptAsync(string pointId) =>
InjectAckAsync(new AckItem { PointId = pointId, Outcome = AckOutcome.ACCEPTED });
public Task InjectDuplicateAsync(string pointId) =>
InjectAckAsync(new AckItem { PointId = pointId, Outcome = AckOutcome.DUPLICATE });
public Task InjectRejectAsync(string pointId, string reasonCode) =>
InjectAckAsync(new AckItem { PointId = pointId, Outcome = AckOutcome.REJECTED, ReasonCode = reasonCode });
}