// 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:async';
// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
// CommandOutput.exitCode in subclasses of CommandOutput.
import 'dart:io' as io;

import 'command_output.dart';
import 'configuration.dart';
import 'path.dart';
import 'test_case.dart';
import 'utils.dart';

/// A command executed as a step in a test case.
abstract class Command {
  /// A descriptive name for this command.
  final String displayName;

  /// When cloning a command object to run it multiple times, we give
  /// the different copies distinct values for index.
  final int index;

  /// Number of times this command *can* be retried.
  int get maxNumRetries => 2;

  /// Reproduction command.
  String get reproductionCommand;

  /// We compute the Command.hashCode lazily and cache it here, since it might
  /// be expensive to compute (and hashCode is called often).
  int? _cachedHashCode;

  Command._(this.displayName, {this.index = 0});

  /// A virtual clone method for a member of the Command hierarchy.
  /// Two clones with the same index will be equal, with different indices
  /// will be distinct. Used to run tests multiple times, since identical
  /// commands are only run once by the dependency graph scheduler.
  Command indexedCopy(int index);

  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int pid = 0]) =>
      CommandOutput(this, exitCode, timedOut, stdout, stderr, time,
          compilationSkipped, pid);

  int get hashCode {
    if (_cachedHashCode == null) {
      var builder = HashCodeBuilder();
      _buildHashCode(builder);
      _cachedHashCode = builder.value;
    }
    return _cachedHashCode!;
  }

  operator ==(Object other) =>
      identical(this, other) ||
      (runtimeType == other.runtimeType && _equal(other as Command));

  void _buildHashCode(HashCodeBuilder builder) {
    builder.add(displayName);
    builder.add(index);
  }

  bool _equal(covariant Command other) =>
      hashCode == other.hashCode &&
      displayName == other.displayName &&
      index == other.index;

  String toString() => reproductionCommand;

  bool get outputIsUpToDate => false;
}

class ProcessCommand extends Command {
  /// Path to the executable of this command.
  String executable;

  /// Command line arguments to the executable.
  final List<String> arguments;

  /// Environment for the command.
  final Map<String, String> environmentOverrides;

  /// Working directory for the command.
  final String? workingDirectory;

  ProcessCommand(String displayName, this.executable, this.arguments,
      [this.environmentOverrides = const {},
      this.workingDirectory,
      int index = 0])
      : super._(displayName, index: index) {
    if (io.Platform.operatingSystem == 'windows') {
      // Windows can't handle the first command if it is a .bat file or the like
      // with the slashes going the other direction.
      // NOTE: Issue 1306
      executable = executable.replaceAll('/', '\\');
    }
  }

  ProcessCommand indexedCopy(int index) {
    return ProcessCommand(displayName, executable, arguments,
        environmentOverrides, workingDirectory, index);
  }

  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(executable);
    builder.addJson(workingDirectory);
    builder.addJson(arguments);
    builder.addJson(environmentOverrides);
  }

  bool _equal(ProcessCommand other) =>
      super._equal(other) &&
      executable == other.executable &&
      deepJsonCompare(arguments, other.arguments) &&
      workingDirectory == other.workingDirectory &&
      deepJsonCompare(environmentOverrides, other.environmentOverrides);

  String get reproductionCommand {
    var env = StringBuffer();
    environmentOverrides.forEach((key, value) =>
        (io.Platform.operatingSystem == 'windows')
            ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
            : env.write('$key=${escapeCommandLineArgument(value)} '));
    var command = ([executable]
          ..addAll(nonBatchArguments)
          ..addAll(arguments))
        .map(escapeCommandLineArgument)
        .join(' ');
    if (workingDirectory != null) {
      command = "$command (working directory: $workingDirectory)";
    }
    return "$env$command";
  }

  bool get outputIsUpToDate => false;

  /// Additional arguments to prepend before [arguments] when running the
  /// process in batch mode.
  List<String> get batchArguments => const [];

  /// Additional arguments to prepend before [arguments] when running the
  /// process in non-batch mode.
  List<String> get nonBatchArguments => const [];
}

