// Copyright (c) 2018, 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.

import 'dart:convert' show jsonDecode;
import 'dart:developer' show debugger;
import 'dart:io' show Directory, File;
import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
    show DiagnosticMessage, getMessageCodeObject;
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
import "package:dev_compiler/src/kernel/target.dart" show DevCompilerTarget;
import 'package:expect/expect.dart' show Expect;
import 'package:front_end/src/api_prototype/compiler_options.dart'
    show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
    show ExperimentalFlag;
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
    show IncrementalCompilerResult;
import "package:front_end/src/api_prototype/memory_file_system.dart"
    show MemoryFileSystem, MemoryFileSystemEntity;
import 'package:front_end/src/base/compiler_context.dart' show CompilerContext;
import 'package:front_end/src/base/incremental_compiler.dart'
    show AdvancedInvalidationResult, IncrementalCompiler, RecorderForTesting;
import 'package:front_end/src/base/incremental_serializer.dart'
    show IncrementalSerializer;
import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;
import 'package:front_end/src/codes/cfe_codes.dart'
    show DiagnosticMessageFromJson, FormattedMessage;
import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation, computePlatformDillName;
import 'package:front_end/src/kernel/utils.dart' show ByteSink;
import 'package:kernel/ast.dart';
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart'
    show ClassHierarchy, ClosedWorldClassHierarchy, ForTestingClassInfo;
import 'package:kernel/src/equivalence.dart'
    show
        EquivalenceResult,
        EquivalenceStrategy,
        EquivalenceVisitor,
        checkEquivalence;
import 'package:kernel/target/targets.dart'
    show
        LateLowering,
        NoneTarget,
        Target,
        TargetFlags,
        TestTargetFlags,
        TestTargetWrapper;
import 'package:kernel/text/ast_to_text.dart'
    show NameSystem, Printer, componentToString;
import "package:testing/testing.dart"
    show
        Chain,
        ChainContext,
        Expectation,
        ExpectationSet,
        Result,
        Step,
        TestDescription;
import "package:vm/modular/target/vm.dart" show VmTarget;
import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;

import 'binary_md_dill_reader.dart' show DillComparer;
import 'utils/suite_utils.dart';
import 'testing/environment_keys.dart';
import "incremental_utils.dart" as util;
import 'test_utils.dart';
import 'testing_utils.dart' show checkEnvironment;
import 'utils/io_utils.dart' show computeRepoDir;
import 'utils/symbolic_language_versions.dart';
import 'utils/values.dart';

void main([List<String> arguments = const []]) => internalMain(createContext,
    arguments: arguments,
    displayName: "incremental suite",
    configurationPath: "../testing.json");

/// Top level yaml properties for an incremental test.
class TestProperties {
  /// Value of [type] for selecting a [basicTest].
  static const String type_basic = 'basic';

  /// Value of [type] for selecting a [NewWorldTest].
  static const String type_newworld = 'newworld';

  /// This selects the type of test.
  ///
  /// [type_basic] runs a [basicTest] with additional properties defined in
  /// [BasicTestProperties].
  ///
  /// [type_newworld] runs a [NewWorldTest] with additional properties defined
  /// in [NewWorldTestProperties].
  static const Property<String> type = Property.required(
      'type', StringValue(options: {type_basic, type_newworld}));
}

/// Additional yaml properties for a [basicTest].
// TODO(johnniwinther,jensj): Document all properties.
class BasicTestProperties {
  static const Property<Map<String, String>> sources =
      Property.required('sources', MapValue(StringValue()));

  static const Property<String> entry =
      Property.required('entry', StringValue());

  static const Property<List<String>?> invalidate =
      Property.optional('invalidate', ListValue(StringValue()));
}

/// Additional yaml properties for a [NewWorldTest].
// TODO(johnniwinther,jensj): Document all properties.
class NewWorldTestProperties {
  static const Property<List<World>> worlds =
      Property.required('worlds', ListValue(CustomValue(World.create)));

  static const Property<Map<String, Map<String, String>>?> modules =
      Property.optional('modules', MapValue(MapValue(StringValue())));

  static const Property<bool> omitPlatform =
      Property.optional('omitPlatform', BoolValue(), defaultValue: true);

  static const Property<bool> forceLateLoweringForTesting = Property.optional(
      'forceLateLoweringForTesting', BoolValue(),
      defaultValue: false);

  static const Property<bool> trackWidgetCreation = Property.optional(
      'trackWidgetCreation', BoolValue(),
      defaultValue: false);

  static const Property<bool> incrementalSerialization = Property.optional(
      'incrementalSerialization', BoolValue(),
      defaultValue: false);

  static const String target_none = 'none';
  static const String target_dartdevc = 'dartdevc';
  static const String target_dart2js = 'dart2js';
  static const String target_vm = 'vm';

  static const Property<String?> target = Property.optional(
      'target',
      StringValue(
          options: {target_none, target_dartdevc, target_dart2js, target_vm}));
}

/// Yaml properties for a [World] within a [NewWorldTest].
// TODO(johnniwinther,jensj): Document all properties.
class WorldProperties {
  static const Property<List<String>?> modules =
      Property.optional('modules', ListValue(StringValue()));

  static const String worldType_updated = 'updated';

  static const Property<String?> worldType =
      Property.optional('worldType', StringValue(options: {worldType_updated}));

  static const Property<bool> noFullComponent =
      Property.optional('noFullComponent', BoolValue(), defaultValue: false);

  static const Property<bool?> expectInitializeFromDill =
      Property.optional('expectInitializeFromDill', BoolValue());

  static const Property<Map<String, String>> sources = Property.optional(
      'sources', MapValue(StringValue()),
      defaultValue: const {});

  static const Property<bool> badSdk =
      Property.optional('badSdk', BoolValue(), defaultValue: false);

  static const Property<bool> enableStringReplacement = Property.optional(
      'enableStringReplacement', BoolValue(),
      defaultValue: false);

  static const Property<String?> packageConfigFile =
      Property.optional('packageConfigFile', StringValue());

  static const Property<String?> experiments =
      Property.optional("experiments", StringValue());

  static const Property<List<String>> entry = Property.required(
      'entry', ListValue(StringValue(), supportSingleton: true));

  static const Property<bool> outlineOnly =
      Property.optional("outlineOnly", BoolValue(), defaultValue: false);

  static const Property<bool> skipOutlineBodyCheck = Property.optional(
      "skipOutlineBodyCheck", BoolValue(),
      defaultValue: false);

  static const Property<bool> fromComponent =
      Property.optional("fromComponent", BoolValue(), defaultValue: false);

  static const Property<List<String>?> invalidate =
      Property.optional("invalidate", ListValue(StringValue()));

  static const Property<bool> simulateTransformer = Property.optional(
      "simulateTransformer", BoolValue(),
      defaultValue: false);

  static const Property<bool?> expectInitializationError =
      Property.optional("expectInitializationError", BoolValue());

  static const Property<bool> compareToPrevious =
      Property.optional("compareToPrevious", BoolValue(), defaultValue: false);

  static const Property<List<String>?> uriToSourcesDoesntInclude =
      Property.optional("uriToSourcesDoesntInclude", ListValue(StringValue()));

  static const Property<List<String>?> uriToSourcesOnlyIncludes =
      Property.optional("uriToSourcesOnlyIncludes", ListValue(StringValue()));

  static const Property<bool> skipClassHierarchyTest = Property.optional(
      "skipClassHierarchyTest", BoolValue(),
      defaultValue: false);

  static const Property<bool> expectsPlatform =
      Property.optional("expectsPlatform", BoolValue(), defaultValue: false);

  static const Property<int?> expectedLibraryCount =
      const Property.optional("expectedLibraryCount", IntValue());

  static const Property<int?> expectedSyntheticLibraryCount =
      Property.optional("expectedSyntheticLibraryCount", IntValue());

  /// The expected result of the advanced invalidation.
  ///
  /// If omitted, this defaults to `noDirectlyInvalidated` which corresponds
  /// to the advanced invalidation result of the initial compilation. This means
  /// that all subsequent world entries must specify the expected advanced
  /// invalidation result.
  static const Property<AdvancedInvalidationResult> advancedInvalidation =
      Property.optional(
          "advancedInvalidation", EnumValue(AdvancedInvalidationResult.values),
          defaultValue: AdvancedInvalidationResult.noDirectlyInvalidated);

  static const Property<bool> checkEntries =
      Property.optional("checkEntries", BoolValue(), defaultValue: false);

  static const Property<bool> checkInvalidatedFiles = Property.optional(
      "checkInvalidatedFiles", BoolValue(),
      defaultValue: true);

  static const Property<List<String>?> expectedInvalidatedUri =
      Property.optional('expectedInvalidatedUri', ListValue(StringValue()));

  static const Property<int?> expectSameErrorsAsWorld =
      Property.optional('expectSameErrorsAsWorld', IntValue());

  static const Property<List<ExpressionCompilation>?> expressionCompilation =
      Property.optional(
          'expressionCompilation',
          ListValue(CustomValue(ExpressionCompilation.create),
              supportSingleton: true));

  static const Property<bool> compareWithFromScratch = Property.optional(
      'compareWithFromScratch', BoolValue(),
      defaultValue: false);

  static const Property<bool> brandNewIncrementalSerializationAllowDifferent =
      Property.optional(
          'brandNewIncrementalSerializationAllowDifferent', BoolValue(),
          defaultValue: false);

  /// Whether the compilation of the world is expected to result in warnings.
  static const Property<bool> warnings =
      Property.optional('warnings', BoolValue(), defaultValue: false);

  /// Whether the compilation of the world is expected to result in compile-time
  /// errors.
  static const Property<bool> errors =
      Property.optional('errors', BoolValue(), defaultValue: false);

  static const Property<List<String>?> neededDillLibraries =
      Property.optional('neededDillLibraries', ListValue(StringValue()));

  static const Property<Map<String, List<String>>?> expectedContent =
      Property.optional('expectedContent', MapValue(ListValue(StringValue())));

  static const Property<bool> incrementalSerializationDoesWork =
      Property.optional('incrementalSerializationDoesWork', BoolValue(),
          defaultValue: false);

  static const Property<List<String>?> serializationShouldNotInclude =
      Property.optional(
          'serializationShouldNotInclude', ListValue(StringValue()));

  static const Property<bool> checkConstantCoverageReferences =
      Property.optional('checkConstantCoverageReferences', BoolValue(),
          defaultValue: true);

  /// If `true`, the compilation is allowed to report an error twice.
  static const Property<bool> allowDuplicateErrors = Property.optional(
      'allowDuplicateErrors', BoolValue(),
      defaultValue: false);

  /// If `true`, the compilation is allowed to report a warning twice.
  static const Property<bool> allowDuplicateWarnings = Property.optional(
      'allowDuplicateWarnings', BoolValue(),
      defaultValue: true);

  /// If `true`, the expect files will contain a print of all errors.
  static const Property<bool> printErrorsInExpect = Property.optional(
      'printErrorsInExpect', BoolValue(),
      defaultValue: false);

  /// If `true`, the just compiled world will be "rejected", i.e.
  /// not saved as the latest component and the previous non-rejected compile
  /// (i.e. the one saved in the latest component) will be relinked, mimicking
  /// a reject via the frontend server. At least for now all checking after this
  /// point will be skipped.
  static const Property<bool> reject =
      Property.optional('reject', BoolValue(), defaultValue: false);
}

/// Yaml properties for an [ExpressionCompilation] with a [World].
// TODO(johnniwinther,jensj): Document all properties.
class ExpressionCompilationProperties {
  static const Property<bool> errors =
      Property.optional('errors', BoolValue(), defaultValue: false);

  static const Property<bool> warnings =
      Property.optional('warnings', BoolValue(), defaultValue: false);

  static const Property<String> uri = Property.required('uri', StringValue());

  static const Property<String> expression =
      Property.required('expression', StringValue());

