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

import 'dart:async' show Future;
import 'dart:convert' show LineSplitter, utf8;
import 'dart:io' show File, Platform, Process, exitCode;

void main(List<String> args) async {
  // General idea: Launch - in separate processes - whatever we want to run
  // concurrently, capturing the stdout and stderr, printing it with some
  // prepended identification.
  // When all runs are done, fail if any fails.
  // Later we might be able to move it to the "testRunner"-system, if that
  // offers any advantages.

  print("NOTE: This machine has ${Platform.numberOfProcessors} processors!"
      "\n\n");

  List<WrappedProcess> startedProcesses = [];
  WrappedProcess? leakTest;
  {
    // Very slow: Leak-test.
    Uri leakTester =
        Platform.script.resolve("flutter_gallery_leak_tester.dart");
    if (!new File.fromUri(leakTester).existsSync()) {
      exitCode = 1;
      print("Couldn't find $leakTester");
    } else {
      // The tools/bots/flutter/compile_flutter.sh script passes `--path`
      // --- we'll just pass everything along.
      leakTest = await run(
        [
          leakTester.toString(),
          ...args,
        ],
        "leak test",
      );
      startedProcesses.add(leakTest);
    }
  }
  {
    // Slow: Leak-test with alternative invalidation.
    Uri leakTester =
        Platform.script.resolve("flutter_gallery_leak_tester.dart");
    if (!new File.fromUri(leakTester).existsSync()) {
      exitCode = 1;
      print("Couldn't find $leakTester");
    } else {
      // Note that the leak test run above will start checking out flutter
      // gallery (etc) and that it has to finish before starting this.
      // We therefore wait for the observatory line being printed before
      // starting. Wait at most 10 minutes though.

      // ignore: unawaited_futures
      () async {
        for (int i = 0; i < 10 * 60; i++) {
          if (leakTest == null || leakTest.observatoryLines.isNotEmpty) {
            break;
          }
          await Future.delayed(new Duration(seconds: 1));
        }

        // The tools/bots/flutter/compile_flutter.sh script passes `--path`
        // --- we'll just pass everything along.
        startedProcesses.add(await run(
          [
            leakTester.toString(),
            ...args,
            "--alternativeInvalidation",
          ],
          "leak test alternative invalidation",
        ));
      }();
    }
  }

  {
    // Weak suite with fuzzing.
    Uri weakSuite = Platform.script.resolve("fasta/weak_suite.dart");
    if (!new File.fromUri(weakSuite).existsSync()) {
      exitCode = 1;
      print("Couldn't find $weakSuite");
    } else {
      startedProcesses.add(await run(
        [
          weakSuite.toString(),
          "-DsemiFuzz=true",
        ],
        "weak suite",
      ));
    }
  }

  {
    // Strong suite with fuzzing.
    Uri strongSuite = Platform.script.resolve("fasta/strong_suite.dart");
    if (!new File.fromUri(strongSuite).existsSync()) {
      exitCode = 1;
      print("Couldn't find $strongSuite");
    } else {
      startedProcesses.add(await run(
        [
          strongSuite.toString(),
          "-DsemiFuzz=true",
        ],
        "strong suite",
      ));
    }
  }

  {
    // Leak tests of incremental suite tests.
    Uri incrementalLeakTest =
        Platform.script.resolve("vm_service_for_leak_detection.dart");
    if (!new File.fromUri(incrementalLeakTest).existsSync()) {
      exitCode = 1;
      print("Couldn't find $incrementalLeakTest");
    } else {
      startedProcesses.add(await run([
        incrementalLeakTest.toString(),
        "--weekly",
      ], "incremental leak test"));
    }
  }

  // Wait for everything to finish.
  List<int> exitCodes =
      await Future.wait(startedProcesses.map((e) => e.process.exitCode));
  if (exitCodes.where((e) => e != 0).isNotEmpty) {
    print("\n\nFound failures!:\n");
    // At least one failed.
    for (WrappedProcess p in startedProcesses) {
      int pExitCode = await p.process.exitCode;
      if (pExitCode != 0) {
        print("${p.id} failed with exist-code $pExitCode");
      }
    }

    throw "There were failures!";
  }
}

Future<WrappedProcess> run(List<String> args, String id) async {
  Stopwatch stopwatch = new Stopwatch()..start();
  Process process = await Process.start(
      Platform.resolvedExecutable, ["--enable-asserts", ...args]);
  List<String> observatoryLines = [];
  process.stderr
      .transform(utf8.decoder)
      .transform(new LineSplitter())
      .listen((line) {
    print("$id stderr> $line");
    if (line.contains("Observatory listening on")) {
      observatoryLines.add(line);
    }
  });
  process.stdout
      .transform(utf8.decoder)
      .transform(new LineSplitter())
      .listen((line) {
    print("$id stdout> $line");
    if (line.contains("Observatory listening on")) {
      observatoryLines.add(line);
    }
  });
  // ignore: unawaited_futures
  process.exitCode.then((int exitCode) {
    stopwatch.stop();
    print("$id finished in ${stopwatch.elapsed.toString()} "
        "with exit code $exitCode");
  });
  return new WrappedProcess(process, id, observatoryLines);
}

class WrappedProcess {
  final Process process;
  final String id;
  final List<String> observatoryLines;

  WrappedProcess(this.process, this.id, this.observatoryLines);
}