class CompilationCommand extends ProcessCommand {
  /// The primary output file that will be created by this command.
  final String outputFile;

  /// If true, then the compilation is run even if the input files are older
  /// than the output file.
  final bool _alwaysCompile;
  final List<Uri> _bootstrapDependencies;

  CompilationCommand(
      String displayName,
      this.outputFile,
      this._bootstrapDependencies,
      String executable,
      List<String> arguments,
      Map<String, String> environmentOverrides,
      {required bool alwaysCompile,
      String? workingDirectory,
      int index = 0})
      : _alwaysCompile = alwaysCompile,
        super(displayName, executable, arguments, environmentOverrides,
            workingDirectory, index);

  CompilationCommand indexedCopy(int index) => CompilationCommand(
      displayName,
      outputFile,
      _bootstrapDependencies,
      executable,
      arguments,
      environmentOverrides,
      alwaysCompile: _alwaysCompile,
      workingDirectory: workingDirectory,
      index: index);

  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
      List<int> stderr, Duration time, bool compilationSkipped,
      [int pid = 0]) {
    if (displayName == 'precompiler' || displayName == 'app_jit') {
      return VMCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, pid);
    } else if (displayName == 'dart2wasm') {
      return Dart2WasmCompilerCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
    }

    return CompilationCommandOutput(
        this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
  }

  bool get outputIsUpToDate {
    if (_alwaysCompile) return false;

    var file = io.File(Path("$outputFile.deps").toNativePath());
    if (!file.existsSync()) return false;

    var lines = file.readAsLinesSync();
    var dependencies = <Uri>[];
    for (var line in lines) {
      line = line.trim();
      if (line.isNotEmpty) {
        dependencies.add(Uri.parse(line));
      }
    }

    dependencies.addAll(_bootstrapDependencies);
    var jsOutputLastModified = TestUtils.lastModifiedCache
        .getLastModified(Uri(scheme: 'file', path: outputFile));
    if (jsOutputLastModified == null) return false;

    for (var dependency in dependencies) {
      var dependencyLastModified =
          TestUtils.lastModifiedCache.getLastModified(dependency);
      if (dependencyLastModified == null ||
          dependencyLastModified.isAfter(jsOutputLastModified)) {
        return false;
      }
    }
    return true;
  }

  @override
  List<String> get batchArguments {
    return [...arguments.where((arg) => arg.startsWith('--enable-experiment'))];
  }

  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(outputFile);
    builder.addJson(_alwaysCompile);
    builder.addJson(_bootstrapDependencies);
  }

  bool _equal(CompilationCommand other) =>
      super._equal(other) &&
      outputFile == other.outputFile &&
      _alwaysCompile == other._alwaysCompile &&
      deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
}

class Dart2jsCompilationCommand extends CompilationCommand {
  final bool useSdk;

  Dart2jsCompilationCommand(
      String outputFile,
      List<Uri> bootstrapDependencies,
      String executable,
      List<String> arguments,
      Map<String, String> environmentOverrides,
      {required this.useSdk,
      required bool alwaysCompile,
      String? workingDirectory,
      int index = 0})
      : super("dart2js", outputFile, bootstrapDependencies, executable,
            arguments, environmentOverrides,
            alwaysCompile: alwaysCompile,
            workingDirectory: workingDirectory,
            index: index);

  @override
  Dart2jsCompilationCommand indexedCopy(int index) => Dart2jsCompilationCommand(
      outputFile,
      _bootstrapDependencies,
      executable,
      arguments,
      environmentOverrides,
      useSdk: useSdk,
      alwaysCompile: _alwaysCompile,
      workingDirectory: workingDirectory,
      index: index);