  static const Property<String?> className =
      Property.optional('className', StringValue());
}

final ExpectationSet staticExpectationSet =
    new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));

const String EXPECTATIONS = '''
[
  {
    "name": "ExpectationFileMismatch",
    "group": "Fail"
  },
  {
    "name": "ExpectationFileMissing",
    "group": "Fail"
  },
  {
    "name": "MissingErrors",
    "group": "Fail"
  },
  {
    "name": "UnexpectedErrors",
    "group": "Fail"
  },
  {
    "name": "MissingWarnings",
    "group": "Fail"
  },
  {
    "name": "UnexpectedWarnings",
    "group": "Fail"
  },
  {
    "name": "ClassHierarchyError",
    "group": "Fail"
  },
  {
    "name": "NeededDillMismatch",
    "group": "Fail"
  },
  {
    "name": "IncrementalSerializationError",
    "group": "Fail"
  },
  {
    "name": "ContentDataMismatch",
    "group": "Fail"
  },
  {
    "name": "MissingInitializationError",
    "group": "Fail"
  },
  {
    "name": "UnexpectedInitializationError",
    "group": "Fail"
  },
  {
    "name": "ReachableLibrariesError",
    "group": "Fail"
  },
  {
    "name": "EquivalenceError",
    "group": "Fail"
  },
  {
    "name": "UriToSourceError",
    "group": "Fail"
  },
  {
    "name": "MissingPlatformLibraries",
    "group": "Fail"
  },
  {
    "name": "UnexpectedPlatformLibraries",
    "group": "Fail"
  },
  {
    "name": "UnexpectedAdvancedInvalidation",
    "group": "Fail"
  },
  {
    "name": "UnexpectedEntryToLibraryCount",
    "group": "Fail"
  },
  {
    "name": "LibraryCountMismatch",
    "group": "Fail"
  },
  {
    "name": "InitializedFromDillMismatch",
    "group": "Fail"
  },
  {
    "name": "ConstantCoverageReferenceWithoutNode",
    "group": "Fail"
  }
]
''';

final Expectation ExpectationFileMismatch =
    staticExpectationSet["ExpectationFileMismatch"];
final Expectation ExpectationFileMissing =
    staticExpectationSet["ExpectationFileMissing"];
final Expectation MissingErrors = staticExpectationSet["MissingErrors"];
final Expectation UnexpectedErrors = staticExpectationSet["UnexpectedErrors"];
final Expectation MissingWarnings = staticExpectationSet["MissingWarnings"];
final Expectation UnexpectedWarnings =
    staticExpectationSet["UnexpectedWarnings"];
final Expectation ClassHierarchyError =
    staticExpectationSet["ClassHierarchyError"];
final Expectation NeededDillMismatch =
    staticExpectationSet["NeededDillMismatch"];
final Expectation IncrementalSerializationError =
    staticExpectationSet["IncrementalSerializationError"];
final Expectation ContentDataMismatch =
    staticExpectationSet["ContentDataMismatch"];
final Expectation MissingInitializationError =
    staticExpectationSet["MissingInitializationError"];
final Expectation UnexpectedInitializationError =
    staticExpectationSet["UnexpectedInitializationError"];
final Expectation ReachableLibrariesError =
    staticExpectationSet["ReachableLibrariesError"];
final Expectation EquivalenceError = staticExpectationSet["EquivalenceError"];
final Expectation UriToSourceError = staticExpectationSet["UriToSourceError"];
final Expectation MissingPlatformLibraries =
    staticExpectationSet["MissingPlatformLibraries"];
final Expectation UnexpectedPlatformLibraries =
    staticExpectationSet["UnexpectedPlatformLibraries"];
final Expectation UnexpectedAdvancedInvalidation =
    staticExpectationSet["UnexpectedAdvancedInvalidation"];
final Expectation UnexpectedEntryToLibraryCount =
    staticExpectationSet["UnexpectedEntryToLibraryCount"];
final Expectation LibraryCountMismatch =
    staticExpectationSet["LibraryCountMismatch"];
final Expectation InitializedFromDillMismatch =
    staticExpectationSet["InitializedFromDillMismatch"];
final Expectation ConstantCoverageReferenceWithoutNode =
    staticExpectationSet["ConstantCoverageReferenceWithoutNode"];

Future<Context> createContext(Chain suite, Map<String, String> environment) {
  const Set<String> knownEnvironmentKeys = {
    EnvironmentKeys.updateExpectations,
    EnvironmentKeys.addDebugBreaks,
    EnvironmentKeys.skipTests,
  };
  checkEnvironment(environment, knownEnvironmentKeys);

  // Disable colors to ensure that expectation files are the same across
  // platforms and independent of stdin/stderr.
  colors.enableColors = false;
  Set<String> skipTests =
      environment[EnvironmentKeys.skipTests]?.split(",").toSet() ?? {};
  return new Future.value(new Context(
    environment[EnvironmentKeys.updateExpectations] == "true",
    environment[EnvironmentKeys.addDebugBreaks] == "true",
    skipTests,
  ));
}

class Context extends ChainContext {
  @override
  final List<Step> steps = const <Step>[
    const ReadTest(),
    const RunCompilations(),
  ];

  final bool updateExpectations;

  /// Add a debug break (via dart:developers `debugger()` call) after each
  /// iteration (or 'world run') when doing a "new world test".
  final bool breakBetween;

  final Set<String> skipTests;

  Context(this.updateExpectations, this.breakBetween, this.skipTests);

  @override
  Future<List<TestDescription>> list(Chain suite) async {
    if (skipTests.isEmpty) return await super.list(suite);
    return filterSkipped(await super.list(suite));
  }

  List<TestDescription> filterSkipped(List<TestDescription> all) {
    List<TestDescription> result = [];
    for (TestDescription testDescription in all) {
      if (!skipTests.contains(testDescription.shortName)) {
        result.add(testDescription);
      }
    }
    return result;
  }

  @override
  Future<void> cleanUp(TestDescription description, Result result) async {
    await cleanupHelper?.outDir?.delete(recursive: true);
    cleanupHelper?.outDir = null;
  }

  @override
  final ExpectationSet expectationSet = staticExpectationSet;

  TestData? cleanupHelper;
}

class TestData {
  YamlMap map;
  Directory? outDir;
  Uri loadedFrom;

  TestData(this.map, this.outDir, this.loadedFrom);
}

class ReadTest extends Step<TestDescription, TestData, Context> {
  const ReadTest();

  @override
  String get name => "read test";

  @override
  Future<Result<TestData>> run(
      TestDescription description, Context context) async {
    Uri uri = description.uri;
    String contents = await new File.fromUri(uri).readAsString();
    TestData data = new TestData(
        loadYamlNode(contents, sourceUrl: uri) as YamlMap,
        Directory.systemTemp.createTempSync("incremental_load_from_dill_test"),
        uri);
    context.cleanupHelper = data;
    return pass(data);
  }
}

class RunCompilations extends Step<TestData, TestData, Context> {
  const RunCompilations();

  @override
  String get name => "run compilations";

  @override
  Future<Result<TestData>> run(TestData data, Context context) async {
    Result<TestData>? result;
    YamlMap map = data.map;
    Set<String> keys = new Set<String>.from(map.keys.cast<String>());
    String type = TestProperties.type.read(map, keys);
    switch (type) {
      case TestProperties.type_basic:
        await basicTest(
          BasicTestProperties.sources.read(map, keys),
          BasicTestProperties.entry.read(map, keys),
          BasicTestProperties.invalidate.read(map, keys),
          data.outDir!,
        );
        break;
      case TestProperties.type_newworld:
        result = await new NewWorldTest(
          data: data,
          context: context,
          worlds: NewWorldTestProperties.worlds.read(map, keys),
          omitPlatform: NewWorldTestProperties.omitPlatform.read(map, keys),
          forceLateLoweringForTesting: NewWorldTestProperties
              .forceLateLoweringForTesting
              .read(map, keys),
          trackWidgetCreation:
              NewWorldTestProperties.trackWidgetCreation.read(map, keys),
          incrementalSerialization:
              NewWorldTestProperties.incrementalSerialization.read(map, keys),
          modules: NewWorldTestProperties.modules.read(map, keys),
          targetName: NewWorldTestProperties.target.read(map, keys),
        ).newWorldTest();
        break;
      default:
        throw "Unexpected type: ${type}";
    }

    if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys";
    return result ?? pass(data);
  }
}

Future<Null> basicTest(Map<String, String> sourceFiles, String entryPoint,
    List<String>? invalidate, Directory outDir) async {
  Uri entryPointUri = outDir.uri.resolve(entryPoint);
  Set<String> invalidateFilenames =
      invalidate == null ? new Set<String>() : new Set<String>.from(invalidate);
  List<Uri> invalidateUris = <Uri>[];
  Uri? packagesUri;
  for (String filename in sourceFiles.keys) {
    Uri uri = outDir.uri.resolve(filename);
    if (invalidateFilenames.contains(filename)) {
      invalidateUris.add(uri);
      invalidateFilenames.remove(filename);
    }
    String source = sourceFiles[filename]!;
    if (filename == ".dart_tool/package_config.json") {
      packagesUri = uri;
    }
    File file = new File.fromUri(uri);
    await file.parent.create(recursive: true);
    await file.writeAsString(source);
  }
  for (String invalidateFilename in invalidateFilenames) {
    if (invalidateFilename.startsWith('package:')) {
      invalidateUris.add(Uri.parse(invalidateFilename));
    } else {
      throw "Error in test yaml: $invalidateFilename was not recognized.";
    }
  }

  Uri output = outDir.uri.resolve("full.dill");
  Uri initializedOutput = outDir.uri.resolve("full_from_initialized.dill");

  Stopwatch stopwatch = new Stopwatch()..start();
  CompilerOptions options = getOptions();
  if (packagesUri != null) {
    options.packagesFileUri = packagesUri;
  }
  await normalCompile(entryPointUri, output, options: options);
  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");

  stopwatch.reset();
  options = getOptions();
  if (packagesUri != null) {
    options.packagesFileUri = packagesUri;
  }
  bool initializedResult = await initializedCompile(
      entryPointUri, initializedOutput, output, invalidateUris,
      options: options);
  print("Initialized compile(s) from ${output.pathSegments.last} "
      "took ${stopwatch.elapsedMilliseconds} ms");
  Expect.isTrue(initializedResult);

  // Compare the two files.
  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
  List<int> initializedDillData =
      new File.fromUri(initializedOutput).readAsBytesSync();
  checkIsEqual(normalDillData, initializedDillData);
}

