// 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.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';

import 'package:async/async.dart';
import 'package:http/testing.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart' hide fail;
import 'package:test/test.dart' as test show fail;
import 'package:test_process/test_process.dart';

import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/exit_codes.dart' as exit_codes;
// 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 'package:pub/src/git.dart' as gitlib;
import 'package:pub/src/http.dart';
import 'package:pub/src/io.dart';
import 'package:pub/src/lock_file.dart';
import 'package:pub/src/log.dart' as log;
import 'package:pub/src/sdk.dart';
import 'package:pub/src/source_registry.dart';
import 'package:pub/src/system_cache.dart';
import 'package:pub/src/utils.dart';
import 'package:pub/src/validator.dart';

import 'descriptor.dart' as d;
import 'descriptor_server.dart';
import 'package_server.dart';

export 'descriptor_server.dart';
export 'package_server.dart';

/// A [Matcher] that matches JavaScript generated by dart2js with minification
/// enabled.
Matcher isMinifiedDart2JSOutput =
    isNot(contains('// The code supports the following hooks'));

/// A [Matcher] that matches JavaScript generated by dart2js with minification
/// disabled.
Matcher isUnminifiedDart2JSOutput =
    contains('// The code supports the following hooks');

/// The entrypoint for pub itself.
final _entrypoint = Entrypoint(pubRoot, SystemCache(isOffline: true));

/// Converts [value] into a YAML string.
String yaml(value) => jsonEncode(value);

/// The path of the package cache directory used for tests, relative to the
/// sandbox directory.
const String cachePath = 'cache';

/// The path of the mock app directory used for tests, relative to the sandbox
/// directory.
const String appPath = 'myapp';

/// The path of the ".packages" file in the mock app used for tests, relative
/// to the sandbox directory.
const String packagesFilePath = '$appPath/.packages';

/// The line from the `.packages` file for [packageName].
String packageSpecLine(String packageName) => File(d.path(packagesFilePath))
    .readAsLinesSync()
    .firstWhere((l) => l.startsWith('$packageName:'));

/// The suffix appended to a precompiled snapshot.
final versionSuffix = testVersion ?? sdk.version;

/// Enum identifying a pub command that can be run with a well-defined success
/// output.
class RunCommand {
  static final get = RunCommand(
      'get', RegExp(r'Got dependencies!|Changed \d+ dependenc(y|ies)!'));
  static final upgrade = RunCommand('upgrade', RegExp(r'''
(No dependencies changed\.|Changed \d+ dependenc(y|ies)!)($|
\d+ packages? (has|have) newer versions incompatible with dependency constraints.
Try `pub outdated` for more information.$)'''));
  static final downgrade = RunCommand('downgrade',
      RegExp(r'(No dependencies changed\.|Changed \d+ dependenc(y|ies)!)$'));

  final String name;
  final RegExp success;
  RunCommand(this.name, this.success);
}

/// Runs the tests defined within [callback] using both pub get and pub upgrade.
///
/// Many tests validate behavior that is the same between pub get and
/// upgrade have the same behavior. Instead of duplicating those tests, this
/// takes a callback that defines get/upgrade agnostic tests and runs them
/// with both commands.
void forBothPubGetAndUpgrade(void Function(RunCommand) callback) {
  group(RunCommand.get.name, () => callback(RunCommand.get));
  group(RunCommand.upgrade.name, () => callback(RunCommand.upgrade));
}

/// Invokes the pub [command] and validates that it completes in an expected
/// way.
///
/// By default, this validates that the command completes successfully and
/// understands the normal output of a successful pub command. If [warning] is
/// given, it expects the command to complete successfully *and* print [warning]
/// to stderr. If [error] is given, it expects the command to *only* print
/// [error] to stderr. [output], [error], [silent], and [warning] may be
/// strings, [RegExp]s, or [Matcher]s.
///
/// If [exitCode] is given, expects the command to exit with that code.
// TODO(rnystrom): Clean up other tests to call this when possible.
Future pubCommand(RunCommand command,
    {Iterable<String> args,
    output,
    error,
    silent,
    warning,
    int exitCode,
    Map<String, String> environment}) async {
  if (error != null && warning != null) {
    throw ArgumentError("Cannot pass both 'error' and 'warning'.");
  }

  var allArgs = [command.name];
  if (args != null) allArgs.addAll(args);

  output ??= command.success;

  if (error != null && exitCode == null) exitCode = 1;

  // No success output on an error.
  if (error != null) output = null;
  if (warning != null) error = warning;

  await runPub(
      args: allArgs,
      output: output,
      error: error,
      silent: silent,
      exitCode: exitCode,
      environment: environment);
}

