// Copyright (c) 2019, 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.md file.

// @dart = 2.9

import 'dart:async' show Timer;
import 'dart:convert' show jsonEncode;
import 'dart:io' show File, Platform, exitCode;
import 'dart:isolate' show Isolate, ReceivePort, SendPort;

import 'package:args/args.dart' show ArgParser;
import 'package:testing/src/chain.dart' show CreateContext, Result, Step;
import 'package:testing/src/expectation.dart' show Expectation;
import 'package:testing/src/log.dart' show Logger;
import 'package:testing/src/run.dart' show runMe;
import 'package:testing/src/suite.dart' as testing show Suite;
import 'package:testing/src/test_description.dart' show TestDescription;

import 'fasta/expression_suite.dart' as expression show createContext;
import 'fasta/fast_strong_suite.dart' as fast_strong show createContext;
import 'fasta/incremental_suite.dart' as incremental show createContext;
import 'fasta/messages_suite.dart' as messages show createContext;
import 'fasta/outline_suite.dart' as outline show createContext;
import 'fasta/strong_tester.dart' as strong show createContext;
import 'fasta/text_serialization_tester.dart' as text_serialization
    show createContext;
import 'fasta/textual_outline_suite.dart' as textual_outline show createContext;
import 'fasta/weak_suite.dart' as weak show createContext;
import 'incremental_bulk_compiler_smoke_suite.dart' as incremental_bulk_compiler
    show createContext;
import 'incremental_load_from_dill_suite.dart' as incremental_load
    show createContext;
import 'lint_suite.dart' as lint show createContext;
import 'parser_suite.dart' as parser show createContext;
import 'parser_all_suite.dart' as parserAll show createContext;
import 'spelling_test_not_src_suite.dart' as spelling_not_src
    show createContext;
import 'spelling_test_src_suite.dart' as spelling_src show createContext;

const suiteNamePrefix = "pkg/front_end/test";

class Options {
  final String configurationName;
  final bool verbose;
  final bool printFailureLog;
  final Uri outputDirectory;
  final String testFilter;
  final List<String> environmentOptions;

  Options(this.configurationName, this.verbose, this.printFailureLog,
      this.outputDirectory, this.testFilter, this.environmentOptions);

  static Options parse(List<String> args) {
    var parser = new ArgParser()
      ..addOption("named-configuration",
          abbr: "n",
          help: "configuration name to use for emitting json result files")
      ..addOption("output-directory",
          help: "directory to which results.json and logs.json are written")
      ..addFlag("verbose",
          abbr: "v", help: "print additional information", defaultsTo: false)
      ..addFlag("print",
          abbr: "p", help: "print failure logs", defaultsTo: false)
      ..addMultiOption('environment',
          abbr: 'D', help: "environment options for the test suite");
    var parsedArguments = parser.parse(args);
    String outputPath = parsedArguments["output-directory"] ?? ".";
    Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
    String filter;
    if (parsedArguments.rest.length == 1) {
      filter = parsedArguments.rest.single;
      if (filter.startsWith("$suiteNamePrefix/")) {
        filter = filter.substring(suiteNamePrefix.length + 1);
      }
    }
    return Options(
        parsedArguments["named-configuration"],
        parsedArguments["verbose"],
        parsedArguments["print"],
        outputDirectory,
        filter,
        parsedArguments['environment']);
  }
}

class ResultLogger implements Logger {
  final String prefix;
  final bool verbose;
  final bool printFailureLog;
  final SendPort resultsPort;
  final SendPort logsPort;
  final Map<String, Stopwatch> stopwatches = {};
  final String configurationName;
  final Set<String> seenTests = {};

  ResultLogger(this.prefix, this.resultsPort, this.logsPort, this.verbose,
      this.printFailureLog, this.configurationName);

  String getTestName(TestDescription description) {
    return "$prefix/${description.shortName}";
  }

  @override
  void logMessage(Object message) {}