Future<Map<String, Uint8List>> createModules(
    Map<String, Map<String, String>> module,
    final List<int> sdkSummaryData,
    Target target,
    Target originalTarget,
    String sdkSummary,
    {required bool trackNeededDillLibraries,
    required Uri checkoutRoot}) async {
  final Uri base = Uri.parse("org-dartlang-test:///");
  final Uri sdkSummaryUri = base.resolve(sdkSummary);

  TestMemoryFileSystem fs =
      new TestMemoryFileSystem(base, holePunchBase: checkoutRoot);
  fs.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);

  // Setup all sources
  for (Map<String, String> moduleSources in module.values) {
    for (String filename in moduleSources.keys) {
      String data = moduleSources[filename]!;
      Uri uri = base.resolve(filename);
      if (await fs.entityForUri(uri).exists()) {
        throw "More than one entry for $filename";
      }
      fs.entityForUri(uri).writeAsStringSync(data);
    }
  }

  Map<String, Uint8List> moduleResult = {};

  for (String moduleName in module.keys) {
    List<Uri> moduleSources = <Uri>[];
    Uri? packagesUri;
    for (String filename in module[moduleName]!.keys) {
      Uri uri = base.resolve(filename);
      if (uri.pathSegments.last == "package_config.json") {
        packagesUri = uri;
      } else {
        moduleSources.add(uri);
      }
    }
    bool outlineOnly = false;
    if (originalTarget is DevCompilerTarget) {
      outlineOnly = true;
    }
    CompilerOptions options =
        getOptions(target: target, sdkSummary: sdkSummary);
    options.fileSystem = fs;
    options.sdkRoot = null;
    options.sdkSummary = sdkSummaryUri;
    options.omitPlatform = true;
    options.onDiagnostic = (DiagnosticMessage message) {
      throw message.ansiFormatted;
    };
    if (packagesUri != null) {
      options.packagesFileUri = packagesUri;
    }
    TestIncrementalCompiler compiler = new TestIncrementalCompiler(
        options, moduleSources.first, /* initializeFrom = */ null, outlineOnly);
    IncrementalCompilerResult? compilerResult = await compiler.computeDelta(
        entryPoints: moduleSources,
        trackNeededDillLibraries: trackNeededDillLibraries);
    Component c = compilerResult.component;
    compilerResult = null;
    c.computeCanonicalNames();
    List<Library> wantedLibs = <Library>[];
    for (Library lib in c.libraries) {
      if (moduleSources.contains(lib.importUri) ||
          moduleSources.contains(lib.fileUri)) {
        wantedLibs.add(lib);
      }
    }
    if (wantedLibs.length != moduleSources.length) {
      throw "Module probably not setup right.";
    }
    Component result = new Component(libraries: wantedLibs)
      ..setMainMethodAndMode(null, false);
    Uint8List resultBytes = util.postProcess(result);
    moduleResult[moduleName] = resultBytes;
  }

  return moduleResult;
}

class ExpressionCompilation {
  final bool errors;
  final bool warnings;
  final String uri;
  final String expression;
  final String? className;

  ExpressionCompilation(
      {required this.errors,
      required this.warnings,
      required this.uri,
      required this.expression,
      required this.className});

  static ExpressionCompilation create(Map yaml) {
    Set<String> keys = new Set<String>.from(yaml.keys);

    bool errors = ExpressionCompilationProperties.errors.read(yaml, keys);
    bool warnings = ExpressionCompilationProperties.warnings.read(yaml, keys);
    String uri = ExpressionCompilationProperties.uri.read(yaml, keys);
    String expression =
        ExpressionCompilationProperties.expression.read(yaml, keys);
    String? className =
        ExpressionCompilationProperties.className.read(yaml, keys);

    if (keys.isNotEmpty) {
      throw "Unknown key(s) for ExpressionCompilation: $keys";
    }
    return new ExpressionCompilation(
        errors: errors,
        warnings: warnings,
        uri: uri,
        expression: expression,
        className: className);
  }
}

class World {
  final List<String>? modules;
  final bool updateWorldType;
  final bool noFullComponent;
  final bool? expectInitializeFromDill;
  final Map<String, String?> sources;
  final bool useBadSdk;
  final bool enableStringReplacement;
  final String? packageConfigFile;
  final String? experiments;
  final List<String> entries;
  final bool outlineOnly;
  final bool skipOutlineBodyCheck;
  final bool fromComponent;
  final List<String>? invalidate;
  final bool simulateTransformer;
  final bool? expectInitializationError;
  final bool compareToPrevious;
  final List<String>? uriToSourcesDoesntInclude;
  final List<String>? uriToSourcesOnlyIncludes;
  final bool skipClassHierarchyTest;
  final bool expectsPlatform;
  final int? expectedLibraryCount;
  final int? expectedSyntheticLibraryCount;
  final bool warnings;
  final bool errors;
  final List<String>? neededDillLibraries;
  final Map<String, List<String>>? expectedContent;
  final bool incrementalSerializationDoesWork;
  final bool allowDuplicateErrors;
  final bool allowDuplicateWarnings;
  final bool printErrorsInExpect;
  final bool reject;

  /// The expected result of the advanced invalidation.
  final AdvancedInvalidationResult advancedInvalidation;

  final bool checkEntries;
  final bool checkInvalidatedFiles;
  final List<String>? expectedInvalidatedUri;
  final int? expectSameErrorsAsWorld;
  final List<ExpressionCompilation>? expressionCompilation;
  final bool compareWithFromScratch;

  /// Don't check for equality when we allow it to be different
  /// (e.g. when the old one contains more, and the new one doesn't).
  final bool brandNewIncrementalSerializationAllowDifferent;

  final List<String>? serializationShouldNotInclude;

  /// Whether to check if the serialized constant coverage references
  /// points to anything in itself.
  final bool checkConstantCoverageReferences;

  World({
    required this.modules,
    required this.updateWorldType,
    required this.noFullComponent,
    required this.expectInitializeFromDill,
    required this.sources,
    required this.useBadSdk,
    required this.enableStringReplacement,
    required this.packageConfigFile,
    required this.experiments,
    required this.entries,
    required this.outlineOnly,
    required this.skipOutlineBodyCheck,
    required this.fromComponent,
    required this.invalidate,
    required this.simulateTransformer,
    required this.expectInitializationError,
    required this.compareToPrevious,
    required this.uriToSourcesDoesntInclude,
    required this.uriToSourcesOnlyIncludes,
    required this.skipClassHierarchyTest,
    required this.expectsPlatform,
    required this.expectedLibraryCount,
    required this.expectedSyntheticLibraryCount,
    required this.advancedInvalidation,
    required this.checkEntries,
    required this.checkInvalidatedFiles,
    required this.expectedInvalidatedUri,
    required this.expectSameErrorsAsWorld,
    required this.expressionCompilation,
    required this.compareWithFromScratch,
    required this.brandNewIncrementalSerializationAllowDifferent,
    required this.warnings,
    required this.errors,
    required this.neededDillLibraries,
    required this.expectedContent,
    required this.incrementalSerializationDoesWork,
    required this.serializationShouldNotInclude,
    required this.checkConstantCoverageReferences,
    required this.allowDuplicateErrors,
    required this.allowDuplicateWarnings,
    required this.printErrorsInExpect,
    required this.reject,
  });

  static World create(Map world) {
    Set<String> keys = new Set<String>.from(world.keys);

    List<String>? modules = WorldProperties.modules.read(world, keys);

    String? worldType = WorldProperties.worldType.read(world, keys);
    bool updateWorldType = worldType == WorldProperties.worldType_updated;

    bool noFullComponent = WorldProperties.noFullComponent.read(world, keys);

    bool? expectInitializeFromDill =
        WorldProperties.expectInitializeFromDill.read(world, keys);

    Map<String, String?> sources = WorldProperties.sources.read(world, keys);

    bool useBadSdk = WorldProperties.badSdk.read(world, keys);

    bool enableStringReplacement =
        WorldProperties.enableStringReplacement.read(world, keys);

    String? packageConfigFile =
        WorldProperties.packageConfigFile.read(world, keys);

    String? experiments = WorldProperties.experiments.read(world, keys);

    List<String> entries = WorldProperties.entry.read(world, keys);

    bool outlineOnly = WorldProperties.outlineOnly.read(world, keys);

    bool skipOutlineBodyCheck =
        WorldProperties.skipOutlineBodyCheck.read(world, keys);

    bool fromComponent = WorldProperties.fromComponent.read(world, keys);

    List<String>? invalidate = WorldProperties.invalidate.read(world, keys);

    bool simulateTransformer =
        WorldProperties.simulateTransformer.read(world, keys);

    bool? expectInitializationError =
        WorldProperties.expectInitializationError.read(world, keys);

    bool compareToPrevious =
        WorldProperties.compareToPrevious.read(world, keys);

    List<String>? uriToSourcesDoesntInclude =
        WorldProperties.uriToSourcesDoesntInclude.read(world, keys);

    List<String>? uriToSourcesOnlyIncludes =
        WorldProperties.uriToSourcesOnlyIncludes.read(world, keys);

    bool skipClassHierarchyTest =
        WorldProperties.skipClassHierarchyTest.read(world, keys);

    bool expectsPlatform = WorldProperties.expectsPlatform.read(world, keys);

    int? expectedLibraryCount =
        WorldProperties.expectedLibraryCount.read(world, keys);

    int? expectedSyntheticLibraryCount =
        WorldProperties.expectedSyntheticLibraryCount.read(world, keys);

    AdvancedInvalidationResult advancedInvalidation =
        WorldProperties.advancedInvalidation.read(world, keys);

    bool checkEntries = WorldProperties.checkEntries.read(world, keys);

    bool checkInvalidatedFiles =
        WorldProperties.checkInvalidatedFiles.read(world, keys);

    List<String>? expectedInvalidatedUri =
        WorldProperties.expectedInvalidatedUri.read(world, keys);

    int? expectSameErrorsAsWorld =
        WorldProperties.expectSameErrorsAsWorld.read(world, keys);

    List<ExpressionCompilation>? expressionCompilation =
        WorldProperties.expressionCompilation.read(world, keys);

    bool compareWithFromScratch =
        WorldProperties.compareWithFromScratch.read(world, keys);

    bool brandNewIncrementalSerializationAllowDifferent = WorldProperties
        .brandNewIncrementalSerializationAllowDifferent
        .read(world, keys);

    bool warnings = WorldProperties.warnings.read(world, keys);

    bool errors = WorldProperties.errors.read(world, keys);

    List<String>? neededDillLibraries =
        WorldProperties.neededDillLibraries.read(world, keys);

    Map<String, List<String>>? expectedContent =
        WorldProperties.expectedContent.read(world, keys);

    bool incrementalSerializationDoesWork =
        WorldProperties.incrementalSerializationDoesWork.read(world, keys);

    List<String>? serializationShouldNotInclude =
        WorldProperties.serializationShouldNotInclude.read(world, keys);

    bool checkConstantCoverageReferences =
        WorldProperties.checkConstantCoverageReferences.read(world, keys);

    bool allowDuplicateErrors =
        WorldProperties.allowDuplicateErrors.read(world, keys);

    bool allowDuplicateWarnings =
        WorldProperties.allowDuplicateWarnings.read(world, keys);

    bool printErrorsInExpect =
        WorldProperties.printErrorsInExpect.read(world, keys);

    bool reject = WorldProperties.reject.read(world, keys);

    if (keys.isNotEmpty) {
      throw "Unknown key(s) for World: $keys";
    }

    return new World(
      modules: modules,
      updateWorldType: updateWorldType,
      noFullComponent: noFullComponent,
      expectInitializeFromDill: expectInitializeFromDill,
      sources: sources,
      useBadSdk: useBadSdk,
      enableStringReplacement: enableStringReplacement,
      packageConfigFile: packageConfigFile,
      experiments: experiments,
      entries: entries,
      outlineOnly: outlineOnly,
      skipOutlineBodyCheck: skipOutlineBodyCheck,
      fromComponent: fromComponent,
      invalidate: invalidate,
      simulateTransformer: simulateTransformer,
      expectInitializationError: expectInitializationError,
      compareToPrevious: compareToPrevious,
      uriToSourcesDoesntInclude: uriToSourcesDoesntInclude,
      uriToSourcesOnlyIncludes: uriToSourcesOnlyIncludes,
      skipClassHierarchyTest: skipClassHierarchyTest,
      expectsPlatform: expectsPlatform,
      expectedLibraryCount: expectedLibraryCount,
      expectedSyntheticLibraryCount: expectedSyntheticLibraryCount,
      advancedInvalidation: advancedInvalidation,
      checkEntries: checkEntries,
      checkInvalidatedFiles: checkInvalidatedFiles,
      expectedInvalidatedUri: expectedInvalidatedUri,
      expectSameErrorsAsWorld: expectSameErrorsAsWorld,
      expressionCompilation: expressionCompilation,
      compareWithFromScratch: compareWithFromScratch,
      brandNewIncrementalSerializationAllowDifferent:
          brandNewIncrementalSerializationAllowDifferent,
      warnings: warnings,
      errors: errors,
      neededDillLibraries: neededDillLibraries,
      expectedContent: expectedContent,
      incrementalSerializationDoesWork: incrementalSerializationDoesWork,
      serializationShouldNotInclude: serializationShouldNotInclude,
      checkConstantCoverageReferences: checkConstantCoverageReferences,
      allowDuplicateErrors: allowDuplicateErrors,
      allowDuplicateWarnings: allowDuplicateWarnings,
      printErrorsInExpect: printErrorsInExpect,
      reject: reject,
    );
  }
}

