// 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.

// @dart = 2.7

import 'dart:async';
import 'dart:io';

import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/kernel/element_map_impl.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;

import '../helpers/compiler_helper.dart';
import '../helpers/memory_compiler.dart';
import '../equivalence/id_equivalence.dart';

export 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
    show DataInterpreter, StringDataInterpreter;
export '../helpers/memory_compiler.dart' show CollectedMessage;

const String specMarker = 'spec';
const String prodMarker = 'prod';
const String canaryMarker = 'canary';
const String twoDeferredFragmentMarker = 'two-frag';
const String threeDeferredFragmentMarker = 'three-frag';

const TestConfig specConfig = TestConfig(specMarker, 'compliance mode', []);

const TestConfig prodConfig = TestConfig(prodMarker, 'production mode',
    [Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString]);

const TestConfig canaryConfig =
    TestConfig(canaryMarker, 'canary mode', [Flags.canary]);

const TestConfig twoDeferredFragmentConfig = TestConfig(
    twoDeferredFragmentMarker,
    'two deferred fragment mode',
    ['${Flags.mergeFragmentsThreshold}=2']);

const TestConfig threeDeferredFragmentConfig = TestConfig(
    threeDeferredFragmentMarker,
    'three deferred fragment mode',
    ['${Flags.mergeFragmentsThreshold}=3']);

/// Default internal configurations not including experimental features.
const List<TestConfig> defaultInternalConfigs = [specConfig, prodConfig];

/// All internal configurations including experimental features.
const List<TestConfig> allInternalConfigs = [specConfig, prodConfig];

/// Compliance mode configurations (with strong mode checks) including
/// experimental features.
const List<TestConfig> allSpecConfigs = [specConfig];

/// Test configuration used in tests shared with CFE.
const TestConfig sharedConfig = TestConfig(dart2jsMarker, 'dart2js', []);

abstract class DataComputer<T> {
  const DataComputer();

  /// Called before testing to setup flags needed for data collection.
  void setup() {}

  /// Function that computes a data mapping for [member].
  ///
  /// Fills [actualMap] with the data.
  void computeMemberData(
      Compiler compiler, MemberEntity member, Map<Id, ActualData<T>> actualMap,
      {bool verbose});

  /// Returns `true` if frontend member should be tested.
  bool get testFrontend => false;

  /// Function that computes a data mapping for [cls].
  ///
  /// Fills [actualMap] with the data.
  void computeClassData(
      Compiler compiler, ClassEntity cls, Map<Id, ActualData<T>> actualMap,
      {bool verbose}) {}

  /// Function that computes a data mapping for [library].
  ///
  /// Fills [actualMap] with the data.
  void computeLibraryData(Compiler compiler, LibraryEntity library,
      Map<Id, ActualData<T>> actualMap,
      {bool verbose}) {}

  /// Returns `true` if this data computer supports tests with compile-time
  /// errors.
  ///
  /// Unsuccessful compilation might leave the compiler in an inconsistent
  /// state, so this testing feature is opt-in.
  bool get supportsErrors => false;

  /// Returns data corresponding to [error].
  T computeErrorData(Compiler compiler, Id id, List<CollectedMessage> errors) =>
      null;

  DataInterpreter<T> get dataValidator;
}

const String stopAfterTypeInference = 'stopAfterTypeInference';

/// Reports [message] as an error using [spannable] as error location.
void reportError(
    DiagnosticReporter reporter, Spannable spannable, String message) {
  reporter
      .reportErrorMessage(spannable, MessageKind.GENERIC, {'text': message});
}