  @override
  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
      List<int> stderr, Duration time, bool compilationSkipped,
      [int? pid = 0]) {
    return Dart2jsCompilerCommandOutput(
        this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
  }

  @override
  List<String> get batchArguments {
    return <String>[
      if (useSdk) ...['compile', 'js'],
      ...super.batchArguments,
    ];
  }

  @override
  List<String> get nonBatchArguments {
    return <String>[
      if (useSdk) ...['compile', 'js'],
      ...super.nonBatchArguments,
    ];
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(useSdk);
  }

  @override
  bool _equal(Dart2jsCompilationCommand other) {
    return super._equal(other) && useSdk == other.useSdk;
  }
}

class DevCompilerCompilationCommand extends CompilationCommand {
  final String compilerPath;

  DevCompilerCompilationCommand(
      String outputFile,
      List<Uri> bootstrapDependencies,
      String executable,
      List<String> arguments,
      Map<String, String> environmentOverrides,
      {required this.compilerPath,
      required bool alwaysCompile,
      String? workingDirectory,
      int index = 0})
      : super("dartdevc", outputFile, bootstrapDependencies, executable,
            arguments, environmentOverrides,
            alwaysCompile: alwaysCompile,
            workingDirectory: workingDirectory,
            index: index);

  @override
  DevCompilerCompilationCommand indexedCopy(int index) =>
      DevCompilerCompilationCommand(outputFile, _bootstrapDependencies,
          executable, arguments, environmentOverrides,
          compilerPath: compilerPath,
          alwaysCompile: _alwaysCompile,
          workingDirectory: workingDirectory,
          index: index);

  @override
  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
      List<int> stderr, Duration time, bool compilationSkipped,
      [int pid = 0]) {
    return DevCompilerCommandOutput(this, exitCode, timedOut, stdout, stderr,
        time, compilationSkipped, pid);
  }

  @override
  List<String> get batchArguments {
    return <String>[
      compilerPath,
      ...super.batchArguments,
    ];
  }

  @override
  List<String> get nonBatchArguments {
    return <String>[
      compilerPath,
      ...super.nonBatchArguments,
    ];
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(compilerPath);
  }

  @override
  bool _equal(DevCompilerCompilationCommand other) {
    return super._equal(other) && compilerPath == other.compilerPath;
  }
}

class FastaCompilationCommand extends CompilationCommand {
  final Uri _compilerLocation;

  FastaCompilationCommand(
      this._compilerLocation,
      String outputFile,
      List<Uri> bootstrapDependencies,
      String executable,
      List<String> arguments,
      Map<String, String> environmentOverrides,
      String? workingDirectory,
      {int index = 0})
      : super("fasta", outputFile, bootstrapDependencies, executable, arguments,
            environmentOverrides,
            alwaysCompile: true,
            workingDirectory: workingDirectory,
            index: index);

  @override
  FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand(
      _compilerLocation,
      outputFile,
      _bootstrapDependencies,
      executable,
      arguments,
      environmentOverrides,
      workingDirectory,
      index: index);

  FastaCommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int? pid = 0]) =>
      FastaCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);

  @override
  List<String> get batchArguments {
    return <String>[
      ...super.batchArguments,
      '--enable-asserts',
      _compilerLocation.resolve("batch.dart").toFilePath(),
    ];
  }

  @override
  String get reproductionCommand {
    String relativizeAndEscape(String argument) {
      if (workingDirectory != null) {
        argument = argument.replaceAll(
            workingDirectory!, Uri.directory(".").toFilePath());
      }
      return escapeCommandLineArgument(argument);
    }

    var buffer = StringBuffer();
    if (workingDirectory != null && !io.Platform.isWindows) {
      buffer.write("(cd ");
      buffer.write(escapeCommandLineArgument(workingDirectory!));
      buffer.write(" ; ");
    }
    environmentOverrides.forEach((key, value) {
      if (io.Platform.isWindows) {
        buffer.write("set ");
      }
      buffer.write(key);
      buffer.write("=");
      buffer.write(relativizeAndEscape(value));
      if (io.Platform.isWindows) {
        buffer.write(" &");
      }
      buffer.write(" ");
    });
    buffer.writeAll(
        (<String>[executable]
              ..add(_compilerLocation.toFilePath())
              ..addAll(arguments))
            .map(relativizeAndEscape),
        " ");
    if (workingDirectory != null) {
      if (io.Platform.isWindows) {
        buffer.write(" (working directory: $workingDirectory)");
      } else {
        buffer.write(" )");
      }
    }
    return "$buffer";
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(_compilerLocation);
  }

  @override
  bool _equal(FastaCompilationCommand other) {
    return super._equal(other) && _compilerLocation == other._compilerLocation;
  }
}