class NewWorldTest {
  final TestData data;
  final Context context;
  final List<World> worlds;
  final Map<String, Map<String, String>>? modules;
  final bool omitPlatform;
  final bool forceLateLoweringForTesting;
  final bool trackWidgetCreation;
  final bool incrementalSerialization;
  final String? targetName;

  // These are fields in a class to make it easier to track down memory leaks
  // via the leak detector test.
  Component? newestWholeComponent;
  Component? sdk;
  Component? component;
  Component? component2;
  Component? component3;

  NewWorldTest({
    required this.data,
    required this.context,
    required this.worlds,
    required this.modules,
    required this.omitPlatform,
    required this.forceLateLoweringForTesting,
    required this.trackWidgetCreation,
    required this.incrementalSerialization,
    required this.targetName,
  });

  Future<Result<TestData>> newWorldTest() async {
    final Uri platformBinariesRoot =
        computePlatformBinariesLocation(forceBuildDir: true);

    // This is somewhat of a hack but will do for now.
    final Uri checkoutRoot = data.loadedFrom.resolve("../../../../");

    TestTargetFlags targetFlags = new TestTargetFlags(
        forceLateLoweringsForTesting:
            forceLateLoweringForTesting ? LateLowering.all : null,
        trackWidgetCreation: trackWidgetCreation);
    Target target = new VmTarget(targetFlags);
    if (targetName != null) {
      if (targetName == NewWorldTestProperties.target_none) {
        target = new NoneTarget(targetFlags);
      } else if (targetName == NewWorldTestProperties.target_dartdevc) {
        target = new DevCompilerTarget(targetFlags);
      } else if (targetName == NewWorldTestProperties.target_dart2js) {
        target = new Dart2jsTarget("dart2js", targetFlags);
      } else if (targetName == NewWorldTestProperties.target_vm) {
        // default.
      } else {
        throw "Unknown target name '$targetName'";
      }
    }
    Target originalTarget = target;
    target = new TestTargetWrapper(target, targetFlags);

    String sdkSummary = computePlatformDillName(
        target,
        () => throw new UnsupportedError(
            "No platform dill for target '${targetName}'."))!;

    final Uri base = Uri.parse("org-dartlang-test:///");
    final Uri sdkSummaryUri = base.resolve(sdkSummary);
    final Uri initializeFrom = base.resolve("initializeFrom.dill");
    Uri platformUri = platformBinariesRoot.resolve(sdkSummary);
    final Uint8List sdkSummaryData =
        await new File.fromUri(platformUri).readAsBytes();

    Uint8List? newestWholeComponentData;
    TestMemoryFileSystem? fs;
    Map<String, String?>? sourceFiles;
    CompilerOptions? options;
    TestIncrementalCompiler? compiler;
    IncrementalSerializer? incrementalSerializer;

    Map<String, Uint8List>? moduleData;
    Map<String, Component>? moduleComponents;

    if (modules != null) {
      moduleData = await createModules(
          modules!, sdkSummaryData, target, originalTarget, sdkSummary,
          checkoutRoot: checkoutRoot, trackNeededDillLibraries: false);
      sdk = newestWholeComponent = new Component();
      new BinaryBuilder(sdkSummaryData,
              filename: null, disableLazyReading: false)
          .readComponent(newestWholeComponent!);
    }

    int worldNum = 0;
    // TODO: When needed, we can do this for warnings too.
    List<Set<String>> worldErrors = [];
    for (World world in worlds) {
      worldNum++;
      print("----------------");
      print("World #$worldNum");
      print("----------------");
      List<Component>? modulesToUse;
      if (world.modules != null) {
        moduleComponents ??= new Map<String, Component>();

        sdk!.adoptChildren();
        for (Component c in moduleComponents.values) {
          c.adoptChildren();
        }

        modulesToUse = <Component>[];
        for (String moduleName in world.modules!) {
          Component? moduleComponent = moduleComponents[moduleName];
          if (moduleComponent != null) {
            modulesToUse.add(moduleComponent);
          }
        }
        for (String moduleName in world.modules!) {
          Component? moduleComponent = moduleComponents[moduleName];
          if (moduleComponent == null) {
            moduleComponent = new Component(nameRoot: sdk!.root);
            new BinaryBuilder(moduleData![moduleName]!,
                    filename: null,
                    disableLazyReading: false,
                    alwaysCreateNewNamedNodes: true)
                .readComponent(moduleComponent);
            moduleComponents[moduleName] = moduleComponent;
            modulesToUse.add(moduleComponent);
          }
        }
      }

      if (!world.updateWorldType) {
        fs = new TestMemoryFileSystem(base, holePunchBase: checkoutRoot);
      }
      fs!.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);
      bool expectInitializeFromDill = false;
      if (newestWholeComponentData != null &&
          newestWholeComponentData.isNotEmpty) {
        fs
            .entityForUri(initializeFrom)
            .writeAsBytesSync(newestWholeComponentData);
        expectInitializeFromDill = true;
      }
      if (world.expectInitializeFromDill != null) {
        expectInitializeFromDill = world.expectInitializeFromDill!;
      }
      if (!world.updateWorldType) {
        sourceFiles = new Map<String, String?>.from(world.sources);
      } else {
        sourceFiles!.addAll(new Map<String, String?>.from(world.sources));
      }
      Uri? packagesUri;
      for (String filename in sourceFiles.keys) {
        String data = sourceFiles[filename] ?? "";
        Uri uri = base.resolve(filename);
        if (filename == ".dart_tool/package_config.json") {
          packagesUri = uri;
        }
        if (world.enableStringReplacement) {
          data = replaceMarkersWithVersions(data);
        }
        fs.entityForUri(uri).writeAsStringSync(data);
      }
      if (world.packageConfigFile != null) {
        packagesUri = base.resolve(world.packageConfigFile!);
      }

      if (!world.updateWorldType) {
        options = getOptions(target: target, sdkSummary: sdkSummary);
        options.fileSystem = fs;
        options.sdkRoot = null;
        options.sdkSummary = sdkSummaryUri;
        if (world.useBadSdk) {
          options.sdkSummary = sdkSummaryUri.resolve("nonexisting.dill");
        }
        options.omitPlatform = omitPlatform;
        if (world.experiments != null) {
          Map<String, bool> flagsFromOptions =
              parseExperimentalArguments([world.experiments!]);
          // Ensure that we run with non-nullable turned off even when the
          // flag is on by default.
          Map<ExperimentalFlag, bool> explicitExperimentalFlags =
              parseExperimentalFlags(flagsFromOptions,
                  onError: (e) =>
                      throw "Error on parsing experiments flags: $e");
          options.explicitExperimentalFlags = explicitExperimentalFlags;
        } else {
          options.explicitExperimentalFlags = {};
        }
      }
      if (packagesUri != null) {
        options!.packagesFileUri = packagesUri;
      }
      bool gotError = false;
      final Set<String> formattedErrors = Set<String>();
      bool gotWarning = false;
      final Set<String> formattedWarnings = Set<String>();
      final Set<String> seenDiagnosticCodes = Set<String>();

      options!.onDiagnostic = (DiagnosticMessage message) {
        String? code = getMessageCodeObject(message)?.name;
        if (code != null) seenDiagnosticCodes.add(code);

        String stringId = message.ansiFormatted.join("\n");
        if (message is FormattedMessage) {
          stringId = message.toJsonString();
        } else if (message is DiagnosticMessageFromJson) {
          stringId = message.toJsonString();
        }
        if (message.severity == Severity.error) {
          gotError = true;
          if (!formattedErrors.add(stringId) && !world.allowDuplicateErrors) {
            Expect.fail("Got the same message twice: ${stringId}");
          }
        } else if (message.severity == Severity.warning) {
          gotWarning = true;
          if (!formattedWarnings.add(stringId) &&
              !world.allowDuplicateWarnings) {
            Expect.fail("Got the same message twice: ${stringId}");
          }
        }
      };

      List<Uri> entries = world.entries.map((e) => base.resolve(e)).toList();
      if (!world.updateWorldType) {
        if (incrementalSerialization == true) {
          incrementalSerializer = new IncrementalSerializer();
        }
        if (world.fromComponent) {
          compiler = new TestIncrementalCompiler.fromComponent(
              options,
              entries.first,
              (modulesToUse != null) ? sdk : newestWholeComponent,
              world.outlineOnly,
              incrementalSerializer);
        } else {
          compiler = new TestIncrementalCompiler(options, entries.first,
              initializeFrom, world.outlineOnly, incrementalSerializer);

          if (modulesToUse != null) {
            throw "You probably shouldn't do this! "
                "Any modules will have another sdk loaded!";
          }
        }
      }

      List<Uri> invalidated = <Uri>[];
      if (world.invalidate != null) {
        for (String filename in world.invalidate!) {
          Uri uri = base.resolve(filename);
          invalidated.add(uri);
          compiler!.invalidate(uri);
        }
      }

      if (modulesToUse != null) {
        compiler!.setModulesToLoadOnNextComputeDelta(modulesToUse);
        compiler.invalidateAllSources();
      }

      Stopwatch stopwatch = new Stopwatch()..start();
      IncrementalCompilerResult? compilerResult = await compiler!.computeDelta(
          entryPoints: entries,
          fullComponent: !world.updateWorldType
              ? false
              : (world.noFullComponent ? false : true),
          trackNeededDillLibraries: modulesToUse != null,
          simulateTransformer: world.simulateTransformer);
      component = compilerResult.component;
      // compilerResult is null'ed out at the end to avoid any
      // "artificial memory leak" on that account.
      if (world.outlineOnly && !world.skipOutlineBodyCheck) {
        for (Library lib in component!.libraries) {
          for (Class c in lib.classes) {
            for (Procedure p in c.procedures) {
              if (p.function.body != null &&
                  p.function.body is! EmptyStatement) {
                throw "Got body (${p.function.body.runtimeType})";
              }
            }
          }
          for (Procedure p in lib.procedures) {
            if (p.function.body != null && p.function.body is! EmptyStatement) {
              throw "Got body (${p.function.body.runtimeType})";
            }
          }
        }
      }
      Result<TestData>? result = performErrorAndWarningCheck(world, data,
          gotError, formattedErrors, gotWarning, formattedWarnings);
      if (result != null) return result;
      bool? expectInitializationError = world.expectInitializationError;
      if (expectInitializationError != null) {
        Set<String> seenInitializationError = seenDiagnosticCodes.intersection({
          "InitializeFromDillNotSelfContainedNoDump",
          "InitializeFromDillNotSelfContained",
          "InitializeFromDillUnknownProblem",
          "InitializeFromDillUnknownProblemNoDump",
        });
        if (expectInitializationError) {
          if (seenInitializationError.isEmpty) {
            return new Result<TestData>(data, MissingInitializationError,
                "Expected to see an initialization error but didn't.");
          }
        } else {
          if (seenInitializationError.isNotEmpty) {
            return new Result<TestData>(
                data,
                UnexpectedInitializationError,
                "Expected not to see an initialization error but did: "
                "$seenInitializationError.");
          }
        }
      }
      util.throwOnEmptyMixinBodies(component!);
      await util.throwOnInsufficientUriToSource(component!,
          fileSystem: gotError ? null : fs);
      print("Compile took ${stopwatch.elapsedMilliseconds} ms");

      Result? contentResult = checkExpectedContent(world, component!);
      if (contentResult != null) return contentResult.copyWithOutput(data);
      result = checkNeededDillLibraries(
          world, data, compilerResult.neededDillLibraries, base);
      if (result != null) return result;

      if (!world.noFullComponent) {
        Set<Library> allLibraries = new Set<Library>();
        for (Library lib in component!.libraries) {
          computeAllReachableLibrariesFor(lib, allLibraries);
        }
        if (allLibraries.length != component!.libraries.length) {
          return new Result<TestData>(
              data,
              ReachableLibrariesError,
              "Expected for the reachable stuff to be equal to "
              "${component!.libraries} but it was $allLibraries");
        }
        Set<Library> tooMany = allLibraries.toSet()
          ..removeAll(component!.libraries);
        if (tooMany.isNotEmpty) {
          return new Result<TestData>(
              data,
              ReachableLibrariesError,
              "Expected for the reachable stuff to be equal to "
              "${component!.libraries} but these were there too: $tooMany "
              "(and others were missing)");
        }
      }

      util.postProcessComponent(component!);
      String actualSerialized = componentToStringSdkFiltered(component!,
          printErrors: world.printErrorsInExpect ? formattedErrors : null);
      print("*****\n\ncomponent:\n"
          "${actualSerialized}\n\n\n");
      result = checkExpectFile(data, worldNum, "", context, actualSerialized);
      if (result != null) return result;

      if (world.compareToPrevious && newestWholeComponent != null) {
        EquivalenceResult result = checkEquivalence(
            newestWholeComponent!, component!,
            strategy: const Strategy());
        if (!result.isEquivalent) {
          return new Result<TestData>(
              data, EquivalenceError, result.toString());
        }
      }

      if (world.reject) {
        util.postProcess(component!);

        // Reject: We keep the original "newest whole component" and also
        // reject/relink it.
        // This mimics what happens when e.g. flutter "reject"s a compile.
        newestWholeComponent?.relink();

        // Add errors or assert will trigger in later worlds.
        worldErrors.add(formattedErrors.toSet());

        // But otherwise skip other stuff - e.g. doing a leak check will find a
        // leak because we (on purpose) have two of the same library at the same
        // time.
        continue;
      } else {
        // Save it.
        newestWholeComponentData = util.postProcess(component!);
        newestWholeComponent = component;
      }

      if (world.checkConstantCoverageReferences) {
        Result<TestData>? result = checkConstantCoverageReferences(
            newestWholeComponentData, omitPlatform, sdkSummaryData, data);
        if (result != null) return result;
      }

      if (world.uriToSourcesDoesntInclude != null) {
        for (String filename in world.uriToSourcesDoesntInclude!) {
          Uri uri = base.resolve(filename);
          if (component!.uriToSource[uri] != null) {
            return new Result<TestData>(
                data,
                UriToSourceError,
                "Expected no uriToSource for $uri but found "
                "${component!.uriToSource[uri]}");
          }
        }
      }
      if (world.uriToSourcesOnlyIncludes != null) {
        Set<Uri> allowed = {};
        for (String filename in world.uriToSourcesOnlyIncludes!) {
          Uri uri = base.resolve(filename);
          allowed.add(uri);
        }
        for (Uri uri in component!.uriToSource.keys) {
          // null is always there, so allow it implicitly.
          // Dart scheme uris too.
          if (uri.isScheme("org-dartlang-sdk")) continue;
          if (!allowed.contains(uri)) {
            return new Result<TestData>(
                data,
                UriToSourceError,
                "Expected no uriToSource for $uri but found "
                "${component!.uriToSource[uri]}");
          }
        }
      }

      if (!world.skipClassHierarchyTest) {
        result = checkClassHierarchy(compilerResult, data, worldNum, context);
        if (result != null) return result;
      }

      int nonSyntheticLibraries = countNonSyntheticLibraries(component!);
      int nonSyntheticPlatformLibraries =
          countNonSyntheticPlatformLibraries(component!);
      int syntheticLibraries = countSyntheticLibraries(component!);
      if (world.expectsPlatform) {
        if (nonSyntheticPlatformLibraries < 5) {
          return new Result<TestData>(
              data,
              MissingPlatformLibraries,
              "Expected to have at least 5 platform libraries "
              "(actually, the entire sdk), "
              "but got $nonSyntheticPlatformLibraries.");
        }
      } else {
        if (nonSyntheticPlatformLibraries != 0) {
          return new Result<TestData>(
              data,
              UnexpectedPlatformLibraries,
              "Expected to have 0 platform libraries "
              "but got $nonSyntheticPlatformLibraries.");
        }
      }
      if (world.expectedLibraryCount != null) {
        if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
            world.expectedLibraryCount!) {
          return new Result<TestData>(
              data,
              LibraryCountMismatch,
              "Expected ${world.expectedLibraryCount} non-synthetic "
              "libraries, got "
              "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
              "(not counting platform libraries)");
        }
      }
      if (world.expectedSyntheticLibraryCount != null) {
        if (syntheticLibraries != world.expectedSyntheticLibraryCount!) {
          return new Result<TestData>(
              data,
              LibraryCountMismatch,
              "Expected ${world.expectedSyntheticLibraryCount} synthetic "
              "libraries, got ${syntheticLibraries}");
        }
      }

