Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Unified Diff: mojo/public/dart/third_party/test/lib/src/runner/loader.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/public/dart/third_party/test/lib/src/runner/loader.dart
diff --git a/mojo/public/dart/third_party/test/lib/src/runner/loader.dart b/mojo/public/dart/third_party/test/lib/src/runner/loader.dart
new file mode 100644
index 0000000000000000000000000000000000000000..abf22b94f957633d5a77205253ff16402deb2b72
--- /dev/null
+++ b/mojo/public/dart/third_party/test/lib/src/runner/loader.dart
@@ -0,0 +1,254 @@
+// Copyright (c) 2015, 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.
+
+library test.runner.loader;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:analyzer/analyzer.dart';
+import 'package:async/async.dart';
+import 'package:path/path.dart' as p;
+import 'package:stack_trace/stack_trace.dart';
+
+import '../backend/invoker.dart';
+import '../backend/metadata.dart';
+import '../backend/test_platform.dart';
+import '../util/dart.dart' as dart;
+import '../util/io.dart';
+import '../util/remote_exception.dart';
+import '../utils.dart';
+import 'browser/server.dart';
+import 'configuration.dart';
+import 'hack_load_vm_file_hook.dart';
+import 'load_exception.dart';
+import 'load_suite.dart';
+import 'parse_metadata.dart';
+import 'runner_suite.dart';
+import 'vm/environment.dart';
+import 'vm/isolate_test.dart';
+
+/// A class for finding test files and loading them into a runnable form.
+class Loader {
+ /// The test runner configuration.
+ final Configuration _config;
+
+ /// The root directory that will be served for browser tests.
+ final String _root;
+
+ /// All suites that have been created by the loader.
+ final _suites = new Set<RunnerSuite>();
+
+ /// The server that serves browser test pages.
+ ///
+ /// This is lazily initialized the first time it's accessed.
+ Future<BrowserServer> get _browserServer {
+ return _browserServerMemo.runOnce(() {
+ return BrowserServer.start(_config, root: _root);
+ });
+ }
+ final _browserServerMemo = new AsyncMemoizer<BrowserServer>();
+
+ /// The memoizer for running [close] exactly once.
+ final _closeMemo = new AsyncMemoizer();
+
+ /// Creates a new loader that loads tests on platforms defined in [_config].
+ ///
+ /// [root] is the root directory that will be served for browser tests. It
+ /// defaults to the working directory.
+ Loader(this._config, {String root})
+ : _root = root == null ? p.current : root;
+
+ /// Loads all test suites in [dir].
+ ///
+ /// This will load tests from files that end in "_test.dart". Any tests that
+ /// fail to load will be emitted as [LoadException]s.
+ ///
+ /// This emits [LoadSuite]s that must then be run to emit the actual
+ /// [RunnerSuite]s defined in the file.
+ Stream<LoadSuite> loadDir(String dir) {
+ return mergeStreams(new Directory(dir).listSync(recursive: true)
+ .map((entry) {
+ if (entry is! File) return new Stream.fromIterable([]);
+
+ if (!entry.path.endsWith("_test.dart")) {
+ return new Stream.fromIterable([]);
+ }
+
+ if (p.split(entry.path).contains('packages')) {
+ return new Stream.fromIterable([]);
+ }
+
+ return loadFile(entry.path);
+ }));
+ }
+
+ /// Loads a test suite from the file at [path].
+ ///
+ /// This emits [LoadSuite]s that must then be run to emit the actual
+ /// [RunnerSuite]s defined in the file.
+ ///
+ /// This will emit a [LoadException] if the file fails to load.
+ Stream<LoadSuite> loadFile(String path) async* {
+ var suiteMetadata;
+ try {
+ suiteMetadata = parseMetadata(path);
+ } on AnalyzerErrorGroup catch (_) {
+ // Ignore the analyzer's error, since its formatting is much worse than
+ // the VM's or dart2js's.
+ suiteMetadata = new Metadata();
+ } on FormatException catch (error, stackTrace) {
+ yield new LoadSuite.forLoadException(
+ new LoadException(path, error), stackTrace: stackTrace);
+ return;
+ }
+ suiteMetadata = _config.metadata.merge(suiteMetadata);
+
+ if (_config.pubServeUrl != null && !p.isWithin('test', path)) {
+ yield new LoadSuite.forLoadException(new LoadException(
+ path, 'When using "pub serve", all test files must be in test/.'));
+ return;
+ }
+
+ for (var platform in _config.platforms) {
+ if (!suiteMetadata.testOn.evaluate(platform, os: currentOS)) continue;
+
+ var metadata = suiteMetadata.forPlatform(platform, os: currentOS);
+
+ // Don't load a skipped suite.
+ if (metadata.skip) {
+ yield new LoadSuite.forSuite(new RunnerSuite(const VMEnvironment(), [
+ new LocalTest(path, metadata, () {})
+ ], path: path, platform: platform, metadata: metadata));
+ continue;
+ }
+
+ var name = (platform.isJS ? "compiling " : "loading ") + path;
+ yield new LoadSuite(name, () {
+ return platform == TestPlatform.vm
+ ? _loadVmFile(path, metadata)
+ : _loadBrowserFile(path, platform, metadata);
+ }, platform: platform);
+ }
+ }
+
+ /// Load the test suite at [path] in [platform].
+ ///
+ /// [metadata] is the suite-level metadata for the test.
+ Future<RunnerSuite> _loadBrowserFile(String path, TestPlatform platform,
+ Metadata metadata) async =>
+ (await _browserServer).loadSuite(path, platform, metadata);
+
+ /// Load the test suite at [path] in VM isolate.
+ ///
+ /// [metadata] is the suite-level metadata for the test.
+ Future<RunnerSuite> _loadVmFile(String path, Metadata metadata) async {
+ if (loadVMFileHook != null) {
+ var suite = await loadVMFileHook(path, metadata, _config);
+ _suites.add(suite);
+ return suite;
+ }
+
+ var receivePort = new ReceivePort();
+
+ var isolate;
+ try {
+ if (_config.pubServeUrl != null) {
+ var url = _config.pubServeUrl.resolveUri(
+ p.toUri(p.relative(path, from: 'test') + '.vm_test.dart'));
+
+ try {
+ isolate = await Isolate.spawnUri(url, [], {
+ 'reply': receivePort.sendPort,
+ 'metadata': metadata.serialize()
+ }, 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);
+ }
+ } else {
+ isolate = await dart.runInIsolate('''
+import "package:test/src/backend/metadata.dart";
+import "package:test/src/runner/vm/isolate_listener.dart";
+
+import "${p.toUri(p.absolute(path))}" as test;
+
+void main(_, Map message) {
+ var sendPort = message['reply'];
+ var metadata = new Metadata.deserialize(message['metadata']);
+ IsolateListener.start(sendPort, metadata, () => test.main);
+}
+''', {
+ 'reply': receivePort.sendPort,
+ 'metadata': metadata.serialize()
+ }, packageRoot: p.toUri(_config.packageRoot), checked: true);
+ }
+ } catch (error, stackTrace) {
+ receivePort.close();
+ if (error is LoadException) rethrow;
+ await new Future.error(new LoadException(path, error), stackTrace);
+ }
+
+ var completer = new Completer();
+
+ var subscription = receivePort.listen((response) {
+ if (response["type"] == "print") {
+ print(response["line"]);
+ } else if (response["type"] == "loadException") {
+ isolate.kill();
+ completer.completeError(
+ new LoadException(path, response["message"]),
+ new Trace.current());
+ } else if (response["type"] == "error") {
+ isolate.kill();
+ var asyncError = RemoteException.deserialize(response["error"]);
+ completer.completeError(
+ new LoadException(path, asyncError.error),
+ asyncError.stackTrace);
+ } else {
+ assert(response["type"] == "success");
+ completer.complete(response["tests"]);
+ }
+ });
+
+ try {
+ var suite = new RunnerSuite(const VMEnvironment(),
+ (await completer.future).map((test) {
+ var testMetadata = new Metadata.deserialize(test['metadata']);
+ return new IsolateTest(test['name'], testMetadata, test['sendPort']);
+ }),
+ metadata: metadata,
+ path: path,
+ platform: TestPlatform.vm,
+ os: currentOS,
+ onClose: isolate.kill);
+ _suites.add(suite);
+ return suite;
+ } finally {
+ subscription.cancel();
+ }
+ }
+
+ /// Closes the loader and releases all resources allocated by it.
+ Future close() {
+ return _closeMemo.runOnce(() async {
+ await Future.wait(_suites.map((suite) => suite.close()));
+ _suites.clear();
+
+ if (!_browserServerMemo.hasRun) return;
+ await (await _browserServer).close();
+ });
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698