/// Compute actual data for all members defined in the program with the
/// [entryPoint] and [memorySourceFiles].
///
/// Actual data is computed using [computeMemberData].
Future<CompiledData<T>> computeData<T>(Uri entryPoint,
    Map<String, String> memorySourceFiles, DataComputer<T> dataComputer,
    {List<String> options: const <String>[],
    bool verbose: false,
    bool testFrontend: false,
    bool printCode: false,
    bool forUserLibrariesOnly: true,
    bool skipUnprocessedMembers: false,
    bool skipFailedCompilations: false,
    Iterable<Id> globalIds: const <Id>[]}) async {
  OutputCollector outputCollector = new OutputCollector();
  DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
  Uri packageConfig;
  Uri wantedPackageConfig = createUriForFileName(".packages");
  for (String key in memorySourceFiles.keys) {
    if (key == wantedPackageConfig.path) {
      packageConfig = wantedPackageConfig;
      break;
    }
  }
  CompilationResult result = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: memorySourceFiles,
      outputProvider: outputCollector,
      diagnosticHandler: diagnosticCollector,
      options: options,
      beforeRun: (compiler) {
        compiler.stopAfterTypeInference =
            options.contains(stopAfterTypeInference);
      },
      packageConfig: packageConfig,
      unsafeToTouchSourceFiles: true);
  if (!result.isSuccess) {
    if (skipFailedCompilations) return null;
    Expect.isTrue(
        dataComputer.supportsErrors,
        "Compilation with compile-time errors not supported for this "
        "testing setup.");
  }
  if (printCode) {
    print('--code------------------------------------------------------------');
    print(outputCollector.getOutput('', OutputType.js));
    print('------------------------------------------------------------------');
  }
  Compiler compiler = result.compiler;

  Map<Uri, Map<Id, ActualData<T>>> actualMaps = <Uri, Map<Id, ActualData<T>>>{};
  Map<Id, ActualData<T>> globalData = <Id, ActualData<T>>{};

  Map<Id, ActualData<T>> actualMapForUri(Uri uri) {
    return actualMaps.putIfAbsent(uri, () => <Id, ActualData<T>>{});
  }

  Map<Uri, Map<int, List<CollectedMessage>>> errors = {};
  for (CollectedMessage error in diagnosticCollector.errors) {
    Map<int, List<CollectedMessage>> map =
        errors.putIfAbsent(error.uri, () => {});
    List<CollectedMessage> list = map.putIfAbsent(error.begin, () => []);
    list.add(error);
  }

  errors.forEach((Uri uri, Map<int, List<CollectedMessage>> map) {
    map.forEach((int offset, List<CollectedMessage> list) {
      NodeId id = new NodeId(offset, IdKind.error);
      T data = dataComputer.computeErrorData(compiler, id, list);
      if (data != null) {
        Map<Id, ActualData<T>> actualMap = actualMapForUri(uri);
        actualMap[id] = new ActualData<T>(id, data, uri, offset, list);
      }
    });
  });

  if (!result.isSuccess) {
    return new Dart2jsCompiledData<T>(
        compiler, null, entryPoint, actualMaps, globalData);
  }

  dynamic closedWorld = testFrontend
      ? compiler.frontendClosedWorldForTesting
      : compiler.backendClosedWorldForTesting;
  ElementEnvironment elementEnvironment = closedWorld?.elementEnvironment;
  CommonElements commonElements = closedWorld.commonElements;

  Map<Id, ActualData<T>> actualMapFor(Entity entity) {
    SourceSpan span =
        compiler.backendStrategy.spanFromSpannable(entity, entity);
    return actualMapForUri(span.uri);
  }

  void processMember(MemberEntity member, Map<Id, ActualData<T>> actualMap) {
    if (member.isAbstract) {
      return;
    }
    if (skipUnprocessedMembers &&
        !closedWorld.processedMembers.contains(member)) {
      return;
    }
    if (member.enclosingClass != null) {
      if (elementEnvironment.isEnumClass(member.enclosingClass)) {
        if (member.isConstructor ||
            member.isInstanceMember ||
            member.name == 'values') {
          return;
        }
      }
      if (member.isConstructor &&
          elementEnvironment.isMixinApplication(member.enclosingClass)) {
        return;
      }
    }
    dataComputer.computeMemberData(compiler, member, actualMap,
        verbose: verbose);
  }

  void processClass(ClassEntity cls, Map<Id, ActualData<T>> actualMap) {
    if (skipUnprocessedMembers && !closedWorld.isImplemented(cls)) {
      return;
    }
    dataComputer.computeClassData(compiler, cls, actualMap, verbose: verbose);
  }

  bool excludeLibrary(LibraryEntity library) {
    return forUserLibrariesOnly &&
        (library.canonicalUri.scheme == 'dart' ||
            library.canonicalUri.scheme == 'package');
  }

  ir.Library getIrLibrary(LibraryEntity library) {
    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
    KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
    LibraryEntity kLibrary =
        elementMap.elementEnvironment.lookupLibrary(library.canonicalUri);
    return elementMap.getLibraryNode(kLibrary);
  }

  for (LibraryEntity library in elementEnvironment.libraries) {
    if (excludeLibrary(library) &&
        !memorySourceFiles.containsKey(getIrLibrary(library).fileUri.path)) {
      continue;
    }

    dataComputer.computeLibraryData(
        compiler, library, actualMapForUri(getIrLibrary(library).fileUri),
        verbose: verbose);
    elementEnvironment.forEachClass(library, (ClassEntity cls) {
      processClass(cls, actualMapFor(cls));
    });
  }

  for (MemberEntity member in closedWorld.processedMembers) {
    if (excludeLibrary(member.library) &&
        !memorySourceFiles
            .containsKey(getIrLibrary(member.library).fileUri.path)) continue;
    processMember(member, actualMapFor(member));
  }

  List<LibraryEntity> globalLibraries = <LibraryEntity>[
    commonElements.coreLibrary,
    elementEnvironment.lookupLibrary(Uri.parse('dart:collection')),
    commonElements.interceptorsLibrary,
    commonElements.jsHelperLibrary,
    commonElements.asyncLibrary,
  ];

  LibraryEntity htmlLibrary =
      elementEnvironment.lookupLibrary(Uri.parse('dart:html'), required: false);
  if (htmlLibrary != null) {
    globalLibraries.add(htmlLibrary);
  }

  ClassEntity getGlobalClass(String className) {
    ClassEntity cls;
    for (LibraryEntity library in globalLibraries) {
      cls ??= elementEnvironment.lookupClass(library, className);
    }
    Expect.isNotNull(
        cls,
        "Global class '$className' not found in the global "
        "libraries: ${globalLibraries.map((l) => l.canonicalUri).join(', ')}");
    return cls;
  }

  MemberEntity getGlobalMember(String memberName) {
    MemberEntity member;
    for (LibraryEntity library in globalLibraries) {
      member ??= elementEnvironment.lookupLibraryMember(library, memberName);
    }
    Expect.isNotNull(
        member,
        "Global member '$memberName' not found in the global "
        "libraries: ${globalLibraries.map((l) => l.canonicalUri).join(', ')}");
    return member;
  }

  for (Id id in globalIds) {
    if (id is MemberId) {
      MemberEntity member;
      if (id.className != null) {
        ClassEntity cls = getGlobalClass(id.className);
        member = elementEnvironment.lookupClassMember(cls, id.memberName);
        member ??= elementEnvironment.lookupConstructor(cls, id.memberName);
        Expect.isNotNull(
            member, "Global member '$member' not found in class $cls.");
      } else {
        member = getGlobalMember(id.memberName);
      }
      processMember(member, globalData);
    } else if (id is ClassId) {
      ClassEntity cls = getGlobalClass(id.className);
      processClass(cls, globalData);
    } else {
      throw new UnsupportedError("Unexpected global id: $id");
    }
  }

  return new Dart2jsCompiledData<T>(
      compiler, elementEnvironment, entryPoint, actualMaps, globalData);
}