  @override
  void logNumberedLines(String text) {}

  @override
  void logProgress(String message) {}

  @override
  void logStepComplete(int completed, int failed, int total,
      testing.Suite suite, TestDescription description, Step step) {}

  @override
  void logStepStart(int completed, int failed, int total, testing.Suite suite,
      TestDescription description, Step step) {}

  @override
  void logSuiteStarted(testing.Suite suite) {}

  @override
  void logSuiteComplete(testing.Suite suite) {}

  handleTestResult(TestDescription testDescription, Result result,
      String fullSuiteName, bool matchedExpectations) {
    String testName = getTestName(testDescription);
    String suite = "pkg";
    String shortTestName = testName.substring(suite.length + 1);
    resultsPort.send(jsonEncode({
      "name": testName,
      "configuration": configurationName,
      "suite": suite,
      "test_name": shortTestName,
      "time_ms": stopwatches[testName].elapsedMilliseconds,
      "expected": "Pass",
      "result": matchedExpectations ? "Pass" : "Fail",
      "matches": matchedExpectations,
    }));
    if (!matchedExpectations) {
      StringBuffer sb = new StringBuffer();
      sb.write(result.log);
      if (result.error != null) {
        sb.write("\n\n${result.error}");
      }
      if (result.trace != null) {
        sb.write("\n\n${result.trace}");
      }
      sb.write("\n\nTo re-run this test, run:");
      sb.write("\n\n   dart pkg/front_end/test/unit_test_suites.dart -p "
          "$testName");
      if (result.autoFixCommand != null) {
        sb.write("\n\nTo automatically update the test expectations, run:");
        sb.write("\n\n   dart pkg/front_end/test/unit_test_suites.dart -p "
            "$testName -D${result.autoFixCommand}");
        if (result.canBeFixWithUpdateExpectations) {
          sb.write('\n\nTo update test expectations for all tests at once, '
              'run:');
          sb.write('\n\n  dart pkg/front_end/tool/update_expectations.dart');
          sb.write('\n\nNote that this takes a long time and should only be '
              'used when many tests need updating.\n');
        }
      }
      String failureLog = sb.toString();
      String outcome = "${result.outcome}";
      logsPort.send(jsonEncode({
        "name": testName,
        "configuration": configurationName,
        "result": outcome,
        "log": failureLog,
      }));
      if (printFailureLog) {
        print('FAILED: $testName: $outcome');
        print(failureLog);
      }
    }
    if (verbose) {
      String result = matchedExpectations ? "PASS" : "FAIL";
      print("${testName}: ${result}");
    }
  }

  void logTestStart(int completed, int failed, int total, testing.Suite suite,
      TestDescription description) {
    String name = getTestName(description);
    stopwatches[name] = Stopwatch()..start();
  }

  @override
  void logTestComplete(int completed, int failed, int total,
      testing.Suite suite, TestDescription description) {}

  @override
  void logUncaughtError(error, StackTrace stackTrace) {}

  void logExpectedResult(testing.Suite suite, TestDescription description,
      Result result, Set<Expectation> expectedOutcomes) {
    handleTestResult(description, result, prefix, true);
  }

  @override
  void logUnexpectedResult(testing.Suite suite, TestDescription description,
      Result result, Set<Expectation> expectedOutcomes) {
    // The test framework (pkg/testing) calls the logger with an unexpected
    // results a second time to create a summary. We ignore the second call
    // here.
    String testName = getTestName(description);
    if (seenTests.contains(testName)) return;
    seenTests.add(testName);
    handleTestResult(description, result, prefix, false);
  }
}

class Suite {
  final String name;
  final CreateContext createContext;
  final String testingRootPath;
  final String path;
  final int shardCount;
  final int shard;
  final String prefix;

  const Suite(this.name, this.createContext, this.testingRootPath,
      {this.path, this.shardCount: 1, this.shard: 0, String prefix})
      : prefix = prefix ?? name;
}

