OLD | NEW |
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.browser.server; | 5 library test.runner.browser.server; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 /// A server that serves JS-compiled tests to browsers. | 34 /// A server that serves JS-compiled tests to browsers. |
35 /// | 35 /// |
36 /// A test suite may be loaded for a given file using [loadSuite]. | 36 /// A test suite may be loaded for a given file using [loadSuite]. |
37 class BrowserServer { | 37 class BrowserServer { |
38 /// Starts the server. | 38 /// Starts the server. |
39 /// | 39 /// |
40 /// [root] is the root directory that the server should serve. It defaults to | 40 /// [root] is the root directory that the server should serve. It defaults to |
41 /// the working directory. | 41 /// the working directory. |
42 /// | 42 /// |
43 /// If [packageRoot] is passed, it's used for all package imports when | 43 /// If [packageRoot] is passed, it's used for all package imports when |
44 /// compiling tests to JS. Otherwise, the package root is inferred from the | 44 /// compiling tests to JS. Otherwise, the package root is inferred from |
45 /// location of the source file. | 45 /// [root]. |
46 /// | 46 /// |
47 /// If [pubServeUrl] is passed, tests will be loaded from the `pub serve` | 47 /// If [pubServeUrl] is passed, tests will be loaded from the `pub serve` |
48 /// instance at that URL rather than from the filesystem. | 48 /// instance at that URL rather than from the filesystem. |
49 /// | 49 /// |
50 /// If [color] is true, console colors will be used when compiling Dart. | 50 /// If [color] is true, console colors will be used when compiling Dart. |
| 51 /// |
| 52 /// If the package root doesn't exist, throws an [ApplicationException]. |
51 static Future<BrowserServer> start({String root, String packageRoot, | 53 static Future<BrowserServer> start({String root, String packageRoot, |
52 Uri pubServeUrl, bool color: false}) { | 54 Uri pubServeUrl, bool color: false}) { |
53 var server = new BrowserServer._(root, packageRoot, pubServeUrl, color); | 55 var server = new BrowserServer._(root, packageRoot, pubServeUrl, color); |
54 return server._load().then((_) => server); | 56 return server._load().then((_) => server); |
55 } | 57 } |
56 | 58 |
57 /// The underlying HTTP server. | 59 /// The underlying HTTP server. |
58 HttpServer _server; | 60 HttpServer _server; |
59 | 61 |
60 /// A randomly-generated secret. | 62 /// A randomly-generated secret. |
(...skipping 20 matching lines...) Expand all Loading... |
81 /// | 83 /// |
82 /// This is `null` if tests are loaded from `pub serve`. | 84 /// This is `null` if tests are loaded from `pub serve`. |
83 final CompilerPool _compilers; | 85 final CompilerPool _compilers; |
84 | 86 |
85 /// The temporary directory in which compiled JS is emitted. | 87 /// The temporary directory in which compiled JS is emitted. |
86 final String _compiledDir; | 88 final String _compiledDir; |
87 | 89 |
88 /// The root directory served statically by this server. | 90 /// The root directory served statically by this server. |
89 final String _root; | 91 final String _root; |
90 | 92 |
91 /// The package root which is passed to `dart2js`. | 93 /// The package root. |
92 final String _packageRoot; | 94 final String _packageRoot; |
93 | 95 |
94 /// The URL for the `pub serve` instance to use to load tests. | 96 /// The URL for the `pub serve` instance to use to load tests. |
95 /// | 97 /// |
96 /// This is `null` if tests should be compiled manually. | 98 /// This is `null` if tests should be compiled manually. |
97 final Uri _pubServeUrl; | 99 final Uri _pubServeUrl; |
98 | 100 |
99 /// The pool of active `pub serve` compilations. | 101 /// The pool of active `pub serve` compilations. |
100 /// | 102 /// |
101 /// Pub itself ensures that only one compilation runs at a time; we just use | 103 /// Pub itself ensures that only one compilation runs at a time; we just use |
(...skipping 20 matching lines...) Expand all Loading... |
122 /// This should only be accessed through [_browserManagerFor]. | 124 /// This should only be accessed through [_browserManagerFor]. |
123 final _browserManagers = new Map<TestPlatform, Future<BrowserManager>>(); | 125 final _browserManagers = new Map<TestPlatform, Future<BrowserManager>>(); |
124 | 126 |
125 /// A map from test suite paths to Futures that will complete once those | 127 /// A map from test suite paths to Futures that will complete once those |
126 /// suites are finished compiling. | 128 /// suites are finished compiling. |
127 /// | 129 /// |
128 /// This is used to make sure that a given test suite is only compiled once | 130 /// This is used to make sure that a given test suite is only compiled once |
129 /// per run, rather than one per browser per run. | 131 /// per run, rather than one per browser per run. |
130 final _compileFutures = new Map<String, Future>(); | 132 final _compileFutures = new Map<String, Future>(); |
131 | 133 |
132 BrowserServer._(String root, this._packageRoot, Uri pubServeUrl, bool color) | 134 BrowserServer._(String root, String packageRoot, Uri pubServeUrl, bool color) |
133 : _root = root == null ? p.current : root, | 135 : _root = root == null ? p.current : root, |
| 136 _packageRoot = packageRootFor(root, packageRoot), |
134 _pubServeUrl = pubServeUrl, | 137 _pubServeUrl = pubServeUrl, |
135 _compiledDir = pubServeUrl == null ? createTempDir() : null, | 138 _compiledDir = pubServeUrl == null ? createTempDir() : null, |
136 _http = pubServeUrl == null ? null : new HttpClient(), | 139 _http = pubServeUrl == null ? null : new HttpClient(), |
137 _compilers = new CompilerPool(color: color); | 140 _compilers = new CompilerPool(color: color); |
138 | 141 |
139 /// Starts the underlying server. | 142 /// Starts the underlying server. |
140 Future _load() { | 143 Future _load() { |
141 var cascade = new shelf.Cascade() | 144 var cascade = new shelf.Cascade() |
142 .add(_webSocketHandler.handler); | 145 .add(_webSocketHandler.handler); |
143 | 146 |
(...skipping 12 matching lines...) Expand all Loading... |
156 return shelf_io.serve(pipeline, 'localhost', 0).then((server) { | 159 return shelf_io.serve(pipeline, 'localhost', 0).then((server) { |
157 _server = server; | 160 _server = server; |
158 }); | 161 }); |
159 } | 162 } |
160 | 163 |
161 /// Returns a handler that serves the contents of the "packages/" directory | 164 /// Returns a handler that serves the contents of the "packages/" directory |
162 /// for any URL that contains "packages/". | 165 /// for any URL that contains "packages/". |
163 /// | 166 /// |
164 /// This is a factory so it can wrap a static handler. | 167 /// This is a factory so it can wrap a static handler. |
165 shelf.Handler _createPackagesHandler() { | 168 shelf.Handler _createPackagesHandler() { |
166 var packageRoot = _packageRoot == null | |
167 ? p.join(_root, 'packages') | |
168 : _packageRoot; | |
169 var staticHandler = | 169 var staticHandler = |
170 createStaticHandler(packageRoot, serveFilesOutsidePath: true); | 170 createStaticHandler(_packageRoot, serveFilesOutsidePath: true); |
171 | 171 |
172 return (request) { | 172 return (request) { |
173 var segments = p.url.split(shelfUrl(request).path); | 173 var segments = p.url.split(shelfUrl(request).path); |
174 | 174 |
175 for (var i = 0; i < segments.length; i++) { | 175 for (var i = 0; i < segments.length; i++) { |
176 if (segments[i] != "packages") continue; | 176 if (segments[i] != "packages") continue; |
177 return staticHandler( | 177 return staticHandler( |
178 shelfChange(request, path: p.url.joinAll(segments.take(i + 1)))); | 178 shelfChange(request, path: p.url.joinAll(segments.take(i + 1)))); |
179 } | 179 } |
180 | 180 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 292 |
293 /// Compile the test suite at [dartPath] to JavaScript. | 293 /// Compile the test suite at [dartPath] to JavaScript. |
294 /// | 294 /// |
295 /// Once the suite has been compiled, it's added to [_jsHandler] so it can be | 295 /// Once the suite has been compiled, it's added to [_jsHandler] so it can be |
296 /// served. | 296 /// served. |
297 Future _compileSuite(String dartPath) { | 297 Future _compileSuite(String dartPath) { |
298 return _compileFutures.putIfAbsent(dartPath, () { | 298 return _compileFutures.putIfAbsent(dartPath, () { |
299 var dir = new Directory(_compiledDir).createTempSync('test_').path; | 299 var dir = new Directory(_compiledDir).createTempSync('test_').path; |
300 var jsPath = p.join(dir, p.basename(dartPath) + ".js"); | 300 var jsPath = p.join(dir, p.basename(dartPath) + ".js"); |
301 | 301 |
302 return _compilers.compile(dartPath, jsPath, | 302 return _compilers.compile(dartPath, jsPath, packageRoot: _packageRoot) |
303 packageRoot: packageRootFor(dartPath, _packageRoot)) | |
304 .then((_) { | 303 .then((_) { |
305 if (_closed) return; | 304 if (_closed) return; |
306 | 305 |
307 _jsHandler.add( | 306 _jsHandler.add( |
308 p.relative(dartPath, from: _root) + '.browser_test.dart.js', | 307 p.relative(dartPath, from: _root) + '.browser_test.dart.js', |
309 (request) { | 308 (request) { |
310 return new shelf.Response.ok(new File(jsPath).readAsStringSync(), | 309 return new shelf.Response.ok(new File(jsPath).readAsStringSync(), |
311 headers: {'Content-Type': 'application/javascript'}); | 310 headers: {'Content-Type': 'application/javascript'}); |
312 }); | 311 }); |
313 }); | 312 }); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 if (_pubServeUrl == null) { | 380 if (_pubServeUrl == null) { |
382 new Directory(_compiledDir).deleteSync(recursive: true); | 381 new Directory(_compiledDir).deleteSync(recursive: true); |
383 } else { | 382 } else { |
384 _http.close(); | 383 _http.close(); |
385 } | 384 } |
386 | 385 |
387 _closeCompleter.complete(); | 386 _closeCompleter.complete(); |
388 }).catchError(_closeCompleter.completeError); | 387 }).catchError(_closeCompleter.completeError); |
389 } | 388 } |
390 } | 389 } |
OLD | NEW |