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:
just-stuff-tm
2026-03-10 20:06:05 -04:00
parent 1913a5aa11
commit 9db79e9d40
4 changed files with 113 additions and 5 deletions
+21 -4
View File
@@ -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) {
+5 -1
View File
@@ -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());