      AdvancedInvalidationResult? actualAdvancedInvalidation =
          compiler.recorderForTesting.advancedInvalidationResult;
      if (world.advancedInvalidation != actualAdvancedInvalidation) {
        return new Result<TestData>(
            data,
            UnexpectedAdvancedInvalidation,
            "Expected advancedInvalidation: "
            "${world.advancedInvalidation}, "
            "advancedInvalidation: "
            "${actualAdvancedInvalidation}.");
      }

      if (!world.noFullComponent) {
        if (world.checkEntries) {
          List<Library> entryLib = component!.libraries
              .where((Library lib) =>
                  entries.contains(lib.importUri) ||
                  entries.contains(lib.fileUri))
              .toList();
          if (entryLib.length != entries.length) {
            return new Result<TestData>(
                data,
                UnexpectedEntryToLibraryCount,
                "Expected the entries to become libraries. "
                "Got ${entryLib.length} libraries for the expected "
                "${entries.length} entries.");
          }
        }
      }
      if (compiler.initializedFromDillForTesting != expectInitializeFromDill) {
        return new Result<TestData>(
            data,
            InitializedFromDillMismatch,
            "Expected that initializedFromDill would be "
            "$expectInitializeFromDill but was "
            "${compiler.initializedFromDillForTesting}");
      }

      if (incrementalSerialization == true &&
          compiler.initializedFromDillForTesting) {
        Expect.isTrue(compiler.initializedIncrementalSerializerForTesting);
      } else {
        Expect.isFalse(compiler.initializedIncrementalSerializerForTesting);
      }

      if (world.checkInvalidatedFiles) {
        Set<Uri>? filteredInvalidated =
            compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
        if (world.invalidate != null) {
          Expect.equals(
              world.invalidate!.length,
              filteredInvalidated?.length ?? 0,
              "Unexpected invalidated files: ${filteredInvalidated}, "
              "actual: ${world.invalidate}.");
          if (world.expectedInvalidatedUri != null) {
            Expect.setEquals(
                world.expectedInvalidatedUri!.map((s) => base.resolve(s)),
                filteredInvalidated!);
          }
        } else {
          Expect.isNull(filteredInvalidated);
          Expect.isNull(world.expectedInvalidatedUri);
        }
      }
      Result<Uint8List?> serializationResult = checkIncrementalSerialization(
          incrementalSerialization, component!, incrementalSerializer, world);
      if (!serializationResult.isPass) {
        return serializationResult.copyWithOutput(data);
      }
      Uint8List? incrementalSerializationBytes = serializationResult.output;

      worldErrors.add(formattedErrors.toSet());
      assert(worldErrors.length == worldNum);
      if (world.expectSameErrorsAsWorld != null) {
        checkErrorsAndWarnings(
          worldErrors[world.expectSameErrorsAsWorld! - 1],
          formattedErrors,
          {},
          {},
        );
      }

      Set<String> prevFormattedErrors = formattedErrors.toSet();
      Set<String> prevFormattedWarnings = formattedWarnings.toSet();

      void clearPrevErrorsEtc() {
        gotError = false;
        formattedErrors.clear();
        gotWarning = false;
        formattedWarnings.clear();
      }

      if (!world.noFullComponent) {
        clearPrevErrorsEtc();
        IncrementalCompilerResult? compilerResult2 =
            await compiler.computeDelta(
                entryPoints: entries,
                fullComponent: true,
                simulateTransformer: world.simulateTransformer);
        component2 = compilerResult2.component;
        compilerResult2 = null;
        Result<TestData>? result = performErrorAndWarningCheck(world, data,
            gotError, formattedErrors, gotWarning, formattedWarnings);
        if (result != null) return result;
        List<int> thisWholeComponent = util.postProcess(component2!);
        String component2String = componentToStringSdkFiltered(component2!,
            printErrors: world.printErrorsInExpect ? formattedErrors : null);
        print("*****\n\ncomponent2:\n$component2String\n\n\n");
        checkIsEqual(newestWholeComponentData, thisWholeComponent);
        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
            prevFormattedWarnings, formattedWarnings);
        newestWholeComponent = component2;

        Result<List<int>?> serializationResult = checkIncrementalSerialization(
            incrementalSerialization,
            component2!,
            incrementalSerializer,
            world);
        if (!serializationResult.isPass) {
          return serializationResult.copyWithOutput(data);
        }
        List<int>? incrementalSerializationBytes2 = serializationResult.output;

        if ((incrementalSerializationBytes == null &&
                incrementalSerializationBytes2 != null) ||
            (incrementalSerializationBytes != null &&
                incrementalSerializationBytes2 == null)) {
          return new Result<TestData>(
              data,
              IncrementalSerializationError,
              "Incremental serialization gave results in one instance, "
              "but not another.");
        }

