Commit Graph

5 Commits

Author SHA1 Message Date
mikkeli cbb2aba8b0 feat(ui): render the event stream and show live throughput figures
Consuming JSON means the familiar iperf3 text layout has to be rebuilt, so a
pure formatter turns each event back into a line — binary units for transfer
totals, decimal units for bitrates, matching how iperf3 quotes each. The view
model keeps the interval series and the end summary as data alongside the
transcript, and a stat row shows current/total, mean, peak and sample count
off that series. A chart can be driven from the same list without re-parsing
text.

Repaints are coalesced on a 250ms timer rather than one per event. Reports can
now arrive several times a second across many streams, and each rebuild
re-renders the whole transcript, so notifying per event made the cost of
drawing scale with the report rate — which competes with the test itself for
CPU and skews the measurement.

Warm-up intervals (-O) are marked omitted by iperf3 and are kept out of the
series so they cannot drag the mean down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 19:35:10 +09:00
mikkeli 02a8ba9c18 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>
2026-08-26 19:03:59 +09:00
mikkeli 3b01b0c4a6 fix(app): stream native output and release run state on every exit path
_isRunning was never cleared on the timeout path, so a single timed-out run
locked the app out of starting another until it was restarted. It is now
cleared in a finally block covering all three exits.

Output was buffered inside the service and only handed over once the run
finished, so the UI showed nothing until the end despite the native layer
streaming line by line. The service republishes each line on outputLines and
the view model appends to a transcript as they arrive.

The channel handler was re-registered on every run and dereferenced
_runCompleter with `!`, which threw once a late callback arrived after the
field had been nulled. It is registered once in the constructor and reads the
completer through a local.

Also drops the duplicated argument list in favour of
TestConfiguration.toCliArgs(), so the flags the UI sends have one definition.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 19:03:22 +09:00
irene 815fc48a15 refactor: fix lint issues and wire up main screen
- Use const Iperf3Result constructor in tests
- Remove unused import from widget_test.dart
- Fix unnecessary underscore warnings in Consumer builders
- Use initializing formal for iperf3Service field
- Wire up main.dart to call Iperf3BinaryPathProvider.initialize()
2026-08-24 06:51:06 +09:00
irene a6922b6a27 feat: add TestRunViewModel with state management 2026-08-24 06:43:37 +09:00