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

Unified Diff: sdk/lib/_internal/pub_generated/test/test_pub.dart

Issue 557563002: Store the async-await compiled pub code directly in the repo. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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: sdk/lib/_internal/pub_generated/test/test_pub.dart
diff --git a/sdk/lib/_internal/pub_generated/test/test_pub.dart b/sdk/lib/_internal/pub_generated/test/test_pub.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f43aabdbb40b7972acd87e031a29fa8e6a5354da
--- /dev/null
+++ b/sdk/lib/_internal/pub_generated/test/test_pub.dart
@@ -0,0 +1,629 @@
+library test_pub;
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+import 'package:http/testing.dart';
+import 'package:path/path.dart' as p;
+import 'package:scheduled_test/scheduled_process.dart';
+import 'package:scheduled_test/scheduled_server.dart';
+import 'package:scheduled_test/scheduled_stream.dart';
+import 'package:scheduled_test/scheduled_test.dart' hide fail;
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:shelf/shelf_io.dart' as shelf_io;
+import 'package:unittest/compact_vm_config.dart';
+import 'package:yaml/yaml.dart';
+import '../lib/src/entrypoint.dart';
+import '../lib/src/exit_codes.dart' as exit_codes;
+import '../lib/src/git.dart' as gitlib;
+import '../lib/src/http.dart';
+import '../lib/src/io.dart';
+import '../lib/src/lock_file.dart';
+import '../lib/src/log.dart' as log;
+import '../lib/src/package.dart';
+import '../lib/src/pubspec.dart';
+import '../lib/src/source/hosted.dart';
+import '../lib/src/source/path.dart';
+import '../lib/src/source_registry.dart';
+import '../lib/src/system_cache.dart';
+import '../lib/src/utils.dart';
+import '../lib/src/validator.dart';
+import '../lib/src/version.dart';
+import 'descriptor.dart' as d;
+import 'serve_packages.dart';
+export 'serve_packages.dart';
+initConfig() {
+ useCompactVMConfiguration();
+ filterStacks = true;
+ unittestConfiguration.timeout = null;
+}
+var _server;
+final _requestedPaths = <String>[];
+Completer<int> _portCompleterCache;
+Matcher isMinifiedDart2JSOutput =
+ isNot(contains("// The code supports the following hooks"));
+Matcher isUnminifiedDart2JSOutput =
+ contains("// The code supports the following hooks");
+Map<String, String> _packageOverrides;
+final _barbackVersions = _findBarbackVersions();
+final _barbackDeps = {
+ new VersionConstraint.parse("<0.15.0"): {
+ "source_maps": "0.9.4"
+ }
+};
+Map<Version, String> _findBarbackVersions() {
+ var versions = {};
+ var currentBarback = p.join(repoRoot, 'pkg', 'barback');
+ versions[new Pubspec.load(currentBarback, new SourceRegistry()).version] =
+ currentBarback;
+ for (var dir in listDir(p.join(repoRoot, 'third_party', 'pkg'))) {
+ var basename = p.basename(dir);
+ if (!basename.startsWith('barback')) continue;
+ versions[new Version.parse(split1(basename, '-').last)] = dir;
+ }
+ return versions;
+}
+void withBarbackVersions(String versionConstraint, void callback()) {
+ var constraint = new VersionConstraint.parse(versionConstraint);
+ var validVersions = _barbackVersions.keys.where(constraint.allows);
+ if (validVersions.isEmpty) {
+ throw new ArgumentError(
+ 'No available barback version matches "$versionConstraint".');
+ }
+ for (var version in validVersions) {
+ group("with barback $version", () {
+ setUp(() {
+ _packageOverrides = {};
+ _packageOverrides['barback'] = _barbackVersions[version];
+ _barbackDeps.forEach((constraint, deps) {
+ if (!constraint.allows(version)) return;
+ deps.forEach((packageName, version) {
+ _packageOverrides[packageName] =
+ p.join(repoRoot, 'third_party', 'pkg', '$packageName-$version');
+ });
+ });
+ currentSchedule.onComplete.schedule(() {
+ _packageOverrides = null;
+ });
+ });
+ callback();
+ });
+ }
+}
+Completer<int> get _portCompleter {
+ if (_portCompleterCache != null) return _portCompleterCache;
+ _portCompleterCache = new Completer<int>();
+ currentSchedule.onComplete.schedule(() {
+ _portCompleterCache = null;
+ }, 'clearing the port completer');
+ return _portCompleterCache;
+}
+Future<int> get port => _portCompleter.future;
+Future<List<String>> getRequestedPaths() {
+ return schedule(() {
+ var paths = _requestedPaths.toList();
+ _requestedPaths.clear();
+ return paths;
+ }, "get previous network requests");
+}
+void serve([List<d.Descriptor> contents]) {
+ var baseDir = d.dir("serve-dir", contents);
+ _hasServer = true;
+ schedule(() {
+ final completer0 = new Completer();
+ scheduleMicrotask(() {
+ try {
+ _closeServer().then((x0) {
+ try {
+ x0;
+ shelf_io.serve(((request) {
+ currentSchedule.heartbeat();
+ var path =
+ p.posix.fromUri(request.url.path.replaceFirst("/", ""));
+ _requestedPaths.add(path);
+ return validateStream(
+ baseDir.load(
+ path)).then((stream) => new shelf.Response.ok(stream)).catchError((error) {
+ return new shelf.Response.notFound('File "$path" not found.');
+ });
+ }), 'localhost', 0).then((x1) {
+ try {
+ var server = x1;
+ _server = server;
+ _portCompleter.complete(_server.port);
+ currentSchedule.onComplete.schedule(_closeServer);
+ completer0.complete(null);
+ } catch (e1) {
+ completer0.completeError(e1);
+ }
+ }, onError: (e2) {
+ completer0.completeError(e2);
+ });
+ } catch (e0) {
+ completer0.completeError(e0);
+ }
+ }, onError: (e3) {
+ completer0.completeError(e3);
+ });
+ } catch (e4) {
+ completer0.completeError(e4);
+ }
+ });
+ return completer0.future;
+ }, 'starting a server serving:\n${baseDir.describe()}');
+}
+Future _closeServer() {
+ if (_server == null) return new Future.value();
+ var future = _server.close();
+ _server = null;
+ _hasServer = false;
+ _portCompleterCache = null;
+ return future;
+}
+bool _hasServer = false;
+String yaml(value) => JSON.encode(value);
+String get sandboxDir => _sandboxDir;
+String _sandboxDir;
+final String pkgPath =
+ p.absolute(p.join(p.dirname(Platform.executable), '../../../../pkg'));
+final String cachePath = "cache";
+final String appPath = "myapp";
+final String packagesPath = "$appPath/packages";
+bool _abortScheduled = false;
+class RunCommand {
+ static final get = new RunCommand(
+ 'get',
+ new RegExp(r'Got dependencies!|Changed \d+ dependenc(y|ies)!'));
+ static final upgrade = new RunCommand(
+ 'upgrade',
+ new RegExp(r'(No dependencies changed\.|Changed \d+ dependenc(y|ies)!)$'));
+ static final downgrade = new RunCommand(
+ 'downgrade',
+ new RegExp(r'(No dependencies changed\.|Changed \d+ dependenc(y|ies)!)$'));
+ final String name;
+ final RegExp success;
+ RunCommand(this.name, this.success);
+}
+void forBothPubGetAndUpgrade(void callback(RunCommand command)) {
+ group(RunCommand.get.name, () => callback(RunCommand.get));
+ group(RunCommand.upgrade.name, () => callback(RunCommand.upgrade));
+}
+void pubCommand(RunCommand command, {Iterable<String> args, output, error,
+ warning, int exitCode}) {
+ if (error != null && warning != null) {
+ throw new ArgumentError("Cannot pass both 'error' and 'warning'.");
+ }
+ var allArgs = [command.name];
+ if (args != null) allArgs.addAll(args);
+ if (output == null) output = command.success;
+ if (error != null && exitCode == null) exitCode = 1;
+ if (error != null) output = null;
+ if (warning != null) error = warning;
+ schedulePub(args: allArgs, output: output, error: error, exitCode: exitCode);
+}
+void pubGet({Iterable<String> args, output, error, warning, int exitCode}) {
+ pubCommand(
+ RunCommand.get,
+ args: args,
+ output: output,
+ error: error,
+ warning: warning,
+ exitCode: exitCode);
+}
+void pubUpgrade({Iterable<String> args, output, error, warning, int exitCode}) {
+ pubCommand(
+ RunCommand.upgrade,
+ args: args,
+ output: output,
+ error: error,
+ warning: warning,
+ exitCode: exitCode);
+}
+void pubDowngrade({Iterable<String> args, output, error, warning, int exitCode})
+ {
+ pubCommand(
+ RunCommand.downgrade,
+ args: args,
+ output: output,
+ error: error,
+ warning: warning,
+ exitCode: exitCode);
+}
+ScheduledProcess pubRun({bool global: false, Iterable<String> args}) {
+ var pubArgs = global ? ["global", "run"] : ["run"];
+ pubArgs.addAll(args);
+ var pub = startPub(args: pubArgs);
+ pub.stdout.expect(consumeWhile(startsWith("Loading")));
+ return pub;
+}
+void integration(String description, void body()) =>
+ _integration(description, body, test);
+void solo_integration(String description, void body()) =>
+ _integration(description, body, solo_test);
+void _integration(String description, void body(), [Function testFn]) {
+ testFn(description, () {
+ currentSchedule.timeout *= 2;
+ if (Platform.operatingSystem == "windows") {
+ currentSchedule.timeout *= 2;
+ }
+ _sandboxDir = createSystemTempDir();
+ d.defaultRoot = sandboxDir;
+ currentSchedule.onComplete.schedule(
+ () => deleteEntry(_sandboxDir),
+ 'deleting the sandbox directory');
+ body();
+ });
+}
+String get testDirectory => p.absolute(p.dirname(libraryPath('test_pub')));
+void scheduleRename(String from, String to) {
+ schedule(
+ () => renameDir(p.join(sandboxDir, from), p.join(sandboxDir, to)),
+ 'renaming $from to $to');
+}
+void scheduleSymlink(String target, String symlink) {
+ schedule(
+ () => createSymlink(p.join(sandboxDir, target), p.join(sandboxDir, symlink)),
+ 'symlinking $target to $symlink');
+}
+void schedulePub({List args, output, error, outputJson,
+ Future<Uri> tokenEndpoint, int exitCode: exit_codes.SUCCESS}) {
+ assert(output == null || outputJson == null);
+ var pub = startPub(args: args, tokenEndpoint: tokenEndpoint);
+ pub.shouldExit(exitCode);
+ var failures = [];
+ var stderr;
+ expect(
+ Future.wait(
+ [pub.stdoutStream().toList(), pub.stderrStream().toList()]).then((results) {
+ var stdout = results[0].join("\n");
+ stderr = results[1].join("\n");
+ if (outputJson == null) {
+ _validateOutput(failures, 'stdout', output, stdout);
+ return null;
+ }
+ return awaitObject(outputJson).then((resolved) {
+ _validateOutputJson(failures, 'stdout', resolved, stdout);
+ });
+ }).then((_) {
+ _validateOutput(failures, 'stderr', error, stderr);
+ if (!failures.isEmpty) throw new TestFailure(failures.join('\n'));
+ }), completes);
+}
+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);
+}
+void confirmPublish(ScheduledProcess pub) {
+ pub.stdout.expect(startsWith('Publishing test_pkg 1.0.0 to '));
+ pub.stdout.expect(
+ emitsLines(
+ "|-- LICENSE\n" "|-- lib\n" "| '-- test_pkg.dart\n" "'-- pubspec.yaml\n" "\n"
+ "Looks great! Are you ready to upload your package (y/n)?"));
+ pub.writeLine("y");
+}
+ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) {
+ String pathInSandbox(String relPath) {
+ return p.join(p.absolute(sandboxDir), relPath);
+ }
+ ensureDir(pathInSandbox(appPath));
+ var dartBin = Platform.executable;
+ if (dartBin.contains(Platform.pathSeparator)) {
+ dartBin = p.absolute(dartBin);
+ }
+ var pubPath = p.join(p.dirname(dartBin), 'snapshots/pub.dart.snapshot');
+ var dartArgs = [pubPath, '--verbose'];
+ dartArgs.addAll(args);
+ if (tokenEndpoint == null) tokenEndpoint = new Future.value();
+ var environmentFuture = tokenEndpoint.then((tokenEndpoint) {
+ var environment = {};
+ environment['_PUB_TESTING'] = 'true';
+ environment['PUB_CACHE'] = pathInSandbox(cachePath);
+ environment['_PUB_TEST_SDK_VERSION'] = "0.1.2+3";
+ if (tokenEndpoint != null) {
+ environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString();
+ }
+ if (_hasServer) {
+ return port.then((p) {
+ environment['PUB_HOSTED_URL'] = "http://localhost:$p";
+ return environment;
+ });
+ }
+ return environment;
+ });
+ return new PubProcess.start(
+ dartBin,
+ dartArgs,
+ environment: environmentFuture,
+ workingDirectory: pathInSandbox(appPath),
+ description: args.isEmpty ? 'pub' : 'pub ${args.first}');
+}
+class PubProcess extends ScheduledProcess {
+ Stream<Pair<log.Level, String>> _log;
+ Stream<String> _stdout;
+ Stream<String> _stderr;
+ PubProcess.start(executable, arguments, {workingDirectory, environment,
+ String description, Encoding encoding: UTF8})
+ : super.start(
+ executable,
+ arguments,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ description: description,
+ encoding: encoding);
+ Stream<Pair<log.Level, String>> _logStream() {
+ if (_log == null) {
+ _log = mergeStreams(
+ _outputToLog(super.stdoutStream(), log.Level.MESSAGE),
+ _outputToLog(super.stderrStream(), log.Level.ERROR));
+ }
+ var pair = tee(_log);
+ _log = pair.first;
+ return pair.last;
+ }
+ final _logLineRegExp = new RegExp(r"^([A-Z ]{4})[:|] (.*)$");
+ final _logLevels = [
+ log.Level.ERROR,
+ log.Level.WARNING,
+ log.Level.MESSAGE,
+ log.Level.IO,
+ log.Level.SOLVER,
+ log.Level.FINE].fold(<String, log.Level>{}, (levels, level) {
+ levels[level.name] = level;
+ return levels;
+ });
+ Stream<Pair<log.Level, String>> _outputToLog(Stream<String> stream,
+ log.Level defaultLevel) {
+ var lastLevel;
+ return stream.map((line) {
+ var match = _logLineRegExp.firstMatch(line);
+ if (match == null) return new Pair<log.Level, String>(defaultLevel, line);
+ var level = _logLevels[match[1]];
+ if (level == null) level = lastLevel;
+ lastLevel = level;
+ return new Pair<log.Level, String>(level, match[2]);
+ });
+ }
+ Stream<String> stdoutStream() {
+ if (_stdout == null) {
+ _stdout = _logStream().expand((entry) {
+ if (entry.first != log.Level.MESSAGE) return [];
+ return [entry.last];
+ });
+ }
+ var pair = tee(_stdout);
+ _stdout = pair.first;
+ return pair.last;
+ }
+ Stream<String> stderrStream() {
+ if (_stderr == null) {
+ _stderr = _logStream().expand((entry) {
+ if (entry.first != log.Level.ERROR &&
+ entry.first != log.Level.WARNING) {
+ return [];
+ }
+ return [entry.last];
+ });
+ }
+ var pair = tee(_stderr);
+ _stderr = pair.first;
+ return pair.last;
+ }
+}
+String get _packageRoot => p.absolute(Platform.packageRoot);
+void ensureGit() {
+ if (Platform.operatingSystem == "windows") {
+ currentSchedule.timeout = new Duration(seconds: 30);
+ }
+ if (!gitlib.isInstalled) {
+ throw new Exception("Git must be installed to run this test.");
+ }
+}
+void makeGlobalPackage(String package, String version,
+ Iterable<d.Descriptor> contents, {Iterable<String> pkg, Map<String,
+ String> hosted}) {
+ serveNoPackages();
+ d.hostedCache([d.dir("$package-$version", contents)]).create();
+ var lockFile = _createLockFile(pkg: pkg, hosted: hosted);
+ var id =
+ new PackageId(package, "hosted", new Version.parse(version), package);
+ lockFile.packages[package] = id;
+ var sources = new SourceRegistry();
+ sources.register(new HostedSource());
+ sources.register(new PathSource());
+ d.dir(
+ cachePath,
+ [
+ d.dir(
+ "global_packages",
+ [d.file("$package.lock", lockFile.serialize(null, sources))])]).create();
+}
+void createLockFile(String package, {Iterable<String> sandbox,
+ Iterable<String> pkg, Map<String, String> hosted}) {
+ var lockFile = _createLockFile(sandbox: sandbox, pkg: pkg, hosted: hosted);
+ var sources = new SourceRegistry();
+ sources.register(new HostedSource());
+ sources.register(new PathSource());
+ d.file(
+ p.join(package, 'pubspec.lock'),
+ lockFile.serialize(null, sources)).create();
+}
+LockFile _createLockFile({Iterable<String> sandbox, Iterable<String> pkg,
+ Map<String, String> hosted}) {
+ var dependencies = {};
+ if (sandbox != null) {
+ for (var package in sandbox) {
+ dependencies[package] = '../$package';
+ }
+ }
+ if (pkg != null) {
+ _addPackage(String package) {
+ if (dependencies.containsKey(package)) return;
+ var packagePath;
+ if (package == 'barback' && _packageOverrides == null) {
+ throw new StateError(
+ "createLockFile() can only create a lock file "
+ "with a barback dependency within a withBarbackVersions() " "block.");
+ }
+ if (_packageOverrides.containsKey(package)) {
+ packagePath = _packageOverrides[package];
+ } else {
+ packagePath = p.join(pkgPath, package);
+ }
+ dependencies[package] = packagePath;
+ var pubspec = loadYaml(readTextFile(p.join(packagePath, 'pubspec.yaml')));
+ var packageDeps = pubspec['dependencies'];
+ if (packageDeps == null) return;
+ packageDeps.keys.forEach(_addPackage);
+ }
+ pkg.forEach(_addPackage);
+ }
+ var lockFile = new LockFile.empty();
+ dependencies.forEach((name, dependencyPath) {
+ var id = new PackageId(name, 'path', new Version(0, 0, 0), {
+ 'path': dependencyPath,
+ 'relative': p.isRelative(dependencyPath)
+ });
+ lockFile.packages[name] = id;
+ });
+ if (hosted != null) {
+ hosted.forEach((name, version) {
+ var id = new PackageId(name, 'hosted', new Version.parse(version), name);
+ lockFile.packages[name] = id;
+ });
+ }
+ return lockFile;
+}
+void useMockClient(MockClient client) {
+ var oldInnerClient = innerHttpClient;
+ innerHttpClient = client;
+ currentSchedule.onComplete.schedule(() {
+ innerHttpClient = oldInnerClient;
+ }, 'de-activating the mock client');
+}
+Map packageMap(String name, String version, [Map dependencies]) {
+ var package = {
+ "name": name,
+ "version": version,
+ "author": "Natalie Weizenbaum <nweiz@google.com>",
+ "homepage": "http://pub.dartlang.org",
+ "description": "A package, I guess."
+ };
+ if (dependencies != null) package["dependencies"] = dependencies;
+ return package;
+}
+String testAssetPath(String target) {
+ var libPath = libraryPath('test_pub');
+ libPath = libPath.replaceAll('pub_generated', 'pub');
+ return p.join(p.dirname(libPath), 'asset', target);
+}
+Map packageVersionApiMap(Map pubspec, {bool full: false}) {
+ var name = pubspec['name'];
+ var version = pubspec['version'];
+ var map = {
+ 'pubspec': pubspec,
+ 'version': version,
+ 'url': '/api/packages/$name/versions/$version',
+ 'archive_url': '/packages/$name/versions/$version.tar.gz',
+ 'new_dartdoc_url': '/api/packages/$name/versions/$version' '/new_dartdoc',
+ 'package_url': '/api/packages/$name'
+ };
+ if (full) {
+ map.addAll({
+ 'downloads': 0,
+ 'created': '2012-09-25T18:38:28.685260',
+ 'libraries': ['$name.dart'],
+ 'uploader': ['nweiz@google.com']
+ });
+ }
+ return map;
+}
+void _validateOutput(List<String> failures, String pipe, expected,
+ String actual) {
+ if (expected == null) return;
+ if (expected is String) {
+ _validateOutputString(failures, pipe, expected, actual);
+ } else {
+ if (expected is RegExp) expected = matches(expected);
+ expect(actual, expected);
+ }
+}
+void _validateOutputString(List<String> failures, String pipe, String expected,
+ String actual) {
+ var actualLines = actual.split("\n");
+ var expectedLines = expected.split("\n");
+ if (expectedLines.last.trim() == '') {
+ expectedLines.removeLast();
+ }
+ var results = [];
+ var failed = false;
+ var length = max(expectedLines.length, actualLines.length);
+ for (var i = 0; i < length; i++) {
+ if (i >= actualLines.length) {
+ failed = true;
+ results.add('? ${expectedLines[i]}');
+ } else if (i >= expectedLines.length) {
+ failed = true;
+ results.add('X ${actualLines[i]}');
+ } else {
+ var expectedLine = expectedLines[i].trim();
+ var actualLine = actualLines[i].trim();
+ if (expectedLine != actualLine) {
+ failed = true;
+ results.add('X ${actualLines[i]}');
+ } else {
+ results.add('| ${actualLines[i]}');
+ }
+ }
+ }
+ if (failed) {
+ failures.add('Expected $pipe:');
+ failures.addAll(expectedLines.map((line) => '| $line'));
+ failures.add('Got:');
+ failures.addAll(results);
+ }
+}
+void _validateOutputJson(List<String> failures, String pipe, expected,
+ String actualText) {
+ var actual;
+ try {
+ actual = JSON.decode(actualText);
+ } on FormatException catch (error) {
+ failures.add('Expected $pipe JSON:');
+ failures.add(expected);
+ failures.add('Got invalid JSON:');
+ failures.add(actualText);
+ }
+ expect(actual, expected);
+}
+typedef Validator ValidatorCreator(Entrypoint entrypoint);
+Future<Pair<List<String>, List<String>>>
+ schedulePackageValidation(ValidatorCreator fn) {
+ return schedule(() {
+ var cache = new SystemCache.withSources(p.join(sandboxDir, cachePath));
+ return syncFuture(() {
+ var validator = fn(new Entrypoint(p.join(sandboxDir, appPath), cache));
+ return validator.validate().then((_) {
+ return new Pair(validator.errors, validator.warnings);
+ });
+ });
+ }, "validating package");
+}
+Matcher pairOf(Matcher firstMatcher, Matcher lastMatcher) =>
+ new _PairMatcher(firstMatcher, lastMatcher);
+class _PairMatcher extends Matcher {
+ final Matcher _firstMatcher;
+ final Matcher _lastMatcher;
+ _PairMatcher(this._firstMatcher, this._lastMatcher);
+ bool matches(item, Map matchState) {
+ if (item is! Pair) return false;
+ return _firstMatcher.matches(item.first, matchState) &&
+ _lastMatcher.matches(item.last, matchState);
+ }
+ Description describe(Description description) {
+ return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
+ }
+}
+StreamMatcher emitsLines(String output) => inOrder(output.split("\n"));

Powered by Google App Engine
This is Rietveld 408576698