mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
test(tcp): harden cancel-race handling and add coverage
- tighten late TCP connect error suppression to manual-cancel disconnecting/disconnected windows - keep TCP handshake failures surfaced outside explicit cancel flow - allow TcpScreen connect action when connector is scanning - add connector-level tests for late-error suppression classifier - add TcpScreen test covering connect from scanning state
This commit is contained in:
parent
1913a5aa11
commit
9db79e9d40
4 changed files with 113 additions and 5 deletions
|
|
@ -1059,10 +1059,14 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
await syncTime();
|
||||
} catch (error) {
|
||||
_appDebugLogService?.error('TCP connection error: $error', tag: 'TCP');
|
||||
final tcpConnectNoLongerActive =
|
||||
_activeTransport != MeshCoreTransportType.tcp ||
|
||||
_state != MeshCoreConnectionState.connecting;
|
||||
if (tcpConnectNoLongerActive) {
|
||||
final tcpConnectCancelledBeforeHandshake =
|
||||
shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: _manualDisconnect,
|
||||
state: _state,
|
||||
activeTransport: _activeTransport,
|
||||
tcpManagerConnected: _tcpManager.isConnected,
|
||||
);
|
||||
if (tcpConnectCancelledBeforeHandshake) {
|
||||
_appDebugLogService?.info(
|
||||
'Ignoring late TCP connect error after cancellation/switch: state=$_state transport=$_activeTransport',
|
||||
tag: 'TCP',
|
||||
|
|
@ -1074,6 +1078,19 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
static bool shouldIgnoreLateTcpConnectError({
|
||||
required bool manualDisconnect,
|
||||
required MeshCoreConnectionState state,
|
||||
required MeshCoreTransportType activeTransport,
|
||||
required bool tcpManagerConnected,
|
||||
}) {
|
||||
return manualDisconnect &&
|
||||
(state == MeshCoreConnectionState.disconnected ||
|
||||
state == MeshCoreConnectionState.disconnecting) &&
|
||||
(activeTransport != MeshCoreTransportType.tcp || !tcpManagerConnected);
|
||||
}
|
||||
|
||||
Future<void> connect(BluetoothDevice device, {String? displayName}) async {
|
||||
if (_state == MeshCoreConnectionState.connecting ||
|
||||
_state == MeshCoreConnectionState.connected) {
|
||||
|
|
|
|||
|
|
@ -224,7 +224,11 @@ class _TcpScreenState extends State<TcpScreen> {
|
|||
}
|
||||
|
||||
Future<void> _connectTcp() async {
|
||||
if (_connector.state != MeshCoreConnectionState.disconnected) return;
|
||||
if (_connector.state == MeshCoreConnectionState.connecting ||
|
||||
_connector.state == MeshCoreConnectionState.connected ||
|
||||
_connector.state == MeshCoreConnectionState.disconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
final host = _hostController.text.trim();
|
||||
final parsedPort = int.tryParse(_portController.text.trim());
|
||||
|
|
|
|||
64
test/connector/meshcore_connector_tcp_error_filter_test.dart
Normal file
64
test/connector/meshcore_connector_tcp_error_filter_test.dart
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_open/connector/meshcore_connector.dart';
|
||||
|
||||
void main() {
|
||||
group('shouldIgnoreLateTcpConnectError', () {
|
||||
test('returns true for manual cancel during disconnecting state', () {
|
||||
final result = MeshCoreConnector.shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: true,
|
||||
state: MeshCoreConnectionState.disconnecting,
|
||||
activeTransport: MeshCoreTransportType.bluetooth,
|
||||
tcpManagerConnected: false,
|
||||
);
|
||||
|
||||
expect(result, isTrue);
|
||||
});
|
||||
|
||||
test(
|
||||
'returns true for manual cancel after reaching disconnected state',
|
||||
() {
|
||||
final result = MeshCoreConnector.shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: true,
|
||||
state: MeshCoreConnectionState.disconnected,
|
||||
activeTransport: MeshCoreTransportType.bluetooth,
|
||||
tcpManagerConnected: false,
|
||||
);
|
||||
|
||||
expect(result, isTrue);
|
||||
},
|
||||
);
|
||||
|
||||
test('returns false when not a manual disconnect', () {
|
||||
final result = MeshCoreConnector.shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: false,
|
||||
state: MeshCoreConnectionState.disconnecting,
|
||||
activeTransport: MeshCoreTransportType.bluetooth,
|
||||
tcpManagerConnected: false,
|
||||
);
|
||||
|
||||
expect(result, isFalse);
|
||||
});
|
||||
|
||||
test('returns false for connected state handshake failures', () {
|
||||
final result = MeshCoreConnector.shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: true,
|
||||
state: MeshCoreConnectionState.connected,
|
||||
activeTransport: MeshCoreTransportType.tcp,
|
||||
tcpManagerConnected: true,
|
||||
);
|
||||
|
||||
expect(result, isFalse);
|
||||
});
|
||||
|
||||
test('returns false when TCP is still active while disconnecting', () {
|
||||
final result = MeshCoreConnector.shouldIgnoreLateTcpConnectError(
|
||||
manualDisconnect: true,
|
||||
state: MeshCoreConnectionState.disconnecting,
|
||||
activeTransport: MeshCoreTransportType.tcp,
|
||||
tcpManagerConnected: true,
|
||||
);
|
||||
|
||||
expect(result, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -135,6 +135,29 @@ void main() {
|
|||
await tester.pump(const Duration(milliseconds: 60));
|
||||
});
|
||||
|
||||
testWidgets('TcpScreen allows connect while connector is scanning', (
|
||||
tester,
|
||||
) async {
|
||||
final connector = _FakeMeshCoreConnector()
|
||||
..initialState = MeshCoreConnectionState.scanning;
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildTestApp(
|
||||
connector: connector,
|
||||
child: const TcpScreen(),
|
||||
locale: const Locale('en'),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Connect'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(connector.connectTcpCalls, 1);
|
||||
expect(connector.lastHost, '192.168.40.10');
|
||||
expect(connector.lastPort, 5000);
|
||||
});
|
||||
|
||||
testWidgets('TcpScreen narrow width long status text does not overflow', (
|
||||
tester,
|
||||
) async {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue