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

// @dart = 2.9

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

import 'package:expect/expect.dart';
import 'package:path/path.dart' as p;

class Result {
  final String cmdline;
  final ProcessResult processResult;

  Result(this.cmdline, this.processResult);

  String get output => processResult.stdout.trim();
}

void reportError(Result result, String msg) {
  print('running ${result.cmdline}:');
  if (result.processResult.stdout.isNotEmpty) {
    print('''

Command stdout:
${result.processResult.stdout}''');
  }

  if (result.processResult.stderr.isNotEmpty) {
    print('''

Command stderr:
${result.processResult.stderr}''');
  }

  Expect.fail(msg);
}

void expectOutput(String what, Result result) {
  if (result.output != what) {
    reportError(
        result,
        'Expected test to print \'${what}\' to stdout. '
        'Actual: ${result.output}');
  }
}

final String scriptSuffix = Platform.isWindows ? ".bat" : "";
final String executableSuffix = Platform.isWindows ? ".exe" : "";
final String buildDir = p.dirname(Platform.executable);
final String platformDill = p.join(buildDir, "vm_platform_strong.dill");
final String genSnapshot = p.join(buildDir, "gen_snapshot${executableSuffix}");
final String dart = p.join(buildDir, "dart${executableSuffix}");
final String dartPrecompiledRuntime =
    p.join(buildDir, "dart_precompiled_runtime${executableSuffix}");
final String genKernel = p.join("pkg", "vm", "bin", "gen_kernel.dart");
final String checkedInDartVM =
    p.join("tools", "sdks", "dart-sdk", "bin", "dart${executableSuffix}");

Future<Result> runDart(String prefix, List<String> arguments,
    {bool printOut: true}) {
  final augmentedArguments = <String>[]
    ..addAll(Platform.executableArguments)
    ..add('--verbosity=warning')
    ..addAll(arguments);
  return runBinary(prefix, Platform.executable, augmentedArguments,
      printOut: printOut);
}

Future<Result> runGenKernel(String prefix, List<String> arguments) {
  final augmentedArguments = <String>[
    "--platform",
    platformDill,
    ...Platform.executableArguments.where((arg) =>
        arg.startsWith('--enable-experiment=') ||
        arg == '--sound-null-safety' ||
        arg == '--no-sound-null-safety'),
    ...arguments,
  ];
  return runGenKernelWithoutStandardOptions(prefix, augmentedArguments);
}

Future<Result> runGenKernelWithoutStandardOptions(
    String prefix, List<String> arguments) {
  return runBinary(prefix, checkedInDartVM, [genKernel, ...arguments]);
}

Future<Result> runGenSnapshot(String prefix, List<String> arguments) {
  return runBinary(prefix, genSnapshot, arguments);
}

Future<Result> runBinary(String prefix, String binary, List<String> arguments,
    {Map<String, String> environment,
    bool runInShell: false,
    bool printOut: true}) async {
  print("+ $binary " + arguments.join(" "));
  final processResult = await Process.run(binary, arguments,
      environment: environment, runInShell: runInShell);
  final result =
      new Result('[$prefix] ${binary} ${arguments.join(' ')}', processResult);

  if (printOut && processResult.stdout.isNotEmpty) {
    print('''

Command stdout:
${processResult.stdout}''');
  }

  if (printOut && processResult.stderr.isNotEmpty) {
    print('''

Command stderr:
${processResult.stderr}''');
  }

  if (result.processResult.exitCode != 0) {
    reportError(result,
        '[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
  }
  return result;
}

withTempDir(Future fun(String dir)) async {
  final Directory tempDir = Directory.systemTemp.createTempSync();
  try {
    await fun(tempDir.path);
  } finally {
    tempDir.deleteSync(recursive: true);
  }
}

checkDeterministicSnapshot(String snapshotKind, String expectedStdout) async {
  await withTempDir((String temp) async {
    final snapshot1Path = p.join(temp, 'snapshot1');
    final snapshot2Path = p.join(temp, 'snapshot2');

    print("Version ${Platform.version}");

    final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
      '--deterministic',
      '--trace_class_finalization',
      '--trace_type_finalization',
      '--trace_compiler',
      '--verbose_gc',
      '--verbosity=warning',
      '--snapshot=$snapshot1Path',
      '--snapshot-kind=$snapshotKind',
      Platform.script.toFilePath(),
      '--child',
    ]);
    expectOutput(expectedStdout, generate1Result);

    final generate2Result = await runDart('GENERATE SNAPSHOT 2', [
      '--deterministic',
      '--trace_class_finalization',
      '--trace_type_finalization',
      '--trace_compiler',
      '--verbose_gc',
      '--verbosity=warning',
      '--snapshot=$snapshot2Path',
      '--snapshot-kind=$snapshotKind',
      Platform.script.toFilePath(),
      '--child',
    ]);
    expectOutput(expectedStdout, generate2Result);

    var snapshot1Bytes = await new File(snapshot1Path).readAsBytes();
    var snapshot2Bytes = await new File(snapshot2Path).readAsBytes();

    var minLength = min(snapshot1Bytes.length, snapshot2Bytes.length);
    for (var i = 0; i < minLength; i++) {
      if (snapshot1Bytes[i] != snapshot2Bytes[i]) {
        Expect.fail("Snapshots differ at byte $i");
      }
    }
    Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
  });
}

runAppJitTest(Uri testScriptUri,
    {Future<Result> Function(String snapshotPath) runSnapshot}) async {
  runSnapshot ??=
      (snapshotPath) => runDart('RUN FROM SNAPSHOT', [snapshotPath]);

  await withTempDir((String temp) async {
    final snapshotPath = p.join(temp, 'app.jit');
    final testPath = testScriptUri.toFilePath();

    final trainingResult = await runDart('TRAINING RUN', [
      '--snapshot=$snapshotPath',
      '--snapshot-kind=app-jit',
      '--verbosity=warning',
      testPath,
      '--train'
    ]);
    expectOutput("OK(Trained)", trainingResult);
    final runResult = await runSnapshot(snapshotPath);
    expectOutput("OK(Run)", runResult);
  });
}
