| Index: utils/tests/pub/test_pub.dart
|
| diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
|
| index c37483de62c768207e008536f7d464befc58a2cf..49b64e88f2767c3d310bce94271b9395a5014107 100644
|
| --- a/utils/tests/pub/test_pub.dart
|
| +++ b/utils/tests/pub/test_pub.dart
|
| @@ -13,59 +13,95 @@
|
| #import('dart:io');
|
|
|
| #import('../../../lib/unittest/unittest.dart');
|
| -#import('../../lib/file_system.dart');
|
| +#import('../../lib/file_system.dart', prefix: 'fs');
|
| +#import('../../pub/io.dart');
|
|
|
| -void testOutput(String description, List<String> pubArgs, String expected,
|
| - [int exitCode = 0]) {
|
| +/**
|
| + * Creates a new [FileDescriptor] with [name] and [contents].
|
| + */
|
| +FileDescriptor file(String name, String contents) =>
|
| + new FileDescriptor(name, contents);
|
| +
|
| +/**
|
| + * Creates a new [DirectoryDescriptor] with [name] and [contents].
|
| + */
|
| +DirectoryDescriptor dir(String name, [List<Descriptor> contents]) =>
|
| + new DirectoryDescriptor(name, contents);
|
| +
|
| +void testPub(String description, [List<Descriptor> cache, List<String> args,
|
| + String output, int exitCode = 0]) {
|
| asyncTest(description, 1, () {
|
| - // Find a dart executable we can use to run pub. Uses the one that the
|
| - // test infrastructure uses.
|
| - final scriptDir = new File(new Options().script).directorySync().path;
|
| - final platform = Platform.operatingSystem();
|
| - final dartBin = joinPaths(scriptDir,
|
| - '../../../tools/testing/bin/$platform/dart');
|
| -
|
| - // Find the main pub entrypoint.
|
| - final pubPath = joinPaths(scriptDir, '../../pub/pub.dart');
|
| -
|
| - final args = [pubPath];
|
| - args.addAll(pubArgs);
|
| -
|
| - final process = new Process.start(dartBin, args);
|
| - final outStream = new StringInputStream(process.stdout);
|
| - final output = <String>[];
|
| - bool processDone = false;
|
| -
|
| - checkComplete() {
|
| - if (!outStream.closed) return;
|
| - if (!processDone) return;
|
| -
|
| - _validateOutput(expected, output);
|
| - callbackDone();
|
| + var createdSandboxDir;
|
| +
|
| + deleteSandboxIfCreated() {
|
| + if (createdSandboxDir != null) {
|
| + deleteDir(createdSandboxDir).then((_) {
|
| + callbackDone();
|
| + });
|
| + } else {
|
| + callbackDone();
|
| + }
|
| }
|
|
|
| - process.stderr.pipe(stderr, close: false);
|
| + final future = _setUpSandbox().chain((sandboxDir) {
|
| + createdSandboxDir = sandboxDir;
|
| + return _setUpCache(sandboxDir, cache);
|
| + }).chain((cacheDir) {
|
| + if (cacheDir != null) {
|
| + // TODO(rnystrom): Hack in the cache directory path. Should pass this
|
| + // in using environment var once #752 is done.
|
| + args.add('--cachedir=${cacheDir.path}');
|
| + }
|
| +
|
| + return _runPub(args);
|
| + });
|
| +
|
| + future.then((result) {
|
| + _validateOutput(output, result.stdout);
|
|
|
| - outStream.onLine = () {
|
| - output.add(outStream.readLine());
|
| - };
|
| + Expect.equals(result.stderr.length, 0,
|
| + 'Did not expect any output on stderr, and got:\n' +
|
| + Strings.join(result.stderr, '\n'));
|
|
|
| - outStream.onClosed = checkComplete;
|
| + Expect.equals(result.exitCode, exitCode,
|
| + 'Pub returned exit code ${result.exitCode}, expected $exitCode.');
|
|
|
| - process.onError = (error) {
|
| - Expect.fail('Failed to run pub: $error');
|
| - processDone = true;
|
| - };
|
| + deleteSandboxIfCreated();
|
| + });
|
|
|
| - process.onExit = (actualExitCode) {
|
| - Expect.equals(actualExitCode, exitCode,
|
| - 'Pub returned exit code $actualExitCode, expected $exitCode.');
|
| - processDone = true;
|
| - checkComplete();
|
| - };
|
| + future.handleException((error) {
|
| + deleteSandboxIfCreated();
|
| + });
|
| });
|
| }
|
|
|
| +Future<Directory> _setUpSandbox() {
|
| + return createTempDir('pub-test-sandbox-');
|
| +}
|
| +
|
| +Future _setUpCache(Directory sandboxDir, List<Descriptor> cache) {
|
| + // No cache.
|
| + if (cache == null) return new Future.immediate(null);
|
| +
|
| + return dir('pub-cache', cache).create(sandboxDir);
|
| +}
|
| +
|
| +Future<ProcessResult> _runPub(List<String> pubArgs) {
|
| + // Find a dart executable we can use to run pub. Uses the one that the
|
| + // test infrastructure uses.
|
| + final scriptDir = new File(new Options().script).directorySync().path;
|
| + final platform = Platform.operatingSystem();
|
| + final dartBin = join(scriptDir, '../../../tools/testing/bin/$platform/dart');
|
| +
|
| + // Find the main pub entrypoint.
|
| + final pubPath = fs.joinPaths(scriptDir, '../../pub/pub.dart');
|
| +
|
| + final args = [pubPath];
|
| + args.addAll(pubArgs);
|
| +
|
| + return runProcess(dartBin, args);
|
| +}
|
| +
|
| /**
|
| * Compares the [actual] output from running pub with [expectedText]. Ignores
|
| * leading and trailing whitespace differences and tries to report the
|
| @@ -104,3 +140,83 @@ void _validateOutput(String expectedText, List<String> actual) {
|
| Expect.fail(message.toString());
|
| }
|
| }
|
| +
|
| +/**
|
| + * Base class for [FileDescriptor] and [DirectoryDescriptor] so that a
|
| + * directory can contain a heterogeneous collection of files and
|
| + * subdirectories.
|
| + */
|
| +class Descriptor {
|
| + /**
|
| + * The short name of this file or directory.
|
| + */
|
| + final String name;
|
| +
|
| + Descriptor(this.name);
|
| +
|
| + /**
|
| + * Creates the file or directory within [dir]. Returns a [Future] that is
|
| + * completed after the creation is done.
|
| + */
|
| + abstract Future create(String dir);
|
| +}
|
| +
|
| +/**
|
| + * Describes a file. These are used both for setting up an expected directory
|
| + * tree before running a test, and for validating that the file system matches
|
| + * some expectations after running it.
|
| + */
|
| +class FileDescriptor extends Descriptor {
|
| + /**
|
| + * The text contents of the file.
|
| + */
|
| + final String contents;
|
| +
|
| + FileDescriptor(String name, this.contents) : super(name);
|
| +
|
| + /**
|
| + * Creates the file within [dir]. Returns a [Future] that is completed after
|
| + * the creation is done.
|
| + */
|
| + Future<File> create(String dir) {
|
| + return writeTextFile(join(dir, name), contents);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Describes a directory and its contents. These are used both for setting up
|
| + * an expected directory tree before running a test, and for validating that
|
| + * the file system matches some expectations after running it.
|
| + */
|
| +class DirectoryDescriptor extends Descriptor {
|
| + /**
|
| + * The files and directories contained in this directory.
|
| + */
|
| + final List<Descriptor> contents;
|
| +
|
| + DirectoryDescriptor(String name, this.contents) : super(name);
|
| +
|
| + /**
|
| + * Creates the file within [dir]. Returns a [Future] that is completed after
|
| + * the creation is done.
|
| + */
|
| + Future<Directory> create(String parentDir) {
|
| + final completer = new Completer<Directory>();
|
| +
|
| + // Create the directory.
|
| + createDir(join(parentDir, name)).then((dir) {
|
| + if (contents == null) {
|
| + completer.complete(dir);
|
| + } else {
|
| + // Recursively create all of its children.
|
| + final childFutures = contents.map((child) => child.create(dir.path));
|
| + Futures.wait(childFutures).then((_) {
|
| + // Only complete once all of the children have been created too.
|
| + completer.complete(dir);
|
| + });
|
| + }
|
| + });
|
| +
|
| + return completer.future;
|
| + }
|
| +}
|
|
|