        if (incrementalSerializationBytes != null) {
          checkIsEqual(
              incrementalSerializationBytes, incrementalSerializationBytes2!);
        }
      }

      if (world.expressionCompilation != null) {
        int expressionCompilationNum = 0;
        for (ExpressionCompilation compilation
            in world.expressionCompilation!) {
          expressionCompilationNum++;
          clearPrevErrorsEtc();
          Uri uri = base.resolve(compilation.uri);
          Procedure procedure = (await compiler.compileExpression(
            compilation.expression,
            {},
            [],
            "debugExpr",
            uri,
            className: compilation.className,
          ))!;
          if (gotError && !compilation.errors) {
            return new Result<TestData>(data, UnexpectedErrors,
                "Got error(s) on expression compilation: ${formattedErrors}.");
          } else if (!gotError && compilation.errors) {
            return new Result<TestData>(
                data, MissingErrors, "Didn't get any errors.");
          }
          if (gotWarning && !compilation.warnings) {
            return new Result<TestData>(
                data,
                UnexpectedWarnings,
                "Got warning(s) on expression compilation: "
                "${formattedWarnings}.");
          } else if (!gotWarning && compilation.warnings) {
            return new Result<TestData>(
                data, MissingWarnings, "Didn't get any warnings.");
          }
          Result<TestData>? result = checkExpectFile(
              data,
              worldNum,
              ".expression.$expressionCompilationNum",
              context,
              nodeToString(procedure));
          if (result != null) return result;
        }
      }

      if (!world.noFullComponent &&
          (incrementalSerialization == true || world.compareWithFromScratch)) {
        // Do compile from scratch and compare.
        clearPrevErrorsEtc();
        TestIncrementalCompiler? compilerFromScratch;

        IncrementalSerializer? incrementalSerializer2;
        if (incrementalSerialization == true) {
          incrementalSerializer2 = new IncrementalSerializer();
        }

        if (world.fromComponent || modulesToUse != null) {
          compilerFromScratch = new TestIncrementalCompiler.fromComponent(
              options,
              entries.first,
              sdk,
              world.outlineOnly,
              incrementalSerializer2);
        } else {
          compilerFromScratch = new TestIncrementalCompiler(options,
              entries.first, null, world.outlineOnly, incrementalSerializer2);
        }

        if (modulesToUse != null) {
          compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
          compilerFromScratch.invalidateAllSources();
        }

        Stopwatch stopwatch = new Stopwatch()..start();
        IncrementalCompilerResult? compilerResult3 =
            await compilerFromScratch.computeDelta(
                entryPoints: entries,
                trackNeededDillLibraries: modulesToUse != null,
                simulateTransformer: world.simulateTransformer);
        component3 = compilerResult3.component;
        compilerResult3 = null;
        compilerFromScratch = null;
        Result<TestData>? result = performErrorAndWarningCheck(world, data,
            gotError, formattedErrors, gotWarning, formattedWarnings);
        if (result != null) return result;
        util.throwOnEmptyMixinBodies(component3!);
        await util.throwOnInsufficientUriToSource(component3!);
        print("Compile took ${stopwatch.elapsedMilliseconds} ms");

        List<int> thisWholeComponent = util.postProcess(component3!);
        String component3String = componentToStringSdkFiltered(component3!,
            printErrors: world.printErrorsInExpect ? formattedErrors : null);
        print("*****\n\ncomponent3:\n$component3String\n\n\n");
        if (world.compareWithFromScratch) {
          checkIsEqual(newestWholeComponentData, thisWholeComponent);
        }
        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
            prevFormattedWarnings, formattedWarnings);

        Result<List<int>?> serializationResult = checkIncrementalSerialization(
            incrementalSerialization,
            component3!,
            incrementalSerializer2,
            world);
        if (!serializationResult.isPass) {
          return serializationResult.copyWithOutput(data);
        }
        List<int>? incrementalSerializationBytes3 = serializationResult.output;

        if ((incrementalSerializationBytes == null &&
                incrementalSerializationBytes3 != null) ||
            (incrementalSerializationBytes != null &&
                incrementalSerializationBytes3 == null)) {
          return new Result<TestData>(
              data,
              IncrementalSerializationError,
              "Incremental serialization gave results in one instance, "
              "but not another.");
        }

        if (incrementalSerializationBytes != null) {
          if (world.brandNewIncrementalSerializationAllowDifferent) {
            // Don't check for equality when we allow it to be different
            // (e.g. when the old one contains more, and the new one doesn't).
          } else {
            checkIsEqual(
                incrementalSerializationBytes, incrementalSerializationBytes3!);
          }
          newestWholeComponentData = incrementalSerializationBytes;
        }
      }

      component = null;
      compilerResult = null;
      component2 = null;
      component3 = null;
      // Dummy tree nodes can (currently) leak though the parent pointer.
      // To avoid that (here) (for leak testing) we'll null them out.
      for (TreeNode treeNode in dummyTreeNodes) {
        treeNode.parent = null;
      }

      if (context.breakBetween) {
        debugger();
        print("Continuing after debug break");
      }
    }
    return new Result<TestData>.pass(data);
  }
}

Result<TestData>? checkConstantCoverageReferences(
    Uint8List newestWholeComponentData,
    bool omitPlatform,
    Uint8List sdkSummaryData,
    TestData data) {
  // Note that this is in a method to avoid "semi-leaks".
  Component loadedComponent = new Component();
  if (omitPlatform) {
    new BinaryBuilder(sdkSummaryData, filename: null)
        .readComponent(loadedComponent);
  }
  new BinaryBuilder(newestWholeComponentData, filename: null)
      .readComponent(loadedComponent);

  for (MapEntry<Uri, Source> source in loadedComponent.uriToSource.entries) {
    Set<Reference>? references = source.value.constantCoverageConstructors;
    if (references != null) {
      for (Reference reference in references) {
        if (reference.node == null) {
          return new Result<TestData>(
              data,
              ConstantCoverageReferenceWithoutNode,
              "Constant coverage reference without node: "
              "${reference.canonicalName} from ${source.value.importUri} "
              "indexed in ${source.key}");
        }
      }
    }
  }
  return null;
}

class Strategy extends EquivalenceStrategy {
  const Strategy();

  @override
  bool checkComponent_libraries(
      EquivalenceVisitor visitor, Component node, Component other) {
    return visitor.checkSets(node.libraries.toSet(), other.libraries.toSet(),
        visitor.matchNamedNodes, visitor.checkNodes, 'libraries');
  }

  @override
  bool checkClass_procedures(
      EquivalenceVisitor visitor, Class node, Class other) {
    // Check procedures as a set instead of a list to allow for reordering.
    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
  }

  @override
  bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
      VariableDeclaration node, VariableDeclaration other) {
    return true;
  }
}

Result<TestData>? checkExpectFile(TestData data, int worldNum,
    String extraUriString, Context context, String actualSerialized) {
  Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
      ".world.$worldNum${extraUriString}.expect");
  String? expected;
  File file = new File.fromUri(uri);
  if (file.existsSync()) {
    expected = file.readAsStringSync();
  }
  if (expected?.replaceAll("\r\n", "\n") != actualSerialized) {
    if (context.updateExpectations) {
      file.writeAsStringSync(actualSerialized);
    } else {
      String extra = "";
      if (expected == null) extra = "Expect file did not exist.\n";
      return new Result<TestData>(
          data,
          expected == null ? ExpectationFileMissing : ExpectationFileMismatch,
          "${extra}Unexpected serialized representation. "
          "Fix or update $uri to contain the below:\n\n"
          "$actualSerialized",
          autoFixCommand: "updateExpectations=true",
          canBeFixWithUpdateExpectations: true);
    }
  }
  return null;
}

