134 lines
4.1 KiB
Dart
134 lines
4.1 KiB
Dart
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:async/async.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'package:stream_channel/stream_channel.dart';
|
|
|
|
import 'package:test/src/backend/test_platform.dart'; // ignore: implementation_imports
|
|
import 'package:test/src/runner/plugin/platform.dart'; // ignore: implementation_imports
|
|
import 'package:test/src/runner/plugin/hack_register_platform.dart' as hack; // ignore: implementation_imports
|
|
|
|
import '../artifacts.dart';
|
|
|
|
final String _kSkyShell = Platform.environment['SKY_SHELL'];
|
|
const String _kHost = '127.0.0.1';
|
|
const String _kPath = '/runner';
|
|
|
|
String shellPath;
|
|
|
|
void installHook() {
|
|
hack.registerPlatformPlugin([TestPlatform.vm], () => new FlutterPlatform());
|
|
}
|
|
|
|
class _ServerInfo {
|
|
final String url;
|
|
final Future<WebSocket> socket;
|
|
final HttpServer server;
|
|
|
|
_ServerInfo(this.server, this.url, this.socket);
|
|
}
|
|
|
|
Future<_ServerInfo> _startServer() async {
|
|
HttpServer server = await HttpServer.bind(_kHost, 0);
|
|
Completer<WebSocket> socket = new Completer<WebSocket>();
|
|
server.listen((HttpRequest request) {
|
|
if (request.uri.path == _kPath)
|
|
socket.complete(WebSocketTransformer.upgrade(request));
|
|
});
|
|
return new _ServerInfo(server, 'ws://$_kHost:${server.port}$_kPath', socket.future);
|
|
}
|
|
|
|
Future<Process> _startProcess(String mainPath, { String packageRoot }) {
|
|
assert(shellPath != null || _kSkyShell != null); // Please provide the path to the shell in the SKY_SHELL environment variable.
|
|
return Process.start(shellPath ?? _kSkyShell, [
|
|
'--enable-checked-mode',
|
|
'--non-interactive',
|
|
'--package-root=$packageRoot',
|
|
mainPath,
|
|
]);
|
|
}
|
|
|
|
class FlutterPlatform extends PlatformPlugin {
|
|
StreamChannel<String> loadChannel(String mainPath, TestPlatform platform) {
|
|
return StreamChannelCompleter.fromFuture(_startTest(mainPath));
|
|
}
|
|
|
|
Future<StreamChannel<String>> _startTest(String mainPath) async {
|
|
_ServerInfo info = await _startServer();
|
|
Directory tempDir = Directory.systemTemp.createTempSync(
|
|
'dart_test_listener');
|
|
File listenerFile = new File('${tempDir.path}/listener.dart');
|
|
listenerFile.createSync();
|
|
listenerFile.writeAsStringSync('''
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:stream_channel/stream_channel.dart';
|
|
import 'package:test/src/runner/plugin/remote_platform_helpers.dart';
|
|
import 'package:test/src/runner/vm/catch_isolate_errors.dart';
|
|
|
|
import '${path.toUri(path.absolute(mainPath))}' as test;
|
|
|
|
void main() {
|
|
String server = Uri.decodeComponent('${Uri.encodeComponent(info.url)}');
|
|
StreamChannel channel = serializeSuite(() {
|
|
catchIsolateErrors();
|
|
return test.main;
|
|
});
|
|
WebSocket.connect(server).then((WebSocket socket) {
|
|
socket.map(JSON.decode).pipe(channel.sink);
|
|
socket.addStream(channel.stream.map(JSON.encode));
|
|
});
|
|
}
|
|
''');
|
|
|
|
Process process = await _startProcess(
|
|
listenerFile.path,
|
|
packageRoot: path.absolute(ArtifactStore.packageRoot)
|
|
);
|
|
|
|
void finalize() {
|
|
if (process != null) {
|
|
Process processToKill = process;
|
|
process = null;
|
|
processToKill.kill();
|
|
}
|
|
if (tempDir != null) {
|
|
Directory dirToDelete = tempDir;
|
|
tempDir = null;
|
|
dirToDelete.deleteSync(recursive: true);
|
|
}
|
|
}
|
|
|
|
try {
|
|
WebSocket socket = await info.socket;
|
|
StreamChannel<String> channel = new StreamChannel<String>(socket.map(JSON.decode), socket);
|
|
return channel.transformStream(
|
|
new StreamTransformer<String, String>.fromHandlers(
|
|
handleDone: (EventSink<String> sink) {
|
|
finalize();
|
|
sink.close();
|
|
}
|
|
)
|
|
).transformSink(new StreamSinkTransformer<String, String>.fromHandlers(
|
|
handleData: (String data, StreamSink<String> sink) {
|
|
sink.add(JSON.encode(data));
|
|
},
|
|
handleDone: (EventSink<String> sink) {
|
|
finalize();
|
|
sink.close();
|
|
}
|
|
));
|
|
} catch(e) {
|
|
finalize();
|
|
rethrow;
|
|
}
|
|
}
|
|
}
|