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

Unified Diff: lib/src/runner/browser/server.dart

Issue 1062523003: Add support for --pub-serve. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: lib/src/runner/browser/server.dart
diff --git a/lib/src/runner/browser/server.dart b/lib/src/runner/browser/server.dart
index 9730e3c2a276ca36808cccd00ca5caabc535146f..87b6ef38edb402a82d4b775dc5b36922bf1fa15b 100644
--- a/lib/src/runner/browser/server.dart
+++ b/lib/src/runner/browser/server.dart
@@ -9,6 +9,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
+import 'package:pool/pool.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_static/shelf_static.dart';
@@ -17,6 +18,8 @@ import 'package:shelf_web_socket/shelf_web_socket.dart';
import '../../backend/suite.dart';
import '../../util/io.dart';
import '../../util/one_off_handler.dart';
+import '../../utils.dart';
+import '../load_exception.dart';
import 'browser_manager.dart';
import 'compiler_pool.dart';
import 'chrome.dart';
@@ -31,9 +34,13 @@ class BrowserServer {
/// compiling tests to JS. Otherwise, the package root is inferred from the
/// location of the source file.
///
+ /// If [pubServeUrl] is passed, tests will be loaded from the `pub serve`
+ /// instance at that URL rather than from the filesystem.
+ ///
/// If [color] is true, console colors will be used when compiling Dart.
- static Future<BrowserServer> start({String packageRoot, bool color: false}) {
- var server = new BrowserServer._(packageRoot, color);
+ static Future<BrowserServer> start({String packageRoot, Uri pubServeUrl,
+ bool color: false}) {
+ var server = new BrowserServer._(packageRoot, pubServeUrl, color);
return server._load().then((_) => server);
}
@@ -51,6 +58,8 @@ class BrowserServer {
final _webSocketHandler = new OneOffHandler();
/// The [CompilerPool] managing active instances of `dart2js`.
+ ///
+ /// This is `null` if tests are loaded from `pub serve`.
final CompilerPool _compilers;
/// The temporary directory in which compiled JS is emitted.
@@ -59,6 +68,20 @@ class BrowserServer {
/// The package root which is passed to `dart2js`.
final String _packageRoot;
+ /// The URL for the `pub serve` instance to use to load tests.
+ ///
+ /// This is `null` if tests should be compiled manually.
+ final Uri _pubServeUrl;
+
+ /// The pool of active `pub serve` compilations.
+ ///
+ /// Pub itself ensures that only one compilation runs at a time; we just use
+ /// this pool to make sure that the output is nice and linear.
+ final _pubServePool = new Pool(1);
+
+ /// The HTTP client to use when caching JS files in `pub serve`.
+ final HttpClient _http;
+
/// The browser in which test suites are loaded and run.
///
/// This is `null` until a suite is loaded.
@@ -76,7 +99,14 @@ class BrowserServer {
}));
var webSocketUrl = url.replace(scheme: 'ws', path: '/$path');
- _browser = new Chrome(url.replace(queryParameters: {
+
+ var hostUrl = url;
+ if (_pubServeUrl != null) {
+ hostUrl = _pubServeUrl.resolve(
+ '/packages/test/src/runner/browser/static/');
+ }
+
+ _browser = new Chrome(hostUrl.replace(queryParameters: {
'managerUrl': webSocketUrl.toString()
}));
@@ -91,18 +121,27 @@ class BrowserServer {
}
Completer<BrowserManager> _browserManagerCompleter;
- BrowserServer._(this._packageRoot, bool color)
- : _compiledDir = Directory.systemTemp.createTempSync('test_').path,
+ BrowserServer._(this._packageRoot, Uri pubServeUrl, bool color)
+ : _pubServeUrl = pubServeUrl,
+ _compiledDir = pubServeUrl == null
+ ? Directory.systemTemp.createTempSync('test_').path
+ : null,
+ _http = pubServeUrl == null ? null : new HttpClient(),
_compilers = new CompilerPool(color: color);
/// Starts the underlying server.
Future _load() {
- var staticPath = p.join(libDir(packageRoot: _packageRoot),
- 'src/runner/browser/static');
var cascade = new shelf.Cascade()
- .add(_webSocketHandler.handler)
- .add(createStaticHandler(staticPath, defaultDocument: 'index.html'))
- .add(createStaticHandler(_compiledDir, defaultDocument: 'index.html'));
+ .add(_webSocketHandler.handler);
+
+ if (_pubServeUrl == null) {
+ var staticPath = p.join(libDir(packageRoot: _packageRoot),
+ 'src/runner/browser/static');
+ cascade = cascade
+ .add(createStaticHandler(staticPath, defaultDocument: 'index.html'))
+ .add(createStaticHandler(_compiledDir,
+ defaultDocument: 'index.html'));
+ }
return shelf_io.serve(cascade.handler, 'localhost', 0).then((server) {
_server = server;
@@ -113,19 +152,67 @@ class BrowserServer {
///
/// This will start a browser to load the suite if one isn't already running.
Future<Suite> loadSuite(String path) {
- return _compileSuite(path).then((dir) {
+ return new Future.sync(() {
+ if (_pubServeUrl != null) {
+
+ var suitePrefix = p.withoutExtension(p.relative(path, from: 'test')) +
+ '.browser_test';
+ var jsUrl = _pubServeUrl.resolve('$suitePrefix.dart.js');
+ return _pubServeSuite(path, jsUrl)
+ .then((_) => _pubServeUrl.resolve('$suitePrefix.html'));
+ } else {
+ return _compileSuite(path).then((dir) {
+ // Add a trailing slash because at least on Chrome, the iframe's
+ // window.location.href will do so automatically, and if that differs
+ // from the original URL communication will fail.
+ return url.resolve(
+ "/" + p.toUri(p.relative(dir, from: _compiledDir)).path + "/");
+ });
+ }
+ }).then((suiteUrl) {
// TODO(nweiz): Don't start the browser until all the suites are compiled.
return _browserManager.then((browserManager) {
- // Add a trailing slash because at least on Chrome, the iframe's
- // window.location.href will do so automatically, and if that differs
- // from the original URL communication will fail.
- var suiteUrl = url.resolve(
- "/" + p.toUri(p.relative(dir, from: _compiledDir)).path + "/");
return browserManager.loadSuite(path, suiteUrl);
});
});
}
+ /// Loads a test suite at [path] from the `pub serve` URL [jsUrl].
+ ///
+ /// This ensures that only one suite is loaded at a time, and that any errors
+ /// are exposed as [LoadException]s.
+ Future _pubServeSuite(String path, Uri jsUrl) {
+ return _pubServePool.withResource(() {
+ var timer = new Timer(new Duration(seconds: 1), () {
+ print('"pub serve" is compiling $path...');
+ });
+
+ return _http.headUrl(jsUrl)
+ .then((request) => request.close())
+ .whenComplete(timer.cancel)
+ .catchError((error, stackTrace) {
+ if (error is! IOException) throw error;
+
+ var message = getErrorMessage(error);
+ if (error is SocketException) {
+ message = "${error.osError.message} "
+ "(errno ${error.osError.errorCode})";
+ }
+
+ throw new LoadException(path,
+ "Error getting $jsUrl: $message\n"
+ 'Make sure "pub serve" is running.');
+ }).then((response) {
+ if (response.statusCode == 200) return;
+
+ throw new LoadException(path,
+ "Error getting $jsUrl: ${response.statusCode} "
+ "${response.reasonPhrase}\n"
+ 'Make sure "pub serve" is serving the test/ directory.');
+ });
+ });
+ }
+
/// Compile the test suite at [dartPath] to JavaScript.
///
/// Returns a [Future] that completes to the path to the JavaScript.
@@ -154,7 +241,12 @@ class BrowserServer {
/// Returns a [Future] that completes once the server is closed and its
/// resources have been fully released.
Future close() {
- new Directory(_compiledDir).deleteSync(recursive: true);
+ if (_pubServeUrl == null) {
+ new Directory(_compiledDir).deleteSync(recursive: true);
+ } else {
+ _http.close();
+ }
+
return _server.close().then((_) {
if (_browserManagerCompleter == null) return null;
return _browserManager.then((_) => _browser.close());

Powered by Google App Engine
This is Rietveld 408576698