| 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 static Future<BrowserServer> start(Configuration config, {String root}) | 42 static Future<BrowserServer> start(Configuration config, {String root}) |
| 43 async { | 43 async { |
| 44 var server = new BrowserServer._(root, config); | 44 var server = new shelf_io.IOServer(await HttpMultiServer.loopback(0)); |
| 45 await server._load(); | 45 return new BrowserServer(server, config, root: root); |
| 46 return server; | |
| 47 } | 46 } |
| 48 | 47 |
| 49 /// The underlying HTTP server. | 48 /// The underlying server. |
| 50 HttpServer _server; | 49 final shelf.Server _server; |
| 51 | 50 |
| 52 /// A randomly-generated secret. | 51 /// A randomly-generated secret. |
| 53 /// | 52 /// |
| 54 /// This is used to ensure that other users on the same system can't snoop | 53 /// This is used to ensure that other users on the same system can't snoop |
| 55 /// on data being served through this server. | 54 /// on data being served through this server. |
| 56 final _secret = randomBase64(24, urlSafe: true); | 55 final _secret = randomBase64(24, urlSafe: true); |
| 57 | 56 |
| 58 /// The URL for this server. | 57 /// The URL for this server. |
| 59 Uri get url => baseUrlForAddress(_server.address, _server.port) | 58 Uri get url => _server.url.resolve(_secret + "/"); |
| 60 .resolve(_secret + "/"); | |
| 61 | 59 |
| 62 /// The test runner configuration. | 60 /// The test runner configuration. |
| 63 Configuration _config; | 61 Configuration _config; |
| 64 | 62 |
| 65 /// A [OneOffHandler] for servicing WebSocket connections for | 63 /// A [OneOffHandler] for servicing WebSocket connections for |
| 66 /// [BrowserManager]s. | 64 /// [BrowserManager]s. |
| 67 /// | 65 /// |
| 68 /// This is one-off because each [BrowserManager] can only connect to a single | 66 /// This is one-off because each [BrowserManager] can only connect to a single |
| 69 /// WebSocket, | 67 /// WebSocket, |
| 70 final _webSocketHandler = new OneOffHandler(); | 68 final _webSocketHandler = new OneOffHandler(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 106 |
| 109 /// A map from test suite paths to Futures that will complete once those | 107 /// A map from test suite paths to Futures that will complete once those |
| 110 /// suites are finished compiling. | 108 /// suites are finished compiling. |
| 111 /// | 109 /// |
| 112 /// This is used to make sure that a given test suite is only compiled once | 110 /// This is used to make sure that a given test suite is only compiled once |
| 113 /// per run, rather than once per browser per run. | 111 /// per run, rather than once per browser per run. |
| 114 final _compileFutures = new Map<String, Future>(); | 112 final _compileFutures = new Map<String, Future>(); |
| 115 | 113 |
| 116 final _mappers = new Map<String, StackTraceMapper>(); | 114 final _mappers = new Map<String, StackTraceMapper>(); |
| 117 | 115 |
| 118 BrowserServer._(String root, Configuration config) | 116 BrowserServer(this._server, Configuration config, {String root}) |
| 119 : _root = root == null ? p.current : root, | 117 : _root = root == null ? p.current : root, |
| 120 _config = config, | 118 _config = config, |
| 121 _compiledDir = config.pubServeUrl == null ? createTempDir() : null, | 119 _compiledDir = config.pubServeUrl == null ? createTempDir() : null, |
| 122 _http = config.pubServeUrl == null ? null : new HttpClient(), | 120 _http = config.pubServeUrl == null ? null : new HttpClient(), |
| 123 _compilers = new CompilerPool(color: config.color); | 121 _compilers = new CompilerPool(color: config.color) { |
| 124 | |
| 125 /// Starts the underlying server. | |
| 126 Future _load() async { | |
| 127 var cascade = new shelf.Cascade() | 122 var cascade = new shelf.Cascade() |
| 128 .add(_webSocketHandler.handler); | 123 .add(_webSocketHandler.handler); |
| 129 | 124 |
| 130 if (_config.pubServeUrl == null) { | 125 if (_config.pubServeUrl == null) { |
| 131 cascade = cascade | 126 cascade = cascade |
| 132 .add(_createPackagesHandler()) | 127 .add(_createPackagesHandler()) |
| 133 .add(_jsHandler.handler) | 128 .add(_jsHandler.handler) |
| 134 .add(createStaticHandler(_root)) | 129 .add(createStaticHandler(_root)) |
| 135 .add(_wrapperHandler); | 130 .add(_wrapperHandler); |
| 136 } | 131 } |
| 137 | 132 |
| 138 var pipeline = new shelf.Pipeline() | 133 var pipeline = new shelf.Pipeline() |
| 139 .addMiddleware(nestingMiddleware(_secret)) | 134 .addMiddleware(nestingMiddleware(_secret)) |
| 140 .addHandler(cascade.handler); | 135 .addHandler(cascade.handler); |
| 141 | 136 |
| 142 _server = await HttpMultiServer.loopback(0); | 137 _server.mount(pipeline); |
| 143 shelf_io.serveRequests(_server, pipeline); | |
| 144 } | 138 } |
| 145 | 139 |
| 146 /// Returns a handler that serves the contents of the "packages/" directory | 140 /// Returns a handler that serves the contents of the "packages/" directory |
| 147 /// for any URL that contains "packages/". | 141 /// for any URL that contains "packages/". |
| 148 /// | 142 /// |
| 149 /// This is a factory so it can wrap a static handler. | 143 /// This is a factory so it can wrap a static handler. |
| 150 shelf.Handler _createPackagesHandler() { | 144 shelf.Handler _createPackagesHandler() { |
| 151 var staticHandler = | 145 var staticHandler = |
| 152 createStaticHandler(_config.packageRoot, serveFilesOutsidePath: true); | 146 createStaticHandler(_config.packageRoot, serveFilesOutsidePath: true); |
| 153 | 147 |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 await Future.wait(futures); | 406 await Future.wait(futures); |
| 413 | 407 |
| 414 if (_config.pubServeUrl == null) { | 408 if (_config.pubServeUrl == null) { |
| 415 new Directory(_compiledDir).deleteSync(recursive: true); | 409 new Directory(_compiledDir).deleteSync(recursive: true); |
| 416 } else { | 410 } else { |
| 417 _http.close(); | 411 _http.close(); |
| 418 } | 412 } |
| 419 }); | 413 }); |
| 420 } | 414 } |
| 421 } | 415 } |
| OLD | NEW |