// Copyright (c) 2017, 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 jsonEncode;

import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/memory_file_system.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:front_end/src/fasta/util/bytes_sink.dart' show BytesSink;
import 'package:front_end/src/fasta/fasta_codes.dart';
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/kernel.dart'
    show
        CanonicalName,
        Library,
        Component,
        loadComponentFromBytes,
        NonNullableByDefaultCompiledMode;
import 'package:package_config/package_config.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

final String emptyPackageConfig = jsonEncode({
  "configVersion": 2,
  "packages": [],
});

final String fooBarPackageConfig = jsonEncode({
  "configVersion": 2,
  "packages": [
    {
      "name": "foo",
      "rootUri": "bar",
    },
  ],
});
final String fooBazPackageConfig = jsonEncode({
  "configVersion": 2,
  "packages": [
    {
      "name": "foo",
      "rootUri": "baz",
    },
  ],
});
final String fooBazDotDotPackageConfig = jsonEncode({
  "configVersion": 2,
  "packages": [
    {
      "name": "foo",
      "rootUri": "../baz",
    },
  ],
});

void main() {
  CompilerContext.runWithDefaultOptions((_) {
    defineReflectiveSuite(() {
      defineReflectiveTests(ProcessedOptionsTest);
    });
    return Future<void>.value();
  });
}

@reflectiveTest
class ProcessedOptionsTest {
  MemoryFileSystem fileSystem =
      new MemoryFileSystem(Uri.parse('org-dartlang-test:///'));

  Component? _mockOutline;

  Component get mockSummary => _mockOutline ??= new Component(libraries: [
        new Library(Uri.parse('org-dartlang-test:///a/b.dart'),
            fileUri: Uri.parse('org-dartlang-test:///a/b.dart'))
      ])
        ..setMainMethodAndMode(
            null, false, NonNullableByDefaultCompiledMode.Weak);

  void test_compileSdk_false() {
    for (var value in [false, true]) {
      var raw = new CompilerOptions()..compileSdk = value;
      var processed = new ProcessedOptions(options: raw);
      expect(processed.compileSdk, value);
    }
  }

  void test_sdk_summary_inferred() {
    // The sdk-summary is inferred by default form sdk-root, when compile-sdk is
    // false
    var raw = new CompilerOptions()
      ..sdkRoot = Uri.parse('org-dartlang-test:///sdk/dir/')
      ..compileSdk = false;
    expect(new ProcessedOptions(options: raw).sdkSummary,
        Uri.parse('org-dartlang-test:///sdk/dir/vm_platform_strong.dill'));

    // But it is left null when compile-sdk is true
    raw = new CompilerOptions()
      ..sdkRoot = Uri.parse('org-dartlang-test:///sdk/dir/')
      ..compileSdk = true;
    expect(new ProcessedOptions(options: raw).sdkSummary, null);
  }

  void test_fileSystem_noBazelRoots() {
    // When no bazel roots are specified, the filesystem should be passed
    // through unmodified.
    var raw = new CompilerOptions()..fileSystem = fileSystem;
    var processed = new ProcessedOptions(options: raw);
    expect(processed.fileSystem, same(fileSystem));
  }

  Future<void> test_getSdkSummaryBytes_summaryLocationProvided() async {
    var uri = Uri.parse('org-dartlang-test:///sdkSummary');

    writeMockSummaryTo(uri);

    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..sdkSummary = uri;
    var processed = new ProcessedOptions(options: raw);

    var bytes = (await processed.loadSdkSummaryBytes())!;
    expect(bytes, isNotEmpty);

    var sdkSummary = loadComponentFromBytes(bytes);
    expect(sdkSummary.libraries.single.importUri,
        mockSummary.libraries.single.importUri);
  }

  Future<void> test_getSdkSummary_summaryLocationProvided() async {
    var uri = Uri.parse('org-dartlang-test:///sdkSummary');
    writeMockSummaryTo(uri);
    await checkMockSummary(new CompilerOptions()
      ..fileSystem = fileSystem
      ..sdkSummary = uri);
  }

