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

Unified Diff: utils/tests/pub/test_pub.dart

Issue 14297021: Move pub into sdk/lib/_internal. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Disallow package: imports of pub. Created 7 years, 8 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: utils/tests/pub/test_pub.dart
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
deleted file mode 100644
index f5cb82c3841bebf3b36463419229bd949daa74ac..0000000000000000000000000000000000000000
--- a/utils/tests/pub/test_pub.dart
+++ /dev/null
@@ -1,637 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/// Test infrastructure for testing pub. Unlike typical unit tests, most pub
-/// tests are integration tests that stage some stuff on the file system, run
-/// pub, and then validate the results. This library provides an API to build
-/// tests like that.
-library test_pub;
-
-import 'dart:async';
-import 'dart:collection' show Queue;
-import 'dart:io' hide sleep;
-import 'dart:json' as json;
-import 'dart:math';
-import 'dart:uri';
-import 'dart:utf';
-
-import 'package:http/testing.dart';
-import 'package:oauth2/oauth2.dart' as oauth2;
-import 'package:pathos/path.dart' as path;
-import 'package:scheduled_test/scheduled_process.dart';
-import 'package:scheduled_test/scheduled_server.dart';
-import 'package:scheduled_test/scheduled_test.dart';
-import 'package:yaml/yaml.dart';
-
-import '../../pub/entrypoint.dart';
-// TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides
-// with the git descriptor method. Maybe we should try to clean up the top level
-// scope a bit?
-import '../../pub/git.dart' as gitlib;
-import '../../pub/git_source.dart';
-import '../../pub/hosted_source.dart';
-import '../../pub/http.dart';
-import '../../pub/io.dart';
-import '../../pub/path_source.dart';
-import '../../pub/safe_http_server.dart';
-import '../../pub/system_cache.dart';
-import '../../pub/utils.dart';
-import '../../pub/validator.dart';
-import 'command_line_config.dart';
-import 'descriptor.dart' as d;
-
-/// This should be called at the top of a test file to set up an appropriate
-/// test configuration for the machine running the tests.
-initConfig() {
- // If we aren't running on the bots, use the human-friendly config.
- if (!runningOnBuildbot) {
- unittestConfiguration = new CommandLineConfiguration();
- }
-}
-
-/// Returns whether we're running on a Dart build bot.
-bool get runningOnBuildbot =>
- Platform.environment.containsKey('BUILDBOT_BUILDERNAME');
-
-/// The current [HttpServer] created using [serve].
-var _server;
-
-/// The list of paths that have been requested from the server since the last
-/// call to [getRequestedPaths].
-final _requestedPaths = <String>[];
-
-/// The cached value for [_portCompleter].
-Completer<int> _portCompleterCache;
-
-/// The completer for [port].
-Completer<int> get _portCompleter {
- if (_portCompleterCache != null) return _portCompleterCache;
- _portCompleterCache = new Completer<int>();
- currentSchedule.onComplete.schedule(() {
- _portCompleterCache = null;
- }, 'clearing the port completer');
- return _portCompleterCache;
-}
-
-/// A future that will complete to the port used for the current server.
-Future<int> get port => _portCompleter.future;
-
-/// Gets the list of paths that have been requested from the server since the
-/// last time this was called (or since the server was first spun up).
-Future<List<String>> getRequestedPaths() {
- return schedule(() {
- var paths = _requestedPaths.toList();
- _requestedPaths.clear();
- return paths;
- });
-}
-
-/// Creates an HTTP server to serve [contents] as static files. This server will
-/// exist only for the duration of the pub run.
-///
-/// Subsequent calls to [serve] will replace the previous server.
-void serve([List<d.Descriptor> contents]) {
- var baseDir = d.dir("serve-dir", contents);
-
- schedule(() {
- return _closeServer().then((_) {
- return SafeHttpServer.bind("127.0.0.1", 0).then((server) {
- _server = server;
- server.listen((request) {
- var response = request.response;
- try {
- var path = request.uri.path.replaceFirst("/", "");
-
- if (_requestedPaths == null) _requestedPaths = <String>[];
- _requestedPaths.add(path);
-
- response.persistentConnection = false;
- var stream = baseDir.load(path);
-
- new ByteStream(stream).toBytes().then((data) {
- response.statusCode = 200;
- response.contentLength = data.length;
- response.add(data);
- response.close();
- }).catchError((e) {
- response.statusCode = 404;
- response.contentLength = 0;
- response.close();
- });
- } catch (e) {
- currentSchedule.signalError(e);
- response.statusCode = 500;
- response.close();
- return;
- }
- });
- _portCompleter.complete(_server.port);
- currentSchedule.onComplete.schedule(_closeServer);
- return null;
- });
- });
- }, 'starting a server serving:\n${baseDir.describe()}');
-}
-
-/// Closes [_server]. Returns a [Future] that will complete after the [_server]
-/// is closed.
-Future _closeServer() {
- if (_server == null) return new Future.value();
- _server.close();
- _server = null;
- _portCompleterCache = null;
- // TODO(nweiz): Remove this once issue 4155 is fixed. Pumping the event loop
- // *seems* to be enough to ensure that the server is actually closed, but I'm
- // putting this at 10ms to be safe.
- return sleep(10);
-}
-
-/// The [d.DirectoryDescriptor] describing the server layout of packages that
-/// are being served via [servePackages]. This is `null` if [servePackages] has
-/// not yet been called for this test.
-d.DirectoryDescriptor _servedPackageDir;
-
-/// A map from package names to version numbers to YAML-serialized pubspecs for
-/// those packages. This represents the packages currently being served by
-/// [servePackages], and is `null` if [servePackages] has not yet been called
-/// for this test.
-Map<String, Map<String, String>> _servedPackages;
-
-/// Creates an HTTP server that replicates the structure of pub.dartlang.org.
-/// [pubspecs] is a list of unserialized pubspecs representing the packages to
-/// serve.
-///
-/// Subsequent calls to [servePackages] will add to the set of packages that
-/// are being served. Previous packages will continue to be served.
-void servePackages(List<Map> pubspecs) {
- if (_servedPackages == null || _servedPackageDir == null) {
- _servedPackages = <String, Map<String, String>>{};
- _servedPackageDir = d.dir('packages', []);
- serve([_servedPackageDir]);
-
- currentSchedule.onComplete.schedule(() {
- _servedPackages = null;
- _servedPackageDir = null;
- }, 'cleaning up served packages');
- }
-
- schedule(() {
- return awaitObject(pubspecs).then((resolvedPubspecs) {
- for (var spec in resolvedPubspecs) {
- var name = spec['name'];
- var version = spec['version'];
- var versions = _servedPackages.putIfAbsent(
- name, () => <String, String>{});
- versions[version] = yaml(spec);
- }
-
- _servedPackageDir.contents.clear();
- for (var name in _servedPackages.keys) {
- var versions = _servedPackages[name].keys.toList();
- _servedPackageDir.contents.addAll([
- d.file('$name.json', json.stringify({'versions': versions})),
- d.dir(name, [
- d.dir('versions', flatten(versions.map((version) {
- return [
- d.file('$version.yaml', _servedPackages[name][version]),
- d.tar('$version.tar.gz', [
- d.file('pubspec.yaml', _servedPackages[name][version]),
- d.libDir(name, '$name $version')
- ])
- ];
- })))
- ])
- ]);
- }
- });
- }, 'initializing the package server');
-}
-
-/// Converts [value] into a YAML string.
-String yaml(value) => json.stringify(value);
-
-/// The full path to the created sandbox directory for an integration test.
-String get sandboxDir => _sandboxDir;
-String _sandboxDir;
-
-/// The path of the package cache directory used for tests. Relative to the
-/// sandbox directory.
-final String cachePath = "cache";
-
-/// The path of the mock SDK directory used for tests. Relative to the sandbox
-/// directory.
-final String sdkPath = "sdk";
-
-/// The path of the mock app directory used for tests. Relative to the sandbox
-/// directory.
-final String appPath = "myapp";
-
-/// The path of the packages directory in the mock app used for tests. Relative
-/// to the sandbox directory.
-final String packagesPath = "$appPath/packages";
-
-/// Set to true when the current batch of scheduled events should be aborted.
-bool _abortScheduled = false;
-
-/// Defines an integration test. The [body] should schedule a series of
-/// operations which will be run asynchronously.
-void integration(String description, void body()) =>
- _integration(description, body, test);
-
-/// Like [integration], but causes only this test to run.
-void solo_integration(String description, void body()) =>
- _integration(description, body, solo_test);
-
-void _integration(String description, void body(), [Function testFn]) {
- testFn(description, () {
- // The windows bots are very slow, so we increase the default timeout.
- if (Platform.operatingSystem == "windows") {
- currentSchedule.timeout = new Duration(seconds: 10);
- }
-
- // By default, don't capture stack traces since they slow the tests way
- // down. To debug failing tests, comment this out.
- currentSchedule.captureStackTraces =
- new Options().arguments.contains('--trace');
-
- // Ensure the SDK version is always available.
- d.dir(sdkPath, [
- d.file('version', '0.1.2.3')
- ]).create();
-
- _sandboxDir = createTempDir();
- d.defaultRoot = sandboxDir;
- currentSchedule.onComplete.schedule(() => deleteEntry(_sandboxDir),
- 'deleting the sandbox directory');
-
- // Schedule the test.
- body();
- });
-}
-
-/// Get the path to the root "util/test/pub" directory containing the pub
-/// tests.
-String get testDirectory {
- var dir = new Options().script;
- while (path.basename(dir) != 'pub') dir = path.dirname(dir);
-
- return path.absolute(dir);
-}
-
-/// Schedules renaming (moving) the directory at [from] to [to], both of which
-/// are assumed to be relative to [sandboxDir].
-void scheduleRename(String from, String to) {
- schedule(
- () => renameDir(
- path.join(sandboxDir, from),
- path.join(sandboxDir, to)),
- 'renaming $from to $to');
-}
-
-/// Schedules creating a symlink at path [symlink] that points to [target],
-/// both of which are assumed to be relative to [sandboxDir].
-void scheduleSymlink(String target, String symlink) {
- schedule(
- () => createSymlink(
- path.join(sandboxDir, target),
- path.join(sandboxDir, symlink)),
- 'symlinking $target to $symlink');
-}
-
-/// Schedules a call to the Pub command-line utility. Runs Pub with [args] and
-/// validates that its results match [output], [error], and [exitCode].
-void schedulePub({List args, Pattern output, Pattern error,
- Future<Uri> tokenEndpoint, int exitCode: 0}) {
- var pub = startPub(args: args, tokenEndpoint: tokenEndpoint);
- pub.shouldExit(exitCode);
-
- expect(Future.wait([
- pub.remainingStdout(),
- pub.remainingStderr()
- ]).then((results) {
- var failures = [];
- _validateOutput(failures, 'stdout', output, results[0].split('\n'));
- _validateOutput(failures, 'stderr', error, results[1].split('\n'));
- if (!failures.isEmpty) throw new TestFailure(failures.join('\n'));
- }), completes);
-}
-
-/// Like [startPub], but runs `pub lish` in particular with [server] used both
-/// as the OAuth2 server (with "/token" as the token endpoint) and as the
-/// package server.
-///
-/// Any futures in [args] will be resolved before the process is started.
-ScheduledProcess startPublish(ScheduledServer server, {List args}) {
- var tokenEndpoint = server.url.then((url) =>
- url.resolve('/token').toString());
- if (args == null) args = [];
- args = flatten(['lish', '--server', tokenEndpoint, args]);
- return startPub(args: args, tokenEndpoint: tokenEndpoint);
-}
-
-/// Handles the beginning confirmation process for uploading a packages.
-/// Ensures that the right output is shown and then enters "y" to confirm the
-/// upload.
-void confirmPublish(ScheduledProcess pub) {
- // TODO(rnystrom): This is overly specific and inflexible regarding different
- // test packages. Should validate this a little more loosely.
- expect(pub.nextLine(), completion(equals('Publishing "test_pkg" 1.0.0:')));
- expect(pub.nextLine(), completion(equals("|-- LICENSE")));
- expect(pub.nextLine(), completion(equals("|-- lib")));
- expect(pub.nextLine(), completion(equals("| '-- test_pkg.dart")));
- expect(pub.nextLine(), completion(equals("'-- pubspec.yaml")));
- expect(pub.nextLine(), completion(equals("")));
-
- pub.writeLine("y");
-}
-
-/// Starts a Pub process and returns a [ScheduledProcess] that supports
-/// interaction with that process.
-///
-/// Any futures in [args] will be resolved before the process is started.
-ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) {
- String pathInSandbox(String relPath) {
- return path.join(path.absolute(sandboxDir), relPath);
- }
-
- ensureDir(pathInSandbox(appPath));
-
- // Find a Dart executable we can use to spawn. Use the same one that was
- // used to run this script itself.
- var dartBin = new Options().executable;
-
- // If the executable looks like a path, get its full path. That way we
- // can still find it when we spawn it with a different working directory.
- if (dartBin.contains(Platform.pathSeparator)) {
- dartBin = new File(dartBin).fullPathSync();
- }
-
- // Find the main pub entrypoint.
- var pubPath = path.join(testDirectory, '..', '..', 'pub', 'pub.dart');
-
- var dartArgs = ['--package-root=$_packageRoot/', '--checked', pubPath,
- '--trace'];
- dartArgs.addAll(args);
-
- if (tokenEndpoint == null) tokenEndpoint = new Future.value();
- var optionsFuture = tokenEndpoint.then((tokenEndpoint) {
- var options = new ProcessOptions();
- options.workingDirectory = pathInSandbox(appPath);
- // TODO(nweiz): remove this when issue 9294 is fixed.
- options.environment = new Map.from(Platform.environment);
- options.environment['PUB_CACHE'] = pathInSandbox(cachePath);
- options.environment['DART_SDK'] = pathInSandbox(sdkPath);
- if (tokenEndpoint != null) {
- options.environment['_PUB_TEST_TOKEN_ENDPOINT'] =
- tokenEndpoint.toString();
- }
- return options;
- });
-
- return new ScheduledProcess.start(dartBin, dartArgs, options: optionsFuture,
- description: args.isEmpty ? 'pub' : 'pub ${args.first}');
-}
-
-/// Whether pub is running from within the Dart SDK, as opposed to from the Dart
-/// source repository.
-bool get _runningFromSdk => path.dirname(relativeToPub('..')) == 'util';
-
-// TODO(nweiz): use the built-in mechanism for accessing this once it exists
-// (issue 9119).
-/// The path to the `packages` directory from which pub loads its dependencies.
-String get _packageRoot {
- if (_runningFromSdk) {
- return path.absolute(relativeToPub(path.join('..', '..', 'packages')));
- } else {
- return path.absolute(path.join(
- path.dirname(new Options().executable), '..', '..', 'packages'));
- }
-}
-
-/// Skips the current test if Git is not installed. This validates that the
-/// current test is running on a buildbot in which case we expect git to be
-/// installed. If we are not running on the buildbot, we will instead see if
-/// git is installed and skip the test if not. This way, users don't need to
-/// have git installed to run the tests locally (unless they actually care
-/// about the pub git tests).
-///
-/// This will also increase the [Schedule] timeout to 30 seconds on Windows,
-/// where Git runs really slowly.
-void ensureGit() {
- if (Platform.operatingSystem == "windows") {
- currentSchedule.timeout = new Duration(seconds: 30);
- }
-
- schedule(() {
- return gitlib.isInstalled.then((installed) {
- if (installed) return;
- if (runningOnBuildbot) return;
- currentSchedule.abort();
- });
- }, 'ensuring that Git is installed');
-}
-
-/// Use [client] as the mock HTTP client for this test.
-///
-/// Note that this will only affect HTTP requests made via http.dart in the
-/// parent process.
-void useMockClient(MockClient client) {
- var oldInnerClient = httpClient.inner;
- httpClient.inner = client;
- currentSchedule.onComplete.schedule(() {
- httpClient.inner = oldInnerClient;
- }, 'de-activating the mock client');
-}
-
-/// Describes a map representing a library package with the given [name],
-/// [version], and [dependencies].
-Map packageMap(String name, String version, [List dependencies]) {
- var package = {
- "name": name,
- "version": version,
- "author": "Nathan Weizenbaum <nweiz@google.com>",
- "homepage": "http://pub.dartlang.org",
- "description": "A package, I guess."
- };
- if (dependencies != null) {
- package["dependencies"] = dependencyListToMap(dependencies);
- }
- return package;
-}
-
-/// Describes a map representing a dependency on a package in the package
-/// repository.
-Map dependencyMap(String name, [String versionConstraint]) {
- var url = port.then((p) => "http://localhost:$p");
- var dependency = {"hosted": {"name": name, "url": url}};
- if (versionConstraint != null) dependency["version"] = versionConstraint;
- return dependency;
-}
-
-/// Converts a list of dependencies as passed to [package] into a hash as used
-/// in a pubspec.
-Future<Map> dependencyListToMap(List<Map> dependencies) {
- return awaitObject(dependencies).then((resolvedDependencies) {
- var result = <String, Map>{};
- for (var dependency in resolvedDependencies) {
- var keys = dependency.keys.where((key) => key != "version");
- var sourceName = only(keys);
- var source;
- switch (sourceName) {
- case "git":
- source = new GitSource();
- break;
- case "hosted":
- source = new HostedSource();
- break;
- case "path":
- source = new PathSource();
- break;
- default:
- throw new Exception('Unknown source "$sourceName"');
- }
-
- result[_packageName(sourceName, dependency[sourceName])] = dependency;
- }
- return result;
- });
-}
-
-/// Return the name for the package described by [description] and from
-/// [sourceName].
-String _packageName(String sourceName, description) {
- switch (sourceName) {
- case "git":
- var url = description is String ? description : description['url'];
- // TODO(rnystrom): Using path.basename on a URL is hacky. If we add URL
- // support to pkg/pathos, should use an explicit builder for that.
- return path.basename(url.replaceFirst(new RegExp(r"(\.git)?/?$"), ""));
- case "hosted":
- if (description is String) return description;
- return description['name'];
- case "path":
- return path.basename(description);
- case "sdk":
- return description;
- default:
- return description;
- }
-}
-
-/// Compares the [actual] output from running pub with [expected]. For [String]
-/// patterns, ignores leading and trailing whitespace differences and tries to
-/// report the offending difference in a nice way. For other [Pattern]s, just
-/// reports whether the output contained the pattern.
-void _validateOutput(List<String> failures, String pipe, Pattern expected,
- List<String> actual) {
- if (expected == null) return;
-
- if (expected is RegExp) {
- _validateOutputRegex(failures, pipe, expected, actual);
- } else {
- _validateOutputString(failures, pipe, expected, actual);
- }
-}
-
-void _validateOutputRegex(List<String> failures, String pipe,
- RegExp expected, List<String> actual) {
- var actualText = actual.join('\n');
- if (actualText.contains(expected)) return;
-
- if (actual.length == 0) {
- failures.add('Expected $pipe to match "${expected.pattern}" but got none.');
- } else {
- failures.add('Expected $pipe to match "${expected.pattern}" but got:');
- failures.addAll(actual.map((line) => '| $line'));
- }
-}
-
-void _validateOutputString(List<String> failures, String pipe,
- String expectedText, List<String> actual) {
- final expected = expectedText.split('\n');
-
- // Strip off the last line. This lets us have expected multiline strings
- // where the closing ''' is on its own line. It also fixes '' expected output
- // to expect zero lines of output, not a single empty line.
- if (expected.last.trim() == '') {
- expected.removeLast();
- }
-
- var results = [];
- var failed = false;
-
- // Compare them line by line to see which ones match.
- var length = max(expected.length, actual.length);
- for (var i = 0; i < length; i++) {
- if (i >= actual.length) {
- // Missing output.
- failed = true;
- results.add('? ${expected[i]}');
- } else if (i >= expected.length) {
- // Unexpected extra output.
- failed = true;
- results.add('X ${actual[i]}');
- } else {
- var expectedLine = expected[i].trim();
- var actualLine = actual[i].trim();
-
- if (expectedLine != actualLine) {
- // Mismatched lines.
- failed = true;
- results.add('X ${actual[i]}');
- } else {
- // Output is OK, but include it in case other lines are wrong.
- results.add('| ${actual[i]}');
- }
- }
- }
-
- // If any lines mismatched, show the expected and actual.
- if (failed) {
- failures.add('Expected $pipe:');
- failures.addAll(expected.map((line) => '| $line'));
- failures.add('Got:');
- failures.addAll(results);
- }
-}
-
-/// A function that creates a [Validator] subclass.
-typedef Validator ValidatorCreator(Entrypoint entrypoint);
-
-/// Schedules a single [Validator] to run on the [appPath]. Returns a scheduled
-/// Future that contains the errors and warnings produced by that validator.
-Future<Pair<List<String>, List<String>>> schedulePackageValidation(
- ValidatorCreator fn) {
- return schedule(() {
- var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath));
-
- return new Future.sync(() {
- var validator = fn(new Entrypoint(path.join(sandboxDir, appPath), cache));
- return validator.validate().then((_) {
- return new Pair(validator.errors, validator.warnings);
- });
- });
- }, "validating package");
-}
-
-/// A matcher that matches a Pair.
-Matcher pairOf(Matcher firstMatcher, Matcher lastMatcher) =>
- new _PairMatcher(firstMatcher, lastMatcher);
-
-class _PairMatcher extends BaseMatcher {
- final Matcher _firstMatcher;
- final Matcher _lastMatcher;
-
- _PairMatcher(this._firstMatcher, this._lastMatcher);
-
- bool matches(item, MatchState matchState) {
- if (item is! Pair) return false;
- return _firstMatcher.matches(item.first, matchState) &&
- _lastMatcher.matches(item.last, matchState);
- }
-
- Description describe(Description description) {
- description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
- }
-}
« no previous file with comments | « utils/tests/pub/real_version_test.dart ('k') | utils/tests/pub/update/git/do_not_update_if_unneeded_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698