Use the package_resolver package.
Closes #327
R=leafp@google.com
Review URL: https://codereview.chromium.org//2184543002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a966e51..b36261f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.12.15+2
+
+* Support running without a `packages/` directory.
+
## 0.12.15+1
* Declare support for version 1.19 of the Dart SDK.
diff --git a/lib/src/runner/browser/compiler_pool.dart b/lib/src/runner/browser/compiler_pool.dart
index 6503db5..39b32f3 100644
--- a/lib/src/runner/browser/compiler_pool.dart
+++ b/lib/src/runner/browser/compiler_pool.dart
@@ -7,6 +7,7 @@
import 'dart:io';
import 'package:async/async.dart';
+import 'package:package_resolver/package_resolver.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
@@ -44,13 +45,11 @@
/// Compile the Dart code at [dartPath] to [jsPath].
///
- /// This wraps the Dart code in the standard browser-testing wrapper. If
- /// [packageRoot] is provided, it's used as the package root for the
- /// compilation.
+ /// This wraps the Dart code in the standard browser-testing wrapper.
///
/// The returned [Future] will complete once the `dart2js` process completes
/// *and* all its output has been printed to the command line.
- Future compile(String dartPath, String jsPath, {String packageRoot}) {
+ Future compile(String dartPath, String jsPath) {
return _pool.withResource(() {
if (_closed) return null;
@@ -73,12 +72,12 @@
var dart2jsPath = _config.dart2jsPath;
if (Platform.isWindows) dart2jsPath += '.bat';
- var args = ["--checked", wrapperPath, "--out=$jsPath"]
- ..addAll(_config.dart2jsArgs);
-
- if (packageRoot != null) {
- args.add("--package-root=${p.toUri(p.absolute(packageRoot))}");
- }
+ var args = [
+ "--checked",
+ wrapperPath,
+ "--out=$jsPath",
+ await PackageResolver.current.processArgument
+ ]..addAll(_config.dart2jsArgs);
if (_config.color) args.add("--enable-diagnostic-colors");
diff --git a/lib/src/runner/browser/platform.dart b/lib/src/runner/browser/platform.dart
index e430231..0d84ccc 100644
--- a/lib/src/runner/browser/platform.dart
+++ b/lib/src/runner/browser/platform.dart
@@ -8,12 +8,14 @@
import 'package:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
+import 'package:package_resolver/package_resolver.dart';
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';
import 'package:shelf_web_socket/shelf_web_socket.dart';
+import 'package:shelf_packages_handler/shelf_packages_handler.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
@@ -120,7 +122,7 @@
if (_config.pubServeUrl == null) {
cascade = cascade
- .add(_createPackagesHandler())
+ .add(packagesDirHandler())
.add(_jsHandler.handler)
.add(createStaticHandler(_root))
.add(_wrapperHandler);
@@ -131,33 +133,12 @@
}
var pipeline = new shelf.Pipeline()
- .addMiddleware(nestingMiddleware(_secret))
- .addHandler(cascade.handler);
+ .addMiddleware(nestingMiddleware(_secret))
+ .addHandler(cascade.handler);
_server.mount(pipeline);
}
- /// Returns a handler that serves the contents of the "packages/" directory
- /// for any URL that contains "packages/".
- ///
- /// This is a factory so it can wrap a static handler.
- shelf.Handler _createPackagesHandler() {
- var staticHandler =
- createStaticHandler(_config.packageRoot, serveFilesOutsidePath: true);
-
- return (request) {
- var segments = p.url.split(request.url.path);
-
- for (var i = 0; i < segments.length; i++) {
- if (segments[i] != "packages") continue;
- return staticHandler(
- request.change(path: p.url.joinAll(segments.take(i + 1))));
- }
-
- return new shelf.Response.notFound("Not found.");
- };
- }
-
/// A handler that serves wrapper files used to bootstrap tests.
shelf.Response _wrapperHandler(shelf.Request request) {
var path = p.fromUri(request.url);
@@ -317,7 +298,8 @@
_mappers[path] = new StackTraceMapper(
await UTF8.decodeStream(response),
mapUrl: url,
- packageRoot: _config.pubServeUrl.resolve('packages'),
+ packageResolver: new SyncPackageResolver.root(
+ _config.pubServeUrl.resolve('packages')),
sdkRoot: _config.pubServeUrl.resolve('packages/\$sdk'));
return;
}
@@ -349,8 +331,7 @@
var dir = new Directory(_compiledDir).createTempSync('test_').path;
var jsPath = p.join(dir, p.basename(dartPath) + ".browser_test.dart.js");
- await _compilers.compile(dartPath, jsPath,
- packageRoot: _config.packageRoot);
+ await _compilers.compile(dartPath, jsPath);
if (_closed) return;
var jsUrl = p.toUri(p.relative(dartPath, from: _root)).path +
@@ -373,7 +354,7 @@
_mappers[dartPath] = new StackTraceMapper(
new File(mapPath).readAsStringSync(),
mapUrl: p.toUri(mapPath),
- packageRoot: p.toUri(_config.packageRoot),
+ packageResolver: await PackageResolver.current.asSync,
sdkRoot: p.toUri(sdkDir));
});
}
diff --git a/lib/src/runner/configuration.dart b/lib/src/runner/configuration.dart
index 321a406..e31b066 100644
--- a/lib/src/runner/configuration.dart
+++ b/lib/src/runner/configuration.dart
@@ -68,10 +68,6 @@
bool get pauseAfterLoad => _pauseAfterLoad ?? false;
final bool _pauseAfterLoad;
- /// The package root for resolving "package:" URLs.
- String get packageRoot => _packageRoot ?? p.join(p.current, 'packages');
- final String _packageRoot;
-
/// The path to dart2js.
String get dart2jsPath => _dart2jsPath ?? p.join(sdkDir, 'bin', 'dart2js');
final String _dart2jsPath;
@@ -283,7 +279,6 @@
PlatformSelector testOn,
bool pauseAfterLoad,
bool color,
- String packageRoot,
String dart2jsPath,
Iterable<String> dart2jsArgs,
String precompiledPath,
@@ -315,7 +310,6 @@
testOn: testOn,
pauseAfterLoad: pauseAfterLoad,
color: color,
- packageRoot: packageRoot,
dart2jsPath: dart2jsPath,
dart2jsArgs: dart2jsArgs,
precompiledPath: precompiledPath,
@@ -386,7 +380,6 @@
PlatformSelector testOn,
bool pauseAfterLoad,
bool color,
- String packageRoot,
String dart2jsPath,
Iterable<String> dart2jsArgs,
this.precompiledPath,
@@ -416,7 +409,6 @@
testOn = testOn ?? PlatformSelector.all,
_pauseAfterLoad = pauseAfterLoad,
_color = color,
- _packageRoot = packageRoot,
_dart2jsPath = dart2jsPath,
dart2jsArgs = dart2jsArgs?.toList() ?? [],
_reporter = reporter,
@@ -491,7 +483,6 @@
testOn: testOn.intersection(other.testOn),
pauseAfterLoad: other._pauseAfterLoad ?? _pauseAfterLoad,
color: other._color ?? _color,
- packageRoot: other._packageRoot ?? _packageRoot,
dart2jsPath: other._dart2jsPath ?? _dart2jsPath,
dart2jsArgs: dart2jsArgs.toList()..addAll(other.dart2jsArgs),
precompiledPath: other.precompiledPath ?? precompiledPath,
@@ -534,7 +525,6 @@
PlatformSelector testOn,
bool pauseAfterLoad,
bool color,
- String packageRoot,
String dart2jsPath,
Iterable<String> dart2jsArgs,
String precompiledPath,
@@ -566,7 +556,6 @@
testOn: testOn ?? this.testOn,
pauseAfterLoad: pauseAfterLoad ?? _pauseAfterLoad,
color: color ?? _color,
- packageRoot: packageRoot ?? _packageRoot,
dart2jsPath: dart2jsPath ?? _dart2jsPath,
dart2jsArgs: dart2jsArgs?.toList() ?? this.dart2jsArgs,
precompiledPath: precompiledPath ?? this.precompiledPath,
diff --git a/lib/src/runner/configuration/args.dart b/lib/src/runner/configuration/args.dart
index 84f59b6..b7ac949 100644
--- a/lib/src/runner/configuration/args.dart
+++ b/lib/src/runner/configuration/args.dart
@@ -24,7 +24,6 @@
help: "Shows this usage information.");
parser.addFlag("version", negatable: false,
help: "Shows the package's version.");
- parser.addOption("package-root", hide: true);
// Note that defaultsTo declarations here are only for documentation purposes.
// We pass null values rather than defaults to [new Configuration] so that it
@@ -192,7 +191,6 @@
jsTrace: _ifParsed('js-trace'),
pauseAfterLoad: _ifParsed('pause-after-load'),
color: _ifParsed('color'),
- packageRoot: _ifParsed('package-root'),
dart2jsPath: _ifParsed('dart2js-path'),
dart2jsArgs: _ifParsed('dart2js-args') as List<String>,
precompiledPath: _ifParsed('precompiled'),
diff --git a/lib/src/runner/vm/platform.dart b/lib/src/runner/vm/platform.dart
index 41ffd41..78ce654 100644
--- a/lib/src/runner/vm/platform.dart
+++ b/lib/src/runner/vm/platform.dart
@@ -69,7 +69,7 @@
});
new IsolateChannel.connectSend(message).pipe(channel);
}
- ''', message, packageRoot: p.toUri(_config.packageRoot), checked: true);
+ ''', message, checked: true);
}
var url = _config.pubServeUrl.resolveUri(
diff --git a/lib/src/util/dart.dart b/lib/src/util/dart.dart
index f6ddff0..05cd260 100644
--- a/lib/src/util/dart.dart
+++ b/lib/src/util/dart.dart
@@ -16,18 +16,13 @@
/// they will be resolved in the same context as the host isolate. [message] is
/// passed to the [main] method of the code being run; the caller is responsible
/// for using this to establish communication with the isolate.
-///
-/// [packageRoot] controls the package root of the isolate. It may be either a
-/// [String] or a [Uri].
-Future<Isolate> runInIsolate(String code, message, {packageRoot,
- bool checked}) async {
- if (packageRoot is String) packageRoot = Uri.parse(packageRoot);
-
+Future<Isolate> runInIsolate(String code, message, {bool checked}) async {
return await Isolate.spawnUri(
Uri.parse('data:application/dart;charset=utf-8,' + Uri.encodeFull(code)),
[],
message,
- packageRoot: packageRoot,
+ packageRoot: await Isolate.packageRoot,
+ packageConfig: await Isolate.packageConfig,
checked: checked);
}
diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart
index 4ede604..3f7f13a 100644
--- a/lib/src/util/io.dart
+++ b/lib/src/util/io.dart
@@ -4,13 +4,11 @@
import 'dart:async';
import 'dart:io';
-import 'dart:mirrors';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import '../backend/operating_system.dart';
-import '../runner/application_exception.dart';
import '../util/stream_queue.dart';
import '../utils.dart';
@@ -52,12 +50,6 @@
? Platform.environment["_UNITTEST_TEMP_DIR"]
: Directory.systemTemp.path;
-/// The path to the `lib` directory of the `test` package.
-String libDir({String packageRoot}) {
- var pathToIo = libraryPath(#test.util.io, packageRoot: packageRoot);
- return p.dirname(p.dirname(p.dirname(pathToIo)));
-}
-
// TODO(nweiz): Make this check [stdioType] once that works within "pub run".
/// Whether "special" strings such as Unicode characters or color escapes are
/// safe to use.
@@ -124,34 +116,6 @@
stderr.writeln(wordWrap("$header $message\n"));
}
-/// Returns the package root at [root].
-///
-/// If [override] is passed, that's used. If the package root doesn't exist, an
-/// [ApplicationException] is thrown.
-String packageRootFor(String root, [String override]) {
- if (root == null) root = p.current;
- var packageRoot = override == null ? p.join(root, 'packages') : override;
-
- if (!new Directory(packageRoot).existsSync()) {
- throw new ApplicationException(
- "Directory ${p.prettyUri(p.toUri(packageRoot))} does not exist.");
- }
-
- return packageRoot;
-}
-
-/// The library name must be globally unique, or the wrong library path may be
-/// returned.
-String libraryPath(Symbol libraryName, {String packageRoot}) {
- var lib = currentMirrorSystem().findLibrary(libraryName);
- if (lib.uri.scheme != 'package') return p.fromUri(lib.uri);
-
- // TODO(nweiz): is there a way to avoid assuming this is being run next to a
- // packages directory?.
- if (packageRoot == null) packageRoot = p.absolute('packages');
- return p.join(packageRoot, p.fromUri(lib.uri.path));
-}
-
/// Repeatedly finds a probably-unused port on localhost and passes it to
/// [tryPort] until it binds successfully.
///
diff --git a/lib/src/util/stack_trace_mapper.dart b/lib/src/util/stack_trace_mapper.dart
index a50c75e..04390fa 100644
--- a/lib/src/util/stack_trace_mapper.dart
+++ b/lib/src/util/stack_trace_mapper.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:package_resolver/package_resolver.dart';
import 'package:source_map_stack_trace/source_map_stack_trace.dart' as mapper;
import 'package:source_maps/source_maps.dart';
@@ -10,19 +11,20 @@
/// The parsed source map.
final Mapping _mapping;
- /// The URI of the package root, as passed to dart2js.
- final Uri _packageRoot;
+ /// The package resolution information passed to dart2js.
+ final SyncPackageResolver _packageResolver;
/// The URI of the SDK root from which dart2js loaded its sources.
final Uri _sdkRoot;
- StackTraceMapper(String contents, {Uri mapUrl, Uri packageRoot, Uri sdkRoot})
+ StackTraceMapper(String contents, {Uri mapUrl,
+ SyncPackageResolver packageResolver, Uri sdkRoot})
: _mapping = parse(contents, mapUrl: mapUrl),
- _packageRoot = packageRoot,
+ _packageResolver = packageResolver,
_sdkRoot = sdkRoot;
/// Converts [trace] into a Dart stack trace.
StackTrace mapStackTrace(StackTrace trace) =>
mapper.mapStackTrace(_mapping, trace,
- packageRoot: _packageRoot, sdkRoot: _sdkRoot);
+ packageResolver: _packageResolver, sdkRoot: _sdkRoot);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 6a4d8e5..c67e91d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
name: test
-version: 0.12.15+1
+version: 0.12.15+2
author: Dart Team <misc@dartlang.org>
description: A library for writing dart unit tests.
homepage: https://github.com/dart-lang/test
environment:
- sdk: '>=1.13.0 <1.20.0'
+ sdk: '>=1.14.0 <2.0.0'
dependencies:
analyzer: '>=0.23.0 <0.28.0'
args: '^0.13.1'
@@ -14,13 +14,15 @@
collection: '^1.8.0'
glob: '^1.0.0'
http_multi_server: '>=1.0.0 <3.0.0'
+ package_resolver: '^1.0.0'
path: '^1.2.0'
pool: '^1.2.0'
pub_semver: '^1.0.0'
shelf: '>=0.6.5 <0.8.0'
+ shelf_packages_handler: '^1.0.0'
shelf_static: '^0.2.0'
shelf_web_socket: '^0.2.0'
- source_map_stack_trace: '^1.0.0'
+ source_map_stack_trace: '^1.1.0'
source_maps: '^0.10.1'
source_span: '^1.0.0'
stack_trace: '^1.2.1'
diff --git a/test/io.dart b/test/io.dart
index b89e40c..331a220 100644
--- a/test/io.dart
+++ b/test/io.dart
@@ -8,7 +8,9 @@
import 'dart:async';
import 'dart:io';
+import 'dart:isolate';
+import 'package:package_resolver/package_resolver.dart';
import 'package:path/path.dart' as p;
import 'package:scheduled_test/descriptor.dart' as d;
import 'package:scheduled_test/scheduled_process.dart';
@@ -17,7 +19,7 @@
import 'package:test/src/util/io.dart';
/// The path to the root directory of the `test` package.
-final String packageDir = p.dirname(p.dirname(libraryPath(#test.test.io)));
+final Future<String> packageDir = PackageResolver.current.packagePath('test');
/// The path to the `pub` executable in the current Dart SDK.
final _pubPath = p.absolute(p.join(
@@ -108,8 +110,7 @@
concurrency ??= 1;
var allArgs = [
- p.absolute(p.join(packageDir, 'bin/test.dart')),
- "--package-root=${p.join(packageDir, 'packages')}",
+ packageDir.then((dir) => p.absolute(p.join(dir, 'bin/test.dart'))),
"--concurrency=$concurrency"
];
if (reporter != null) allArgs.add("--reporter=$reporter");
@@ -133,13 +134,12 @@
/// Runs Dart.
ScheduledProcess runDart(List<String> args, {Map<String, String> environment,
String description}) {
- var allArgs = Platform.executableArguments.map((arg) {
- // The package root might be relative, so we need to make it absolute if
- // we're going to run in a different working directory.
- if (!arg.startsWith("--package-root=")) return arg;
- return "--package-root=" +
- p.absolute(p.fromUri(arg.substring("--package-root=".length)));
- }).toList()..addAll(args);
+ var allArgs = Platform.executableArguments
+ .where((arg) =>
+ !arg.startsWith("--package-root=") && !arg.startsWith("--packages="))
+ .toList()
+ ..add(PackageResolver.current.processArgument)
+ ..addAll(args);
return new ScheduledProcess.start(
p.absolute(Platform.resolvedExecutable), allArgs,
diff --git a/test/runner/browser/loader_test.dart b/test/runner/browser/loader_test.dart
index 1c924d3..4eae04b 100644
--- a/test/runner/browser/loader_test.dart
+++ b/test/runner/browser/loader_test.dart
@@ -34,11 +34,9 @@
""";
void main() {
- setUp(() {
+ setUp(() async {
_sandbox = createTempDir();
- _loader = new Loader(new Configuration(
- platforms: [TestPlatform.chrome],
- packageRoot: p.join(packageDir, 'packages')),
+ _loader = new Loader(new Configuration(platforms: [TestPlatform.chrome]),
root: _sandbox);
/// TODO(nweiz): Use scheduled_test for this once it's compatible with this
/// version of test.
@@ -127,9 +125,7 @@
test("loads a suite both in the browser and the VM", () async {
var loader = new Loader(
- new Configuration(
- platforms: [TestPlatform.vm, TestPlatform.chrome],
- packageRoot: p.join(packageDir, 'packages')),
+ new Configuration(platforms: [TestPlatform.vm, TestPlatform.chrome]),
root: _sandbox);
var path = p.join(_sandbox, 'a_test.dart');
diff --git a/test/runner/configuration/configuration_test.dart b/test/runner/configuration/configuration_test.dart
index 2a4a2e0..92c824d 100644
--- a/test/runner/configuration/configuration_test.dart
+++ b/test/runner/configuration/configuration_test.dart
@@ -30,7 +30,6 @@
expect(merged.color, equals(canUseSpecialChars));
expect(merged.shardIndex, isNull);
expect(merged.totalShards, isNull);
- expect(merged.packageRoot, equals(p.join(p.current, 'packages')));
expect(merged.dart2jsPath, equals(p.join(sdkDir, 'bin', 'dart2js')));
expect(merged.precompiledPath, isNull);
expect(merged.reporter, equals(defaultReporter));
@@ -52,7 +51,6 @@
color: true,
shardIndex: 3,
totalShards: 10,
- packageRoot: "root",
dart2jsPath: "/tmp/dart2js",
precompiledPath: "/tmp/js",
reporter: "json",
@@ -72,7 +70,6 @@
expect(merged.color, isTrue);
expect(merged.shardIndex, equals(3));
expect(merged.totalShards, equals(10));
- expect(merged.packageRoot, equals("root"));
expect(merged.dart2jsPath, equals("/tmp/dart2js"));
expect(merged.precompiledPath, equals("/tmp/js"));
expect(merged.reporter, equals("json"));
@@ -94,7 +91,6 @@
color: true,
shardIndex: 3,
totalShards: 10,
- packageRoot: "root",
dart2jsPath: "/tmp/dart2js",
precompiledPath: "/tmp/js",
reporter: "json",
@@ -113,7 +109,6 @@
expect(merged.color, isTrue);
expect(merged.shardIndex, equals(3));
expect(merged.totalShards, equals(10));
- expect(merged.packageRoot, equals("root"));
expect(merged.dart2jsPath, equals("/tmp/dart2js"));
expect(merged.precompiledPath, equals("/tmp/js"));
expect(merged.reporter, equals("json"));
@@ -136,7 +131,6 @@
color: false,
shardIndex: 2,
totalShards: 4,
- packageRoot: "root",
dart2jsPath: "/tmp/dart2js",
precompiledPath: "/tmp/js",
reporter: "json",
@@ -155,7 +149,6 @@
color: true,
shardIndex: 3,
totalShards: 10,
- packageRoot: "boot",
dart2jsPath: "../dart2js",
precompiledPath: "../js",
reporter: "compact",
@@ -174,7 +167,6 @@
expect(merged.color, isTrue);
expect(merged.shardIndex, equals(3));
expect(merged.totalShards, equals(10));
- expect(merged.packageRoot, equals("boot"));
expect(merged.dart2jsPath, equals("../dart2js"));
expect(merged.precompiledPath, equals("../js"));
expect(merged.reporter, equals("compact"));
diff --git a/test/runner/loader_test.dart b/test/runner/loader_test.dart
index f93bae9..182d2e2 100644
--- a/test/runner/loader_test.dart
+++ b/test/runner/loader_test.dart
@@ -33,10 +33,10 @@
""";
void main() {
- setUp(() {
+ setUp(() async {
_sandbox = createTempDir();
_loader = new Loader(
- new Configuration(packageRoot: p.join(packageDir, 'packages')),
+ new Configuration(),
root: _sandbox);
});
diff --git a/test/runner/precompiled_paths_test.dart b/test/runner/precompiled_paths_test.dart
index a60a0c8..a5763da 100644
--- a/test/runner/precompiled_paths_test.dart
+++ b/test/runner/precompiled_paths_test.dart
@@ -7,6 +7,7 @@
import 'dart:io';
+import 'package:package_resolver/package_resolver.dart';
import 'package:path/path.dart' as p;
import 'package:scheduled_test/descriptor.dart' as d;
import 'package:scheduled_test/scheduled_process.dart';
@@ -39,7 +40,7 @@
d.dir("precompiled", []).create();
var dart2js = new ScheduledProcess.start(p.join(sdkDir, 'bin', 'dart2js'), [
- "--package-root=${p.join(p.current, 'packages')}",
+ PackageResolver.current.processArgument,
"to_precompile.dart",
"--out=precompiled/test.dart.browser_test.dart.js"
], workingDirectory: sandbox);