class VMKernelCompilationCommand extends CompilationCommand {
  VMKernelCompilationCommand(
      String outputFile,
      List<Uri> bootstrapDependencies,
      String executable,
      List<String> arguments,
      Map<String, String> environmentOverrides,
      {required bool alwaysCompile,
      int index = 0})
      : super('vm_compile_to_kernel', outputFile, bootstrapDependencies,
            executable, arguments, environmentOverrides,
            alwaysCompile: alwaysCompile, index: index);

  VMKernelCompilationCommand indexedCopy(int index) =>
      VMKernelCompilationCommand(outputFile, _bootstrapDependencies, executable,
          arguments, environmentOverrides,
          alwaysCompile: _alwaysCompile, index: index);

  VMKernelCompilationCommandOutput createOutput(
          int exitCode,
          bool timedOut,
          List<int> stdout,
          List<int> stderr,
          Duration time,
          bool compilationSkipped,
          [int? pid = 0]) =>
      VMKernelCompilationCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);

  int get maxNumRetries => 1;
}

/// This is just a Pair(String, Map) class with hashCode and operator ==
class AddFlagsKey {
  final String flags;
  final Map env;
  AddFlagsKey(this.flags, this.env);
  // Just use object identity for environment map
  bool operator ==(Object other) =>
      other is AddFlagsKey && flags == other.flags && env == other.env;
  int get hashCode => flags.hashCode ^ env.hashCode;
}

class BrowserTestCommand extends Command {
  Runtime get browser => configuration.runtime;
  final String url;
  final TestConfiguration configuration;

  BrowserTestCommand(this.url, this.configuration, {int index = 0})
      : super._(configuration.runtime.name, index: index);

  BrowserTestCommand indexedCopy(int index) =>
      BrowserTestCommand(url, configuration, index: index);

  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(browser.name);
    builder.addJson(url);
    builder.add(configuration);
  }

  bool _equal(BrowserTestCommand other) =>
      super._equal(other) &&
      browser == other.browser &&
      url == other.url &&
      identical(configuration, other.configuration);

  String get reproductionCommand {
    var parts = [
      io.Platform.resolvedExecutable,
      'pkg/test_runner/bin/launch_browser.dart',
      browser.name,
      url
    ];
    return parts.map(escapeCommandLineArgument).join(' ');
  }

  int get maxNumRetries => 4;
}

class AnalysisCommand extends ProcessCommand {
  AnalysisCommand(String executable, List<String> arguments,
      Map<String, String> environmentOverrides, {int index = 0})
      : super('dart2analyzer', executable, arguments, environmentOverrides,
            null, index);

  AnalysisCommand indexedCopy(int index) =>
      AnalysisCommand(executable, arguments, environmentOverrides,
          index: index);

  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int? pid = 0]) =>
      AnalysisCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
}

class CompareAnalyzerCfeCommand extends ProcessCommand {
  CompareAnalyzerCfeCommand(String executable, List<String> arguments,
      Map<String, String> environmentOverrides, {int index = 0})
      : super('compare_analyzer_cfe', executable, arguments,
            environmentOverrides, null, index);

  CompareAnalyzerCfeCommand indexedCopy(int index) =>
      CompareAnalyzerCfeCommand(executable, arguments, environmentOverrides,
          index: index);

  CompareAnalyzerCfeCommandOutput createOutput(
          int exitCode,
          bool timedOut,
          List<int> stdout,
          List<int> stderr,
          Duration time,
          bool compilationSkipped,
          [int? pid = 0]) =>
      CompareAnalyzerCfeCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
}

