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

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

Issue 1062523003: Add support for --pub-serve. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 8 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 13
14 import '../backend/metadata.dart'; 14 import '../backend/metadata.dart';
15 import '../backend/suite.dart'; 15 import '../backend/suite.dart';
16 import '../backend/test_platform.dart'; 16 import '../backend/test_platform.dart';
17 import '../util/dart.dart'; 17 import '../util/dart.dart';
18 import '../util/io.dart'; 18 import '../util/io.dart';
19 import '../util/isolate_wrapper.dart';
19 import '../util/remote_exception.dart'; 20 import '../util/remote_exception.dart';
20 import '../utils.dart'; 21 import '../utils.dart';
21 import 'browser/server.dart'; 22 import 'browser/server.dart';
22 import 'load_exception.dart'; 23 import 'load_exception.dart';
23 import 'parse_metadata.dart'; 24 import 'parse_metadata.dart';
24 import 'vm/isolate_test.dart'; 25 import 'vm/isolate_test.dart';
25 26
26 /// A class for finding test files and loading them into a runnable form. 27 /// A class for finding test files and loading them into a runnable form.
27 class Loader { 28 class Loader {
28 /// All platforms for which tests should be loaded. 29 /// All platforms for which tests should be loaded.
29 final List<TestPlatform> _platforms; 30 final List<TestPlatform> _platforms;
30 31
31 /// Whether to enable colors for Dart compilation. 32 /// Whether to enable colors for Dart compilation.
32 final bool _color; 33 final bool _color;
33 34
34 /// The package root to use for loading tests, or `null` to use the automatic 35 /// The package root to use for loading tests, or `null` to use the automatic
35 /// root. 36 /// root.
36 final String _packageRoot; 37 final String _packageRoot;
37 38
39 /// The URL for the `pub serve` instance to use to load tests.
40 ///
41 /// This is `null` if tests should be loaded from the filesystem.
42 final Uri _pubServeUrl;
43
38 /// All isolates that have been spun up by the loader. 44 /// All isolates that have been spun up by the loader.
39 final _isolates = new Set<Isolate>(); 45 final _isolates = new Set<Isolate>();
40 46
41 /// The server that serves browser test pages. 47 /// The server that serves browser test pages.
42 /// 48 ///
43 /// This is lazily initialized the first time it's accessed. 49 /// This is lazily initialized the first time it's accessed.
44 Future<BrowserServer> get _browserServer { 50 Future<BrowserServer> get _browserServer {
45 if (_browserServerCompleter == null) { 51 if (_browserServerCompleter == null) {
46 _browserServerCompleter = new Completer(); 52 _browserServerCompleter = new Completer();
47 BrowserServer.start(packageRoot: _packageRoot, color: _color) 53 BrowserServer.start(
54 packageRoot: _packageRoot,
55 pubServeUrl: _pubServeUrl,
56 color: _color)
48 .then(_browserServerCompleter.complete) 57 .then(_browserServerCompleter.complete)
49 .catchError(_browserServerCompleter.completeError); 58 .catchError(_browserServerCompleter.completeError);
50 } 59 }
51 return _browserServerCompleter.future; 60 return _browserServerCompleter.future;
52 } 61 }
53 Completer<BrowserServer> _browserServerCompleter; 62 Completer<BrowserServer> _browserServerCompleter;
54 63
55 /// Creates a new loader. 64 /// Creates a new loader.
56 /// 65 ///
57 /// If [packageRoot] is passed, it's used as the package root for all loaded 66 /// If [packageRoot] is passed, it's used as the package root for all loaded
58 /// tests. Otherwise, the `packages/` directories next to the test entrypoints 67 /// tests. Otherwise, the `packages/` directories next to the test entrypoints
59 /// will be used. 68 /// will be used.
60 /// 69 ///
70 /// If [pubServeUrl] is passed, tests will be loaded from the `pub serve`
71 /// instance at that URL rather than from the filesystem.
72 ///
61 /// If [color] is true, console colors will be used when compiling Dart. 73 /// If [color] is true, console colors will be used when compiling Dart.
62 Loader(Iterable<TestPlatform> platforms, {String packageRoot, 74 Loader(Iterable<TestPlatform> platforms, {String packageRoot,
63 bool color: false}) 75 Uri pubServeUrl, bool color: false})
64 : _platforms = platforms.toList(), 76 : _platforms = platforms.toList(),
77 _pubServeUrl = pubServeUrl,
65 _packageRoot = packageRoot, 78 _packageRoot = packageRoot,
66 _color = color; 79 _color = color;
67 80
68 /// Loads all test suites in [dir]. 81 /// Loads all test suites in [dir].
69 /// 82 ///
70 /// This will load tests from files that end in "_test.dart". 83 /// This will load tests from files that end in "_test.dart".
71 Future<List<Suite>> loadDir(String dir) { 84 Future<List<Suite>> loadDir(String dir) {
72 return Future.wait(new Directory(dir).listSync(recursive: true) 85 return Future.wait(new Directory(dir).listSync(recursive: true)
73 .map((entry) { 86 .map((entry) {
74 if (entry is! File) return new Future.value([]); 87 if (entry is! File) return new Future.value([]);
(...skipping 18 matching lines...) Expand all
93 // the VM's or dart2js's. 106 // the VM's or dart2js's.
94 metadata = new Metadata(); 107 metadata = new Metadata();
95 } on FormatException catch (error) { 108 } on FormatException catch (error) {
96 throw new LoadException(path, error); 109 throw new LoadException(path, error);
97 } 110 }
98 111
99 return Future.wait(_platforms.map((platform) { 112 return Future.wait(_platforms.map((platform) {
100 return new Future.sync(() { 113 return new Future.sync(() {
101 if (!metadata.testOn.evaluate(platform, os: currentOS)) return null; 114 if (!metadata.testOn.evaluate(platform, os: currentOS)) return null;
102 115
116 if (_pubServeUrl != null && !p.isWithin('test', path)) {
117 throw new LoadException(path,
118 'When using "pub serve", all test files must be in test/.');
119 }
120
103 if (platform == TestPlatform.chrome) return _loadBrowserFile(path); 121 if (platform == TestPlatform.chrome) return _loadBrowserFile(path);
104 assert(platform == TestPlatform.vm); 122 assert(platform == TestPlatform.vm);
105 return _loadVmFile(path); 123 return _loadVmFile(path);
106 }).then((suite) { 124 }).then((suite) {
107 if (suite == null) return null; 125 if (suite == null) return null;
108 return suite.change(metadata: metadata).filter(platform, os: currentOS); 126 return suite.change(metadata: metadata).filter(platform, os: currentOS);
109 }); 127 });
110 })).then((suites) => suites.where((suite) => suite != null).toList()); 128 })).then((suites) => suites.where((suite) => suite != null).toList());
111 } 129 }
112 130
113 /// Load the test suite at [path] in a browser. 131 /// Load the test suite at [path] in a browser.
114 Future<Suite> _loadBrowserFile(String path) => 132 Future<Suite> _loadBrowserFile(String path) =>
115 _browserServer.then((browserServer) => browserServer.loadSuite(path)); 133 _browserServer.then((browserServer) => browserServer.loadSuite(path));
116 134
117 /// Load the test suite at [path] in VM isolate. 135 /// Load the test suite at [path] in VM isolate.
118 Future<Suite> _loadVmFile(String path) { 136 Future<Suite> _loadVmFile(String path) {
119 var packageRoot = packageRootFor(path, _packageRoot); 137 var packageRoot = packageRootFor(path, _packageRoot);
120 var receivePort = new ReceivePort(); 138 var receivePort = new ReceivePort();
121 return runInIsolate(''' 139
140 return new Future.sync(() {
141 if (_pubServeUrl != null) {
142 var url = _pubServeUrl.resolve(
143 p.withoutExtension(p.relative(path, from: 'test')) +
144 '.vm_test.dart');
145 return Isolate.spawnUri(url, [], {'reply': receivePort.sendPort})
146 .then((isolate) => new IsolateWrapper(isolate, () {}))
147 .catchError((error, stackTrace) {
148 if (error is! IsolateSpawnException) throw error;
149
150 if (error.message.contains("OS Error: Connection refused")) {
151 throw new LoadException(path,
152 "Error getting $url: Connection refused\n"
153 'Make sure "pub serve" is running.');
154 } else if (error.message.contains("404 Not Found")) {
155 throw new LoadException(path,
156 "Error getting $url: 404 Not Found\n"
157 'Make sure "pub serve" is serving the test/ directory.');
158 }
159
160 throw new LoadException(path, error);
161 });
162 } else {
163 return runInIsolate('''
122 import "package:test/src/runner/vm/isolate_listener.dart"; 164 import "package:test/src/runner/vm/isolate_listener.dart";
123 165
124 import "${p.toUri(p.absolute(path))}" as test; 166 import "${p.toUri(p.absolute(path))}" as test;
125 167
126 void main(_, Map message) { 168 void main(_, Map message) {
127 var sendPort = message['reply']; 169 var sendPort = message['reply'];
128 IsolateListener.start(sendPort, () => test.main); 170 IsolateListener.start(sendPort, () => test.main);
129 } 171 }
130 ''', { 172 ''', {
131 'reply': receivePort.sendPort 173 'reply': receivePort.sendPort
132 }, packageRoot: packageRoot) 174 }, packageRoot: packageRoot);
133 .catchError((error, stackTrace) { 175 }
176 }).catchError((error, stackTrace) {
134 receivePort.close(); 177 receivePort.close();
178 if (error is LoadException) throw error;
135 return new Future.error(new LoadException(path, error), stackTrace); 179 return new Future.error(new LoadException(path, error), stackTrace);
136 }).then((isolate) { 180 }).then((isolate) {
137 _isolates.add(isolate); 181 _isolates.add(isolate);
138 return receivePort.first; 182 return receivePort.first;
139 }).then((response) { 183 }).then((response) {
140 if (response["type"] == "loadException") { 184 if (response["type"] == "loadException") {
141 return new Future.error(new LoadException(path, response["message"])); 185 return new Future.error(new LoadException(path, response["message"]));
142 } else if (response["type"] == "error") { 186 } else if (response["type"] == "error") {
143 var asyncError = RemoteException.deserialize(response["error"]); 187 var asyncError = RemoteException.deserialize(response["error"]);
144 return new Future.error( 188 return new Future.error(
(...skipping 12 matching lines...) Expand all
157 Future close() { 201 Future close() {
158 for (var isolate in _isolates) { 202 for (var isolate in _isolates) {
159 isolate.kill(); 203 isolate.kill();
160 } 204 }
161 _isolates.clear(); 205 _isolates.clear();
162 206
163 if (_browserServerCompleter == null) return new Future.value(); 207 if (_browserServerCompleter == null) return new Future.value();
164 return _browserServer.then((browserServer) => browserServer.close()); 208 return _browserServer.then((browserServer) => browserServer.close());
165 } 209 }
166 } 210 }
OLDNEW
« no previous file with comments | « lib/src/runner/load_exception.dart ('k') | lib/src/util/io.dart » ('j') | lib/src/util/io.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698