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

Side by Side Diff: lib/src/runner/loader.dart

Issue 1196413003: Add a LoadSuite class. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library test.runner.loader; 5 library test.runner.loader;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 import 'dart:isolate'; 9 import 'dart:isolate';
10 10
11 import 'package:analyzer/analyzer.dart'; 11 import 'package:analyzer/analyzer.dart';
12 import 'package:path/path.dart' as p; 12 import 'package:path/path.dart' as p;
13 import 'package:stack_trace/stack_trace.dart';
13 14
14 import '../backend/invoker.dart'; 15 import '../backend/invoker.dart';
15 import '../backend/metadata.dart'; 16 import '../backend/metadata.dart';
16 import '../backend/suite.dart'; 17 import '../backend/suite.dart';
17 import '../backend/test_platform.dart'; 18 import '../backend/test_platform.dart';
18 import '../util/async_thunk.dart'; 19 import '../util/async_thunk.dart';
19 import '../util/dart.dart' as dart; 20 import '../util/dart.dart' as dart;
20 import '../util/io.dart'; 21 import '../util/io.dart';
21 import '../util/isolate_wrapper.dart'; 22 import '../util/isolate_wrapper.dart';
22 import '../util/remote_exception.dart'; 23 import '../util/remote_exception.dart';
23 import '../utils.dart'; 24 import '../utils.dart';
24 import 'browser/server.dart'; 25 import 'browser/server.dart';
25 import 'load_exception.dart'; 26 import 'load_exception.dart';
27 import 'load_suite.dart';
26 import 'parse_metadata.dart'; 28 import 'parse_metadata.dart';
27 import 'vm/isolate_test.dart'; 29 import 'vm/isolate_test.dart';
28 30
29 /// A class for finding test files and loading them into a runnable form. 31 /// A class for finding test files and loading them into a runnable form.
30 class Loader { 32 class Loader {
31 /// All platforms for which tests should be loaded. 33 /// All platforms for which tests should be loaded.
32 final List<TestPlatform> _platforms; 34 final List<TestPlatform> _platforms;
33 35
34 /// Whether to enable colors for Dart compilation. 36 /// Whether to enable colors for Dart compilation.
35 final bool _color; 37 final bool _color;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 _root = root == null ? p.current : root, 99 _root = root == null ? p.current : root,
98 _packageRoot = packageRootFor(root, packageRoot), 100 _packageRoot = packageRootFor(root, packageRoot),
99 _color = color, 101 _color = color,
100 _jsTrace = jsTrace, 102 _jsTrace = jsTrace,
101 _metadata = metadata == null ? new Metadata() : metadata; 103 _metadata = metadata == null ? new Metadata() : metadata;
102 104
103 /// Loads all test suites in [dir]. 105 /// Loads all test suites in [dir].
104 /// 106 ///
105 /// This will load tests from files that end in "_test.dart". Any tests that 107 /// This will load tests from files that end in "_test.dart". Any tests that
106 /// fail to load will be emitted as [LoadException]s. 108 /// fail to load will be emitted as [LoadException]s.
107 Stream<Suite> loadDir(String dir) { 109 ///
110 /// This emits [LoadSuite]s that must then be run to emit the actual [Suite]s
111 /// defined in the file.
112 Stream<LoadSuite> loadDir(String dir) {
108 return mergeStreams(new Directory(dir).listSync(recursive: true) 113 return mergeStreams(new Directory(dir).listSync(recursive: true)
109 .map((entry) { 114 .map((entry) {
110 if (entry is! File) return new Stream.fromIterable([]); 115 if (entry is! File) return new Stream.fromIterable([]);
111 116
112 if (!entry.path.endsWith("_test.dart")) { 117 if (!entry.path.endsWith("_test.dart")) {
113 return new Stream.fromIterable([]); 118 return new Stream.fromIterable([]);
114 } 119 }
115 120
116 if (p.split(entry.path).contains('packages')) { 121 if (p.split(entry.path).contains('packages')) {
117 return new Stream.fromIterable([]); 122 return new Stream.fromIterable([]);
118 } 123 }
119 124
120 return loadFile(entry.path); 125 return loadFile(entry.path);
121 })); 126 }));
122 } 127 }
123 128
124 /// Loads a test suite from the file at [path]. 129 /// Loads a test suite from the file at [path].
125 /// 130 ///
131 /// This emits [LoadSuite]s that must then be run to emit the actual [Suite]s
132 /// defined in the file.
133 ///
126 /// This will emit a [LoadException] if the file fails to load. 134 /// This will emit a [LoadException] if the file fails to load.
127 Stream<Suite> loadFile(String path) async* { 135 Stream<LoadSuite> loadFile(String path) async* {
128 var suiteMetadata; 136 var suiteMetadata;
129 try { 137 try {
130 suiteMetadata = parseMetadata(path); 138 suiteMetadata = parseMetadata(path);
131 } on AnalyzerErrorGroup catch (_) { 139 } on AnalyzerErrorGroup catch (_) {
132 // Ignore the analyzer's error, since its formatting is much worse than 140 // Ignore the analyzer's error, since its formatting is much worse than
133 // the VM's or dart2js's. 141 // the VM's or dart2js's.
134 suiteMetadata = new Metadata(); 142 suiteMetadata = new Metadata();
135 } on FormatException catch (error, stackTrace) { 143 } on FormatException catch (error, stackTrace) {
136 await new Future.error(new LoadException(path, error), stackTrace); 144 yield new LoadSuite.forLoadException(
145 new LoadException(path, error), stackTrace: stackTrace);
146 return;
137 } 147 }
138 suiteMetadata = _metadata.merge(suiteMetadata); 148 suiteMetadata = _metadata.merge(suiteMetadata);
139 149
150 if (_pubServeUrl != null && !p.isWithin('test', path)) {
151 yield new LoadSuite.forLoadException(new LoadException(
152 path, 'When using "pub serve", all test files must be in test/.'));
153 return;
154 }
155
140 for (var platform in _platforms) { 156 for (var platform in _platforms) {
141 if (!suiteMetadata.testOn.evaluate(platform, os: currentOS)) continue; 157 if (!suiteMetadata.testOn.evaluate(platform, os: currentOS)) continue;
142 158
143 var metadata = suiteMetadata.forPlatform(platform, os: currentOS); 159 var metadata = suiteMetadata.forPlatform(platform, os: currentOS);
144 160
145 // Don't load a skipped suite. 161 // Don't load a skipped suite.
146 if (metadata.skip) { 162 if (metadata.skip) {
147 yield new Suite([ 163 yield new LoadSuite.forSuite(new Suite([
148 new LocalTest(path, metadata, () {}) 164 new LocalTest(path, metadata, () {})
149 ], path: path, platform: platform.name, metadata: metadata); 165 ], path: path, platform: platform.name, metadata: metadata));
150 continue; 166 continue;
151 } 167 }
152 168
153 try { 169 var name = (platform.isJS ? "compiling " : "loading ") + path;
154 if (_pubServeUrl != null && !p.isWithin('test', path)) { 170 yield new LoadSuite(name, () {
155 throw new LoadException(path, 171 return platform == TestPlatform.vm
156 'When using "pub serve", all test files must be in test/.'); 172 ? _loadVmFile(path, metadata)
157 } 173 : _loadBrowserFile(path, platform, metadata);
158 174 }, platform: platform.name);
159 var suite = platform == TestPlatform.vm
160 ? await _loadVmFile(path, metadata)
161 : await _loadBrowserFile(path, platform, metadata);
162 if (suite != null) yield suite;
163 } catch (error, stackTrace) {
164 yield* errorStream(error, stackTrace);
165 }
166 } 175 }
167 } 176 }
168 177
169 /// Load the test suite at [path] in [platform]. 178 /// Load the test suite at [path] in [platform].
170 /// 179 ///
171 /// [metadata] is the suite-level metadata for the test. 180 /// [metadata] is the suite-level metadata for the test.
172 Future<Suite> _loadBrowserFile(String path, TestPlatform platform, 181 Future<Suite> _loadBrowserFile(String path, TestPlatform platform,
173 Metadata metadata) async => 182 Metadata metadata) async =>
174 (await _browserServer).loadSuite(path, platform, metadata); 183 (await _browserServer).loadSuite(path, platform, metadata);
175 184
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 'metadata': metadata.serialize() 234 'metadata': metadata.serialize()
226 }, packageRoot: p.toUri(_packageRoot), checked: true); 235 }, packageRoot: p.toUri(_packageRoot), checked: true);
227 } 236 }
228 } catch (error, stackTrace) { 237 } catch (error, stackTrace) {
229 receivePort.close(); 238 receivePort.close();
230 if (error is LoadException) rethrow; 239 if (error is LoadException) rethrow;
231 await new Future.error(new LoadException(path, error), stackTrace); 240 await new Future.error(new LoadException(path, error), stackTrace);
232 } 241 }
233 242
234 _isolates.add(isolate); 243 _isolates.add(isolate);
235 var response = await receivePort.first;
236 244
237 if (response["type"] == "loadException") { 245 var completer = new Completer();
238 throw new LoadException(path, response["message"]); 246
239 } else if (response["type"] == "error") { 247 var subscription = receivePort.listen((response) {
240 var asyncError = RemoteException.deserialize(response["error"]); 248 if (response["type"] == "print") {
241 await new Future.error( 249 print(response["line"]);
242 new LoadException(path, asyncError.error), 250 } else if (response["type"] == "loadException") {
243 asyncError.stackTrace); 251 completer.completeError(
252 new LoadException(path, response["message"]),
253 new Trace.current());
254 } else if (response["type"] == "error") {
255 var asyncError = RemoteException.deserialize(response["error"]);
256 completer.completeError(
257 new LoadException(path, asyncError.error),
258 asyncError.stackTrace);
259 } else {
260 assert(response["type"] == "success");
261 completer.complete(response["tests"]);
262 }
263 });
264
265 try {
266 return new Suite((await completer.future).map((test) {
267 var testMetadata = new Metadata.deserialize(test['metadata']);
268 return new IsolateTest(test['name'], testMetadata, test['sendPort']);
269 }), metadata: metadata, path: path, platform: "VM");
270 } finally {
271 subscription.cancel();
244 } 272 }
245
246 return new Suite(response["tests"].map((test) {
247 var testMetadata = new Metadata.deserialize(test['metadata']);
248 return new IsolateTest(test['name'], testMetadata, test['sendPort']);
249 }), metadata: metadata, path: path, platform: "VM");
250 } 273 }
251 274
252 /// Closes the loader and releases all resources allocated by it. 275 /// Closes the loader and releases all resources allocated by it.
253 Future close() { 276 Future close() {
254 return _closeThunk.run(() async { 277 return _closeThunk.run(() async {
255 for (var isolate in _isolates) { 278 for (var isolate in _isolates) {
256 isolate.kill(); 279 isolate.kill();
257 } 280 }
258 _isolates.clear(); 281 _isolates.clear();
259 282
260 if (!_browserServerThunk.hasRun) return; 283 if (!_browserServerThunk.hasRun) return;
261 await (await _browserServer).close(); 284 await (await _browserServer).close();
262 }); 285 });
263 } 286 }
264 } 287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698