class SpecParseCommand extends ProcessCommand {
  SpecParseCommand(String executable, List<String> arguments,
      Map<String, String> environmentOverrides, {int index = 0})
      : super('spec_parser', executable, arguments, environmentOverrides, null,
            index);

  SpecParseCommand indexedCopy(int index) =>
      SpecParseCommand(executable, arguments, environmentOverrides,
          index: index);

  SpecParseCommandOutput createOutput(
          int exitCode,
          bool timedOut,
          List<int> stdout,
          List<int> stderr,
          Duration time,
          bool compilationSkipped,
          [int? pid = 0]) =>
      SpecParseCommandOutput(
          this, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
}

class VMCommand extends ProcessCommand {
  VMCommand(String executable, List<String> arguments,
      Map<String, String> environmentOverrides,
      {int index = 0})
      : super('vm', executable, arguments, environmentOverrides, null, index);

  VMCommand indexedCopy(int index) =>
      VMCommand(executable, arguments, environmentOverrides, index: index);

  CommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int pid = 0]) =>
      VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);
}

// Run a VM test under RR, and copy the trace if it crashes. Using a helper
// script like the precompiler does not work because the RR traces are large
// and we must diligently erase them for non-crashes even if the test times
// out and would be killed by the harness, so the copying and cleanup logic
// must be in the harness.
class RRCommand extends Command {
  VMCommand originalCommand;
  late VMCommand wrappedCommand;
  late io.Directory recordingDir;
  late io.Directory savedDir;

  RRCommand(this.originalCommand)
      : super._("rr", index: originalCommand.index) {
    final suffix = "/rr-trace-" + originalCommand.hashCode.toString();
    recordingDir = io.Directory(io.Directory.systemTemp.path + suffix);
    savedDir = io.Directory("out" + suffix);
    final executable = "rr";
    final arguments = <String>[
      "record",
      "--chaos",
      "--output-trace-dir=" + recordingDir.path,
    ];
    arguments.add(originalCommand.executable);
    arguments.addAll(originalCommand.arguments);
    wrappedCommand = VMCommand(
        executable, arguments, originalCommand.environmentOverrides,
        index: originalCommand.index);
  }

  RRCommand indexedCopy(int index) =>
      RRCommand(originalCommand.indexedCopy(index));

  Future<CommandOutput> run(
      int timeout, TestConfiguration configuration) async {
    // rr will fail if the output trace directory already exists. Delete any
    // that might be leftover from interrupting the harness.
    if (await recordingDir.exists()) {
      await recordingDir.delete(recursive: true);
    }
    final output = await RunningProcess(wrappedCommand, timeout,
            configuration: configuration)
        .run();
    if (output.hasCrashed) {
      if (await savedDir.exists()) {
        await savedDir.delete(recursive: true);
      }
      await recordingDir.rename(savedDir.path);
      await io.File(savedDir.path + "/command.txt")
          .writeAsString(wrappedCommand.reproductionCommand);
      await io.File(savedDir.path + "/stdout.txt").writeAsBytes(output.stdout);
      await io.File(savedDir.path + "/stderr.txt").writeAsBytes(output.stderr);
    } else {
      await recordingDir.delete(recursive: true);
    }

    return VMCommandOutput(this, output.exitCode, output.hasTimedOut,
        output.stdout, output.stderr, output.time, output.pid);
  }

  String get reproductionCommand =>
      wrappedCommand.reproductionCommand + " (rr replay " + savedDir.path + ")";

  void _buildHashCode(HashCodeBuilder builder) {
    originalCommand._buildHashCode(builder);
    builder.add(42);
  }

  bool _equal(RRCommand other) =>
      hashCode == other.hashCode &&
      originalCommand._equal(other.originalCommand);
}

abstract class AdbCommand {
  String get buildPath;
  List<String> get extraLibraries;
}

