anchor.diff:    }, name: 'Driver');
   }
   
  -class BaseTest {
  -  static const emptyOptionsFile = 'data/empty_options.yaml';
  -
  -  StringSink _savedOutSink, _savedErrorSink;
  -  int _savedExitCode;
  -  ExitHandler _savedExitHandler;
  -
  -  Driver driver;
  -
  -  AnalysisOptions get analysisOptions => driver.analysisDriver.analysisOptions;
  -
  -  bool get usePreviewDart2 => false;
  -
  -  /// Normalize text with bullets.
  -  String bulletToDash(item) => '$item'.replaceAll('•', '-');
  -
  -  /// Start a driver for the given [source], optionally providing additional
  -  /// [args] and an [options] file path. The value of [options] defaults to an
  -  /// empty options file to avoid unwanted configuration from an otherwise
  -  /// discovered options file.
  -  Future<void> drive(
  -    String source, {
  -    String options: emptyOptionsFile,
  -    List<String> args: const <String>[],
  -  }) {
  -    return driveMany([source], options: options, args: args);
  -  }
  -
  -  /// Like [drive], but takes an array of sources.
  -  Future<void> driveMany(
  -    List<String> sources, {
  -    String options: emptyOptionsFile,
  -    List<String> args: const <String>[],
  -  }) async {
  -    options = _p(options);
  -
  -    driver = new Driver(isTesting: true);
  -    var cmd = <String>[];
  -    if (options != null) {
  -      cmd = <String>[
  -        '--options',
  -        path.join(testDirectory, options),
  -      ];
  -    }
  -    cmd..addAll(sources.map(_adjustFileSpec))..addAll(args);
  -    if (usePreviewDart2) {
  -      cmd.insert(0, '--preview-dart-2');
  -    }
  -
  -    await driver.start(cmd);
  -  }
  -
  -  void setUp() {
  -    ansi.runningTests = true;
  -    _savedOutSink = outSink;
  -    _savedErrorSink = errorSink;
  -    _savedExitHandler = exitHandler;
  -    _savedExitCode = exitCode;
  -    exitHandler = (code) => exitCode = code;
  -    outSink = new StringBuffer();
  -    errorSink = new StringBuffer();
  -  }
  -
  -  void tearDown() {
  -    outSink = _savedOutSink;
  -    errorSink = _savedErrorSink;
  -    exitCode = _savedExitCode;
  -    exitHandler = _savedExitHandler;
  -    ansi.runningTests = false;
  -  }
  -
  -  /// Convert a file specification from a relative path to an absolute path.
  -  /// Handles the case where the file specification is of the form "$uri|$path".
  -  String _adjustFileSpec(String fileSpec) {
  -    int uriPrefixLength = fileSpec.indexOf('|') + 1;
  -    String uriPrefix = fileSpec.substring(0, uriPrefixLength);
  -    String relativePath = fileSpec.substring(uriPrefixLength);
  -    return '$uriPrefix${path.join(testDirectory, relativePath)}';
  -  }
  -
  -  /**
  -   * Convert the given posix [filePath] to conform to this provider's path context.
  -   *
  -   * This is a utility method for testing; paths passed in to other methods in
  -   * this class are never converted automatically.
  -   */
  -  String _p(String filePath) {
  -    if (filePath == null) {
  -      return null;
  -    }
  -    if (path.style == path.windows.style) {
  -      filePath =
  -          filePath.replaceAll(path.posix.separator, path.windows.separator);
  -    }
  -    return filePath;
  -  }
  -}
  -
  -@reflectiveTest
  -class BuildModeTest extends BaseTest {
  -  test_buildLinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var outputPath = path.join(tempDir, 'test_file.dart.sum');
  -      await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
  -        '--build-summary-only',
  -        '--build-summary-output=$outputPath'
  -      ]);
  -      var output = new File(outputPath);
  -      expect(output.existsSync(), isTrue);
  -      PackageBundle bundle =
  -          new PackageBundle.fromBuffer(await output.readAsBytes());
  -      var testFileUri = 'file:///test_file.dart';
  -      expect(bundle.unlinkedUnitUris, equals([testFileUri]));
  -      expect(bundle.linkedLibraryUris, equals([testFileUri]));
  -      expect(exitCode, 0);
  -    });
  -  }
  -
  -  test_buildLinked_buildSummaryOutputSemantic() async {
  -    await withTempDirAsync((tempDir) async {
  -      var testDart = path.join(tempDir, 'test.dart');
  -      var testSumFull = path.join(tempDir, 'test.sum.full');
  -      var testSumSemantic = path.join(tempDir, 'test.sum.sem');
  -
  -      new File(testDart).writeAsStringSync('var v = 42;');
  -
  -      await _doDrive(testDart, additionalArgs: [
  -        '--build-summary-only',
  -        '--build-summary-output=$testSumFull',
  -        '--build-summary-output-semantic=$testSumSemantic',
  -      ]);
  -      expect(exitCode, 0);
  -
  -      // The full summary is produced.
  -      {
  -        var file = new File(testSumFull);
  -        expect(file.existsSync(), isTrue);
  -        var bytes = file.readAsBytesSync();
  -        var bundle = new PackageBundle.fromBuffer(bytes);
  -        var v = bundle.unlinkedUnits[0].variables[0];
  -        expect(v.name, 'v');
  -        expect(v.nameOffset, 4);
  -      }
  -
  -      // The semantic summary is produced.
  -      {
  -        var file = new File(testSumSemantic);
  -        expect(file.existsSync(), isTrue);
  -        var bytes = file.readAsBytesSync();
  -        var bundle = new PackageBundle.fromBuffer(bytes);
  -        var v = bundle.unlinkedUnits[0].variables[0];
  -        expect(v.name, 'v');
  -        expect(v.nameOffset, 0);
  -      }
  -    });
  -  }
  -
  -  test_buildLinked_fromUnlinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var aDart = path.join(tempDir, 'a.dart');
  -      var bDart = path.join(tempDir, 'b.dart');
  -
  -      var aUri = 'package:aaa/a.dart';
  -      var bUri = 'package:bbb/b.dart';
  -
  -      var aUnlinked = path.join(tempDir, 'a.unlinked');
  -      var bUnlinked = path.join(tempDir, 'b.unlinked');
  -      var abLinked = path.join(tempDir, 'ab.linked');
  -
  -      new File(aDart).writeAsStringSync('var a = 1;');
  -      new File(bDart).writeAsStringSync('''
  -import 'package:aaa/a.dart';
  -var b = a;
  -''');
  -
  -      Future<void> buildUnlinked(String uri, String path, String output) async {
  -        await _doDrive(path, uri: uri, additionalArgs: [
  -          '--build-summary-only',
  -          '--build-summary-only-unlinked',
  -          '--build-summary-output=$output'
  -        ]);
  -        expect(exitCode, 0);
  -        expect(new File(output).existsSync(), isTrue);
  -      }
  -
  -      await buildUnlinked(aUri, aDart, aUnlinked);
  -      await buildUnlinked(bUri, bDart, bUnlinked);
  -
  -      await new Driver(isTesting: true).start([
  -        '--dart-sdk',
  -        _findSdkDirForSummaries(),
  -        '--build-mode',
  -        '--build-summary-unlinked-input=$aUnlinked,$bUnlinked',
  -        '--build-summary-output=$abLinked'
  -      ]);
  -      expect(exitCode, 0);
  -      var bytes = new File(abLinked).readAsBytesSync();
  -      var bundle = new PackageBundle.fromBuffer(bytes);
  -
  -      // Only linked information.
  -      expect(bundle.unlinkedUnitUris, isEmpty);
  -      expect(bundle.linkedLibraryUris, unorderedEquals([aUri, bUri]));
  -
  -      // Strong mode type inference was performed.
  -      expect(bundle.linkedLibraries[0].units[0].types, isNotEmpty);
  -      expect(bundle.linkedLibraries[1].units[0].types, isNotEmpty);
  -    });
  -  }
  -
  -  test_buildSuppressExitCode_fail_whenFileNotFound() async {
  -    await _doDrive(path.join('data', 'non_existent_file.dart'),
  -        additionalArgs: ['--build-suppress-exit-code']);
  -    expect(exitCode, isNot(0));
  -  }
  -
  -  test_buildSuppressExitCode_success_evenIfHasError() async {
  -    await _doDrive(path.join('data', 'file_with_error.dart'),
  -        additionalArgs: ['--build-suppress-exit-code']);
  -    expect(exitCode, 0);
  -  }
  -
  -  test_buildUnlinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var outputPath = path.join(tempDir, 'test_file.dart.sum');
  -      await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
  -        '--build-summary-only',
  -        '--build-summary-only-unlinked',
  -        '--build-summary-output=$outputPath'
  -      ]);
  -      var output = new File(outputPath);
  -      expect(output.existsSync(), isTrue);
  -      PackageBundle bundle =
  -          new PackageBundle.fromBuffer(await output.readAsBytes());
  -      var testFileUri = 'file:///test_file.dart';
  -      expect(bundle.unlinkedUnits.length, 1);
  -      expect(bundle.unlinkedUnitUris, equals([testFileUri]));
  -      expect(bundle.linkedLibraryUris, isEmpty);
  -      expect(exitCode, 0);
  -    });
  -  }
  -
  -  test_consumeLinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var aDart = path.join(tempDir, 'a.dart');
  -      var bDart = path.join(tempDir, 'b.dart');
  -      var cDart = path.join(tempDir, 'c.dart');
  -
  -      var aUri = 'package:aaa/a.dart';
  -      var bUri = 'package:bbb/b.dart';
  -      var cUri = 'package:ccc/c.dart';
  -
  -      var aSum = path.join(tempDir, 'a.sum');
  -      var bSum = path.join(tempDir, 'b.sum');
  -      var cSum = path.join(tempDir, 'c.sum');
  -
  -      new File(aDart).writeAsStringSync('class A {}');
  -      new File(bDart).writeAsStringSync('''
  -export 'package:aaa/a.dart';
  -class B {}
  -''');
  -      new File(cDart).writeAsStringSync('''
  -import 'package:bbb/b.dart';
  -var a = new A();
  -var b = new B();
  -''');
  -
  -      // Analyze package:aaa/a.dart and compute summary.
  -      {
  -        await _doDrive(aDart,
  -            uri: aUri, additionalArgs: ['--build-summary-output=$aSum']);
  -        expect(exitCode, 0);
  -        var bytes = new File(aSum).readAsBytesSync();
  -        var bundle = new PackageBundle.fromBuffer(bytes);
  -        expect(bundle.unlinkedUnitUris, equals([aUri]));
  -        expect(bundle.linkedLibraryUris, equals([aUri]));
  -      }
  -
  -      // Analyze package:bbb/b.dart and compute summary.
  -      {
  -        await _doDrive(bDart, uri: bUri, additionalArgs: [
  -          '--build-summary-input=$aSum',
  -          '--build-summary-output=$bSum'
  -        ]);
  -        expect(exitCode, 0);
  -        var bytes = new File(bSum).readAsBytesSync();
  -        var bundle = new PackageBundle.fromBuffer(bytes);
  -        expect(bundle.unlinkedUnitUris, equals([bUri]));
  -        expect(bundle.linkedLibraryUris, equals([bUri]));
  -      }
  -
  -      // Analyze package:ccc/c.dart and compute summary.
  -      {
  -        await _doDrive(cDart, uri: cUri, additionalArgs: [
  -          '--build-summary-input=$aSum,$bSum',
  -          '--build-summary-output=$cSum'
  -        ]);
  -        expect(exitCode, 0);
  -        var bytes = new File(cSum).readAsBytesSync();
  -        var bundle = new PackageBundle.fromBuffer(bytes);
  -        expect(bundle.unlinkedUnitUris, equals([cUri]));
  -        expect(bundle.linkedLibraryUris, equals([cUri]));
  -      }
  -    });
  -  }
  -
  -  test_dartSdkSummaryPath_strong() async {
  -    await withTempDirAsync((tempDir) async {
  -      String sdkPath = _findSdkDirForSummaries();
  -      String strongSummaryPath =
  -          path.join(sdkPath, 'lib', '_internal', 'strong.sum');
  -
  -      var testDart = path.join(tempDir, 'test.dart');
  -      var testSum = path.join(tempDir, 'test.sum');
  -      new File(testDart).writeAsStringSync('var v = 42;');
  -
  -      await _doDrive(testDart,
  -          additionalArgs: [
  -            '--build-summary-only',
  -            '--build-summary-output=$testSum'
  -          ],
  -          dartSdkSummaryPath: strongSummaryPath);
  -      var output = new File(testSum);
  -      expect(output.existsSync(), isTrue);
  -      expect(exitCode, 0);
  -    });
  -  }
  -
  -  test_error_linkedAsUnlinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var aDart = path.join(tempDir, 'a.dart');
  -      var bDart = path.join(tempDir, 'b.dart');
  -
  -      var aUri = 'package:aaa/a.dart';
  -      var bUri = 'package:bbb/b.dart';
  -
  -      var aSum = path.join(tempDir, 'a.sum');
  -      var bSum = path.join(tempDir, 'b.sum');
  -
  -      new File(aDart).writeAsStringSync('class A {}');
  -
  -      // Build linked a.sum
  -      await _doDrive(aDart, uri: aUri, additionalArgs: [
  -        '--build-summary-only',
  -        '--build-summary-output=$aSum'
  -      ]);
  -      expect(new File(aSum).existsSync(), isTrue);
  -
  -      // Try to consume linked a.sum as unlinked.
  -      try {
  -        await _doDrive(bDart, uri: bUri, additionalArgs: [
  -          '--build-summary-unlinked-input=$aSum',
  -          '--build-summary-output=$bSum'
  -        ]);
  -        fail('ArgumentError expected.');
  -      } on ArgumentError catch (e) {
  -        expect(
  -            e.message,
  -            contains(
  -                'Got a linked summary for --build-summary-input-unlinked'));
  -      }
  -    });
  -  }
  -
  -  test_error_notUriPipePath() async {
  -    await withTempDirAsync((tempDir) async {
  -      var testDart = path.join(tempDir, 'test.dart');
  -      new File(testDart).writeAsStringSync('var v = 42;');
  -
  -      // We pass just path, not "uri|path", this is a fatal error.
  -      await drive(testDart, args: ['--build-mode', '--format=machine']);
  -      expect(exitCode, ErrorSeverity.ERROR.ordinal);
  -    });
  -  }
  -
  -  test_error_unlinkedAsLinked() async {
  -    await withTempDirAsync((tempDir) async {
  -      var aDart = path.join(tempDir, 'a.dart');
  -      var bDart = path.join(tempDir, 'b.dart');
  -
  -      var aUri = 'package:aaa/a.dart';
  -      var bUri = 'package:bbb/b.dart';
  -
  -      var aSum = path.join(tempDir, 'a.sum');
  -      var bSum = path.join(tempDir, 'b.sum');
  -
  -      new File(aDart).writeAsStringSync('class A {}');
  -
  -      // Build unlinked a.sum
  -      await _doDrive(aDart, uri: aUri, additionalArgs: [
  -        '--build-summary-only',
  -        '--build-summary-only-unlinked',
  -        '--build-summary-output=$aSum'
  -      ]);
  -      expect(new File(aSum).existsSync(), isTrue);
  -
  -      // Try to consume unlinked a.sum as linked.
  -      try {
  -        await _doDrive(bDart, uri: bUri, additionalArgs: [
  -          '--build-summary-input=$aSum',
  -          '--build-summary-output=$bSum'
  -        ]);
  -        fail('ArgumentError expected.');
  -      } on ArgumentError catch (e) {
  -        expect(e.message,
  -            contains('Got an unlinked summary for --build-summary-input'));
  -      }
  -    });
  -  }
  -
  -  test_fail_whenHasError() async {
  -    await _doDrive(path.join('data', 'file_with_error.dart'));
  -    expect(exitCode, isNot(0));
  -  }
  -
  -  test_noStatistics() async {
  -    await _doDrive(path.join('data', 'test_file.dart'));
  -    // Should not print statistics summary.
  -    expect(outSink.toString(), isEmpty);
  -    expect(errorSink.toString(), isEmpty);
  -    expect(exitCode, 0);
  -  }
  -
  -  test_onlyErrors_partFirst() async {
  -    await withTempDirAsync((tempDir) async {
  -      var aDart = path.join(tempDir, 'a.dart');
  -      var bDart = path.join(tempDir, 'b.dart');
  -
  -      var aUri = 'package:aaa/a.dart';
  -      var bUri = 'package:aaa/b.dart';
  -
  -      new File(aDart).writeAsStringSync(r'''
  -library lib;
  -part 'b.dart';
  -class A {}
  -''');
  -      new File(bDart).writeAsStringSync('''
  -part of lib;
  -class B {}
  -var a = new A();
  -var b = new B();
  -''');
  -
  -      // Analyze b.dart (part) and then a.dart (its library).
  -      // No errors should be reported - the part should know its library.
  -      await _doDrive(bDart, uri: bUri, additionalArgs: ['$aUri|$aDart']);
  -      expect(errorSink, isEmpty);
  -    });
  -  }
  -
  +class AbstractBuildModeTest extends BaseTest {
     Future<void> _doDrive(String path,
         {String uri,
         List<String> additionalArgs: const [],
  
positive.code:   @override
    noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
  }
  
negative.code:   }
  }
  
  class BaseTest {
    static const emptyOptionsFile = 'data/empty_options.yaml';
  
    StringSink _savedOutSink, _savedErrorSink;
    int _savedExitCode;
    ExitHandler _savedExitHandler;
  
    Driver driver;
  
    AnalysisOptions get analysisOptions => driver.analysisDriver.analysisOptions;
  
    bool get usePreviewDart2 => false;
  
    /// Normalize text with bullets.
    String bulletToDash(item) => '$item'.replaceAll('•', '-');
  
    /// Start a driver for the given [source], optionally providing additional
    /// [args] and an [options] file path. The value of [options] defaults to an
    /// empty options file to avoid unwanted configuration from an otherwise
    /// discovered options file.
    Future<void> drive(
      String source, {
      String options: emptyOptionsFile,
      List<String> args: const <String>[],
    }) {
      return driveMany([source], options: options, args: args);
    }
  
    /// Like [drive], but takes an array of sources.
    Future<void> driveMany(
      List<String> sources, {
      String options: emptyOptionsFile,
      List<String> args: const <String>[],
    }) async {
      options = _p(options);
  
      driver = new Driver(isTesting: true);
      var cmd = <String>[];
      if (options != null) {
        cmd = <String>[
          '--options',
          path.join(testDirectory, options),
        ];
      }
      cmd..addAll(sources.map(_adjustFileSpec))..addAll(args);
      if (usePreviewDart2) {
        cmd.insert(0, '--preview-dart-2');
      }
  
      await driver.start(cmd);
    }
  
    void setUp() {
      ansi.runningTests = true;
      _savedOutSink = outSink;
      _savedErrorSink = errorSink;
      _savedExitHandler = exitHandler;
      _savedExitCode = exitCode;
      exitHandler = (code) => exitCode = code;
      outSink = new StringBuffer();
      errorSink = new StringBuffer();
    }
  
    void tearDown() {
      outSink = _savedOutSink;
      errorSink = _savedErrorSink;
      exitCode = _savedExitCode;
      exitHandler = _savedExitHandler;
      ansi.runningTests = false;
    }
  
    /// Convert a file specification from a relative path to an absolute path.
    /// Handles the case where the file specification is of the form "$uri|$path".
    String _adjustFileSpec(String fileSpec) {
      int uriPrefixLength = fileSpec.indexOf('|') + 1;
      String uriPrefix = fileSpec.substring(0, uriPrefixLength);
      String relativePath = fileSpec.substring(uriPrefixLength);
      return '$uriPrefix${path.join(testDirectory, relativePath)}';
    }
  
    /**
     * Convert the given posix [filePath] to conform to this provider's path context.
     *
     * This is a utility method for testing; paths passed in to other methods in
     * this class are never converted automatically.
     */
    String _p(String filePath) {
      if (filePath == null) {
        return null;
      }
      if (path.style == path.windows.style) {
        filePath =
            filePath.replaceAll(path.posix.separator, path.windows.separator);
      }
      return filePath;
    }
  }
  
  @reflectiveTest
  class BuildModeSummaryDependenciesTest extends AbstractBuildModeTest {
    String tempDir;
  
    /// Any direct export is a dependency.
    test_export_direct() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], 'class A {}');
        await _assertDependencies('c', [a], '''
  export 'package:a/a.dart';
  ''', [a]);
      });
    }
  
    /// Imports of dependencies are not necessary dependencies.
    /// Here our dependency does not use its dependency.
    test_import2_notUsed() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], '');
        var b = await _buildPackage('b', [a], '''
  import 'package:a/a.dart';
  ''');
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  ''', [b]);
      });
    }
  
    test_import2_usedAsFieldType() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], 'class A {}');
        var b = await _buildPackage('b', [a], '''
  import 'package:a/a.dart';
  class B {
    A f;
  }
  ''');
  
        // We don't use `f`, so don't depend on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  var x = B();
  ''', [b]);
  
        // We use `f` for type inference.
        // So, dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  var x = B().f;
  ''', [a, b]);
  
        // We reference `f` in initializer, but not for type inference.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  Object x = B().f;
  ''', [b]);
  
        // We perform full analysis, so request the type of `f`;
        // So, dependency on "a".
        await _assertDependencies(
          'c',
          [a, b],
          '''
  import 'package:b/b.dart';
  Object x = B().f;
  ''',
          [a, b],
          summaryOnly: false,
        );
      });
    }
  
    test_import2_usedAsSupertype() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], 'class A {}');
        var b = await _buildPackage('b', [a], '''
  import 'package:a/a.dart';
  class B extends A {}
  ''');
  
        // We don't invoke anything on class `B`, so don't ask its supertype.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  B x;
  ''', [b]);
  
        // We infer the type of `x` to `B`.
        // But we don't ask `B` for its supertype.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  var x = B();
  ''', [b]);
  
        // We perform full analysis, and check that `new B()` is assignable
        // to `B x`. While doing this, we ask for `B` supertype.
        // So, dependency on "a".
        await _assertDependencies(
          'c',
          [a, b],
          '''
  import 'package:b/b.dart';
  var x = B();
  ''',
          [a, b],
          summaryOnly: false,
        );
      });
    }
  
    test_import2_usedAsTopLevelVariableType() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], 'class A {}');
        var b = await _buildPackage('b', [a], '''
  import 'package:a/a.dart';
  A v;
  ''');
  
        // We don't use `v`.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  ''', [b]);
  
        // We use `v` for type inference.
        // So, dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  var x = v;
  ''', [a, b]);
  
        // We don't use `v` for type inference.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  Object x = v;
  ''', [b]);
  
        // We perform full analysis, and request the type of `v`.
        // So, dependency on "a".
        await _assertDependencies(
          'c',
          [a, b],
          '''
  import 'package:b/b.dart';
  Object x = v;
  ''',
          [a, b],
          summaryOnly: false,
        );
  
        // We use `v` in a method body.
        // So, no dependency on "a".
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  main() {
    v;
  }
  ''', [b]);
  
        // We perform full analysis, so ask for the type of `v`.
        // So, dependency on "a".
        await _assertDependencies(
          'c',
          [a, b],
          '''
  import 'package:b/b.dart';
  main() {
    v;
  }
  ''',
          [a, b],
          summaryOnly: false,
        );
      });
    }
  
    /// Any direct import is a dependency.
    test_import_direct() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], '');
        var b = await _buildPackage('b', [], '');
        await _assertDependencies('c', [a, b], '''
  import 'package:a/a.dart';
  import 'package:b/b.dart';
  ''', [a, b]);
      });
    }
  
    /// Exports of dependencies are dependencies.
    test_import_export() async {
      await _withTempDir(() async {
        var a = await _buildPackage('a', [], 'class A {}');
        var b = await _buildPackage('b', [a], '''
  export 'package:a/a.dart';
  ''');
        await _assertDependencies('c', [a, b], '''
  import 'package:b/b.dart';
  ''', [a, b]);
      });
    }
  
    Future<void> _assertDependencies(
      String name,
      List<_DependencyPackage> inputPackages,
      String content,
      List<_DependencyPackage> expectedPackages, {
      bool summaryOnly = true,
    }) async {
      var pkg = await _buildPackage(name, inputPackages, content,
          summaryOnly: summaryOnly);
  
      var depString = File(pkg.dep).readAsStringSync();
      var expectedList = expectedPackages.map((p) => p.sum).toList();
      expect(depString.split('\n'), unorderedEquals(expectedList));
    }
  
    Future<_DependencyPackage> _buildPackage(
      String name,
      List<_DependencyPackage> inputPackages,
      String content, {
      bool summaryOnly = true,
    }) async {
      var filePath = path.join(tempDir, '$name.dart');
      File(filePath).writeAsStringSync(content);
      var pkg = _DependencyPackage(
        name: name,
        path: filePath,
        uri: 'package:$name/$name.dart',
        sum: path.join(tempDir, '$name.sum'),
        dep: path.join(tempDir, '$name.dep'),
      );
  
      var args = <String>[];
      if (summaryOnly) {
        args.add('--build-summary-only');
      }
      for (var input in inputPackages) {
        args.add('--build-summary-input=${input.sum}');
      }
      args.add('--build-summary-output=${pkg.sum}');
      args.add('--summary-deps-output=${pkg.dep}');
  
      await _doDrive(pkg.path, uri: pkg.uri, additionalArgs: args);
      expect(exitCode, 0);
  
      return pkg;
    }
  
    Future<void> _withTempDir(Future<void> f()) async {
      await withTempDirAsync((tempDir) async {
        this.tempDir = tempDir;
        await f();
      });
    }
  }
  
  @reflectiveTest
  class BuildModeTest extends AbstractBuildModeTest {
    test_buildLinked() async {
      await withTempDirAsync((tempDir) async {
        var outputPath = path.join(tempDir, 'test_file.dart.sum');
        await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
          '--build-summary-only',
          '--build-summary-output=$outputPath'
        ]);
        var output = new File(outputPath);
        expect(output.existsSync(), isTrue);
        PackageBundle bundle =
            new PackageBundle.fromBuffer(await output.readAsBytes());
        var testFileUri = 'file:///test_file.dart';
        expect(bundle.unlinkedUnitUris, equals([testFileUri]));
        expect(bundle.linkedLibraryUris, equals([testFileUri]));
        expect(exitCode, 0);
      });
    }
  
    test_buildLinked_buildSummaryOutputSemantic() async {
      await withTempDirAsync((tempDir) async {
        var testDart = path.join(tempDir, 'test.dart');
        var testSumFull = path.join(tempDir, 'test.sum.full');
        var testSumSemantic = path.join(tempDir, 'test.sum.sem');
  
        new File(testDart).writeAsStringSync('var v = 42;');
  
        await _doDrive(testDart, additionalArgs: [
          '--build-summary-only',
          '--build-summary-output=$testSumFull',
          '--build-summary-output-semantic=$testSumSemantic',
        ]);
        expect(exitCode, 0);
  
        // The full summary is produced.
        {
          var file = new File(testSumFull);
          expect(file.existsSync(), isTrue);
          var bytes = file.readAsBytesSync();
          var bundle = new PackageBundle.fromBuffer(bytes);
          var v = bundle.unlinkedUnits[0].variables[0];
          expect(v.name, 'v');
          expect(v.nameOffset, 4);
        }
  
        // The semantic summary is produced.
        {
          var file = new File(testSumSemantic);
          expect(file.existsSync(), isTrue);
          var bytes = file.readAsBytesSync();
          var bundle = new PackageBundle.fromBuffer(bytes);
          var v = bundle.unlinkedUnits[0].variables[0];
          expect(v.name, 'v');
          expect(v.nameOffset, 0);
        }
      });
    }
  
    test_buildLinked_fromUnlinked() async {
      await withTempDirAsync((tempDir) async {
        var aDart = path.join(tempDir, 'a.dart');
        var bDart = path.join(tempDir, 'b.dart');
  
        var aUri = 'package:aaa/a.dart';
        var bUri = 'package:bbb/b.dart';
  
        var aUnlinked = path.join(tempDir, 'a.unlinked');
        var bUnlinked = path.join(tempDir, 'b.unlinked');
        var abLinked = path.join(tempDir, 'ab.linked');
  
        new File(aDart).writeAsStringSync('var a = 1;');
        new File(bDart).writeAsStringSync('''
  import 'package:aaa/a.dart';
  var b = a;
  ''');
  
        Future<void> buildUnlinked(String uri, String path, String output) async {
          await _doDrive(path, uri: uri, additionalArgs: [
            '--build-summary-only',
            '--build-summary-only-unlinked',
            '--build-summary-output=$output'
          ]);
          expect(exitCode, 0);
          expect(new File(output).existsSync(), isTrue);
        }
  
        await buildUnlinked(aUri, aDart, aUnlinked);
        await buildUnlinked(bUri, bDart, bUnlinked);
  
        await new Driver(isTesting: true).start([
          '--dart-sdk',
          _findSdkDirForSummaries(),
          '--build-mode',
          '--build-summary-unlinked-input=$aUnlinked,$bUnlinked',
          '--build-summary-output=$abLinked'
        ]);
        expect(exitCode, 0);
        var bytes = new File(abLinked).readAsBytesSync();
        var bundle = new PackageBundle.fromBuffer(bytes);
  
        // Only linked information.
        expect(bundle.unlinkedUnitUris, isEmpty);
        expect(bundle.linkedLibraryUris, unorderedEquals([aUri, bUri]));
  
        // Strong mode type inference was performed.
        expect(bundle.linkedLibraries[0].units[0].types, isNotEmpty);
        expect(bundle.linkedLibraries[1].units[0].types, isNotEmpty);
      });
    }
  
    test_buildSuppressExitCode_fail_whenFileNotFound() async {
      await _doDrive(path.join('data', 'non_existent_file.dart'),
          additionalArgs: ['--build-suppress-exit-code']);
      expect(exitCode, isNot(0));
    }
  
    test_buildSuppressExitCode_success_evenIfHasError() async {
      await _doDrive(path.join('data', 'file_with_error.dart'),
          additionalArgs: ['--build-suppress-exit-code']);
      expect(exitCode, 0);
    }
  
    test_buildUnlinked() async {
      await withTempDirAsync((tempDir) async {
        var outputPath = path.join(tempDir, 'test_file.dart.sum');
        await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [
          '--build-summary-only',
          '--build-summary-only-unlinked',
          '--build-summary-output=$outputPath'
        ]);
        var output = new File(outputPath);
        expect(output.existsSync(), isTrue);
        PackageBundle bundle =
            new PackageBundle.fromBuffer(await output.readAsBytes());
        var testFileUri = 'file:///test_file.dart';
        expect(bundle.unlinkedUnits.length, 1);
        expect(bundle.unlinkedUnitUris, equals([testFileUri]));
        expect(bundle.linkedLibraryUris, isEmpty);
        expect(exitCode, 0);
      });
    }
  
    test_consumeLinked() async {
      await withTempDirAsync((tempDir) async {
        var aDart = path.join(tempDir, 'a.dart');
        var bDart = path.join(tempDir, 'b.dart');
        var cDart = path.join(tempDir, 'c.dart');
  
        var aUri = 'package:aaa/a.dart';
        var bUri = 'package:bbb/b.dart';
        var cUri = 'package:ccc/c.dart';
  
        var aSum = path.join(tempDir, 'a.sum');
        var bSum = path.join(tempDir, 'b.sum');
        var cSum = path.join(tempDir, 'c.sum');
  
        new File(aDart).writeAsStringSync('class A {}');
        new File(bDart).writeAsStringSync('''
  export 'package:aaa/a.dart';
  class B {}
  ''');
        new File(cDart).writeAsStringSync('''
  import 'package:bbb/b.dart';
  var a = new A();
  var b = new B();
  ''');
  
        // Analyze package:aaa/a.dart and compute summary.
        {
          await _doDrive(aDart,
              uri: aUri, additionalArgs: ['--build-summary-output=$aSum']);
          expect(exitCode, 0);
          var bytes = new File(aSum).readAsBytesSync();
          var bundle = new PackageBundle.fromBuffer(bytes);
          expect(bundle.unlinkedUnitUris, equals([aUri]));
          expect(bundle.linkedLibraryUris, equals([aUri]));
        }
  
        // Analyze package:bbb/b.dart and compute summary.
        {
          await _doDrive(bDart, uri: bUri, additionalArgs: [
            '--build-summary-input=$aSum',
            '--build-summary-output=$bSum'
          ]);
          expect(exitCode, 0);
          var bytes = new File(bSum).readAsBytesSync();
          var bundle = new PackageBundle.fromBuffer(bytes);
          expect(bundle.unlinkedUnitUris, equals([bUri]));
          expect(bundle.linkedLibraryUris, equals([bUri]));
        }
  
        // Analyze package:ccc/c.dart and compute summary.
        {
          await _doDrive(cDart, uri: cUri, additionalArgs: [
            '--build-summary-input=$aSum,$bSum',
            '--build-summary-output=$cSum'
          ]);
          expect(exitCode, 0);
          var bytes = new File(cSum).readAsBytesSync();
          var bundle = new PackageBundle.fromBuffer(bytes);
          expect(bundle.unlinkedUnitUris, equals([cUri]));
          expect(bundle.linkedLibraryUris, equals([cUri]));
        }
      });
    }
  
    test_dartSdkSummaryPath_strong() async {
      await withTempDirAsync((tempDir) async {
        String sdkPath = _findSdkDirForSummaries();
        String strongSummaryPath =
            path.join(sdkPath, 'lib', '_internal', 'strong.sum');
  
        var testDart = path.join(tempDir, 'test.dart');
        var testSum = path.join(tempDir, 'test.sum');
        new File(testDart).writeAsStringSync('var v = 42;');
  
        await _doDrive(testDart,
            additionalArgs: [
              '--build-summary-only',
              '--build-summary-output=$testSum'
            ],
            dartSdkSummaryPath: strongSummaryPath);
        var output = new File(testSum);
        expect(output.existsSync(), isTrue);
        expect(exitCode, 0);
      });
    }
  
    test_error_linkedAsUnlinked() async {
      await withTempDirAsync((tempDir) async {
        var aDart = path.join(tempDir, 'a.dart');
        var bDart = path.join(tempDir, 'b.dart');
  
        var aUri = 'package:aaa/a.dart';
        var bUri = 'package:bbb/b.dart';
  
        var aSum = path.join(tempDir, 'a.sum');
        var bSum = path.join(tempDir, 'b.sum');
  
        new File(aDart).writeAsStringSync('class A {}');
  
        // Build linked a.sum
        await _doDrive(aDart, uri: aUri, additionalArgs: [
          '--build-summary-only',
          '--build-summary-output=$aSum'
        ]);
        expect(new File(aSum).existsSync(), isTrue);
  
        // Try to consume linked a.sum as unlinked.
        try {
          await _doDrive(bDart, uri: bUri, additionalArgs: [
            '--build-summary-unlinked-input=$aSum',
            '--build-summary-output=$bSum'
          ]);
          fail('ArgumentError expected.');
        } on ArgumentError catch (e) {
          expect(
              e.message,
              contains(
                  'Got a linked summary for --build-summary-input-unlinked'));
        }
      });
    }
  
    test_error_notUriPipePath() async {
      await withTempDirAsync((tempDir) async {
        var testDart = path.join(tempDir, 'test.dart');
        new File(testDart).writeAsStringSync('var v = 42;');
  
        // We pass just path, not "uri|path", this is a fatal error.
        await drive(testDart, args: ['--build-mode', '--format=machine']);
        expect(exitCode, ErrorSeverity.ERROR.ordinal);
      });
    }
  
    test_error_unlinkedAsLinked() async {
      await withTempDirAsync((tempDir) async {
        var aDart = path.join(tempDir, 'a.dart');
        var bDart = path.join(tempDir, 'b.dart');
  
        var aUri = 'package:aaa/a.dart';
        var bUri = 'package:bbb/b.dart';
  
        var aSum = path.join(tempDir, 'a.sum');
        var bSum = path.join(tempDir, 'b.sum');
  
        new File(aDart).writeAsStringSync('class A {}');
  
        // Build unlinked a.sum
        await _doDrive(aDart, uri: aUri, additionalArgs: [
          '--build-summary-only',
          '--build-summary-only-unlinked',
          '--build-summary-output=$aSum'
        ]);
        expect(new File(aSum).existsSync(), isTrue);
  
        // Try to consume unlinked a.sum as linked.
        try {
          await _doDrive(bDart, uri: bUri, additionalArgs: [
            '--build-summary-input=$aSum',
            '--build-summary-output=$bSum'
          ]);
          fail('ArgumentError expected.');
        } on ArgumentError catch (e) {
          expect(e.message,
              contains('Got an unlinked summary for --build-summary-input'));
        }
      });
    }
  
    test_fail_whenHasError() async {
      await _doDrive(path.join('data', 'file_with_error.dart'));
      expect(exitCode, isNot(0));
    }
  
    test_noStatistics() async {
      await _doDrive(path.join('data', 'test_file.dart'));
      // Should not print statistics summary.
      expect(outSink.toString(), isEmpty);
      expect(errorSink.toString(), isEmpty);
      expect(exitCode, 0);
    }
  
    test_onlyErrors_partFirst() async {
      await withTempDirAsync((tempDir) async {
        var aDart = path.join(tempDir, 'a.dart');
        var bDart = path.join(tempDir, 'b.dart');
  
        var aUri = 'package:aaa/a.dart';
        var bUri = 'package:aaa/b.dart';
  
        new File(aDart).writeAsStringSync(r'''
  library lib;
  part 'b.dart';
  class A {}
  ''');
        new File(bDart).writeAsStringSync('''
  part of lib;
  class B {}
  var a = new A();
  var b = new B();
  ''');
  
        // Analyze b.dart (part) and then a.dart (its library).
        // No errors should be reported - the part should know its library.
        await _doDrive(bDart, uri: bUri, additionalArgs: ['$aUri|$aDart']);
        expect(errorSink, isEmpty);
      });
    }
  }
  
  @reflectiveTest
  class ExitCodesTest extends BaseTest {
    test_bazelWorkspace_relativePath() async {
  