/// Check that the class hierarchy is up-to-date with reality.
///
/// This has the option to do expect files, but it's disabled by default
/// while we're trying to figure out if it's useful or not.
Result<TestData>? checkClassHierarchy(IncrementalCompilerResult compilerResult,
    TestData data, int worldNum, Context context,
    {bool checkExpectFile = false}) {
  ClassHierarchy? classHierarchy = compilerResult.classHierarchy;
  if (classHierarchy is! ClosedWorldClassHierarchy) {
    return new Result<TestData>(
        data,
        ClassHierarchyError,
        "Expected the class hierarchy to be ClosedWorldClassHierarchy "
        "but it wasn't. It was ${classHierarchy.runtimeType}");
  }
  List<ForTestingClassInfo> classHierarchyData =
      classHierarchy.getTestingClassInfo();
  Map<Class, ForTestingClassInfo> classHierarchyMap =
      new Map<Class, ForTestingClassInfo>();
  for (ForTestingClassInfo info in classHierarchyData) {
    if (classHierarchyMap[info.classNode] != null) {
      return new Result<TestData>(
          data, ClassHierarchyError, "Two entries for ${info.classNode}");
    }
    classHierarchyMap[info.classNode] = info;
  }

  Component component = compilerResult.component;
  StringBuffer sb = new StringBuffer();
  for (Library library in component.libraries) {
    if (library.importUri.isScheme("dart")) continue;
    sb.writeln("Library ${library.importUri}");
    for (Class c in library.classes) {
      sb.writeln("  - Class ${c.name}");

      Set<Class> checkedSupertypes = <Class>{};
      Result<TestData>? checkSupertype(Supertype? supertype) {
        if (supertype == null) return null;
        Class superclass = supertype.classNode;
        if (checkedSupertypes.add(superclass)) {
          Supertype? asSuperClass =
              classHierarchy.getClassAsInstanceOf(c, superclass);
          if (asSuperClass == null) {
            return new Result<TestData>(data, ClassHierarchyError,
                "${superclass} not found as a superclass of $c");
          }
          Result<TestData>? result = checkSupertype(superclass.supertype);
          if (result != null) return result;
          result = checkSupertype(superclass.mixedInType);
          if (result != null) return result;
          for (Supertype interface in superclass.implementedTypes) {
            result = checkSupertype(interface);
            if (result != null) return result;
          }
        }
        return null;
      }

      Result<TestData>? result = checkSupertype(c.asThisSupertype);
      if (result != null) return result;

      ForTestingClassInfo? info = classHierarchyMap[c];
      if (info == null) {
        return new Result<TestData>(data, ClassHierarchyError,
            "Didn't find any class hierarchy info for $c");
      }

      if (info.lazyDeclaredGettersAndCalls != null) {
        sb.writeln("    - lazyDeclaredGettersAndCalls:");
        for (Member member in info.lazyDeclaredGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }

        // Expect these to be the same as in the class.
        Set<Member> members = info.lazyDeclaredGettersAndCalls!.toSet();
        for (Field f in c.fields) {
          if (f.isStatic) continue;
          if (!members.remove(f)) {
            return new Result<TestData>(
                data,
                ClassHierarchyError,
                "Didn't find ${f.name.text} in lazyDeclaredGettersAndCalls "
                "for ${c.name} in ${library.importUri}");
          }
        }
        for (Procedure p in c.procedures) {
          if (p.isStatic) continue;
          if (p.isSetter) continue;
          if (!members.remove(p)) {
            return new Result<TestData>(
                data,
                ClassHierarchyError,
                "Didn't find ${p.name.text} in lazyDeclaredGettersAndCalls "
                "for ${c.name} in ${library.importUri}");
          }
        }
        if (members.isNotEmpty) {
          return new Result<TestData>(
              data,
              ClassHierarchyError,
              "Still have ${members.map((m) => m.name.text)} left "
              "for ${c.name} in ${library.importUri}");
        }
      }
      if (info.lazyDeclaredSetters != null) {
        sb.writeln("    - lazyDeclaredSetters:");
        for (Member member in info.lazyDeclaredSetters!) {
          sb.writeln("      - ${member.name.text}");
        }

        // Expect these to be the same as in the class.
        Set<Member> members = info.lazyDeclaredSetters!.toSet();
        for (Field f in c.fields) {
          if (f.isStatic) continue;
          if (!f.hasSetter) continue;
          if (!members.remove(f)) {
            return new Result<TestData>(data, ClassHierarchyError,
                "Didn't find $f in lazyDeclaredSetters for $c");
          }
        }
        for (Procedure p in c.procedures) {
          if (p.isStatic) continue;
          if (!p.isSetter) continue;
          if (!members.remove(p)) {
            return new Result<TestData>(data, ClassHierarchyError,
                "Didn't find $p in lazyDeclaredSetters for $c");
          }
        }
        if (members.isNotEmpty) {
          return new Result<TestData>(
              data,
              ClassHierarchyError,
              "Still have ${members.map((m) => m.name.text)} left "
              "for ${c.name} in ${library.importUri}");
        }
      }
      if (info.lazyImplementedGettersAndCalls != null) {
        sb.writeln("    - lazyImplementedGettersAndCalls:");
        for (Member member in info.lazyImplementedGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyImplementedSetters != null) {
        sb.writeln("    - lazyImplementedSetters:");
        for (Member member in info.lazyImplementedSetters!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyInterfaceGettersAndCalls != null) {
        sb.writeln("    - lazyInterfaceGettersAndCalls:");
        for (Member member in info.lazyInterfaceGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyInterfaceSetters != null) {
        sb.writeln("    - lazyInterfaceSetters:");
        for (Member member in info.lazyInterfaceSetters!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
    }
  }
  if (checkExpectFile) {
    String actualClassHierarchy = sb.toString();
    Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
        ".world.$worldNum.class_hierarchy.expect");
    String? expected;
    File file = new File.fromUri(uri);
    if (file.existsSync()) {
      expected = file.readAsStringSync();
    }
    if (expected != actualClassHierarchy) {
      if (context.updateExpectations) {
        file.writeAsStringSync(actualClassHierarchy);
      } else {
        String extra = "";
        if (expected == null) extra = "Expect file did not exist.\n";
        return new Result<TestData>(
            data,
            ClassHierarchyError,
            "${extra}Unexpected serialized representation. "
            "Fix or update $uri to contain the below:\n\n"
            "$actualClassHierarchy");
      }
    }
  }
  return null;
}

void checkErrorsAndWarnings(
    Set<String> prevFormattedErrors,
    Set<String> formattedErrors,
    Set<String> prevFormattedWarnings,
    Set<String> formattedWarnings) {
  if (prevFormattedErrors.length != formattedErrors.length) {
    Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
        "now had ${formattedErrors.length}.\n\n"
        "Before:\n"
        "${prevFormattedErrors.join("\n")}"
        "\n\n"
        "Now:\n"
        "${formattedErrors.join("\n")}");
  }
  if ((prevFormattedErrors.toSet()..removeAll(formattedErrors)).isNotEmpty) {
    Expect.fail("Previously got error messages $prevFormattedErrors, "
        "now had ${formattedErrors}.");
  }
  if (prevFormattedWarnings.length != formattedWarnings.length) {
    Expect.fail("Previously had ${prevFormattedWarnings.length} errors, "
        "now had ${formattedWarnings.length}.");
  }
  if ((prevFormattedWarnings.toSet()..removeAll(formattedWarnings))
      .isNotEmpty) {
    Expect.fail("Previously got error messages $prevFormattedWarnings, "
        "now had ${formattedWarnings}.");
  }
}

Result<Uint8List?> checkIncrementalSerialization(
    bool? incrementalSerialization,
    Component component,
    IncrementalSerializer? incrementalSerializer,
    World world) {
  if (incrementalSerialization == true) {
    Component c = new Component(nameRoot: component.root)
      ..setMainMethodAndMode(null, false);
    c.libraries.addAll(component.libraries);
    c.uriToSource.addAll(component.uriToSource);
    Map<String, Set<String>> originalContent = buildMapOfContent(c);
    ByteSink sink = new ByteSink();
    int librariesBefore = c.libraries.length;
    incrementalSerializer!.writePackagesToSinkAndTrimComponent(c, sink);
    int librariesAfter = c.libraries.length;
    if (librariesAfter > librariesBefore) {
      return new Result<Uint8List>(null, IncrementalSerializationError,
          "Incremental serialization added libraries!");
    }
    if (librariesBefore == librariesAfter &&
        world.incrementalSerializationDoesWork) {
      return new Result<Uint8List>(null, IncrementalSerializationError,
          "Incremental serialization didn't remove any libraries!");
    }
    if (librariesAfter < librariesBefore && sink.builder.isEmpty) {
      return new Result<Uint8List>(
          null,
          IncrementalSerializationError,
          "Incremental serialization didn't output any bytes, "
          "but did remove libraries");
    } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) {
      return new Result<Uint8List>(
          null,
          IncrementalSerializationError,
          "Incremental serialization did output bytes, "
          "but didn't remove libraries");
    }
    if (librariesAfter < librariesBefore) {
      // If we actually did incrementally serialize anything, check the output!
      BinaryPrinter printer = new BinaryPrinter(sink);
      printer.writeComponentFile(c);
      Uint8List bytes = sink.builder.takeBytes();

      // Load the bytes back in.
      Component loadedComponent = new Component();
      new BinaryBuilder(bytes, filename: null).readComponent(loadedComponent);

      // Check that it doesn't contain anything we said it shouldn't.
      if (world.serializationShouldNotInclude != null) {
        Set<Uri> includedImportUris =
            loadedComponent.libraries.map((l) => l.importUri).toSet();
        for (String uriString in world.serializationShouldNotInclude!) {
          Uri uri = Uri.parse(uriString);
          if (includedImportUris.contains(uri)) {
            return new Result<Uint8List>(
                null,
                IncrementalSerializationError,
                "Incremental serialization shouldn't include "
                "$uriString but did.");
          }
        }
      }

      // Check that it contains at least what we want.
      Map<String, Set<String>> afterContent =
          buildMapOfContent(loadedComponent);
      // Remove any keys in afterContent not in the original as the written
      // one is allowed to contain *more*.
      Set<String> newKeys = afterContent.keys.toSet()
        ..removeAll(originalContent.keys);
      for (String key in newKeys) {
        afterContent.remove(key);
      }
      Result? result = checkExpectedContentData(afterContent, originalContent);
      if (result != null) return result.copyWithOutput<Uint8List?>(null);

      // Check that the result is self-contained.
      result = checkSelfContained(loadedComponent);
      if (result != null) return result.copyWithOutput<Uint8List?>(null);

      return new Result<Uint8List>.pass(bytes);
    }
  }
  return new Result<Uint8List?>.pass(null);
}

Result? checkSelfContained(Component component) {
  Set<Library> got = new Set<Library>.from(component.libraries);
  for (Library lib in component.libraries) {
    for (LibraryDependency dependency in lib.dependencies) {
      if (dependency.importedLibraryReference.node == null ||
          !got.contains(dependency.targetLibrary)) {
        if (dependency.importedLibraryReference.canonicalName
            .toString()
            .startsWith("root::dart:")) {
          continue;
        }
        return Result(
            null,
            IncrementalSerializationError,
            "Component didn't contain ${dependency.importedLibraryReference} "
            "and it should have.");
      }
    }
  }
  return null;
}

void computeAllReachableLibrariesFor(Library lib, Set<Library> allLibraries) {
  Set<Library> libraries = new Set<Library>();
  List<Library> workList = <Library>[];
  allLibraries.add(lib);
  libraries.add(lib);
  workList.add(lib);
  while (workList.isNotEmpty) {
    Library library = workList.removeLast();
    for (LibraryDependency dependency in library.dependencies) {
      if (dependency.targetLibrary.importUri.isScheme("dart")) continue;
      if (libraries.add(dependency.targetLibrary)) {
        workList.add(dependency.targetLibrary);
        allLibraries.add(dependency.targetLibrary);
      }
    }
  }
}

Result? checkExpectedContent(World world, Component component) {
  if (world.expectedContent != null) {
    Map<String, Set<String>> actualContent = buildMapOfContent(component);
    return checkExpectedContentData(actualContent, world.expectedContent!);
  }
  return null;
}

Result? checkExpectedContentData(Map<String, Set<String>> actualContent,
    Map<String, Iterable<String>> expectedContent) {
  Result<TestData> createFailureResult() {
    return new Result(
        null,
        ContentDataMismatch,
        "Expected and actual content not the same.\n"
        "Expected $expectedContent.\n"
        "Got $actualContent");
  }

  if (actualContent.length != expectedContent.length) {
    return createFailureResult();
  }
  Set<String> missingKeys = actualContent.keys.toSet()
    ..removeAll(expectedContent.keys);
  if (missingKeys.isNotEmpty) {
    return createFailureResult();
  }
  for (MapEntry<String, Iterable<String>> entry in expectedContent.entries) {
    Set<String> expected = new Set<String>.from(entry.value);
    Set<String> actual = actualContent[entry.key]!.toSet();
    if (expected.length != actual.length) {
      return createFailureResult();
    }
    actual.removeAll(expected);
    if (actual.isNotEmpty) {
      return createFailureResult();
    }
  }
  return null;
}

Map<String, Set<String>> buildMapOfContent(Component component) {
  Map<String, Set<String>> actualContent = new Map<String, Set<String>>();
  for (Library lib in component.libraries) {
    Set<String> libContent =
        actualContent[lib.importUri.toString()] = new Set<String>();
    for (Class c in lib.classes) {
      libContent.add("Class ${c.name}");
    }
    for (Procedure p in lib.procedures) {
      libContent.add("Procedure ${p.name.text}");
    }
    for (Field f in lib.fields) {
      libContent.add("Field ${f.name.text}");
    }
  }
  return actualContent;
}

Result<TestData>? checkNeededDillLibraries(
    World world, TestData data, Set<Library>? neededDillLibraries, Uri base) {
  if (world.neededDillLibraries != null) {
    List<Uri> actualContent = <Uri>[];
    for (Library lib in neededDillLibraries!) {
      if (lib.importUri.isScheme("dart")) continue;
      actualContent.add(lib.importUri);
    }

    List<Uri> expectedContent = <Uri>[];
    for (String entry in world.neededDillLibraries!) {
      expectedContent.add(base.resolve(entry));
    }

    Result<TestData> createFailureResult() {
      return new Result<TestData>(
          data,
          NeededDillMismatch,
          "Expected and actual content not the same.\n"
          "Expected $expectedContent.\n"
          "Got $actualContent");
    }

    if (actualContent.length != expectedContent.length) {
      return createFailureResult();
    }
    Set<Uri> notInExpected =
        actualContent.toSet().difference(expectedContent.toSet());
    Set<Uri> notInActual =
        expectedContent.toSet().difference(actualContent.toSet());
    if (notInExpected.isNotEmpty) {
      return createFailureResult();
    }
    if (notInActual.isNotEmpty) {
      return createFailureResult();
    }
  }
  return null;
}

String nodeToString(TreeNode node) {
  StringBuffer buffer = new StringBuffer();
  new Printer(buffer, syntheticNames: new NameSystem()).writeNode(node);
  return '$buffer';
}

String componentToStringSdkFiltered(Component component,
    {required final Set<String>? printErrors}) {
  Component c = new Component();
  List<Uri> dartUris = <Uri>[];
  for (Library lib in component.libraries) {
    if (lib.importUri.isScheme("dart")) {
      dartUris.add(lib.importUri);
    } else {
      if (lib.fileUri.isScheme("holePunch")) {
        // Skip this.
        continue;
      }
      c.libraries.add(lib);
    }
  }
  c.setMainMethodAndMode(component.mainMethodName, true);
  c.problemsAsJson = component.problemsAsJson;

  StringBuffer s = new StringBuffer();
  s.write(componentToString(c));

  addConstantCoverageToExpectation(component, s,
      skipImportUri: (Uri? importUri) => importUri?.scheme == "dart");

  if (dartUris.isNotEmpty) {
    s.writeln("");
    s.writeln("And ${dartUris.length} platform libraries:");
    for (Uri uri in dartUris) {
      s.writeln(" - $uri");
    }
  }

  if (printErrors != null && printErrors.isNotEmpty) {
    s.writeln("");
    s.writeln("A total of ${printErrors.length} errors:");
    for (String error in printErrors) {
      // Make the error more readable if it's a json.
      Map<String, dynamic>? decoded;
      try {
        decoded = jsonDecode(error);
      } catch (_) {}
      if (decoded != null && decoded["plainTextFormatted"] is List) {
        List plainTextFormatted = decoded["plainTextFormatted"] as List;
        if (plainTextFormatted.isNotEmpty &&
            plainTextFormatted.first is String) {
          error = plainTextFormatted.first;
        }
      }
      s.writeln(" - $error");
    }
  }

  return s.toString();
}

int countNonSyntheticLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (!lib.isSynthetic) result++;
  }
  return result;
}

int countNonSyntheticPlatformLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (!lib.isSynthetic && lib.importUri.isScheme("dart")) result++;
  }
  return result;
}

int countSyntheticLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (lib.isSynthetic) result++;
  }
  return result;
}

Result<TestData>? performErrorAndWarningCheck(
    World world,
    TestData data,
    bool gotError,
    Set<String> formattedErrors,
    bool gotWarning,
    Set<String> formattedWarnings) {
  if (world.errors && !gotError) {
    return new Result<TestData>(
        data, MissingErrors, "Expected error, but didn't get any.");
  } else if (!world.errors && gotError) {
    return new Result<TestData>(
        data, UnexpectedErrors, "Got unexpected error(s): $formattedErrors.");
  }
  if (world.warnings && !gotWarning) {
    return new Result<TestData>(
        data, MissingWarnings, "Expected warning, but didn't get any.");
  } else if (!world.warnings && gotWarning) {
    return new Result<TestData>(data, UnexpectedWarnings,
        "Got unexpected warnings(s): $formattedWarnings.");
  }
  return null;
}