class AdbPrecompilationCommand extends Command implements AdbCommand {
  final String buildPath; // Path to the output directory of the build.
  final String processTestFilename;
  final String abstractSocketTestFilename;
  final String precompiledTestDirectory;
  final List<String> arguments;
  final bool useElf;
  final List<String> extraLibraries;

  AdbPrecompilationCommand(
      this.buildPath,
      this.processTestFilename,
      this.abstractSocketTestFilename,
      this.precompiledTestDirectory,
      this.arguments,
      this.useElf,
      this.extraLibraries,
      {int index = 0})
      : super._("adb_precompilation", index: index);

  AdbPrecompilationCommand indexedCopy(int index) => AdbPrecompilationCommand(
      buildPath,
      processTestFilename,
      abstractSocketTestFilename,
      precompiledTestDirectory,
      arguments,
      useElf,
      extraLibraries,
      index: index);

  VMCommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int pid = 0]) =>
      VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);

  _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.add(buildPath);
    builder.add(precompiledTestDirectory);
    builder.add(arguments);
    builder.add(useElf);
    extraLibraries.forEach(builder.add);
  }

  bool _equal(AdbPrecompilationCommand other) =>
      super._equal(other) &&
      buildPath == other.buildPath &&
      useElf == other.useElf &&
      arguments == other.arguments &&
      precompiledTestDirectory == other.precompiledTestDirectory &&
      deepJsonCompare(extraLibraries, other.extraLibraries);

  String toString() => 'Steps to push precompiled runner and precompiled code '
      'to an attached device. Uses (and requires) adb.';

  @override
  String get reproductionCommand => throw UnimplementedError();
}

class AdbDartkCommand extends Command implements AdbCommand {
  final String buildPath;
  final String processTestFilename;
  final String abstractSocketTestFilename;
  final String kernelFile;
  final List<String> arguments;
  final List<String> extraLibraries;

  AdbDartkCommand(
      this.buildPath,
      this.processTestFilename,
      this.abstractSocketTestFilename,
      this.kernelFile,
      this.arguments,
      this.extraLibraries,
      {int index = 0})
      : super._("adb_precompilation", index: index);

  AdbDartkCommand indexedCopy(int index) => AdbDartkCommand(
      buildPath,
      processTestFilename,
      abstractSocketTestFilename,
      kernelFile,
      arguments,
      extraLibraries,
      index: index);

  _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.add(buildPath);
    builder.add(kernelFile);
    builder.add(arguments);
    builder.add(extraLibraries);
  }

  bool _equal(AdbDartkCommand other) =>
      super._equal(other) &&
      buildPath == other.buildPath &&
      arguments == other.arguments &&
      extraLibraries == other.extraLibraries &&
      kernelFile == other.kernelFile;

  VMCommandOutput createOutput(int exitCode, bool timedOut, List<int> stdout,
          List<int> stderr, Duration time, bool compilationSkipped,
          [int pid = 0]) =>
      VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);

  String toString() => 'Steps to push Dart VM and Dill file '
      'to an attached device. Uses (and requires) adb.';

  @override
  String get reproductionCommand => throw UnimplementedError();
}

class JSCommandLineCommand extends ProcessCommand {
  JSCommandLineCommand(
      String displayName, String executable, List<String> arguments,
      [Map<String, String> environmentOverrides = const {}, int index = 0])
      : super(displayName, executable, arguments, environmentOverrides, null,
            index);

  JSCommandLineCommand indexedCopy(int index) => JSCommandLineCommand(
      displayName, executable, arguments, environmentOverrides, index);

  JSCommandLineOutput createOutput(
          int exitCode,
          bool timedOut,
          List<int> stdout,
          List<int> stderr,
          Duration time,
          bool compilationSkipped,
          [int? pid = 0]) =>
      JSCommandLineOutput(this, exitCode, timedOut, stdout, stderr, time);
}

/// [ScriptCommand]s are executed by dart code.
abstract class ScriptCommand extends Command {
  ScriptCommand._(String displayName, {int index = 0})
      : super._(displayName, index: index);

  Future<ScriptCommandOutput> run();
}