class Dart2jsCompiledData<T> extends CompiledData<T> {
  final Compiler compiler;
  final ElementEnvironment elementEnvironment;

  Dart2jsCompiledData(
      this.compiler,
      this.elementEnvironment,
      Uri mainUri,
      Map<Uri, Map<Id, ActualData<T>>> actualMaps,
      Map<Id, ActualData<T>> globalData)
      : super(mainUri, actualMaps, globalData);

  @override
  int getOffsetFromId(Id id, Uri uri) {
    return compiler.reporter
        .spanFromSpannable(computeSpannable(elementEnvironment, uri, id))
        ?.begin;
  }

  @override
  void reportError(Uri uri, int offset, String message,
      {bool succinct: false}) {
    compiler.reporter.reportErrorMessage(
        computeSourceSpanFromUriOffset(uri, offset),
        MessageKind.GENERIC,
        {'text': message});
  }
}

typedef void Callback();

class TestConfig {
  final String marker;
  final String name;
  final List<String> options;

  const TestConfig(this.marker, this.name, this.options);
}

/// Check code for all test files int [data] using [computeFromAst] and
/// [computeFromKernel] from the respective front ends. If [skipForKernel]
/// contains the name of the test file it isn't tested for kernel.
///
/// [libDirectory] contains the directory for any supporting libraries that need
/// to be loaded. We expect supporting libraries to have the same prefix as the
/// original test in [dataDir]. So, for example, if testing `foo.dart` in
/// [dataDir], then this function will consider any files named `foo.*\.dart`,
/// such as `foo2.dart`, `foo_2.dart`, and `foo_blah_blah_blah.dart` in
/// [libDirectory] to be supporting library files for `foo.dart`.
/// [setUpFunction] is called once for every test that is executed.
/// If [forUserSourceFilesOnly] is true, we examine the elements in the main
/// file and any supporting libraries.
Future<void> checkTests<T>(Directory dataDir, DataComputer<T> dataComputer,
    {List<String> skip: const <String>[],
    bool filterActualData(IdValue idValue, ActualData<T> actualData),
    List<String> options: const <String>[],
    List<String> args: const <String>[],
    bool forUserLibrariesOnly: true,
    Callback setUpFunction,
    int shards: 1,
    int shardIndex: 0,
    void onTest(Uri uri),
    List<TestConfig> testedConfigs = const [],
    Map<String, List<String>> perTestOptions = const {}}) async {
  if (testedConfigs.isEmpty) testedConfigs = defaultInternalConfigs;
  Set<String> testedMarkers =
      testedConfigs.map((config) => config.marker).toSet();
  Expect.isTrue(
      testedConfigs.length == testedMarkers.length,
      "Unexpected test markers $testedMarkers. "
      "Tested configs: $testedConfigs.");

  dataComputer.setup();

  Future<Map<String, TestResult<T>>> checkTest(TestData testData,
      {bool testAfterFailures,
      bool verbose,
      bool succinct,
      bool printCode,
      Map<String, List<String>> skipMap,
      Uri nullUri}) async {
    for (TestConfig testConfiguration in testedConfigs) {
      Expect.isTrue(
          testData.expectedMaps.containsKey(testConfiguration.marker),
          "Unexpected test marker '${testConfiguration.marker}'. "
          "Supported markers: ${testData.expectedMaps.keys}.");
    }

    String name = testData.name;
    List<String> testOptions = options.toList();
    if (name.endsWith('_ea.dart')) {
      testOptions.add(Flags.enableAsserts);
    }
    if (perTestOptions.containsKey(name)) {
      testOptions.addAll(perTestOptions[name]);
    }

    if (setUpFunction != null) setUpFunction();

    Map<String, TestResult<T>> results = {};
    if (skip.contains(name)) {
      print('--skipped ------------------------------------------------------');
    } else {
      for (TestConfig testConfiguration in testedConfigs) {
        if (skipForConfig(testData.name, testConfiguration.marker, skipMap)) {
          continue;
        }
        print('--from (${testConfiguration.name})-------------');
        results[testConfiguration.marker] = await runTestForConfiguration(
            testConfiguration, dataComputer, testData, testOptions,
            filterActualData: filterActualData,
            verbose: verbose,
            succinct: succinct,
            testAfterFailures: testAfterFailures,
            forUserLibrariesOnly: forUserLibrariesOnly,
            printCode: printCode);
      }
    }
    return results;
  }

  await runTests<T>(dataDir,
      args: args,
      shards: shards,
      shardIndex: shardIndex,
      onTest: onTest,
      createUriForFileName: createUriForFileName,
      onFailure: Expect.fail,
      runTest: checkTest);
}

