proto-socket/dart/crosstest/dart_web.dart
toki 5df325bf96 feat: Dart Web E2E 테스트 및 크로스 테스트 추가
- Dart Web 브라우저 E2E 테스트 프레임워크 추가
- browser_ws_dart_io_test, browser_ws_kotlin_test 등 브라우저 통합 테스트 추가
- Dart Web 크로스테스트 케이스 추가 (go, kotlin, python, typescript)
- TypeScript 브라우저 웹소켓 클라이언트 개선
- Node.js 웹소켓 서버 클라이언트 업데이트
- 테스트 실행 매트릭스 스킬 및 스크립트 업데이트
- README.md 문서 업데이트
2026-05-25 00:30:37 +09:00

111 lines
3.3 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:proto_socket/proto_socket.dart';
const _host = '127.0.0.1';
const _wsPort = 29098;
const _heartbeatIntervalSeconds = 30;
const _heartbeatWaitSeconds = 10;
const _serverObservationWindow = Duration(milliseconds: 500);
const _processTimeout = Duration(seconds: 60);
const _streamTimeout = Duration(seconds: 5);
final _repoRoot = File.fromUri(Platform.script).parent.parent.parent.path;
final _dartDir = Directory('$_repoRoot/dart').path;
class _ServerWsClient extends WsProtobufClient {
_ServerWsClient(WebSocket ws)
: super(ws, _heartbeatIntervalSeconds, _heartbeatWaitSeconds, {
TestData.getDefault().info_.qualifiedMessageName: TestData.fromBuffer,
});
}
class _DartWebWsServer extends WsProtobufServer {
final void Function(WsProtobufClient) onConnected;
_DartWebWsServer(int port, this.onConnected)
: super(_host, port, (ws) => _ServerWsClient(ws));
@override
void onClientConnected(WsProtobufClient client) => onConnected(client);
}
Future<void> main() async {
print(
'INFO typeName dart=${TestData.getDefault().info_.qualifiedMessageName}');
try {
await _runWebWsSuite();
print('PASS scenario=send-push');
print('PASS scenario=request-response');
print('PASS all dart-server/dart-web-client crosstests passed');
} catch (error) {
stderr.writeln('FAIL crosstest error=$error');
exitCode = 1;
}
}
Future<void> _runWebWsSuite() async {
final received = Completer<bool>();
final server = _DartWebWsServer(_wsPort, (client) {
client.addRequestListener<TestData, TestData>((req) async {
print('SERVER_RECEIVED index=${req.index} message=${req.message}');
if (req.index == 101 && req.message == 'fire from dart web client') {
if (!received.isCompleted) {
received.complete(true);
}
unawaited(client.send(TestData()
..index = 200
..message = 'push from dart server'));
}
return TestData()
..index = req.index * 2
..message = 'echo: ${req.message}';
});
});
await server.start();
try {
await _runDartBrowserTest('test/browser_ws_dart_io_test.dart');
final ok = await received.future
.timeout(_serverObservationWindow, onTimeout: () => false);
if (!ok) {
throw StateError('WS web send-push server did not receive expected data');
}
} finally {
await server.stop();
}
}
Future<void> _runDartBrowserTest(String testPath) async {
final process = await Process.start(
'dart',
['test', '-p', 'chrome', testPath],
workingDirectory: _dartDir,
);
final stdoutDone = process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(print)
.asFuture<void>();
final stderrDone = process.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(stderr.writeln)
.asFuture<void>();
final code = await process.exitCode.timeout(_processTimeout, onTimeout: () {
process.kill(ProcessSignal.sigkill);
return -1;
});
await Future.wait([stdoutDone, stderrDone])
.timeout(_streamTimeout, onTimeout: () {
throw StateError('dart browser test streams did not finish');
});
if (code != 0) {
throw StateError('dart browser test failed exitCode=$code');
}
}