proto-socket/dart/crosstest/dart_web.dart

142 lines
4.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 _wssPort = 29099;
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;
final _certFile = '$_repoRoot/dart/test/certs/server.crt';
final _keyFile = '$_repoRoot/dart/test/certs/server.key';
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));
_DartWebWsServer.secure(
int port, SecurityContext securityContext, this.onConnected)
: super.secure(_host, port, securityContext, (ws) => _ServerWsClient(ws));
@override
void onClientConnected(WsProtobufClient client) => onConnected(client);
}
Future<void> main() async {
print(
'INFO typeName dart=${TestData.getDefault().info_.qualifiedMessageName}');
try {
await _runWebSuites();
print('PASS scenario=ws-send-push');
print('PASS scenario=ws-request-response');
print('PASS scenario=wss-send-push');
print('PASS scenario=wss-request-response');
print('PASS all dart-server/dart-web-client crosstests passed');
} catch (error) {
stderr.writeln('FAIL crosstest error=$error');
exitCode = 1;
}
}
Future<void> _runWebSuites() async {
final wsReceived = Completer<bool>();
final wssReceived = Completer<bool>();
final securityContext = SecurityContext()
..useCertificateChain(_certFile)
..usePrivateKey(_keyFile);
final wsServer = _DartWebWsServer(_wsPort, (client) {
_configureWebClient(client, wsReceived);
});
final wssServer =
_DartWebWsServer.secure(_wssPort, securityContext, (client) {
_configureWebClient(client, wssReceived);
});
await wsServer.start();
await wssServer.start();
try {
await _runDartBrowserTest('test/browser_ws_dart_io_test.dart');
await _expectReceived('WS', wsReceived);
await _expectReceived('WSS', wssReceived);
} finally {
await Future.wait([
wssServer.stop(),
wsServer.stop(),
]);
}
}
void _configureWebClient(WsProtobufClient client, Completer<bool> received) {
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}';
});
}
Future<void> _expectReceived(String transport, Completer<bool> received) async {
final ok = await received.future
.timeout(_serverObservationWindow, onTimeout: () => false);
if (!ok) {
throw StateError(
'$transport web send-push server did not receive expected data');
}
}
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');
}
}