Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -244,20 +244,33 @@ protected override async Task<IReadOnlyList<string>> ExecuteTextCommandAsync(
int responseTimeoutMs = 1000,
int completionTimeoutMs = 250,
CancellationToken cancellationToken = default,
Func<CancellationToken, Task>? prepareAsync = null)
Func<CancellationToken, Task>? prepareAsync = null,
Func<Task>? finalizeAsync = null)
{
cancellationToken.ThrowIfCancellationRequested();

// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
try
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();

// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}

var before = SentCommands.Count;
setupAction();
return ResponsesSince(before);
}
finally
{
// Honor the exchange's finalize phase the way the real device does: it runs
// however the exchange ended, still inside the exchange (#407).
if (finalizeAsync != null)
{
await finalizeAsync().ConfigureAwait(false);
}
}

var before = SentCommands.Count;
setupAction();
return ResponsesSince(before);
}

protected override async Task<IReadOnlyList<string>> ExecuteTextCommandAsync(
Expand Down
35 changes: 24 additions & 11 deletions src/Daqifi.Core.Tests/Device/DaqifiDeviceDrainErrorQueueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,33 @@ protected override async Task<IReadOnlyList<string>> ExecuteTextCommandAsync(
int responseTimeoutMs = 1000,
int completionTimeoutMs = 250,
CancellationToken cancellationToken = default,
Func<CancellationToken, Task>? prepareAsync = null)
Func<CancellationToken, Task>? prepareAsync = null,
Func<Task>? finalizeAsync = null)
{
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
try
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}

cancellationToken.ThrowIfCancellationRequested();
setupAction();
ExecuteTextCommandCallCount++;
var reply = Replies.Count > 0 ? Replies.Dequeue() : Array.Empty<string>();
return reply;
}
finally
{
// Honor the exchange's finalize phase the way the real device does: it runs
// however the exchange ended, still inside the exchange (#407).
if (finalizeAsync != null)
{
await finalizeAsync().ConfigureAwait(false);
}
}

cancellationToken.ThrowIfCancellationRequested();
setupAction();
ExecuteTextCommandCallCount++;
var reply = Replies.Count > 0 ? Replies.Dequeue() : Array.Empty<string>();
return reply;
}
}
}
Expand Down
104 changes: 65 additions & 39 deletions src/Daqifi.Core.Tests/Device/DaqifiDeviceInitializeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,25 +433,38 @@ protected override async Task<IReadOnlyList<string>> ExecuteTextCommandAsync(
int responseTimeoutMs = 1000,
int completionTimeoutMs = 250,
CancellationToken cancellationToken = default,
Func<CancellationToken, Task>? prepareAsync = null)
Func<CancellationToken, Task>? prepareAsync = null,
Func<Task>? finalizeAsync = null)
{
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
try
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}

// Run the setup action so that Send() calls inside it are captured
setupAction();
TextCommandAttemptCount++;
// Run the setup action so that Send() calls inside it are captured
setupAction();
TextCommandAttemptCount++;

if (_failFirstAttempt && TextCommandAttemptCount == 1)
if (_failFirstAttempt && TextCommandAttemptCount == 1)
{
return new[] { "**ERROR: -200, \"Execution error\"\r\n" };
}

return _textCommandResponse;
}
finally
{
return new[] { "**ERROR: -200, \"Execution error\"\r\n" };
// Honor the exchange's finalize phase the way the real device does: it runs
// however the exchange ended, still inside the exchange (#407).
if (finalizeAsync != null)
{
await finalizeAsync().ConfigureAwait(false);
}
}

return _textCommandResponse;
}
}

Expand Down Expand Up @@ -513,40 +526,53 @@ protected override async Task<IReadOnlyList<string>> ExecuteTextCommandAsync(
int responseTimeoutMs = 1000,
int completionTimeoutMs = 250,
CancellationToken cancellationToken = default,
Func<CancellationToken, Task>? prepareAsync = null)
Func<CancellationToken, Task>? prepareAsync = null,
Func<Task>? finalizeAsync = null)
{
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
try
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}
// Honor the exchange's prepare phase the way the real device does: it runs first,
// before anything this exchange sends (#396).
if (prepareAsync != null)
{
await prepareAsync(cancellationToken).ConfigureAwait(false);
}

var before = _sent.Count;
setupAction();
var sentThisCall = _sent.Skip(before).ToList();
var isUsbStep = sentThisCall.Any(d => d.Contains("STReam:INTerface"));
var before = _sent.Count;
setupAction();
var sentThisCall = _sent.Skip(before).ToList();
var isUsbStep = sentThisCall.Any(d => d.Contains("STReam:INTerface"));

if (isUsbStep)
{
UsbStepAttemptCount++;

switch (_usbStepBehavior)
if (isUsbStep)
{
case UsbStepBehavior.ScpiError:
return new[] { "**ERROR: -200, \"Execution error\"\r\n" };
case UsbStepBehavior.ScpiErrorThenSucceed:
if (UsbStepAttemptCount == 1)
{
UsbStepAttemptCount++;

switch (_usbStepBehavior)
{
case UsbStepBehavior.ScpiError:
return new[] { "**ERROR: -200, \"Execution error\"\r\n" };
}
break;
case UsbStepBehavior.Cancel:
throw new OperationCanceledException();
case UsbStepBehavior.ScpiErrorThenSucceed:
if (UsbStepAttemptCount == 1)
{
return new[] { "**ERROR: -200, \"Execution error\"\r\n" };
}
break;
case UsbStepBehavior.Cancel:
throw new OperationCanceledException();
}
}
}

return Array.Empty<string>();
return Array.Empty<string>();
}
finally
{
// Honor the exchange's finalize phase the way the real device does: it runs
// however the exchange ended, still inside the exchange (#407).
if (finalizeAsync != null)
{
await finalizeAsync().ConfigureAwait(false);
}
}
}
}
}
Expand Down
Loading