Uri createUriForFileName(String fileName) {
  // Pretend this is a web/native test to allow use of 'native'
  // keyword and import of private libraries.
  return Uri.parse('memory:sdk/tests/web/native/$fileName');
}

Future<TestResult<T>> runTestForConfiguration<T>(TestConfig testConfiguration,
    DataComputer<T> dataComputer, TestData testData, List<String> options,
    {bool filterActualData(IdValue idValue, ActualData<T> actualData),
    bool verbose: false,
    bool succinct: false,
    bool printCode: false,
    bool forUserLibrariesOnly: true,
    bool testAfterFailures: false}) async {
  MemberAnnotations<IdValue> annotations =
      testData.expectedMaps[testConfiguration.marker];
  CompiledData<T> compiledData = await computeData(
      testData.entryPoint, testData.memorySourceFiles, dataComputer,
      options: [...options, ...testConfiguration.options],
      verbose: verbose,
      printCode: printCode,
      testFrontend: dataComputer.testFrontend,
      forUserLibrariesOnly: forUserLibrariesOnly,
      globalIds: annotations.globalData.keys);
  return await checkCode(testConfiguration.name, testData.testFileUri,
      testData.code, annotations, compiledData, dataComputer.dataValidator,
      filterActualData: filterActualData,
      fatalErrors: !testAfterFailures,
      onFailure: Expect.fail,
      succinct: succinct);
}

