From 88a64b77bf04159061ae3d9f7f8eafac8c3c83c6 Mon Sep 17 00:00:00 2001 From: William Hesse Date: Mon, 19 Sep 2016 18:43:16 +0200 Subject: [PATCH] Add support for package spec to testing HttpServer. BUG=https://github.com/dart-lang/sdk/issues/27065 R=terry@google.com Review URL: https://codereview.chromium.org/2347423003 . --- tools/.packages | 9 - tools/testing/dart/http_server.dart | 183 ++++++++++---------- tools/testing/dart/test_configurations.dart | 5 +- 3 files changed, 95 insertions(+), 102 deletions(-) delete mode 100644 tools/.packages diff --git a/tools/.packages b/tools/.packages deleted file mode 100644 index 888665a2fdd..00000000000 --- a/tools/.packages +++ /dev/null @@ -1,9 +0,0 @@ -# The test runner logic depends on `package:yaml`, because it is not structured -# as a pub package, we generated this file manually to contain all of yaml's -# transitive dependencies. -charcode:../third_party/pkg/charcode/lib/ -collection:../third_party/pkg/collection/lib/ -path:../third_party/pkg/path/lib/ -source_span:../third_party/pkg/source_span/lib/ -string_scanner:../third_party/pkg/string_scanner/lib/ -yaml:../third_party/pkg/yaml/lib/ diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart index 82f45ccecf1..5213dae2d1e 100644 --- a/tools/testing/dart/http_server.dart +++ b/tools/testing/dart/http_server.dart @@ -9,13 +9,10 @@ import 'dart:io'; import 'dart:convert' show HtmlEscape; -import 'path.dart'; import 'test_suite.dart'; // For TestUtils. -// TODO(efortuna): Rewrite to not use the args library and simply take an -// expected number of arguments, so test.dart doesn't rely on the args library? -// See discussion on https://codereview.chromium.org/11931025/. import 'vendored_pkg/args/args.dart'; import 'utils.dart'; +import 'package:package_resolver/package_resolver.dart'; class DispatchingServer { HttpServer server; @@ -52,9 +49,10 @@ class DispatchingServer { /// directory (i.e. '$DartDirectory/X'). /// /root_build/X: This will serve the corresponding file from the build /// directory (i.e. '$BuildDirectory/X'). -/// /FOO/packages/BAR: This will serve the corresponding file from the packages -/// directory (i.e. '$BuildDirectory/packages/BAR') or the -/// passed-in package root +/// /FOO/packages/PAZ/BAR: This will serve files from the packages listed in +/// the package spec .packages. Supports a package +/// root or custom package spec, and uses [dart_dir]/.packages +/// as the default. This will serve file lib/BAR from the package PAZ. /// /ws: This will upgrade the connection to a WebSocket connection and echo /// all data back to the client. /// @@ -64,10 +62,6 @@ class DispatchingServer { const PREFIX_BUILDDIR = 'root_build'; const PREFIX_DARTDIR = 'root_dart'; -// TODO(kustermann,ricow): We could change this to the following scheme: -// http://host:port/root_packages/X -> $BuildDir/packages/X -// Issue: 8368 - main(List arguments) { // This script is in [dart]/tools/testing/dart. TestUtils.setDartDirUri(Platform.script.resolve('../../..')); @@ -97,7 +91,7 @@ main(List arguments) { if (args['help']) { print(parser.getUsage()); } else { - var servers = new TestingServers(new Path(args['build-directory']), + var servers = new TestingServers(args['build-directory'], args['csp'], args['runtime'], null, args['package-root'], args['packages']); var port = int.parse(args['port']); @@ -129,26 +123,35 @@ class TestingServers { ]; List _serverList = []; - Path _buildDirectory = null; - Path _dartDirectory = null; - Path _packageRoot; - Path _packages; + Uri _buildDirectory = null; + Uri _dartDirectory = null; + Uri _packageRoot; + Uri _packages; final bool useContentSecurityPolicy; final String runtime; DispatchingServer _server; + SyncPackageResolver _resolver; - TestingServers(Path buildDirectory, this.useContentSecurityPolicy, + TestingServers(String buildDirectory, this.useContentSecurityPolicy, [String this.runtime = 'none', String dartDirectory, String packageRoot, String packages]) { - _buildDirectory = TestUtils.absolutePath(buildDirectory); - _dartDirectory = - dartDirectory == null ? TestUtils.dartDir : new Path(dartDirectory); - _packageRoot = packageRoot == null - ? (packages == null ? _buildDirectory.append('packages') : null) - : new Path(packageRoot); - _packages = packages == null ? null : new Path(packages); + _buildDirectory = Uri.base.resolveUri(new Uri.directory(buildDirectory)); + if (dartDirectory == null) { + _dartDirectory = TestUtils.dartDirUri; + } else { + _dartDirectory = Uri.base.resolveUri(new Uri.directory(dartDirectory)); + } + if (packageRoot == null ) { + if (packages == null ) { + _packages = _dartDirectory.resolve('.packages'); + } else { + _packages = new Uri.file(packages); + } + } else { + _packageRoot = new Uri.directory(packageRoot); + } } int get port => _serverList[0].port; @@ -163,23 +166,37 @@ class TestingServers { * "Access-Control-Allow-Origin: client:port1 * "Access-Control-Allow-Credentials: true" */ - Future startServers(String host, {int port: 0, int crossOriginPort: 0}) { - return _startHttpServer(host, port: port).then((server) { - _server = server; - return _startHttpServer(host, - port: crossOriginPort, allowedPort: _serverList[0].port); - }); + Future startServers(String host, + {int port: 0, + int crossOriginPort: 0}) async { + if (_packages != null) { + _resolver = await SyncPackageResolver.loadConfig(_packages); + } else { + _resolver = new SyncPackageResolver.root(_packageRoot); + } + _server = await _startHttpServer(host, port: port); + await _startHttpServer(host, port: crossOriginPort, + allowedPort: _serverList[0].port); } String httpServerCommandline() { var dart = Platform.resolvedExecutable; - var dartDir = TestUtils.dartDir; - var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); - var buildDirectory = _buildDirectory.toNativePath(); - var csp = useContentSecurityPolicy ? '--csp ' : ''; - return '$dart $script -p $port -c $crossOriginPort $csp' - '--build-directory=$buildDirectory --runtime=$runtime ' - '--package-root=$_packageRoot'; + var script = _dartDirectory.resolve('tools/testing/dart/http_server.dart'); + var buildDirectory = _buildDirectory.toFilePath(); + var command = [dart, script.toFilePath(), + '-p', port, + '-c', crossOriginPort, + '--build-directory=$buildDirectory', + '--runtime=$runtime']; + if (useContentSecurityPolicy) { + command.add('--csp'); + } + if (_packages != null) { + command.add('--packages=${_packages.toFilePath()}'); + } else if (_packageRoot != null) { + command.add('--package-root=${_packageRoot.toFilePath()}'); + } + return command.join(' '); } void stopServers() { @@ -208,30 +225,24 @@ class TestingServers { }); } - void _handleFileOrDirectoryRequest(HttpRequest request, int allowedPort) { + _handleFileOrDirectoryRequest(HttpRequest request, + int allowedPort) async { // Enable browsers to cache file/directory responses. var response = request.response; response.headers .set("Cache-Control", "max-age=$_CACHE_EXPIRATION_IN_SECONDS"); - var path = _getFilePathFromRequestPath(request.uri.path); + var path = _getFileUriFromRequestUri(request.uri); if (path != null) { - var file = new File(path.toNativePath()); - file.exists().then((exists) { - if (exists) { - _sendFileContent(request, response, allowedPort, path, file); - } else { - var directory = new Directory(path.toNativePath()); - directory.exists().then((exists) { - if (exists) { - _listDirectory(directory).then((entries) { - _sendDirectoryListing(entries, request, response); - }); - } else { - _sendNotFound(request); - } - }); - } - }); + var file = new File.fromUri(path); + var directory = new Directory.fromUri(path); + if (await file.exists()){ + _sendFileContent(request, response, allowedPort, file); + } else if (await directory.exists()) { + _sendDirectoryListing( + await _listDirectory(directory), request, response); + } else { + _sendNotFound(request); + } } else { if (request.uri.path == '/') { var entries = [ @@ -277,33 +288,21 @@ class TestingServers { }); } - Path _getFilePathFromRequestPath(String urlRequestPath) { + Uri _getFileUriFromRequestUri(Uri request) { // Go to the top of the file to see an explanation of the URL path scheme. - var requestPath = new Path(urlRequestPath.substring(1)).canonicalize(); - var pathSegments = requestPath.segments(); - if (pathSegments.length > 0) { - var basePath; - var relativePath; - if (pathSegments[0] == PREFIX_BUILDDIR) { - basePath = _buildDirectory; - relativePath = new Path(pathSegments.skip(1).join('/')); - } else if (pathSegments[0] == PREFIX_DARTDIR) { - basePath = _dartDirectory; - relativePath = new Path(pathSegments.skip(1).join('/')); - } - var packagesIndex = pathSegments.indexOf('packages'); - if (packagesIndex != -1) { - if (_packages != null) { - // TODO(27065): Package spec file not supported by http server yet - return null; - } - var start = packagesIndex + 1; - basePath = _packageRoot; - relativePath = new Path(pathSegments.skip(start).join('/')); - } - if (basePath != null && relativePath != null) { - return basePath.join(relativePath); - } + List pathSegments = request.normalizePath().pathSegments; + if (pathSegments.length == 0) return null; + int packagesIndex = pathSegments.indexOf('packages'); + if (packagesIndex != -1) { + var packageUri = new Uri(scheme: 'package', + pathSegments: pathSegments.skip(packagesIndex + 1)); + return _resolver.resolveUri(packageUri); + } + if (pathSegments[0] == PREFIX_BUILDDIR) { + return _buildDirectory.resolve(pathSegments.skip(1).join('/')); + } + if (pathSegments[0] == PREFIX_DARTDIR) { + return _dartDirectory.resolve(pathSegments.skip(1).join('/')); } return null; } @@ -313,11 +312,13 @@ class TestingServers { var entries = []; directory.list().listen((FileSystemEntity fse) { - var filename = new Path(fse.path).filename; + var segments = fse.uri.pathSegments; if (fse is File) { + var filename = segments.last; entries.add(new _Entry(filename, filename)); } else if (fse is Directory) { - entries.add(new _Entry(filename, '$filename/')); + var dirname = segments[segments.length - 2]; + entries.add(new _Entry(dirname, '$dirname/')); } }, onDone: () { completer.complete(entries); @@ -348,7 +349,7 @@ class TestingServers { response.write(header); for (var entry in entries) { response.write( - '
  • ' + '
  • ' '${entry.displayName}
  • '); } response.write(footer); @@ -360,7 +361,7 @@ class TestingServers { } void _sendFileContent(HttpRequest request, HttpResponse response, - int allowedPort, Path path, File file) { + int allowedPort, File file) { if (allowedPort != -1) { var headerOrigin = request.headers.value('Origin'); var allowedOrigin; @@ -396,15 +397,15 @@ class TestingServers { response.headers.set("X-WebKit-CSP", content_header_value); } } - if (path.filename.endsWith('.html')) { + if (file.path.endsWith('.html')) { response.headers.set('Content-Type', 'text/html'); - } else if (path.filename.endsWith('.js')) { + } else if (file.path.endsWith('.js')) { response.headers.set('Content-Type', 'application/javascript'); - } else if (path.filename.endsWith('.dart')) { + } else if (file.path.endsWith('.dart')) { response.headers.set('Content-Type', 'application/dart'); - } else if (path.filename.endsWith('.css')) { + } else if (file.path.endsWith('.css')) { response.headers.set('Content-Type', 'text/css'); - } else if (path.filename.endsWith('.xml')) { + } else if (file.path.endsWith('.xml')) { response.headers.set('Content-Type', 'text/xml'); } response.headers.removeAll("X-Frame-Options"); diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart index 47e233be798..f82e62dad59 100644 --- a/tools/testing/dart/test_configurations.dart +++ b/tools/testing/dart/test_configurations.dart @@ -132,11 +132,12 @@ Future testConfigurations(List configurations) async { // server for cross-domain tests can be found by calling // getCrossOriginPortNumber(). var servers = new TestingServers( - new Path(TestUtils.buildDir(conf)), + TestUtils.buildDir(conf), useContentSecurityPolicy, conf['runtime'], null, - conf['package_root']); + conf['package_root'], + conf['packages']); serverFutures.add(servers.startServers(conf['local_ip'], port: conf['test_server_port'], crossOriginPort: conf['test_server_cross_origin_port']));