Add more tests Review URL: https://codereview.chromium.org//1152173005
diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 78254ee..52f208d 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart
@@ -44,9 +44,9 @@ if (baseUri.scheme == "file") { return new Future<Packages>.sync(() => findPackagesFromFile(baseUri)); } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, _httpGet); + return findPackagesFromNonFile(baseUri, loader: _httpGet); } else if (loader != null) { - return findPackagesFromNonFile(baseUri, loader); + return findPackagesFromNonFile(baseUri, loader: loader); } else { return new Future<Packages>.value(Packages.noPackages); } @@ -138,7 +138,7 @@ /// of the requestsed `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future<Packages> findPackagesFromNonFile(Uri nonFileUri, - [Future<List<int>> loader(Uri name)]) { + {Future<List<int>> loader(Uri name)}) { if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List<int> fileBytes) {
diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 612dc34..9563762 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart
@@ -70,7 +70,7 @@ FilePackagesDirectoryPackages(this._packageDir); Uri _getBase(String packageName) => - new Uri.directory(path.join(packageName,'')); + new Uri.directory(path.join(_packageDir.path, packageName, '')); Iterable<String> _listPackageNames() { return _packageDir.listSync()
diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart index 310e1ee..79f5b35 100644 --- a/pkgs/package_config/test/all.dart +++ b/pkgs/package_config/test/all.dart
@@ -2,8 +2,10 @@ // 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 'parse_test.dart' as parse; +import "discovery_test.dart" as discovery; +import "parse_test.dart" as parse; main() { parse.main(); + discovery.main(); }
diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart new file mode 100644 index 0000000..4a88928 --- /dev/null +++ b/pkgs/package_config/test/discovery_test.dart
@@ -0,0 +1,281 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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 "dart:async"; +import "dart:io"; +import "package:test/test.dart"; +import "package:package_config/packages.dart"; +import "package:package_config/discovery.dart"; +import "package:path/path.dart" as path; + +const packagesFile = """ +# A comment +foo=file:///dart/packages/foo/ +bar=http://example.com/dart/packages/bar/ +baz=packages/baz/ +"""; + +void validatePackagesFile(Packages resolver, Uri location) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +} + +void validatePackagesDir(Packages resolver, Uri location) { + // Expect three packages: foo, bar and baz + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(location.resolve("packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(location.resolve("packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + if (location.scheme == "file") { + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); + } else { + expect(() => resolver.packages, throws); + } +} + + +Uri pkg(String packageName, String packagePath) { + var path; + if (packagePath.startsWith('/')) { + path = "$packageName$packagePath"; + } else { + path = "$packageName/$packagePath"; + } + return new Uri(scheme: "package", path: path); +} + +main() { + generalTest(".packages", + {".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}}}, + (Uri location) async { + Packages resolver; + resolver = await findPackages(location); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + var specificDiscovery = (location.scheme == "file") + ? findPackagesFromFile + : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesFile(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + }); + + generalTest("packages/", + {"packages": { "foo": {}, "bar": {}, "baz": {}}, + "script.dart": "main(){}"}, + (Uri location) async { + Packages resolver; + bool isFile = (location.scheme == "file"); + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + var specificDiscovery = isFile + ? findPackagesFromFile + : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesDir(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + fileTest(".packages recursive", + {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, + (Uri location) async { + Packages resolver; + resolver = await findPackages(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromFile(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = + await findPackagesFromFile(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + }); + + httpTest(".packages not recursive", + {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, + (Uri location) async { + Packages resolver; + var subdir = location.resolve("subdir/"); + resolver = await findPackages(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackages(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + }); + + fileTest("no packages", + {"script.dart": "main(){}"}, + (Uri location) async { + // A file: location with no .packages or packages returns + // Packages.noPackages. + Packages resolver; + resolver = await findPackages(location); + expect(resolver, same(Packages.noPackages)); + resolver = await findPackages(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + }); + + httpTest("no packages", + {"script.dart": "main(){}"}, + (Uri location) async { + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + test(".packages w/ loader", () async { + Uri location = Uri.parse("krutch://example.com/path/"); + Future loader(Uri file) async { + if (file.path.endsWith(".packages")) { + return packagesFile.codeUnits; + } + throw "not found"; + } + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("script.dart"), + loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader: loader); + validatePackagesFile(resolver, location); + }); + + test("no packages w/ loader", () async { + Uri location = Uri.parse("krutch://example.com/path/"); + Future loader(Uri file) async { + throw "not found"; + } + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart"), + loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader:loader); + validatePackagesDir(resolver, location); + }); +} + +/// Create a directory structure from [description] and run [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void fileTest(String name, + Map description, + Future fileTest(Uri directory)) { + group("file-test", () { + Directory tempDir = Directory.systemTemp.createTempSync("file-test"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(new Uri.directory(tempDir.path))); + }); +} + +/// HTTP-server the directory structure from [description] and run [htpTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void httpTest(String name, Map description, Future httpTest(Uri directory)) { + group("http-test", () { + var serverSub; + var uri; + setUp(() { + return HttpServer + .bind(InternetAddress.LOOPBACK_IP_V4, 0) + .then((server) { + uri = new Uri(scheme: "http", + host: "127.0.0.1", + port: server.port, + path: "/"); + serverSub = server.listen((HttpRequest request) { + // No error handling. + var path = request.uri.path; + if (path.startsWith('/')) path = path.substring(1); + if (path.endsWith('/')) path = path.substring(0, path.length - 1); + var parts = path.split('/'); + var fileOrDir = description; + for (int i = 0; i < parts.length; i++) { + fileOrDir = fileOrDir[parts[i]]; + if (fileOrDir == null) { + request.response.statusCode = 404; + request.response.close(); + } + } + request.response.write(fileOrDir); + request.response.close(); + }); + }); + }); + tearDown(() => serverSub.cancel()); + test(name, () => httpTest(uri)); + }); +} + +void generalTest(String name, Map description, Future action(Uri location)) { + fileTest(name, description, action); + httpTest(name, description, action); +} + +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + if (content is Map) { + Directory subDir = new Directory(path.join(target.path, name)); + subDir.createSync(); + _createFiles(subDir, content); + } else { + File file = new File(path.join(target.path, name)); + file.writeAsStringSync(content, flush: true); + } + }); +} + +