| Index: lib/src/runner/browser/server.dart
|
| diff --git a/lib/src/runner/browser/server.dart b/lib/src/runner/browser/server.dart
|
| index a4bab92f33566e94463a9cd1d028d333fa6897e1..b70a807342a4c33bfd08e649fcbe6ac3da758470 100644
|
| --- a/lib/src/runner/browser/server.dart
|
| +++ b/lib/src/runner/browser/server.dart
|
| @@ -27,17 +27,9 @@ import '../../util/stack_trace_mapper.dart';
|
| import '../../utils.dart';
|
| import '../application_exception.dart';
|
| import '../load_exception.dart';
|
| -import 'browser.dart';
|
| import 'browser_manager.dart';
|
| import 'compiler_pool.dart';
|
| -import 'chrome.dart';
|
| -import 'content_shell.dart';
|
| -import 'dartium.dart';
|
| -import 'firefox.dart';
|
| -import 'internet_explorer.dart';
|
| -import 'phantom_js.dart';
|
| import 'polymer.dart';
|
| -import 'safari.dart';
|
|
|
| /// A server that serves JS-compiled tests to browsers.
|
| ///
|
| @@ -128,11 +120,6 @@ class BrowserServer {
|
| /// The memoizer for running [close] exactly once.
|
| final _closeMemo = new AsyncMemoizer();
|
|
|
| - /// All currently-running browsers.
|
| - ///
|
| - /// These are controlled by [_browserManager]s.
|
| - final _browsers = new Map<TestPlatform, Browser>();
|
| -
|
| /// A map from browser identifiers to futures that will complete to the
|
| /// [BrowserManager]s for those browsers, or the errors that occurred when
|
| /// trying to load those managers.
|
| @@ -296,17 +283,10 @@ void main() {
|
| var browserManager = await _browserManagerFor(browser);
|
| if (_closed) return null;
|
|
|
| - if (browserManager != null) {
|
| - var suite = await browserManager.loadSuite(path, suiteUrl, metadata,
|
| - mapper: browser.isJS ? _mappers[path] : null);
|
| - if (_closed) return null;
|
| - if (suite != null) return suite;
|
| - }
|
| -
|
| - // If the browser manager fails to load a suite and the server isn't
|
| - // closed, it's probably because the browser failed. We emit the failure
|
| - // here to ensure that it gets surfaced.
|
| - return _browsers[browser].onExit;
|
| + var suite = await browserManager.loadSuite(path, suiteUrl, metadata,
|
| + mapper: browser.isJS ? _mappers[path] : null);
|
| + if (_closed) return null;
|
| + return suite;
|
| }
|
|
|
| /// Loads a test suite at [path] from the `pub serve` URL [jsUrl].
|
| @@ -410,58 +390,23 @@ void main() {
|
| var manager = _browserManagers[platform];
|
| if (manager != null) return Result.release(manager);
|
|
|
| - var completer = new Completer();
|
| + var completer = new Completer.sync();
|
| + var path = _webSocketHandler.create(webSocketHandler(completer.complete));
|
| + var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
|
| + var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl)
|
| + .resolve('packages/test/src/runner/browser/static/index.html')
|
| + .replace(queryParameters: {'managerUrl': webSocketUrl.toString()});
|
| +
|
| + var future = BrowserManager.start(platform, hostUrl, completer.future);
|
|
|
| // Capture errors and release them later to avoid Zone issues. This call to
|
| // [_browserManagerFor] is running in a different [LoadSuite] than future
|
| // calls, which means they're also running in different error zones so
|
| // errors can't be freely passed between them. Storing the error or value as
|
| // an explicit [Result] fixes that.
|
| - _browserManagers[platform] = Result.capture(completer.future);
|
| - var path = _webSocketHandler.create(webSocketHandler((webSocket) {
|
| - completer.complete(new BrowserManager(platform, webSocket));
|
| - }));
|
| + _browserManagers[platform] = Result.capture(future);
|
|
|
| - var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
|
| -
|
| - var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl)
|
| - .resolve('packages/test/src/runner/browser/static/index.html');
|
| -
|
| - var browser = _newBrowser(hostUrl.replace(queryParameters: {
|
| - 'managerUrl': webSocketUrl.toString()
|
| - }), platform);
|
| - _browsers[platform] = browser;
|
| -
|
| - // TODO(nweiz): Gracefully handle the browser being killed before the
|
| - // tests complete.
|
| - browser.onExit.then((_) {
|
| - if (completer.isCompleted) return;
|
| - if (!_closed) return;
|
| - completer.complete(null);
|
| - }).catchError((error, stackTrace) {
|
| - if (completer.isCompleted) return;
|
| - completer.completeError(error, stackTrace);
|
| - });
|
| -
|
| - return completer.future.timeout(new Duration(seconds: 30), onTimeout: () {
|
| - throw new ApplicationException(
|
| - "Timed out waiting for ${platform.name} to connect.");
|
| - });
|
| - }
|
| -
|
| - /// Starts the browser identified by [browser] and has it load [url].
|
| - Browser _newBrowser(Uri url, TestPlatform browser) {
|
| - switch (browser) {
|
| - case TestPlatform.dartium: return new Dartium(url);
|
| - case TestPlatform.contentShell: return new ContentShell(url);
|
| - case TestPlatform.chrome: return new Chrome(url);
|
| - case TestPlatform.phantomJS: return new PhantomJS(url);
|
| - case TestPlatform.firefox: return new Firefox(url);
|
| - case TestPlatform.safari: return new Safari(url);
|
| - case TestPlatform.internetExplorer: return new InternetExplorer(url);
|
| - default:
|
| - throw new ArgumentError("$browser is not a browser.");
|
| - }
|
| + return future;
|
| }
|
|
|
| /// Closes the server and releases all its resources.
|
| @@ -470,7 +415,12 @@ void main() {
|
| /// resources have been fully released.
|
| Future close() {
|
| return _closeMemo.runOnce(() async {
|
| - var futures = _browsers.values.map((browser) => browser.close()).toList();
|
| + var futures = _browserManagers.values.map((future) async {
|
| + var result = await future;
|
| + if (result.isError) return;
|
| +
|
| + await result.asValue.value.close();
|
| + }).toList();
|
|
|
| futures.add(_server.close());
|
| futures.add(_compilers.close());
|
|
|