fix: report a user-requested stop as stopped rather than failed

Stopping a test shuts down the control socket, so iperf_run_client() returns
-1 with "unable to send control message ... Broken pipe". That is the
expected consequence of the stop, not a fault, but the bridge read the
negative return as a failure — so pressing STOP left the UI showing
"Error (exit 1)" above a broken-pipe message.

The bridge now consults its own g_stop flag before classifying the outcome,
and the distinction travels up as Iperf3Result.stopped so the status line can
say "Stopped". A stop is reported with exit code 0: the run ended the way the
user asked it to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 19:03:59 +09:00
parent fb6ec3af37
commit 02a8ba9c18
7 changed files with 63 additions and 3 deletions
@@ -120,6 +120,31 @@ void main() {
await run;
});
test('wasStopped reflects a user-requested stop', () async {
final mock = _MockIperf3Service(
onRun: (_) async => const Iperf3Result(
rawOutput: 'stopped early',
exitCode: 0,
stopped: true,
),
);
final vm = TestRunViewModel(iperf3Service: mock);
await vm.runTest(const TestConfiguration(server: '192.168.1.1'));
// A user stop is a normal outcome: completed, not error.
expect(vm.state, equals(TestRunState.completed));
expect(vm.wasStopped, isTrue);
});
test('wasStopped is false for a run that finished on its own', () async {
final mock = _MockIperf3Service(
onRun: (_) async =>
const Iperf3Result(rawOutput: 'done', exitCode: 0),
);
final vm = TestRunViewModel(iperf3Service: mock);
await vm.runTest(const TestConfiguration(server: '192.168.1.1'));
expect(vm.wasStopped, isFalse);
});
test('a second runTest while running is ignored', () async {
final mock = _MockIperf3Service();
final gate = Completer<Iperf3Result>();