| 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"));
|
|
|