Future pubGet(
        {Iterable<String> args,
        output,
        error,
        warning,
        int exitCode,
        Map<String, String> environment}) =>
    pubCommand(RunCommand.get,
        args: args,
        output: output,
        error: error,
        warning: warning,
        exitCode: exitCode,
        environment: environment);

Future pubUpgrade(
        {Iterable<String> args,
        output,
        error,
        warning,
        int exitCode,
        Map<String, String> environment}) =>
    pubCommand(RunCommand.upgrade,
        args: args,
        output: output,
        error: error,
        warning: warning,
        exitCode: exitCode,
        environment: environment);

Future pubDowngrade(
        {Iterable<String> args,
        output,
        error,
        warning,
        int exitCode,
        Map<String, String> environment}) =>
    pubCommand(RunCommand.downgrade,
        args: args,
        output: output,
        error: error,
        warning: warning,
        exitCode: exitCode,
        environment: environment);

/// Schedules starting the "pub [global] run" process and validates the
/// expected startup output.
///
/// If [global] is `true`, this invokes "pub global run", otherwise it does
/// "pub run".
///
/// Returns the `pub run` process.
Future<PubProcess> pubRun(
    {bool global = false,
    Iterable<String> args,
    Map<String, String> environment,
    bool verbose = true}) async {
  var pubArgs = global ? ['global', 'run'] : ['run'];
  pubArgs.addAll(args);
  var pub = await startPub(
    args: pubArgs,
    environment: environment,
    verbose: verbose,
  );

  // Loading sources and transformers isn't normally printed, but the pub test
  // infrastructure runs pub in verbose mode, which enables this.
  expect(pub.stdout, mayEmitMultiple(startsWith('Loading')));

  return pub;
}

/// Schedules starting the "pub run --v2" process and validates the
/// expected startup output.
///
/// Returns the `pub run` process.
Future<PubProcess> pubRunFromDartDev({Iterable<String> args}) async {
  final pub = await startPub(args: ['run', '--dart-dev-run', ...args]);

  // Loading sources and transformers isn't normally printed, but the pub test
  // infrastructure runs pub in verbose mode, which enables this.
  expect(pub.stdout, mayEmitMultiple(startsWith('Loading')));

  return pub;
}

/// Schedules renaming (moving) the directory at [from] to [to], both of which
/// are assumed to be relative to [d.sandbox].
void renameInSandbox(String from, String to) {
  renameDir(_pathInSandbox(from), _pathInSandbox(to));
}

/// Schedules creating a symlink at path [symlink] that points to [target],
/// both of which are assumed to be relative to [d.sandbox].
void symlinkInSandbox(String target, String symlink) {
  createSymlink(_pathInSandbox(target), _pathInSandbox(symlink));
}