/// Compute a [Spannable] from an [id] in the library [mainUri].
Spannable computeSpannable(
    ElementEnvironment elementEnvironment, Uri mainUri, Id id) {
  if (id is NodeId) {
    return new SourceSpan(mainUri, id.value, id.value + 1);
  } else if (id is MemberId) {
    if (elementEnvironment == null) {
      // If compilation resulted in error we might not have an
      // element environment.
      return NO_LOCATION_SPANNABLE;
    }
    String memberName = id.memberName;
    bool isSetter = false;
    if (memberName != '[]=' && memberName != '==' && memberName.endsWith('=')) {
      isSetter = true;
      memberName = memberName.substring(0, memberName.length - 1);
    }
    LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
    if (id.className != null) {
      ClassEntity cls = elementEnvironment.lookupClass(library, id.className);
      if (cls == null) {
        // Constant expression in CFE might remove inlined parts of sources.
        print("No class '${id.className}' in $mainUri.");
        return NO_LOCATION_SPANNABLE;
      }
      MemberEntity member = elementEnvironment
          .lookupClassMember(cls, memberName, setter: isSetter);
      if (member == null) {
        ConstructorEntity constructor =
            elementEnvironment.lookupConstructor(cls, memberName);
        if (constructor == null) {
          // Constant expression in CFE might remove inlined parts of sources.
          print("No class member '${memberName}' in $cls.");
          return NO_LOCATION_SPANNABLE;
        }
        return constructor;
      }
      return member;
    } else {
      MemberEntity member = elementEnvironment
          .lookupLibraryMember(library, memberName, setter: isSetter);
      if (member == null) {
        // Constant expression in CFE might remove inlined parts of sources.
        print("No member '${memberName}' in $mainUri.");
        return NO_LOCATION_SPANNABLE;
      }
      return member;
    }
  } else if (id is ClassId) {
    LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
    ClassEntity cls = elementEnvironment.lookupClass(library, id.className);
    if (cls == null) {
      // Constant expression in CFE might remove inlined parts of sources.
      print("No class '${id.className}' in $mainUri.");
      return NO_LOCATION_SPANNABLE;
    }
    return cls;
  } else if (id is LibraryId) {
    return new SourceSpan(id.uri, null, null);
  }
  throw new UnsupportedError('Unsupported id $id.');
}