  void writeMockSummaryTo(Uri uri) {
    var sink = new BytesSink();
    new BinaryPrinter(sink).writeComponentFile(mockSummary);
    fileSystem.entityForUri(uri).writeAsBytesSync(sink.builder.takeBytes());
  }

  Future<Null> checkMockSummary(CompilerOptions raw) async {
    var processed = new ProcessedOptions(options: raw);
    var sdkSummary =
        (await processed.loadSdkSummary(new CanonicalName.root()))!;
    expect(sdkSummary.libraries.single.importUri,
        mockSummary.libraries.single.importUri);
  }

  Future<void> test_getUriTranslator_explicitLibrariesSpec() async {
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(emptyPackageConfig);
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///libraries.json'))
        .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
    var raw = new CompilerOptions()
      ..packagesFileUri =
          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
      ..fileSystem = fileSystem
      ..librariesSpecificationUri =
          Uri.parse('org-dartlang-test:///libraries.json');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    expect(uriTranslator.dartLibraries.libraryInfoFor('foo')!.uri.path,
        '/bar.dart');
  }

  Future<void> test_getUriTranslator_inferredLibrariesSpec() async {
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(emptyPackageConfig);
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///mysdk/lib/libraries.json'))
        .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri =
          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
      ..compileSdk = true
      ..sdkRoot = Uri.parse('org-dartlang-test:///mysdk/');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    expect(uriTranslator.dartLibraries.libraryInfoFor('foo')!.uri.path,
        '/mysdk/lib/bar.dart');
  }

  Future<void> test_getUriTranslator_notInferredLibrariesSpec() async {
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(emptyPackageConfig);
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///mysdk/lib/libraries.json'))
        .writeAsStringSync('{"none":{"libraries":{"foo":{"uri":"bar.dart"}}}}');
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri =
          Uri.parse('org-dartlang-test:///.dart_tool/package_config.json')
      ..compileSdk = false // libraries.json is only inferred if true
      ..sdkRoot = Uri.parse('org-dartlang-test:///mysdk/');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    expect(uriTranslator.dartLibraries.libraryInfoFor('foo'), isNull);
  }

  void checkPackageExpansion(
      String packageName, String packageDir, PackageConfig packages) {
    var input = Uri.parse('package:$packageName/a.dart');
    var expected = Uri.parse('org-dartlang-test:///$packageDir/a.dart');
    expect(packages.resolve(input), expected);
  }

  Future<void> test_getUriTranslator_explicitPackagesFile() async {
    // This .dart_tool/package_config.json file should be ignored.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    // This one should be used.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///explicit.json'))
        .writeAsStringSync(fooBazPackageConfig);
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.json');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'baz', uriTranslator.packages);
  }