/// Runs Pub with [args] and validates that its results match [output] (or
/// [outputJson]), [error], [silent] (for logs that are silent by default), and
/// [exitCode].
///
/// [output], [error], and [silent] can be [String]s, [RegExp]s, or [Matcher]s.
///
/// If [outputJson] is given, validates that pub outputs stringified JSON
/// matching that object, which can be a literal JSON object or any other
/// [Matcher].
///
/// If [environment] is given, any keys in it will override the environment
/// variables passed to the spawned process.
Future runPub(
    {List<String> args,
    output,
    error,
    outputJson,
    silent,
    int exitCode = exit_codes.SUCCESS,
    String workingDirectory,
    Map<String, String> environment}) async {
  // Cannot pass both output and outputJson.
  assert(output == null || outputJson == null);

  var pub = await startPub(
      args: args, workingDirectory: workingDirectory, environment: environment);
  await pub.shouldExit(exitCode);

  expect(() async {
    var actualOutput = (await pub.stdoutStream().toList()).join('\n');
    var actualError = (await pub.stderrStream().toList()).join('\n');
    var actualSilent = (await pub.silentStream().toList()).join('\n');

    var failures = <String>[];
    if (outputJson == null) {
      _validateOutput(failures, 'stdout', output, actualOutput);
    } else {
      _validateOutputJson(failures, 'stdout', outputJson, actualOutput);
    }

    _validateOutput(failures, 'stderr', error, actualError);
    _validateOutput(failures, 'silent', silent, actualSilent);

    if (failures.isNotEmpty) test.fail(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.
Future<PubProcess> startPublish(PackageServer server,
    {List<String> args}) async {
  var tokenEndpoint = Uri.parse(server.url).resolve('/token').toString();
  args = ['lish', '--server', server.url, ...?args];
  return await 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.
Future confirmPublish(TestProcess pub) async {
  // TODO(rnystrom): This is overly specific and inflexible regarding different
  // test packages. Should validate this a little more loosely.
  await expectLater(
      pub.stdout, emits(startsWith('Publishing test_pkg 1.0.0 to ')));
  await expectLater(
      pub.stdout,
      emitsThrough(matches(
        r'^Do you want to publish [^ ]+ [^ ]+ (y/N)?',
      )));
  pub.stdin.writeln('y');
}

/// Resolves [path] relative to the package cache in the sandbox.
String pathInCache(String path) => p.join(d.sandbox, cachePath, path);

/// Gets the absolute path to [relPath], which is a relative path in the test
/// sandbox.
String _pathInSandbox(String relPath) => p.join(d.sandbox, relPath);

String testVersion = '0.1.2+3';

/// Gets the environment variables used to run pub in a test context.
Map<String, String> getPubTestEnvironment([String tokenEndpoint]) {
  var environment = {
    '_PUB_TESTING': 'true',
    'PUB_CACHE': _pathInSandbox(cachePath),
    'PUB_ENVIRONMENT': 'test-environment',

    // Ensure a known SDK version is set for the tests that rely on that.
    '_PUB_TEST_SDK_VERSION': testVersion
  };

  if (tokenEndpoint != null) {
    environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint;
  }

  if (globalServer != null) {
    environment['PUB_HOSTED_URL'] = 'http://localhost:${globalServer.port}';
  }

  return environment;
}

/// Starts a Pub process and returns a [PubProcess] that supports interaction
/// with that process.
///
/// Any futures in [args] will be resolved before the process is started.
///
/// If [environment] is given, any keys in it will override the environment
/// variables passed to the spawned process.
Future<PubProcess> startPub(
    {Iterable<String> args,
    String tokenEndpoint,
    String workingDirectory,
    Map<String, String> environment,
    bool verbose = true}) async {
  args ??= [];

  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 = Platform.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 = p.absolute(dartBin);
  }

  var pubPath = p.absolute(p.join(pubRoot, 'bin/pub.dart'));

  // If there's a snapshot for "pub" available we use it. If the snapshot is
  // out-of-date local source the tests will be useless, therefore it is
  // recommended to use a temporary file with a unique name for each test run.
  // Note: running tests without a snapshot is significantly slower.
  //
  // TODO(nweiz): When the test runner supports plugins, create one to
  // auto-generate the snapshot before each run.
  final snapshotPath = Platform.environment['_PUB_TEST_SNAPSHOT'] ?? '';
  if (snapshotPath.isNotEmpty && fileExists(snapshotPath)) {
    pubPath = snapshotPath;
  }

  final dotPackagesPath = (await Isolate.packageConfig).toString();

  var dartArgs = ['--packages=$dotPackagesPath'];
  dartArgs..addAll([pubPath, if (verbose) '--verbose'])..addAll(args);

  return await PubProcess.start(dartBin, dartArgs,
      environment: getPubTestEnvironment(tokenEndpoint)
        ..addAll(environment ?? {}),
      workingDirectory: workingDirectory ?? _pathInSandbox(appPath),
      description: args.isEmpty ? 'pub' : 'pub ${args.first}');
}

/// A subclass of [TestProcess] that parses pub's verbose logging output and
/// makes [stdout] and [stderr] work as though pub weren't running in verbose
/// mode.
class PubProcess extends TestProcess {
  StreamSplitter<Pair<log.Level, String>> get _logSplitter {
    __logSplitter ??= StreamSplitter(StreamGroup.merge([
      _outputToLog(super.stdoutStream(), log.Level.MESSAGE),
      _outputToLog(super.stderrStream(), log.Level.ERROR)
    ]));
    return __logSplitter;
  }

  StreamSplitter<Pair<log.Level, String>> __logSplitter;

  static Future<PubProcess> start(String executable, Iterable<String> arguments,
      {String workingDirectory,
      Map<String, String> environment,
      bool includeParentEnvironment = true,
      bool runInShell = false,
      String description,
      Encoding encoding,
      bool forwardStdio = false}) async {
    var process = await Process.start(executable, arguments.toList(),
        workingDirectory: workingDirectory,
        environment: environment,
        includeParentEnvironment: includeParentEnvironment,
        runInShell: runInShell);

    if (description == null) {
      var humanExecutable = p.isWithin(p.current, executable)
          ? p.relative(executable)
          : executable;
      description = '$humanExecutable ${arguments.join(' ')}';
    }

    encoding ??= utf8;
    return PubProcess(process, description,
        encoding: encoding, forwardStdio: forwardStdio);
  }

  /// This is protected.
  PubProcess(process, description,
      {Encoding encoding, bool forwardStdio = false})
      : super(process, description,
            encoding: encoding, forwardStdio: forwardStdio);

  final _logLineRegExp = RegExp(r'^([A-Z ]{4})[:|] (.*)$');
  final Map<String, log.Level> _logLevels = [
    log.Level.ERROR,
    log.Level.WARNING,
    log.Level.MESSAGE,
    log.Level.IO,
    log.Level.SOLVER,
    log.Level.FINE
  ].fold({}, (levels, level) {
    levels[level.name] = level;
    return levels;
  });

  Stream<Pair<log.Level, String>> _outputToLog(
      Stream<String> stream, log.Level defaultLevel) {
    log.Level lastLevel;
    return stream.map((line) {
      var match = _logLineRegExp.firstMatch(line);
      if (match == null) return Pair<log.Level, String>(defaultLevel, line);

      var level = _logLevels[match[1]] ?? lastLevel;
      lastLevel = level;
      return Pair<log.Level, String>(level, match[2]);
    });
  }

  @override
  Stream<String> stdoutStream() {
    return _logSplitter.split().expand((entry) {
      if (entry.first != log.Level.MESSAGE) return [];
      return [entry.last];
    });
  }

  @override
  Stream<String> stderrStream() {
    return _logSplitter.split().expand((entry) {
      if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) {
        return [];
      }
      return [entry.last];
    });
  }

  /// A stream of log messages that are silent by default.
  Stream<String> silentStream() {
    return _logSplitter.split().expand((entry) {
      if (entry.first == log.Level.MESSAGE) return [];
      if (entry.first == log.Level.ERROR) return [];
      if (entry.first == log.Level.WARNING) return [];
      return [entry.last];
    });
  }
}

/// Fails the current test if Git is not installed.
///
/// We require machines running these tests to have git installed. This
/// validation gives an easier-to-understand error when that requirement isn't
/// met than just failing in the middle of a test when pub invokes git.
void ensureGit() {
  if (!gitlib.isInstalled) fail('Git must be installed to run this test.');
}

/// Creates a lock file for [package] without running `pub get`.
///
/// [sandbox] is a list of path dependencies to be found in the sandbox
/// directory.
///
/// [hosted] is a list of package names to version strings for dependencies on
/// hosted packages.
Future createLockFile(String package,
    {Iterable<String> sandbox, Map<String, String> hosted}) async {
  var cache = SystemCache(rootDir: _pathInSandbox(cachePath));

  var lockFile =
      _createLockFile(cache.sources, sandbox: sandbox, hosted: hosted);

  await d.dir(package, [
    d.file('pubspec.lock', lockFile.serialize(null)),
    d.file('.packages', lockFile.packagesFile(cache, package))
  ]).create();
}

/// Like [createLockFile], but creates only a `.packages` file without a
/// lockfile.
Future createPackagesFile(String package,
    {Iterable<String> sandbox, Map<String, String> hosted}) async {
  var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
  var lockFile =
      _createLockFile(cache.sources, sandbox: sandbox, hosted: hosted);

  await d.dir(package,
      [d.file('.packages', lockFile.packagesFile(cache, package))]).create();
}

/// Creates a lock file for [sources] without running `pub get`.
///
/// [sandbox] is a list of path dependencies to be found in the sandbox
/// directory.
///
/// [hosted] is a list of package names to version strings for dependencies on
/// hosted packages.
LockFile _createLockFile(SourceRegistry sources,
    {Iterable<String> sandbox, Map<String, String> hosted}) {
  var dependencies = {};

  if (sandbox != null) {
    for (var package in sandbox) {
      dependencies[package] = '../$package';
    }
  }

  var packages = dependencies.keys.map((name) {
    var dependencyPath = dependencies[name];
    return sources.path.idFor(name, Version(0, 0, 0), dependencyPath);
  }).toList();

  if (hosted != null) {
    hosted.forEach((name, version) {
      var id = sources.hosted.idFor(name, Version.parse(version));
      packages.add(id);
    });
  }

  return LockFile(packages);
}

/// Returns the path to the version of [package] used by pub.
String packagePath(String package) {
  if (runningFromDartRepo) {
    return dirExists(p.join(dartRepoRoot, 'pkg', package))
        ? p.join(dartRepoRoot, 'pkg', package)
        : p.join(dartRepoRoot, 'third_party', 'pkg', package);
  }

  var id = _entrypoint.lockFile.packages[package];
  if (id == null) {
    throw StateError(
        'The tests rely on "$package", but it\'s not in the lockfile.');
  }

  return p.join(
      SystemCache.defaultDir, 'hosted/pub.dartlang.org/$package-${id.version}');
}

/// Uses [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 = innerHttpClient;
  innerHttpClient = client;
  addTearDown(() {
    innerHttpClient = oldInnerClient;
  });
}

/// Describes a map representing a library package with the given [name],
/// [version], and [dependencies].
Map packageMap(
  String name,
  String version, [
  Map dependencies,
  Map devDependencies,
  Map environment,
]) {
  var package = <String, dynamic>{
    'name': name,
    'version': version,
    'homepage': 'http://pub.dartlang.org',
    'description': 'A package, I guess.'
  };

  if (dependencies != null) package['dependencies'] = dependencies;
  if (devDependencies != null) package['dev_dependencies'] = devDependencies;
  if (environment != null) package['environment'] = environment;
  return package;
}

/// Resolves [target] relative to the path to pub's `test/asset` directory.
String testAssetPath(String target) => p.join(pubRoot, 'test', 'asset', target);

/// Returns a Map in the format used by the pub.dartlang.org API to represent a
/// package version.
///
/// [pubspec] is the parsed pubspec of the package version. If [full] is true,
/// this returns the complete map, including metadata that's only included when
/// requesting the package version directly.
Map packageVersionApiMap(String hostedUrl, Map pubspec, {bool full = false}) {
  var name = pubspec['name'];
  var version = pubspec['version'];
  var map = {
    'pubspec': pubspec,
    'version': version,
    'archive_url': '$hostedUrl/packages/$name/versions/$version.tar.gz',
  };

  if (full) {
    map.addAll({
      'downloads': 0,
      'created': '2012-09-25T18:38:28.685260',
      'libraries': ['$name.dart'],
      'uploader': ['nweiz@google.com']
    });
  }

  return map;
}

/// Returns the name of the shell script for a binstub named [name].
///
/// Adds a ".bat" extension on Windows.
String binStubName(String name) => Platform.isWindows ? '$name.bat' : name;

/// Compares the [actual] output from running pub with [expected].
///
/// If [expected] is a [String], ignores leading and trailing whitespace
/// differences and tries to report the offending difference in a nice way.
///
/// If it's a [RegExp] or [Matcher], just reports whether the output matches.
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');

  // 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 (expectedLines.last.trim() == '') {
    expectedLines.removeLast();
  }

  var results = <String>[];
  var failed = false;

  // Compare them line by line to see which ones match.
  var length = max(expectedLines.length, actualLines.length);
  for (var i = 0; i < length; i++) {
    if (i >= actualLines.length) {
      // Missing output.
      failed = true;
      results.add('? ${expectedLines[i]}');
    } else if (i >= expectedLines.length) {
      // Unexpected extra output.
      failed = true;
      results.add('X ${actualLines[i]}');
    } else {
      var expectedLine = expectedLines[i].trim();
      var actualLine = actualLines[i].trim();

      if (expectedLine != actualLine) {
        // Mismatched lines.
        failed = true;
        results.add('X ${actualLines[i]}');
      } else {
        // Output is OK, but include it in case other lines are wrong.
        results.add('| ${actualLines[i]}');
      }
    }
  }

  // If any lines mismatched, show the expected and actual.
  if (failed) {
    failures.add('Expected $pipe:');
    failures.addAll(expectedLines.map((line) => '| $line'));
    failures.add('Got:');
    failures.addAll(results);
  }
}

