| 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 |