  Future<void>
      test_getUriTranslator_explicitPackagesFile_withBaseLocation() async {
    // This .dart_tool/package_config.json file should be ignored.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    // This one should be used.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///base/location/explicit.json'))
        .writeAsStringSync(fooBazPackageConfig);
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri =
          Uri.parse('org-dartlang-test:///base/location/explicit.json');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'base/location/baz', uriTranslator.packages);
  }

  Future<void> test_getUriTranslator_implicitPackagesFile_ambiguous() async {
    // This .dart_tool/package_config.json file should be ignored.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    // This one should be used.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///explicit.json'))
        .writeAsStringSync(fooBazPackageConfig);
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri = Uri.parse('org-dartlang-test:///explicit.json');
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'baz', uriTranslator.packages);
  }

  Future<void> test_getUriTranslator_implicitPackagesFile_nextToScript() async {
    // Create the base directory.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
        .createDirectory();
    // Packages directory should be ignored (.dart_tool/package_config.json is
    // the only one that will be automatically found).
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/packages/'))
        .createDirectory();
    // This .packages file should be ignored.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
        .writeAsStringSync("foo:packages1");
    // This .packages file should be ignored.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/.packages'))
        .writeAsStringSync("foo:packages2");
    // This .dart_tool/package_config.json file should be ignored.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    // This one should be used.
    fileSystem
        .entityForUri(Uri.parse(
            'org-dartlang-test:///base/location/.dart_tool/package_config.json'))
        .writeAsStringSync(fooBazDotDotPackageConfig);
    var raw = new CompilerOptions()..fileSystem = fileSystem;
    var processed = new ProcessedOptions(
        options: raw,
        inputs: [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'base/location/baz', uriTranslator.packages);
  }

  Future<void> test_getUriTranslator_implicitPackagesFile_searchAbove() async {
    // Create the base directory.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
        .createDirectory();
    // This .dart_tool/package_config.json file should be ignored.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    // This one should be used.
    fileSystem
        .entityForUri(Uri.parse(
            'org-dartlang-test:///base/.dart_tool/package_config.json'))
        .writeAsStringSync(fooBazDotDotPackageConfig);
    var raw = new CompilerOptions()..fileSystem = fileSystem;
    var processed = new ProcessedOptions(
        options: raw,
        inputs: [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'base/baz', uriTranslator.packages);
  }

  Future<void>
      test_getUriTranslator_implicitPackagesFile_packagesDirectory() async {
    // Create the base directory.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
        .createDirectory();

    // packages/ directory is deprecated and should be ignored.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/packages/'))
        .createDirectory();

    // .packages is deprecated and should be ignored.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///.packages'))
        .writeAsStringSync('foo:packages1\n');
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/.packages'))
        .writeAsStringSync('foo:packages2\n');

    // .dart_tool/package_config.json
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    fileSystem
        .entityForUri(Uri.parse(
            'org-dartlang-test:///base/.dart_tool/package_config.json'))
        .writeAsStringSync(fooBazDotDotPackageConfig);
    var raw = new CompilerOptions()..fileSystem = fileSystem;
    var processed = new ProcessedOptions(
        options: raw,
        inputs: [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
    var uriTranslator = await processed.getUriTranslator();
    checkPackageExpansion('foo', 'base/baz', uriTranslator.packages);
  }

  Future<void> test_getUriTranslator_implicitPackagesFile_noPackages() async {
    // Create the base directory.
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///base/location/'))
        .createDirectory();
    var errors = [];
    // There is no .dart_tool/package_config.json file.
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var processed = new ProcessedOptions(
        options: raw,
        inputs: [Uri.parse('org-dartlang-test:///base/location/script.dart')]);
    var uriTranslator = await processed.getUriTranslator();
    expect(errors, isEmpty);
    expect(uriTranslator.packages.packages, isEmpty);
  }

  Future<void> test_getUriTranslator_noPackages() async {
    var errors = <DiagnosticMessage>[];
    // .dart_tool/package_config.json file should be ignored when specifying
    // empty Uri.
    fileSystem
        .entityForUri(
            Uri.parse('org-dartlang-test:///.dart_tool/package_config.json'))
        .writeAsStringSync(fooBarPackageConfig);
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..packagesFileUri = new Uri()
      ..onDiagnostic = errors.add;
    var processed = new ProcessedOptions(options: raw);
    var uriTranslator = await processed.getUriTranslator();
    expect(uriTranslator.packages.packages, isEmpty);
    expect((errors.single as FormattedMessage).problemMessage,
        startsWith(_stringPrefixOf(templateCantReadFile)));
  }

  Future<void> test_validateOptions_noInputs() async {
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');
    var errors = <DiagnosticMessage>[];
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options = new ProcessedOptions(options: raw);
    var result = await options.validateOptions();
    expect((errors.single as FormattedMessage).problemMessage,
        messageMissingInput.problemMessage);
    expect(result, isFalse);
  }

  Future<void> test_validateOptions_input_doesnt_exist() async {
    var errors = [];
    var raw = new CompilerOptions()
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    var result = await options.validateOptions();
    expect(errors, isEmpty);
    expect(result, isTrue);
  }

  Future<void> test_validateOptions_root_exists() async {
    var sdkRoot = Uri.parse('org-dartlang-test:///sdk/root/');
    fileSystem
        // Note: this test is a bit hackish because the memory file system
        // doesn't have the notion of directories.
        .entityForUri(sdkRoot)
        .writeAsStringSync('\n');
    fileSystem
        .entityForUri(sdkRoot.resolve('vm_platform_strong.dill'))
        .writeAsStringSync('\n');
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');

    var errors = [];
    var raw = new CompilerOptions()
      ..sdkRoot = sdkRoot
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    var result = await options.validateOptions();
    // Note: we check this first so test failures show the cause directly.
    expect(errors, isEmpty);
    expect(result, isTrue);
  }

  Future<void> test_validateOptions_root_doesnt_exists() async {
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');
    var sdkRoot = Uri.parse('org-dartlang-test:///sdk/root');
    var errors = <DiagnosticMessage>[];
    var raw = new CompilerOptions()
      ..sdkRoot = sdkRoot
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    expect(await options.validateOptions(), isFalse);
    expect((errors.first as FormattedMessage).problemMessage,
        startsWith(_stringPrefixOf(templateSdkRootNotFound)));
  }

  Future<void> test_validateOptions_summary_exists() async {
    var sdkSummary = Uri.parse('org-dartlang-test:///sdk/root/outline.dill');
    fileSystem.entityForUri(sdkSummary).writeAsStringSync('\n');
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');

    var errors = [];
    var raw = new CompilerOptions()
      ..sdkSummary = sdkSummary
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    var result = await options.validateOptions();
    expect(errors, isEmpty);
    expect(result, isTrue);
  }

  Future<void> test_validateOptions_summary_doesnt_exists() async {
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');
    var sdkSummary = Uri.parse('org-dartlang-test:///sdk/root/outline.dill');
    var errors = <DiagnosticMessage>[];
    var raw = new CompilerOptions()
      ..sdkSummary = sdkSummary
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    expect(await options.validateOptions(), isFalse);
    expect((errors.single as FormattedMessage).problemMessage,
        startsWith(_stringPrefixOf(templateSdkSummaryNotFound)));
  }

  Future<void> test_validateOptions_inferred_summary_exists() async {
    var sdkRoot = Uri.parse('org-dartlang-test:///sdk/root/');
    var sdkSummary =
        Uri.parse('org-dartlang-test:///sdk/root/vm_platform_strong.dill');
    fileSystem.entityForUri(sdkRoot).writeAsStringSync('\n');
    fileSystem.entityForUri(sdkSummary).writeAsStringSync('\n');
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');

    var errors = [];
    var raw = new CompilerOptions()
      ..sdkRoot = sdkRoot
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    var result = await options.validateOptions();
    expect(errors, isEmpty);
    expect(result, isTrue);
  }

  Future<void> test_validateOptions_inferred_summary_doesnt_exists() async {
    var sdkRoot = Uri.parse('org-dartlang-test:///sdk/root/');
    var sdkSummary = Uri.parse('org-dartlang-test:///sdk/root/outline.dill');
    fileSystem.entityForUri(sdkRoot).writeAsStringSync('\n');
    fileSystem
        .entityForUri(Uri.parse('org-dartlang-test:///foo.dart'))
        .writeAsStringSync('main(){}\n');
    var errors = <DiagnosticMessage>[];
    var raw = new CompilerOptions()
      ..sdkSummary = sdkSummary
      ..fileSystem = fileSystem
      ..onDiagnostic = errors.add;
    var options =
        new ProcessedOptions(options: raw, inputs: [Uri.parse('foo.dart')]);
    expect(await options.validateOptions(), isFalse);
    expect((errors.single as FormattedMessage).problemMessage,
        startsWith(_stringPrefixOf(templateSdkSummaryNotFound)));
  }

  /// Returns the longest prefix of the text in a message template that doesn't
  /// mention a template argument.
  String _stringPrefixOf(Template template) {
    var messageTemplate = template.problemMessageTemplate;
    var index = messageTemplate.indexOf('#');
    var prefix = messageTemplate.substring(0, index - 1);

    // Check that the prefix is not empty and that it contains more than one
    // word.
    expect(prefix.length > 0, isTrue);
    expect(prefix.contains(' '), isTrue);
    return prefix;
  }
}