/// Validates that [actualText] is a string of JSON that matches [expected],
/// which may be a literal JSON object, or any other [Matcher].
void _validateOutputJson(
    List<String> failures, String pipe, expected, String actualText) {
  Map actual;
  try {
    actual = jsonDecode(actualText);
  } on FormatException {
    failures.add('Expected $pipe JSON:');
    failures.add(expected);
    failures.add('Got invalid JSON:');
    failures.add(actualText);
  }

  // Remove dart2js's timing logs, which would otherwise cause tests to fail
  // flakily when compilation takes a long time.
  actual['log']?.removeWhere((entry) =>
      entry['level'] == 'Fine' &&
      entry['message'].startsWith('Not yet complete after'));

  // Match against the expectation.
  expect(actual, expected);
}

/// A function that creates a [Validator] subclass.
typedef ValidatorCreator = Validator Function(Entrypoint entrypoint);

/// Schedules a single [Validator] to run on the [appPath].
///
/// Returns a scheduled Future that contains the validator after validation.
Future<Validator> validatePackage(ValidatorCreator fn) async {
  var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
  var validator = fn(Entrypoint(_pathInSandbox(appPath), cache));
  await validator.validate();
  return validator;
}

/// A matcher that matches a Pair.
Matcher pairOf(firstMatcher, lastMatcher) =>
    _PairMatcher(wrapMatcher(firstMatcher), wrapMatcher(lastMatcher));

class _PairMatcher extends Matcher {
  final Matcher _firstMatcher;
  final Matcher _lastMatcher;

  _PairMatcher(this._firstMatcher, this._lastMatcher);

  @override
  bool matches(item, Map matchState) {
    if (item is! Pair) return false;
    return _firstMatcher.matches(item.first, matchState) &&
        _lastMatcher.matches(item.last, matchState);
  }

  @override
  Description describe(Description description) {
    return description.addAll('(', ', ', ')', [_firstMatcher, _lastMatcher]);
  }
}

/// Returns a matcher that asserts that a string contains [times] distinct
/// occurrences of [pattern], which must be a regular expression pattern.
Matcher matchesMultiple(String pattern, int times) {
  var buffer = StringBuffer(pattern);
  for (var i = 1; i < times; i++) {
    buffer.write(r'(.|\n)*');
    buffer.write(pattern);
  }
  return matches(buffer.toString());
}

/// A [StreamMatcher] that matches multiple lines of output.
StreamMatcher emitsLines(String output) => emitsInOrder(output.split('\n'));
