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

Side by Side Diff: lib/src/runner/browser/server.dart

Issue 1258363003: Expose the Observatory URL when debugging. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « lib/src/runner/browser/dartium.dart ('k') | lib/src/runner/environment.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.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
11 import 'package:async/async.dart'; 11 import 'package:async/async.dart';
12 import 'package:http_multi_server/http_multi_server.dart'; 12 import 'package:http_multi_server/http_multi_server.dart';
13 import 'package:path/path.dart' as p; 13 import 'package:path/path.dart' as p;
14 import 'package:pool/pool.dart'; 14 import 'package:pool/pool.dart';
15 import 'package:shelf/shelf.dart' as shelf; 15 import 'package:shelf/shelf.dart' as shelf;
16 import 'package:shelf/shelf_io.dart' as shelf_io; 16 import 'package:shelf/shelf_io.dart' as shelf_io;
17 import 'package:shelf_static/shelf_static.dart'; 17 import 'package:shelf_static/shelf_static.dart';
18 import 'package:shelf_web_socket/shelf_web_socket.dart'; 18 import 'package:shelf_web_socket/shelf_web_socket.dart';
19 19
20 import '../../backend/metadata.dart'; 20 import '../../backend/metadata.dart';
21 import '../../backend/suite.dart'; 21 import '../../backend/suite.dart';
22 import '../../backend/test_platform.dart'; 22 import '../../backend/test_platform.dart';
23 import '../../util/io.dart'; 23 import '../../util/io.dart';
24 import '../../util/one_off_handler.dart'; 24 import '../../util/one_off_handler.dart';
25 import '../../util/path_handler.dart'; 25 import '../../util/path_handler.dart';
26 import '../../util/stack_trace_mapper.dart'; 26 import '../../util/stack_trace_mapper.dart';
27 import '../../utils.dart'; 27 import '../../utils.dart';
28 import '../application_exception.dart'; 28 import '../application_exception.dart';
29 import '../load_exception.dart'; 29 import '../load_exception.dart';
30 import 'browser.dart';
31 import 'browser_manager.dart'; 30 import 'browser_manager.dart';
32 import 'compiler_pool.dart'; 31 import 'compiler_pool.dart';
33 import 'chrome.dart';
34 import 'content_shell.dart';
35 import 'dartium.dart';
36 import 'firefox.dart';
37 import 'internet_explorer.dart';
38 import 'phantom_js.dart';
39 import 'polymer.dart'; 32 import 'polymer.dart';
40 import 'safari.dart';
41 33
42 /// A server that serves JS-compiled tests to browsers. 34 /// A server that serves JS-compiled tests to browsers.
43 /// 35 ///
44 /// 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].
45 class BrowserServer { 37 class BrowserServer {
46 /// Starts the server. 38 /// Starts the server.
47 /// 39 ///
48 /// [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
49 /// the working directory. 41 /// the working directory.
50 /// 42 ///
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 113
122 /// The HTTP client to use when caching JS files in `pub serve`. 114 /// The HTTP client to use when caching JS files in `pub serve`.
123 final HttpClient _http; 115 final HttpClient _http;
124 116
125 /// Whether [close] has been called. 117 /// Whether [close] has been called.
126 bool get _closed => _closeMemo.hasRun; 118 bool get _closed => _closeMemo.hasRun;
127 119
128 /// The memoizer for running [close] exactly once. 120 /// The memoizer for running [close] exactly once.
129 final _closeMemo = new AsyncMemoizer(); 121 final _closeMemo = new AsyncMemoizer();
130 122
131 /// All currently-running browsers.
132 ///
133 /// These are controlled by [_browserManager]s.
134 final _browsers = new Map<TestPlatform, Browser>();
135
136 /// A map from browser identifiers to futures that will complete to the 123 /// A map from browser identifiers to futures that will complete to the
137 /// [BrowserManager]s for those browsers, or the errors that occurred when 124 /// [BrowserManager]s for those browsers, or the errors that occurred when
138 /// trying to load those managers. 125 /// trying to load those managers.
139 /// 126 ///
140 /// This should only be accessed through [_browserManagerFor]. 127 /// This should only be accessed through [_browserManagerFor].
141 final _browserManagers = 128 final _browserManagers =
142 new Map<TestPlatform, Future<Result<BrowserManager>>>(); 129 new Map<TestPlatform, Future<Result<BrowserManager>>>();
143 130
144 /// A map from test suite paths to Futures that will complete once those 131 /// A map from test suite paths to Futures that will complete once those
145 /// suites are finished compiling. 132 /// suites are finished compiling.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 suiteUrl = url.resolveUri(p.toUri( 276 suiteUrl = url.resolveUri(p.toUri(
290 p.withoutExtension(p.relative(path, from: _root)) + ".html")); 277 p.withoutExtension(p.relative(path, from: _root)) + ".html"));
291 } 278 }
292 279
293 if (_closed) return null; 280 if (_closed) return null;
294 281
295 // TODO(nweiz): Don't start the browser until all the suites are compiled. 282 // TODO(nweiz): Don't start the browser until all the suites are compiled.
296 var browserManager = await _browserManagerFor(browser); 283 var browserManager = await _browserManagerFor(browser);
297 if (_closed) return null; 284 if (_closed) return null;
298 285
299 if (browserManager != null) { 286 var suite = await browserManager.loadSuite(path, suiteUrl, metadata,
300 var suite = await browserManager.loadSuite(path, suiteUrl, metadata, 287 mapper: browser.isJS ? _mappers[path] : null);
301 mapper: browser.isJS ? _mappers[path] : null); 288 if (_closed) return null;
302 if (_closed) return null; 289 return suite;
303 if (suite != null) return suite;
304 }
305
306 // If the browser manager fails to load a suite and the server isn't
307 // closed, it's probably because the browser failed. We emit the failure
308 // here to ensure that it gets surfaced.
309 return _browsers[browser].onExit;
310 } 290 }
311 291
312 /// Loads a test suite at [path] from the `pub serve` URL [jsUrl]. 292 /// Loads a test suite at [path] from the `pub serve` URL [jsUrl].
313 /// 293 ///
314 /// This ensures that only one suite is loaded at a time, and that any errors 294 /// This ensures that only one suite is loaded at a time, and that any errors
315 /// are exposed as [LoadException]s. 295 /// are exposed as [LoadException]s.
316 Future _pubServeSuite(String path, Uri jsUrl) { 296 Future _pubServeSuite(String path, Uri jsUrl) {
317 return _pubServePool.withResource(() async { 297 return _pubServePool.withResource(() async {
318 var timer = new Timer(new Duration(seconds: 1), () { 298 var timer = new Timer(new Duration(seconds: 1), () {
319 print('"pub serve" is compiling $path...'); 299 print('"pub serve" is compiling $path...');
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 }); 383 });
404 } 384 }
405 385
406 /// Returns the [BrowserManager] for [platform], which should be a browser. 386 /// Returns the [BrowserManager] for [platform], which should be a browser.
407 /// 387 ///
408 /// If no browser manager is running yet, starts one. 388 /// If no browser manager is running yet, starts one.
409 Future<BrowserManager> _browserManagerFor(TestPlatform platform) { 389 Future<BrowserManager> _browserManagerFor(TestPlatform platform) {
410 var manager = _browserManagers[platform]; 390 var manager = _browserManagers[platform];
411 if (manager != null) return Result.release(manager); 391 if (manager != null) return Result.release(manager);
412 392
413 var completer = new Completer(); 393 var completer = new Completer.sync();
394 var path = _webSocketHandler.create(webSocketHandler(completer.complete));
395 var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
396 var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl)
397 .resolve('packages/test/src/runner/browser/static/index.html')
398 .replace(queryParameters: {'managerUrl': webSocketUrl.toString()});
399
400 var future = BrowserManager.start(platform, hostUrl, completer.future);
414 401
415 // Capture errors and release them later to avoid Zone issues. This call to 402 // Capture errors and release them later to avoid Zone issues. This call to
416 // [_browserManagerFor] is running in a different [LoadSuite] than future 403 // [_browserManagerFor] is running in a different [LoadSuite] than future
417 // calls, which means they're also running in different error zones so 404 // calls, which means they're also running in different error zones so
418 // errors can't be freely passed between them. Storing the error or value as 405 // errors can't be freely passed between them. Storing the error or value as
419 // an explicit [Result] fixes that. 406 // an explicit [Result] fixes that.
420 _browserManagers[platform] = Result.capture(completer.future); 407 _browserManagers[platform] = Result.capture(future);
421 var path = _webSocketHandler.create(webSocketHandler((webSocket) {
422 completer.complete(new BrowserManager(platform, webSocket));
423 }));
424 408
425 var webSocketUrl = url.replace(scheme: 'ws').resolve(path); 409 return future;
426
427 var hostUrl = (_pubServeUrl == null ? url : _pubServeUrl)
428 .resolve('packages/test/src/runner/browser/static/index.html');
429
430 var browser = _newBrowser(hostUrl.replace(queryParameters: {
431 'managerUrl': webSocketUrl.toString()
432 }), platform);
433 _browsers[platform] = browser;
434
435 // TODO(nweiz): Gracefully handle the browser being killed before the
436 // tests complete.
437 browser.onExit.then((_) {
438 if (completer.isCompleted) return;
439 if (!_closed) return;
440 completer.complete(null);
441 }).catchError((error, stackTrace) {
442 if (completer.isCompleted) return;
443 completer.completeError(error, stackTrace);
444 });
445
446 return completer.future.timeout(new Duration(seconds: 30), onTimeout: () {
447 throw new ApplicationException(
448 "Timed out waiting for ${platform.name} to connect.");
449 });
450 }
451
452 /// Starts the browser identified by [browser] and has it load [url].
453 Browser _newBrowser(Uri url, TestPlatform browser) {
454 switch (browser) {
455 case TestPlatform.dartium: return new Dartium(url);
456 case TestPlatform.contentShell: return new ContentShell(url);
457 case TestPlatform.chrome: return new Chrome(url);
458 case TestPlatform.phantomJS: return new PhantomJS(url);
459 case TestPlatform.firefox: return new Firefox(url);
460 case TestPlatform.safari: return new Safari(url);
461 case TestPlatform.internetExplorer: return new InternetExplorer(url);
462 default:
463 throw new ArgumentError("$browser is not a browser.");
464 }
465 } 410 }
466 411
467 /// Closes the server and releases all its resources. 412 /// Closes the server and releases all its resources.
468 /// 413 ///
469 /// Returns a [Future] that completes once the server is closed and its 414 /// Returns a [Future] that completes once the server is closed and its
470 /// resources have been fully released. 415 /// resources have been fully released.
471 Future close() { 416 Future close() {
472 return _closeMemo.runOnce(() async { 417 return _closeMemo.runOnce(() async {
473 var futures = _browsers.values.map((browser) => browser.close()).toList(); 418 var futures = _browserManagers.values.map((future) async {
419 var result = await future;
420 if (result.isError) return;
421
422 await result.asValue.value.close();
423 }).toList();
474 424
475 futures.add(_server.close()); 425 futures.add(_server.close());
476 futures.add(_compilers.close()); 426 futures.add(_compilers.close());
477 427
478 await Future.wait(futures); 428 await Future.wait(futures);
479 429
480 if (_pubServeUrl == null) { 430 if (_pubServeUrl == null) {
481 new Directory(_compiledDir).deleteSync(recursive: true); 431 new Directory(_compiledDir).deleteSync(recursive: true);
482 } else { 432 } else {
483 _http.close(); 433 _http.close();
484 } 434 }
485 }); 435 });
486 } 436 }
487 } 437 }
OLDNEW
« no previous file with comments | « lib/src/runner/browser/dartium.dart ('k') | lib/src/runner/environment.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698