import 'dart:async'; import 'package:iperf3gui/domain/models/iperf3_event.dart'; import 'package:iperf3gui/domain/models/iperf3_result.dart'; import 'package:iperf3gui/domain/models/test_configuration.dart'; import 'package:iperf3gui/domain/services/iperf3_runner.dart'; /// In-memory [Iperf3Runner] for tests. /// /// Implements the interface rather than the concrete service, so it tracks the /// five members the UI actually depends on instead of every public member the /// MethodChannel implementation happens to have. class FakeIperf3Runner implements Iperf3Runner { FakeIperf3Runner({this.onRun}); /// Supplies the result for each [run], and may [emit] events first. Future Function(TestConfiguration)? onRun; final StreamController _controller = StreamController.broadcast(); /// Configurations passed to [run], in order. final List runCalls = []; int stopCallCount = 0; bool disposed = false; bool _isRunning = false; int get runCallCount => runCalls.length; /// Push an event as if the native layer had reported it. void emit(Iperf3Event event) => _controller.add(event); @override Stream get events => _controller.stream; @override bool get isRunning => _isRunning; @override Future run(TestConfiguration config) async { runCalls.add(config); _isRunning = true; try { if (onRun != null) return await onRun!(config); return const Iperf3Result(rawOutput: '', exitCode: 0); } finally { _isRunning = false; } } @override Future stop() async { stopCallCount++; } @override Future dispose() async { disposed = true; await _controller.close(); } }