Class ProtoDevice

Namespace
ProtoTest.Devices
Assembly
ProtoTest.Devices.dll

One typed device a suite talks to - a charger, a meter, a sensor. Derive from it, add the domain methods your scenario reads (BootAsync, PlugInAsync), and compose the protected protocol primitives; the instance is created per test by Proto.Context.Devices().For<TDevice>("id") and released with the test.

public abstract class ProtoDevice
Inheritance
ProtoDevice
Inherited Members
Extension Methods

Remarks

Concurrency: one device instance is one conversation. Connection creation is single-flight and sends are serialized, so concurrent sends share one connection instead of opening one each. One receive may be in flight at a time - a second concurrent receive fails fast with an error naming the device, because it would steal frames from the first. A send that races a disconnect fails with the same named device error instead of a disposed-socket exception. Sends and receives may run concurrently (one in each direction), and the test's end disconnects the device, records device.connected = false and emits the same device.disconnect an explicit call does.

Properties

Exchange

A readable log of the frames exchanged so far, for failure messages.

protected IReadOnlyList<string> Exchange { get; }

Property Value

IReadOnlyList<string>

Id

Gets the device id, as registered and as the trace records it.

public string Id { get; }

Property Value

string

Methods

ConnectAsync(CancellationToken)

Connects the device if it is not connected yet; the transport connects lazily anyway.

protected ValueTask ConnectAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

ValueTask

DisconnectAsync(CancellationToken)

Closes the connection; the device can connect again afterwards.

protected ValueTask DisconnectAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

ValueTask

ExpectAsync(string, Func<DeviceFrame, bool>, TimeSpan?, CancellationToken)

Waits for a frame matching match and records the wait as an asserted device.command: a match contributes device coverage, a timeout fails with the description and the frames seen so far.

protected ValueTask<DeviceFrame> ExpectAsync(string description, Func<DeviceFrame, bool> match, TimeSpan? timeout = null, CancellationToken cancellationToken = default)

Parameters

description string
match Func<DeviceFrame, bool>
timeout TimeSpan?
cancellationToken CancellationToken

Returns

ValueTask<DeviceFrame>

ExpectMessageAsync<TMessage>(Func<TMessage, bool>?, string?, TimeSpan?, CancellationToken)

Waits for a frame that reads as TMessage and, when given, satisfies match; frames that are not that message are skipped. The wait is recorded like ExpectAsync(string, Func<DeviceFrame, bool>, TimeSpan?, CancellationToken), named after the message type unless description says otherwise.

protected ValueTask<TMessage> ExpectMessageAsync<TMessage>(Func<TMessage, bool>? match = null, string? description = null, TimeSpan? timeout = null, CancellationToken cancellationToken = default)

Parameters

match Func<TMessage, bool>
description string
timeout TimeSpan?
cancellationToken CancellationToken

Returns

ValueTask<TMessage>

Type Parameters

TMessage

ListenAsync(CancellationToken)

Starts listening for the device to connect to the test and returns the address to hand the system under test, with the port the operating system chose. Only a listening transport supports it, such as a client registered with AddTcpListener; the first send or receive waits for the connection.

protected ValueTask<string> ListenAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

ValueTask<string>

ReceiveAsync(CancellationToken)

Receives the next frame and records it as a device.receive operation.

protected ValueTask<DeviceFrame> ReceiveAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Returns

ValueTask<DeviceFrame>

SendAsync(DeviceFrame, CancellationToken)

Sends one frame and records it as a device.send operation.

protected ValueTask SendAsync(DeviceFrame frame, CancellationToken cancellationToken = default)

Parameters

frame DeviceFrame
cancellationToken CancellationToken

Returns

ValueTask

SendMessageAsync<TMessage>(TMessage, CancellationToken)

Sends a message type as the frame a device sends: its data string, or its bytes for a binary message.

protected ValueTask SendMessageAsync<TMessage>(TMessage message, CancellationToken cancellationToken = default) where TMessage : notnull

Parameters

message TMessage
cancellationToken CancellationToken

Returns

ValueTask

Type Parameters

TMessage

SendTextAsync(string, CancellationToken)

Sends one text frame.

protected ValueTask SendTextAsync(string text, CancellationToken cancellationToken = default)

Parameters

text string
cancellationToken CancellationToken

Returns

ValueTask