Files
Rtty/desktop/test/regression_ws_test.dart

78 lines
3.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 多端解耦 + 控制权强制回归验证(连真实 Rust 服务端)。
import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:web_socket_channel/io.dart';
import 'support.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('多端解耦 + 控制权强制 + 会话清理', () async {
if (!await isServerUp('127.0.0.1', 8080)) {
markTestSkipped('Rtty server not running');
return;
}
final base = 'ws://127.0.0.1:8080/ws';
// 1. 桌面端client=desktop收 raw 二进制,不收 snapshot。
final desktop = IOWebSocketChannel.connect(Uri.parse('$base?client=desktop'));
final dOut = <String>[];
desktop.stream.listen((m) {
if (m is List<int>) {
dOut.add('binary:${utf8.decode(m, allowMalformed: true)}');
} else if (m is String) {
dOut.add('text:${m.length > 100 ? m.substring(0, 100) : m}');
} else {
dOut.add('$m');
}
});
await Future<void>.delayed(const Duration(milliseconds: 700));
final dHasBinary = dOut.any((e) => e.startsWith('binary:'));
final dHasSnapshot = dOut.any((e) => e.contains('mobile_snapshot'));
expect(dHasBinary, isTrue, reason: '桌面端应收到原始 ANSI 二进制 $dOut');
expect(dHasSnapshot, isFalse, reason: '桌面端不应收到语义快照 $dOut');
// 2. 移动端client=mobile收 snapshot不收 binary。
final mobile = IOWebSocketChannel.connect(Uri.parse('$base?client=mobile'));
final mOut = <String>[];
mobile.stream.listen((m) {
if (m is List<int>) {
mOut.add('binary:${utf8.decode(m, allowMalformed: true)}');
} else if (m is String) {
mOut.add('text:${m.length > 100 ? m.substring(0, 100) : m}');
} else {
mOut.add('$m');
}
});
await Future<void>.delayed(const Duration(milliseconds: 700));
final mHasSnapshot = mOut.any((e) => e.contains('mobile_snapshot'));
final mHasBinary = mOut.any((e) => e.startsWith('binary:'));
expect(mHasSnapshot, isTrue, reason: '移动端应收到语义快照 $mOut');
expect(mHasBinary, isFalse, reason: '移动端不应收到二进制 $mOut');
// 3. 桌面端发命令,确认 raw 输出回显。
desktop.sink.add(jsonEncode({'type': 'input', 'data': 'echo D_E2E\r\n'}));
await Future<void>.delayed(const Duration(milliseconds: 900));
expect(dOut.join('\n').contains('D_E2E'), isTrue, reason: '桌面端命令回显');
// 4. 控制权强制:桌面端 claim 后,移动端输入被拒。
desktop.sink.add(jsonEncode({'type': 'claim_control'}));
await Future<void>.delayed(const Duration(milliseconds: 400));
mobile.sink
.add(jsonEncode({'type': 'input', 'data': 'echo BLOCKED_SHOULD_NOT_SHOW\r\n'}));
await Future<void>.delayed(const Duration(milliseconds: 900));
final both = (dOut.join('\n') + mOut.join('\n'));
expect(both.contains('BLOCKED_SHOULD_NOT_SHOW'), isFalse,
reason: '非控制者输入应被阻止');
// 5. 会话清理exit 触发会话移除。
desktop.sink.add(jsonEncode({'type': 'input', 'data': 'exit\r\n'}));
await Future<void>.delayed(const Duration(milliseconds: 1300));
desktop.sink.close();
mobile.sink.close();
});
}