Chromium Code Reviews

Side by Side 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.
Jump to:
View unified diff |
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library test.runner.loader;
6
7 import 'dart:async';
8 import 'dart:io';
9 import 'dart:isolate';
10
11 import 'package:analyzer/analyzer.dart';
12 import 'package:async/async.dart';
13 import 'package:path/path.dart' as p;
14 import 'package:stack_trace/stack_trace.dart';
15
16 import '../backend/invoker.dart';
17 import '../backend/metadata.dart';
18 import '../backend/test_platform.dart';
19 import '../util/dart.dart' as dart;
20 import '../util/io.dart';
21 import '../util/remote_exception.dart';
22 import '../utils.dart';
23 import 'browser/server.dart';
24 import 'configuration.dart';
25 import 'hack_load_vm_file_hook.dart';
26 import 'load_exception.dart';
27 import 'load_suite.dart';
28 import 'parse_metadata.dart';
29 import 'runner_suite.dart';
30 import 'vm/environment.dart';
31 import 'vm/isolate_test.dart';
32
33 /// A class for finding test files and loading them into a runnable form.
34 class Loader {
35 /// The test runner configuration.
36 final Configuration _config;
37
38 /// The root directory that will be served for browser tests.
39 final String _root;
40
41 /// All suites that have been created by the loader.
42 final _suites = new Set<RunnerSuite>();
43
44 /// The server that serves browser test pages.
45 ///
46 /// This is lazily initialized the first time it's accessed.
47 Future<BrowserServer> get _browserServer {
48 return _browserServerMemo.runOnce(() {
49 return BrowserServer.start(_config, root: _root);
50 });
51 }
52 final _browserServerMemo = new AsyncMemoizer<BrowserServer>();
53
54 /// The memoizer for running [close] exactly once.
55 final _closeMemo = new AsyncMemoizer();
56
57 /// Creates a new loader that loads tests on platforms defined in [_config].
58 ///
59 /// [root] is the root directory that will be served for browser tests. It
60 /// defaults to the working directory.
61 Loader(this._config, {String root})
62 : _root = root == null ? p.current : root;
63
64 /// Loads all test suites in [dir].
65 ///
66 /// This will load tests from files that end in "_test.dart". Any tests that
67 /// fail to load will be emitted as [LoadException]s.
68 ///
69 /// This emits [LoadSuite]s that must then be run to emit the actual
70 /// [RunnerSuite]s defined in the file.
71 Stream<LoadSuite> loadDir(String dir) {
72 return mergeStreams(new Directory(dir).listSync(recursive: true)
73 .map((entry) {
74 if (entry is! File) return new Stream.fromIterable([]);
75
76 if (!entry.path.endsWith("_test.dart")) {
77 return new Stream.fromIterable([]);
78 }
79
80 if (p.split(entry.path).contains('packages')) {
81 return new Stream.fromIterable([]);
82 }
83
84 return loadFile(entry.path);
85 }));
86 }
87
88 /// Loads a test suite from the file at [path].
89 ///
90 /// This emits [LoadSuite]s that must then be run to emit the actual
91 /// [RunnerSuite]s defined in the file.
92 ///
93 /// This will emit a [LoadException] if the file fails to load.
94 Stream<LoadSuite> loadFile(String path) async* {
95 var suiteMetadata;
96 try {
97 suiteMetadata = parseMetadata(path);
98 } on AnalyzerErrorGroup catch (_) {
99 // Ignore the analyzer's error, since its formatting is much worse than
100 // the VM's or dart2js's.
101 suiteMetadata = new Metadata();
102 } on FormatException catch (error, stackTrace) {
103 yield new LoadSuite.forLoadException(
104 new LoadException(path, error), stackTrace: stackTrace);
105 return;
106 }
107 suiteMetadata = _config.metadata.merge(suiteMetadata);
108
109 if (_config.pubServeUrl != null && !p.isWithin('test', path)) {
110 yield new LoadSuite.forLoadException(new LoadException(
111 path, 'When using "pub serve", all test files must be in test/.'));
112 return;
113 }
114
115 for (var platform in _config.platforms) {
116 if (!suiteMetadata.testOn.evaluate(platform, os: currentOS)) continue;
117
118 var metadata = suiteMetadata.forPlatform(platform, os: currentOS);
119
120 // Don't load a skipped suite.
121 if (metadata.skip) {
122 yield new LoadSuite.forSuite(new RunnerSuite(const VMEnvironment(), [
123 new LocalTest(path, metadata, () {})
124 ], path: path, platform: platform, metadata: metadata));
125 continue;
126 }
127
128 var name = (platform.isJS ? "compiling " : "loading ") + path;
129 yield new LoadSuite(name, () {
130 return platform == TestPlatform.vm
131 ? _loadVmFile(path, metadata)
132 : _loadBrowserFile(path, platform, metadata);
133 }, platform: platform);
134 }
135 }
136
137 /// Load the test suite at [path] in [platform].
138 ///
139 /// [metadata] is the suite-level metadata for the test.
140 Future<RunnerSuite> _loadBrowserFile(String path, TestPlatform platform,
141 Metadata metadata) async =>
142 (await _browserServer).loadSuite(path, platform, metadata);
143
144 /// Load the test suite at [path] in VM isolate.
145 ///
146 /// [metadata] is the suite-level metadata for the test.
147 Future<RunnerSuite> _loadVmFile(String path, Metadata metadata) async {
148 if (loadVMFileHook != null) {
149 var suite = await loadVMFileHook(path, metadata, _config);
150 _suites.add(suite);
151 return suite;
152 }
153
154 var receivePort = new ReceivePort();
155
156 var isolate;
157 try {
158 if (_config.pubServeUrl != null) {
159 var url = _config.pubServeUrl.resolveUri(
160 p.toUri(p.relative(path, from: 'test') + '.vm_test.dart'));
161
162 try {
163 isolate = await Isolate.spawnUri(url, [], {
164 'reply': receivePort.sendPort,
165 'metadata': metadata.serialize()
166 }, checked: true);
167 } on IsolateSpawnException catch (error) {
168 if (error.message.contains("OS Error: Connection refused") ||
169 error.message.contains("The remote computer refused")) {
170 throw new LoadException(path,
171 "Error getting $url: Connection refused\n"
172 'Make sure "pub serve" is running.');
173 } else if (error.message.contains("404 Not Found")) {
174 throw new LoadException(path,
175 "Error getting $url: 404 Not Found\n"
176 'Make sure "pub serve" is serving the test/ directory.');
177 }
178
179 throw new LoadException(path, error);
180 }
181 } else {
182 isolate = await dart.runInIsolate('''
183 import "package:test/src/backend/metadata.dart";
184 import "package:test/src/runner/vm/isolate_listener.dart";
185
186 import "${p.toUri(p.absolute(path))}" as test;
187
188 void main(_, Map message) {
189 var sendPort = message['reply'];
190 var metadata = new Metadata.deserialize(message['metadata']);
191 IsolateListener.start(sendPort, metadata, () => test.main);
192 }
193 ''', {
194 'reply': receivePort.sendPort,
195 'metadata': metadata.serialize()
196 }, packageRoot: p.toUri(_config.packageRoot), checked: true);
197 }
198 } catch (error, stackTrace) {
199 receivePort.close();
200 if (error is LoadException) rethrow;
201 await new Future.error(new LoadException(path, error), stackTrace);
202 }
203
204 var completer = new Completer();
205
206 var subscription = receivePort.listen((response) {
207 if (response["type"] == "print") {
208 print(response["line"]);
209 } else if (response["type"] == "loadException") {
210 isolate.kill();
211 completer.completeError(
212 new LoadException(path, response["message"]),
213 new Trace.current());
214 } else if (response["type"] == "error") {
215 isolate.kill();
216 var asyncError = RemoteException.deserialize(response["error"]);
217 completer.completeError(
218 new LoadException(path, asyncError.error),
219 asyncError.stackTrace);
220 } else {
221 assert(response["type"] == "success");
222 completer.complete(response["tests"]);
223 }
224 });
225
226 try {
227 var suite = new RunnerSuite(const VMEnvironment(),
228 (await completer.future).map((test) {
229 var testMetadata = new Metadata.deserialize(test['metadata']);
230 return new IsolateTest(test['name'], testMetadata, test['sendPort']);
231 }),
232 metadata: metadata,
233 path: path,
234 platform: TestPlatform.vm,
235 os: currentOS,
236 onClose: isolate.kill);
237 _suites.add(suite);
238 return suite;
239 } finally {
240 subscription.cancel();
241 }
242 }
243
244 /// Closes the loader and releases all resources allocated by it.
245 Future close() {
246 return _closeMemo.runOnce(() async {
247 await Future.wait(_suites.map((suite) => suite.close()));
248 _suites.clear();
249
250 if (!_browserServerMemo.hasRun) return;
251 await (await _browserServer).close();
252 });
253 }
254 }
OLDNEW

Powered by Google App Engine