const List<Suite> suites = [
  const Suite(
      "fasta/expression", expression.createContext, "../../testing.json"),
  const Suite("fasta/outline", outline.createContext, "../../testing.json"),
  const Suite(
      "fasta/fast_strong", fast_strong.createContext, "../../testing.json"),
  const Suite(
      "fasta/incremental", incremental.createContext, "../../testing.json"),
  const Suite("fasta/messages", messages.createContext, "../../testing.json"),
  const Suite("fasta/text_serialization1", text_serialization.createContext,
      "../../testing.json",
      path: "fasta/text_serialization_tester.dart",
      shardCount: 4,
      shard: 0,
      prefix: "fasta/text_serialization"),
  const Suite("fasta/text_serialization2", text_serialization.createContext,
      "../../testing.json",
      path: "fasta/text_serialization_tester.dart",
      shardCount: 4,
      shard: 1,
      prefix: "fasta/text_serialization"),
  const Suite("fasta/text_serialization3", text_serialization.createContext,
      "../../testing.json",
      path: "fasta/text_serialization_tester.dart",
      shardCount: 4,
      shard: 2,
      prefix: "fasta/text_serialization"),
  const Suite("fasta/text_serialization4", text_serialization.createContext,
      "../../testing.json",
      path: "fasta/text_serialization_tester.dart",
      shardCount: 4,
      shard: 3,
      prefix: "fasta/text_serialization"),
  const Suite("fasta/strong1", strong.createContext, "../../testing.json",
      path: "fasta/strong_tester.dart",
      shardCount: 4,
      shard: 0,
      prefix: "fasta/strong"),
  const Suite("fasta/strong2", strong.createContext, "../../testing.json",
      path: "fasta/strong_tester.dart",
      shardCount: 4,
      shard: 1,
      prefix: "fasta/strong"),
  const Suite("fasta/strong3", strong.createContext, "../../testing.json",
      path: "fasta/strong_tester.dart",
      shardCount: 4,
      shard: 2,
      prefix: "fasta/strong"),
  const Suite("fasta/strong4", strong.createContext, "../../testing.json",
      path: "fasta/strong_tester.dart",
      shardCount: 4,
      shard: 3,
      prefix: "fasta/strong"),
  const Suite("incremental_bulk_compiler_smoke",
      incremental_bulk_compiler.createContext, "../testing.json"),
  const Suite("incremental_load_from_dill", incremental_load.createContext,
      "../testing.json"),
  const Suite("lint", lint.createContext, "../testing.json"),
  const Suite("parser", parser.createContext, "../testing.json"),
  const Suite("parser_all", parserAll.createContext, "../testing.json"),
  const Suite("spelling_test_not_src", spelling_not_src.createContext,
      "../testing.json"),
  const Suite(
      "spelling_test_src", spelling_src.createContext, "../testing.json"),
  const Suite("fasta/weak", weak.createContext, "../../testing.json"),
  const Suite("fasta/textual_outline", textual_outline.createContext,
      "../../testing.json"),
];

const Duration timeoutDuration = Duration(minutes: 30);

class SuiteConfiguration {
  final String name;
  final SendPort resultsPort;
  final SendPort logsPort;
  final bool verbose;
  final bool printFailureLog;
  final String configurationName;
  final String testFilter;
  final List<String> environmentOptions;

  const SuiteConfiguration(
      this.name,
      this.resultsPort,
      this.logsPort,
      this.verbose,
      this.printFailureLog,
      this.configurationName,
      this.testFilter,
      this.environmentOptions);
}

