blob: d0120c62fa71da9cd82cc5f81b831c3e3213b501 [file] [log] [blame]
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. 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:isolate';
import 'package:path/path.dart' as p;
import 'package:stream_channel/stream_channel.dart';
import '../../backend/test_platform.dart';
import '../../util/dart.dart' as dart;
import '../configuration.dart';
import '../load_exception.dart';
import '../plugin/platform.dart';
/// A platform that loads tests in isolates spawned within this Dart process.
class VMPlatform extends PlatformPlugin {
/// The test runner configuration.
final _config = Configuration.current;
VMPlatform();
StreamChannel loadChannel(String path, TestPlatform platform) {
assert(platform == TestPlatform.vm);
var isolate;
var channel = StreamChannelCompleter.fromFuture(() async {
var receivePort = new ReceivePort();
try {
isolate = await _spawnIsolate(path, receivePort.sendPort);
} catch (error) {
receivePort.close();
rethrow;
}
return new IsolateChannel.connectReceive(receivePort);
}());
// Once the connection is closed by either end, kill the isolate.
return channel
.transformStream(new StreamTransformer.fromHandlers(handleDone: (sink) {
if (isolate != null) isolate.kill();
sink.close();
}));
}
/// Spawns an isolate and passes it [message].
///
/// This isolate connects an [IsolateChannel] to [message] and sends the
/// serialized tests over that channel.
Future<Isolate> _spawnIsolate(String path, SendPort message) async {
if (_config.pubServeUrl == null) {
return await dart.runInIsolate('''
import "dart:isolate";
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 "${p.toUri(p.absolute(path))}" as test;
void main(_, SendPort message) {
var channel = serializeSuite(() {
catchIsolateErrors();
return test.main;
});
new IsolateChannel.connectSend(message).pipe(channel);
}
''', message, checked: true);
}
var url = _config.pubServeUrl
.resolveUri(p.toUri(p.relative(path, from: 'test') + '.vm_test.dart'));
try {
return await Isolate.spawnUri(url, [], message, checked: true);
} on IsolateSpawnException catch (error) {
if (error.message.contains("OS Error: Connection refused") ||
error.message.contains("The remote computer refused")) {
throw new LoadException(
path,
"Error getting $url: Connection refused\n"
'Make sure "pub serve" is running.');
} else if (error.message.contains("404 Not Found")) {
throw new LoadException(
path,
"Error getting $url: 404 Not Found\n"
'Make sure "pub serve" is serving the test/ directory.');
}
throw new LoadException(path, error);
}
}
}