void checkIsEqual(List<int> a, List<int> b) {
  int length = a.length;
  if (b.length < length) {
    length = b.length;
  }
  for (int i = 0; i < length; ++i) {
    if (a[i] != b[i]) {
      print("Data differs at byte ${i + 1}.");

      StringBuffer message = new StringBuffer();
      message.writeln("Data differs at byte ${i + 1}.");
      message.writeln("");
      message.writeln("Will try to find more useful information:");

      final String repoDir = computeRepoDir();
      File binaryMd = new File("$repoDir/pkg/kernel/binary.md");
      String binaryMdContent = binaryMd.readAsStringSync();

      DillComparer dillComparer = new DillComparer();
      if (dillComparer.compare(a, b, binaryMdContent, message)) {
        message.writeln(
            "Somehow the two different byte-lists compared to the same.");
      }

      Expect.fail(message.toString());
    }
  }
  Expect.equals(a.length, b.length);
}

CompilerOptions getOptions({Target? target, String? sdkSummary}) {
  target ??= new VmTarget(new TargetFlags());
  sdkSummary ??= 'vm_platform.dill';
  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
  CompilerOptions options = new CompilerOptions()
    ..target = target
    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
    ..omitPlatform = true
    ..onDiagnostic = (DiagnosticMessage message) {
      if (message.severity == Severity.error ||
          message.severity == Severity.warning) {
        Expect.fail(
            "Unexpected error: ${message.plainTextFormatted.join('\n')}");
      }
    }
    ..sdkSummary = sdkRoot.resolve(sdkSummary)
    ..environmentDefines = const {};
  return options;
}

Future<bool> normalCompile(Uri input, Uri output,
    {CompilerOptions? options}) async {
  options ??= getOptions();
  TestIncrementalCompiler compiler =
      new TestIncrementalCompiler(options, input);
  List<int> bytes =
      await normalCompileToBytes(input, options: options, compiler: compiler);
  new File.fromUri(output).writeAsBytesSync(bytes);
  return compiler.initializedFromDillForTesting;
}

Future<Uint8List> normalCompileToBytes(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  Component component = await normalCompileToComponent(input,
      options: options, compiler: compiler);
  return util.postProcess(component);
}

Future<Component> normalCompileToComponent(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  Component component =
      await normalCompilePlain(input, options: options, compiler: compiler);
  util.throwOnEmptyMixinBodies(component);
  await util.throwOnInsufficientUriToSource(component);
  return component;
}

Future<Component> normalCompilePlain(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  options ??= getOptions();
  compiler ??= new TestIncrementalCompiler(options, input);
  return (await compiler.computeDelta()).component;
}

Future<bool> initializedCompile(
    Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
    {CompilerOptions? options}) async {
  options ??= getOptions();
  TestIncrementalCompiler compiler =
      new TestIncrementalCompiler(options, input, initializeWith);
  for (Uri invalidateUri in invalidateUris) {
    compiler.invalidate(invalidateUri);
  }
  IncrementalCompilerResult initializedCompilerResult =
      await compiler.computeDelta();
  Component initializedComponent = initializedCompilerResult.component;
  util.throwOnEmptyMixinBodies(initializedComponent);
  await util.throwOnInsufficientUriToSource(initializedComponent);
  bool result = compiler.initializedFromDillForTesting;
  new File.fromUri(output)
      .writeAsBytesSync(util.postProcess(initializedComponent));
  int actuallyInvalidatedCount = compiler
          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
          ?.length ??
      0;
  if (result && actuallyInvalidatedCount < invalidateUris.length) {
    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
        "got $actuallyInvalidatedCount");
  }

  IncrementalCompilerResult initializedFullCompilerResult =
      await compiler.computeDelta(fullComponent: true);
  Component initializedFullComponent = initializedFullCompilerResult.component;
  util.throwOnEmptyMixinBodies(initializedFullComponent);
  await util.throwOnInsufficientUriToSource(initializedFullComponent);
  Expect.equals(initializedComponent.libraries.length,
      initializedFullComponent.libraries.length);
  Expect.equals(initializedComponent.uriToSource.length,
      initializedFullComponent.uriToSource.length);

  for (Uri invalidateUri in invalidateUris) {
    compiler.invalidate(invalidateUri);
  }

  IncrementalCompilerResult partialResult = await compiler.computeDelta();
  Component partialComponent = partialResult.component;
  util.throwOnEmptyMixinBodies(partialComponent);
  await util.throwOnInsufficientUriToSource(partialComponent);
  actuallyInvalidatedCount = (compiler
          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
          ?.length ??
      0);
  if (actuallyInvalidatedCount < invalidateUris.length) {
    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
        "got $actuallyInvalidatedCount");
  }

  IncrementalCompilerResult emptyResult = await compiler.computeDelta();
  Component emptyComponent = emptyResult.component;
  util.throwOnEmptyMixinBodies(emptyComponent);
  await util.throwOnInsufficientUriToSource(emptyComponent);

  List<Uri> fullLibUris =
      initializedComponent.libraries.map((lib) => lib.importUri).toList();
  List<Uri> partialLibUris =
      partialComponent.libraries.map((lib) => lib.importUri).toList();
  List<Uri> emptyLibUris =
      emptyComponent.libraries.map((lib) => lib.importUri).toList();

  Expect.isTrue(fullLibUris.length > partialLibUris.length ||
      partialLibUris.length == invalidateUris.length);
  Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);

  Expect.isTrue(emptyLibUris.isEmpty);

  return result;
}

class TestIncrementalCompiler extends IncrementalCompiler {
  @override
  final TestRecorderForTesting recorderForTesting =
      new TestRecorderForTesting();
  final Uri entryPoint;

  /// Filter out the automatically added entryPoint, unless it's explicitly
  /// specified as being invalidated.
  /// Also filter out uris with "nonexisting.dart" in the name as synthetic
  /// libraries are invalidated automatically too.
  /// This is not perfect, but works for what it's currently used for.
  Set<Uri>? getFilteredInvalidatedImportUrisForTesting(
      List<Uri> invalidatedUris) {
    if (recorderForTesting.invalidatedImportUrisForTesting == null) return null;

    Set<String> invalidatedFilenames =
        invalidatedUris.map((uri) => uri.pathSegments.last).toSet();
    Set<Uri> result = new Set<Uri>();
    for (Uri uri in recorderForTesting.invalidatedImportUrisForTesting!) {
      if (uri.pathSegments.isNotEmpty &&
          uri.pathSegments.last == "nonexisting.dart") {
        continue;
      }
      if (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
          invalidatedFilenames.contains(uri.pathSegments.last)) {
        result.add(uri);
      }
    }

    return result.isEmpty ? null : result;
  }

  TestIncrementalCompiler(CompilerOptions options, this.entryPoint,
      [Uri? initializeFrom,
      bool? outlineOnly,
      IncrementalSerializer? incrementalSerializer])
      : super(
            new CompilerContext(
                new ProcessedOptions(options: options, inputs: [entryPoint])),
            initializeFrom,
            outlineOnly,
            incrementalSerializer);

  TestIncrementalCompiler.fromComponent(CompilerOptions options,
      this.entryPoint, Component? componentToInitializeFrom,
      [bool? outlineOnly, IncrementalSerializer? incrementalSerializer])
      : super.fromComponent(
            new CompilerContext(
                new ProcessedOptions(options: options, inputs: [entryPoint])),
            componentToInitializeFrom,
            outlineOnly,
            incrementalSerializer);

  @override
  Future<IncrementalCompilerResult> computeDelta(
      {List<Uri>? entryPoints,
      bool fullComponent = false,
      bool trackNeededDillLibraries = false,
      bool? simulateTransformer}) async {
    IncrementalCompilerResult result = await super.computeDelta(
        entryPoints: entryPoints,
        fullComponent: fullComponent,
        trackNeededDillLibraries: trackNeededDillLibraries);

    // We should at least have the SDK builders available. Slight smoke test.
    if (!dillTargetForTesting!.loader.libraryImportUris
        .map((uri) => uri.toString())
        .contains("dart:core")) {
      throw "Loaders builder should contain the sdk, "
          "but didn't even contain dart:core.";
    }

    if (simulateTransformer == true) {
      doSimulateTransformer(result.component);
    }
    return result;
  }
}

class TestRecorderForTesting extends RecorderForTesting {
  Set<Uri>? invalidatedImportUrisForTesting;
  AdvancedInvalidationResult? advancedInvalidationResult;
  int? rebuildBodiesCount;

  @override
  void recordInvalidatedImportUris(List<Uri> uris) {
    invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toSet();
  }

  @override
  void recordNonFullComponent(Component component) {
    // It should at least contain the sdk. Slight smoke test.
    if (!component.libraries
        .map((lib) => lib.importUri.toString())
        .contains("dart:core")) {
      throw "Loaders builder should contain the sdk, "
          "but didn't even contain dart:core.";
    }
  }

  @override
  void recordRebuildBodiesCount(int count) {
    rebuildBodiesCount = count;
    assert(
        count == 0 ||
            advancedInvalidationResult == AdvancedInvalidationResult.bodiesOnly,
        "Unexpected successful advanced invalidation: "
        "${advancedInvalidationResult}");
  }

  @override
  void recordAdvancedInvalidationResult(AdvancedInvalidationResult result) {
    advancedInvalidationResult = result;
  }

  @override
  void recordTemporaryFile(Uri uri) {
    File f = new File.fromUri(uri);
    if (f.existsSync()) f.deleteSync();
  }
}

void doSimulateTransformer(Component c) {
  for (Library lib in c.libraries) {
    if (lib.fields
        .where((f) => f.name.text == "unique_SimulateTransformer")
        .toList()
        .isNotEmpty) {
      continue;
    }
    Name fieldName = new Name("unique_SimulateTransformer");
    Field field = new Field.immutable(fieldName,
        isFinal: true,
        fieldReference: lib.reference.canonicalName
            ?.getChildFromFieldWithName(fieldName)
            .reference,
        getterReference: lib.reference.canonicalName
            ?.getChildFromFieldGetterWithName(fieldName)
            .reference,
        fileUri: lib.fileUri);
    lib.addField(field);
    for (Class c in lib.classes) {
      if (c.fields
          .where((f) => f.name.text == "unique_SimulateTransformer")
          .toList()
          .isNotEmpty) {
        continue;
      }
      fieldName = new Name("unique_SimulateTransformer");
      field = new Field.immutable(fieldName,
          isFinal: true,
          fieldReference: lib.reference.canonicalName
              ?.getChildFromFieldWithName(fieldName)
              .reference,
          getterReference: c.reference.canonicalName
              ?.getChildFromFieldGetterWithName(fieldName)
              .reference,
          fileUri: c.fileUri);
      c.addField(field);
    }
  }
}

class TestMemoryFileSystem extends MemoryFileSystem {
  Uri holePunchBase;

  TestMemoryFileSystem(Uri currentDirectory, {required this.holePunchBase})
      : super(currentDirectory);

  @override
  MemoryFileSystemEntity entityForUri(Uri uri) {
    if (uri.isScheme("holePunch")) {
      // "Copy" the file into the memory file system.
      Uri holePunchResolved = holePunchBase.resolve(uri.path);
      File f = new File.fromUri(holePunchResolved);
      MemoryFileSystemEntity entity = super.entityForUri(uri);
      if (f.existsSync()) {
        entity.writeAsBytesSync(f.readAsBytesSync());
      }
      return entity;
    }
    // Try to "sanitize" the uri as a real file system does, namely
    // "a/b.dart" and "a//b.dart" returns the same file.
    if (uri.pathSegments.contains("")) {
      Uri newUri = uri.replace(
          pathSegments: uri.pathSegments.where((element) => element != ""));
      return super.entityForUri(newUri);
    }
    return super.entityForUri(uri);
  }
}