void runSuite(SuiteConfiguration configuration) {
  Suite suite = suites.where((s) => s.name == configuration.name).single;
  String name = suite.prefix;
  String fullSuiteName = "$suiteNamePrefix/$name";
  Uri suiteUri = Platform.script.resolve(suite.path ?? "${name}_suite.dart");
  if (!new File.fromUri(suiteUri).existsSync()) {
    throw "File doesn't exist: $suiteUri";
  }
  ResultLogger logger = ResultLogger(
      fullSuiteName,
      configuration.resultsPort,
      configuration.logsPort,
      configuration.verbose,
      configuration.printFailureLog,
      configuration.configurationName);
  runMe(<String>[
    if (configuration.testFilter != null) configuration.testFilter,
    if (configuration.environmentOptions != null)
      for (String option in configuration.environmentOptions) '-D${option}',
  ], suite.createContext,
      me: suiteUri,
      configurationPath: suite.testingRootPath,
      logger: logger,
      shards: suite.shardCount,
      shard: suite.shard);
}

void writeLinesToFile(Uri uri, List<String> lines) async {
  await File.fromUri(uri).writeAsString(lines.map((line) => "$line\n").join());
}

main([List<String> arguments = const <String>[]]) async {
  List<String> results = [];
  List<String> logs = [];
  Options options = Options.parse(arguments);
  ReceivePort resultsPort = new ReceivePort()
    ..listen((resultEntry) => results.add(resultEntry));
  ReceivePort logsPort = new ReceivePort()
    ..listen((logEntry) => logs.add(logEntry));
  List<Future<bool>> futures = [];
  // Run test suites and record the results and possible failure logs.
  for (Suite suite in suites) {
    String name = suite.name;
    String filter = options.testFilter;
    if (filter != null) {
      // Skip suites that are not hit by the test filter, is there is one.
      if (!filter.startsWith(suite.prefix)) {
        continue;
      }
      // Remove the 'fasta/' from filters, if there, because it is not used
      // in the name defined in testing.json.
      if (filter.startsWith("fasta/")) {
        filter = filter.substring("fasta/".length);
      }
    }
    // Start the test suite in a new isolate.
    ReceivePort exitPort = new ReceivePort();
    SuiteConfiguration configuration = SuiteConfiguration(
        name,
        resultsPort.sendPort,
        logsPort.sendPort,
        options.verbose,
        options.printFailureLog,
        options.configurationName,
        filter,
        options.environmentOptions);
    Future future = Future<bool>(() async {
      Stopwatch stopwatch = Stopwatch()..start();
      print("Running suite $name");
      Isolate isolate = await Isolate.spawn<SuiteConfiguration>(
          runSuite, configuration,
          onExit: exitPort.sendPort);
      bool timedOut = false;
      Timer timer = Timer(timeoutDuration, () {
        timedOut = true;
        print("Suite $name timed out after "
            "${timeoutDuration.inMilliseconds}ms");
        isolate.kill(priority: Isolate.immediate);
      });
      await exitPort.first;
      timer.cancel();
      if (!timedOut) {
        int seconds = stopwatch.elapsedMilliseconds ~/ 1000;
        print("Suite $name finished (took ${seconds} seconds)");
      }
      return timedOut;
    });
    futures.add(future);
  }
  // Wait for isolates to terminate and clean up.
  Iterable<bool> timeouts = await Future.wait(futures);
  resultsPort.close();
  logsPort.close();
  // Write results.json and logs.json.
  Uri resultJsonUri = options.outputDirectory.resolve("results.json");
  Uri logsJsonUri = options.outputDirectory.resolve("logs.json");
  await writeLinesToFile(resultJsonUri, results);
  await writeLinesToFile(logsJsonUri, logs);
  print("Log files written to ${resultJsonUri.toFilePath()} and"
      " ${logsJsonUri.toFilePath()}");
  // Return with exit code 1 if at least one suite timed out.
  bool timeout = timeouts.any((timeout) => timeout);
  if (timeout) {
    exitCode = 1;
  } else {
    // The testing framework (package:testing) sets the exitCode to `1` if any
    // test failed, so we reset it here to indicate that the test runner was
    // successful.
    exitCode = 0;
  }
}
