73 lines
2.9 KiB
C#
73 lines
2.9 KiB
C#
using System.IO.Pipelines;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
|
|
|
|
/// <summary>
|
|
/// Bidirectional in-memory stream pair for IPC tests. Two <c>System.IO.Pipelines.Pipe</c>
|
|
/// instances — one per direction — exposed as <see cref="System.IO.Stream"/> endpoints
|
|
/// via <c>PipeReader.AsStream</c> / <c>PipeWriter.AsStream</c>. Lets the test set up a
|
|
/// <c>FocasIpcClient</c> on one end and a minimal fake server loop on the other without
|
|
/// standing up a real named pipe.
|
|
/// </summary>
|
|
internal sealed class IpcLoopback : IAsyncDisposable
|
|
{
|
|
public Stream ClientSide { get; }
|
|
public Stream ServerSide { get; }
|
|
|
|
public IpcLoopback()
|
|
{
|
|
var clientToServer = new Pipe();
|
|
var serverToClient = new Pipe();
|
|
|
|
ClientSide = new DuplexPipeStream(serverToClient.Reader.AsStream(), clientToServer.Writer.AsStream());
|
|
ServerSide = new DuplexPipeStream(clientToServer.Reader.AsStream(), serverToClient.Writer.AsStream());
|
|
}
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
await ClientSide.DisposeAsync();
|
|
await ServerSide.DisposeAsync();
|
|
}
|
|
|
|
private sealed class DuplexPipeStream(Stream read, Stream write) : Stream
|
|
{
|
|
public override bool CanRead => true;
|
|
public override bool CanWrite => true;
|
|
public override bool CanSeek => false;
|
|
public override long Length => throw new NotSupportedException();
|
|
public override long Position
|
|
{
|
|
get => throw new NotSupportedException();
|
|
set => throw new NotSupportedException();
|
|
}
|
|
|
|
public override int Read(byte[] buffer, int offset, int count) => read.Read(buffer, offset, count);
|
|
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken ct) =>
|
|
read.ReadAsync(buffer, offset, count, ct);
|
|
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken ct = default) =>
|
|
read.ReadAsync(buffer, ct);
|
|
|
|
public override void Write(byte[] buffer, int offset, int count) => write.Write(buffer, offset, count);
|
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken ct) =>
|
|
write.WriteAsync(buffer, offset, count, ct);
|
|
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken ct = default) =>
|
|
write.WriteAsync(buffer, ct);
|
|
|
|
public override void Flush() => write.Flush();
|
|
public override Task FlushAsync(CancellationToken ct) => write.FlushAsync(ct);
|
|
|
|
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
|
|
public override void SetLength(long value) => throw new NotSupportedException();
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
read.Dispose();
|
|
write.Dispose();
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|
|
}
|