// 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:convert';
// 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 'package:dart2js_tools/deobfuscate_stack_trace.dart';
import 'package:status_file/expectation.dart';
import 'package:test_runner/src/static_error.dart';

import 'browser_controller.dart';
import 'command.dart';
import 'configuration.dart';
import 'path.dart';
import 'process_queue.dart';
import 'terminal.dart';
import 'test_case.dart';
import 'test_progress.dart';
import 'utils.dart';

/// CommandOutput records the output of a completed command: the process's exit
/// code, the standard output and standard error, whether the process timed out,
/// and the time the process took to run. It does not contain a pointer to the
/// [TestCase] this is the output of, so some functions require the test case
/// to be passed as an argument.
class CommandOutput {
  final Command command;

  final bool hasTimedOut;

  final Duration time;

  final int exitCode;

  final int pid;

  final List<int> stdout;
  final List<int> stderr;

  final bool compilationSkipped;

  final List<String> diagnostics = [];

  CommandOutput(
    this.command,
    this.exitCode,
    this.hasTimedOut,
    this.stdout,
    this.stderr,
    this.time,
    this.compilationSkipped,
    this.pid,
  );

  Expectation result(TestCase testCase) {
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (_didFail(testCase)) return Expectation.fail;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    return Expectation.pass;
  }

  bool get hasCrashed {
    // dart2js exits with code 253 in case of unhandled exceptions.
    // The dart binary exits with code 253 in case of an API error such
    // as an invalid snapshot file.
    // The batch mode can also exit 253 (unhandledCompilerExceptionExitCode).
    // In either case an exit code of 253 is considered a crash.
    if (exitCode == unhandledCompilerExceptionExitCode) return true;
    if (exitCode == parseFailExitCode) return false;
    if (hasTimedOut) return false;
    if (io.Platform.isWindows) {
      // The VM uses std::abort to terminate on asserts.
      // std::abort terminates with exit code 3 on Windows.
      if (exitCode == 3) return true;

      // When VM is built with Crashpad support we get STATUS_FATAL_APP_EXIT
      // for all crashes that Crashpad has intercepted.
      if (exitCode == 0x40000015) return true;

      // If a program receives an uncaught system exception, the program
      // terminates with the exception code as exit code.
      // https://msdn.microsoft.com/en-us/library/cc704588.aspx lists status
      // codes basically saying that codes starting with 0xC0, 0x80 or 0x40
      // are crashes, so look at the 4 most significant bits in 32-bit-space
      // make sure its either 0b1100, 0b1000 or 0b0100.
      var masked = (exitCode & 0xF0000000) >> 28;
      return (exitCode < 0) && (masked >= 4) && ((masked & 3) == 0);
    }
    return exitCode < 0;
  }

  bool get hasCoreDump {
    // Unhandled dart exceptions don't produce crashdumps.
    return hasCrashed && exitCode != 253;
  }

  bool _didFail(TestCase testCase) => exitCode != 0 && !hasCrashed;

  bool get canRunDependentCommands {
    // TODO(kustermann): We may need to change this
    return !hasTimedOut && exitCode == 0;
  }

  bool get successful {
    // TODO(kustermann): We may need to change this
    return !hasTimedOut && exitCode == 0;
  }

  bool get hasNonUtf8 => exitCode == nonUtfFakeExitCode;

  /// Whether the command's output was too long and was truncated.
  bool get truncatedOutput => exitCode == truncatedFakeExitCode;

  /// Called when producing output for a test failure to describe this output.
  void describe(TestCase testCase, Progress progress, OutputWriter output) {
    output.subsection("exit code");
    output.write(exitCode.toString());

    if (diagnostics.isNotEmpty) {
      output.subsection("diagnostics");
      output.writeAll(diagnostics);
    }

    if (stdout.isNotEmpty) {
      output.subsection("stdout");
      output.writeAll(decodeLines(stdout));
    }

    if (stderr.isNotEmpty) {
      output.subsection("stderr");
      output.writeAll(decodeLines(stderr));
    }
  }
}

class BrowserTestJsonResult {
  static const _allowedTypes = [
    'sync_exception',
    'window_onerror',
    'script_onerror',
    'window_compilationerror',
    'print',
    'message_received',
    'dom',
    'debug',
  ];

  final Expectation outcome;
  final String htmlDom;
  final List<dynamic> events;

  BrowserTestJsonResult(this.outcome, this.htmlDom, this.events);

  static BrowserTestJsonResult? parseFromString(String content) {
    void validate(String message, bool isValid) {
      if (!isValid) {
        throw "InvalidFormat sent from browser driving page: $message:\n\n"
            "$content";
      }
    }

    try {
      var events = jsonDecode(content);
      if (events != null) {
        validate("Message must be a List", events is List);
        // TODO(srawlins): This will promote `events` in null safety.
        var eventList = events as List<dynamic>;

        var messagesByType = {
          for (var type in _allowedTypes) type: <String?>[],
        };

        for (var entry in eventList) {
          validate("Entry must be a Map", entry is Map);

          var type = entry['type'];
          validate("'type' must be a String", type is String);
          validate(
            "'type' has to be in $_allowedTypes.",
            _allowedTypes.contains(type),
          );

          var value = entry['value'];
          validate("'value' must be a String", value is String);

          var timestamp = entry['timestamp'];
          validate("'timestamp' must be a number", timestamp is num);

          var stackTrace = entry['stack_trace'];
          if (stackTrace != null) {
            validate("'stack_trace' must be a String", stackTrace is String);
          }

          messagesByType[type]!.add(value as String?);
        }
        validate(
          "The message must have exactly one 'dom' entry.",
          messagesByType['dom']!.length == 1,
        );

        var dom = messagesByType['dom']![0]!;
        if (dom.endsWith('\n')) {
          dom = '$dom\n';
        }

        return BrowserTestJsonResult(
          _getOutcome(messagesByType),
          dom,
          eventList,
        );
      }
    } catch (error) {
      // If something goes wrong, we know the content was not in the correct
      // JSON format. So we can't parse it.
      // The caller is responsible for falling back to the old way of
      // determining if a test failed.
    }

    return null;
  }

  static Expectation _getOutcome(Map<String, List<String?>> messagesByType) {
    occurred(String type) => messagesByType[type]!.isNotEmpty;

    searchForMsg(List<String> types, String message) {
      return types.any((type) => messagesByType[type]!.contains(message));
    }

    // TODO(kustermann,ricow): I think this functionality doesn't work in
    // test_controller.js: So far I haven't seen anything being reported on
    // "window.compilationerror"
    if (occurred('window_compilationerror')) {
      return Expectation.compileTimeError;
    }

    if (occurred('sync_exception') ||
        occurred('window_onerror') ||
        occurred('script_onerror')) {
      return Expectation.runtimeError;
    }

    if (messagesByType['dom']![0]!.contains('FAIL')) {
      return Expectation.runtimeError;
    }

    // We search for these messages in 'print' and 'message_received' because
    // the unittest implementation posts these messages using
    // "window.postMessage()" instead of the normal "print()" them.

    var isAsyncTest = searchForMsg([
      'print',
      'message_received',
    ], 'unittest-suite-wait-for-done');
    var isAsyncSuccess =
        searchForMsg(['print', 'message_received'], 'unittest-suite-success') ||
        searchForMsg(['print', 'message_received'], 'unittest-suite-done');

    if (isAsyncTest) {
      if (isAsyncSuccess) {
        return Expectation.pass;
      }
      return Expectation.runtimeError;
    }

    var mainStarted = searchForMsg([
      'print',
      'message_received',
    ], 'dart-calling-main');
    var mainDone = searchForMsg([
      'print',
      'message_received',
    ], 'dart-main-done');

    if (mainStarted && mainDone) {
      return Expectation.pass;
    }
    return Expectation.fail;
  }
}

class BrowserCommandOutput extends CommandOutput
    with _UnittestSuiteMessagesMixin {
  final BrowserTestJsonResult? _jsonResult;
  final BrowserTestOutput _result;
  final Expectation _outcome;

  /// Directory that is being served under `http:/.../root_build/` to browser
  /// tests.
  final String _buildDirectory;

  factory BrowserCommandOutput(
    BrowserTestCommand command,
    BrowserTestOutput result,
  ) {
    Expectation outcome;

    var parsedResult = BrowserTestJsonResult.parseFromString(
      result.lastKnownMessage,
    );
    if (parsedResult != null) {
      outcome = parsedResult.outcome;
    } else {
      // Old way of determining whether a test failed or passed.
      if (result.lastKnownMessage.contains("FAIL")) {
        outcome = Expectation.runtimeError;
      } else if (result.lastKnownMessage.contains("PASS")) {
        outcome = Expectation.pass;
      } else {
        outcome = Expectation.runtimeError;
      }
    }

    var stderr = "";
    if (result.didTimeout) {
      if (result.delayUntilTestStarted != null) {
        stderr =
            "This test timed out. The delay until the test actually "
            "started was: ${result.delayUntilTestStarted}.";
      } else {
        stderr = "This test did not notify test.py that it started running.";
      }
    }

    return BrowserCommandOutput._internal(
      command,
      result,
      outcome,
      parsedResult,
      command.configuration.buildDirectory,
      utf8.encode(""),
      utf8.encode(stderr),
    );
  }

  BrowserCommandOutput._internal(
    Command command,
    BrowserTestOutput result,
    this._outcome,
    this._jsonResult,
    this._buildDirectory,
    List<int> stdout,
    List<int> stderr,
  ) : _result = result,
      super(
        command,
        0,
        result.didTimeout,
        stdout,
        stderr,
        result.duration,
        false,
        0,
      );

  @override
  Expectation result(TestCase testCase) {
    // Handle timeouts first.
    if (_result.didTimeout) {
      return Expectation.timeout;
    }

    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;
    return _outcome;
  }

  @override
  void describe(TestCase testCase, Progress progress, OutputWriter output) {
    if (_jsonResult != null) {
      _describeEvents(progress, output, _jsonResult);
    } else {
      // We couldn't parse the events, so fallback to showing the last message.
      output.section("Last message");
      output.write(_result.lastKnownMessage);
    }

    super.describe(testCase, progress, output);

    if (_result.browserOutput.stdout.isNotEmpty) {
      output.subsection("Browser stdout");
      output.write(_result.browserOutput.stdout.toString());
    }

    if (_result.browserOutput.stderr.isNotEmpty) {
      output.subsection("Browser stderr");
      output.write(_result.browserOutput.stderr.toString());
    }
  }

  void _describeEvents(
    Progress progress,
    OutputWriter output,
    BrowserTestJsonResult jsonResult,
  ) {
    // Always show the error events since those are most useful.
    var errorShown = false;

    void showError(String header, event) {
      output.subsection(header);
      var value = event["value"] as String?;
      if (event["stack_trace"] != null) {
        value = '$value\n${event["stack_trace"]}';
      }
      errorShown = true;
      output.write(value);

      // Skip deobfuscation if there is no indication that there is a stack
      // trace in the string value.
      if (!value!.contains('.js:')) return;
      var stringStack = value
          // Convert `http:` URIs to relative `file:` URIs.
          .replaceAll(RegExp(r'http://[^/]*/root_build/'), '$_buildDirectory/')
          .replaceAll(RegExp(r'http://[^/]*/root_dart/'), '')
          // Remove query parameters (seen in .html URIs).
          .replaceAll(RegExp(r'\?[^:\n]*:'), ':');
      // TODO(sigmund): change internal deobfuscation code to avoid spurious
      // error messages when files do not have a corresponding source-map.
      _deobfuscateAndWriteStack(stringStack, output);
    }

    for (var event in jsonResult.events) {
      if (event["type"] == "sync_exception") {
        showError("Runtime error", event);
      } else if (event["type"] == "window_onerror") {
        showError("Runtime window.onerror", event);
      }
    }

    // Show the events unless the above error was sufficient.
    // TODO(rnystrom): Let users enable or disable this explicitly?
    if (errorShown && progress != Progress.verbose) {
      return;
    }

    output.subsection("Events");
    for (var event in jsonResult.events) {
      switch (event["type"] as String?) {
        case "debug":
          output.write('- debug "${event["value"]}"');
          break;

        case "dom":
          output.write('- dom\n${indent(event["value"] as String, 2)}');
          break;

        case "print":
          output.write('- print "${event["value"]}"');
          break;

        case "window_onerror":
          var value = event["value"] as String;
          value = indent(value.trim(), 2);
          value = "- ${value.substring(2)}";
          output.write(value);
          break;

        default:
          output.write(
            "- ${const JsonEncoder.withIndent('      ').convert(event)}",
          );
      }
    }
  }
}

/// A parsed analyzer error diagnostic.
class AnalyzerError implements Comparable<AnalyzerError> {
  /// The set of static warnings which must be expected in a test. Any warning
  /// not listed here does not need to be expected, and never causes a test to
  /// fail.
  static const Set<String> _validatedWarnings = {
    'dead_null_aware_expression',
    'invalid_null_aware_operator',
    'invalid_null_aware_element_or_map_entry',
    'missing_enum_constant_in_switch',
    'unnecessary_non_null_assertion',
    'unnecessary_null_assert_pattern',
    'unnecessary_null_check_pattern',
    'unreachable_switch_case',
    'unreachable_switch_default',
  };

  /// Whether [code] is a warning that should be expected by a test.
  ///
  /// Any warning whose code is not covered here is implicitly ignored by the
  /// test runner. Tests often have unused local variables, dead code, etc. and
  /// we don't want to clutter up the test expectations with those.
  static bool isValidatedWarning(String code) =>
      _validatedWarnings.contains(code);

  /// The set of hints which must be expected in a test. Any hint not specified
  /// here which is reported by the analyzer does not need to be expected, and
  /// never causes a test to fail.
  static const Set<String> _specifiedHints = {};

  /// Parses all errors from analyzer [stdout] output.
  static List<AnalyzerError> parseStdout(String stdout) {
    var result = <AnalyzerError>[];

    var jsonData = json.decode(stdout) as Map<String, dynamic>;
    var version = jsonData['version'];
    if (version != 1) {
      DebugLogger.error('Unexpected analyzer JSON data version: $version');
      throw UnimplementedError();
    }

    for (var diagnostic in jsonData['diagnostics'] as List<dynamic>) {
      var diagnosticMap = diagnostic as Map<String, dynamic>;

      var code = diagnosticMap['code'] as String;
      var type = diagnosticMap['type'] as String?;

      if (type == 'HINT' && !_specifiedHints.contains(code)) {
        // The analyzer can report hints which do not need to be expected in
        // the test source. These can be ignored.
        // TODO(srawlins): Hints will start to change to be warnings. There are
        // some warnings produced now which must be expected. See
        // [StaticError._analyzerWarningCodes]. When we change hints to
        // warnings, we will need to ignore them here.
        continue;
      }

      if (type == 'STATIC_WARNING' && !_validatedWarnings.contains(code)) {
        continue;
      }

      if (type == 'LINT') continue;

      var errorCode = '$type.${code.toUpperCase()}';

      var error = _parse(
        diagnosticMap,
        diagnosticMap['problemMessage'] as String,
        errorCode,
      );
      result.add(error);

      var contextMessages = diagnosticMap['contextMessages'] as List<dynamic>?;
      for (var contextMessage in contextMessages ?? const []) {
        var contextMessageMap = contextMessage as Map<String, dynamic>;
        error.contextMessages.add(
          _parse(contextMessageMap, contextMessageMap['message'] as String),
        );
      }
    }

    return result;
  }

  static AnalyzerError _parse(
    Map<String, dynamic> diagnostic,
    String message, [
    String? errorCode,
  ]) {
    var location = diagnostic['location'] as Map<String, dynamic>;

    var range = location['range'] as Map<String, dynamic>;
    var start = range['start'] as Map<String, dynamic>;
    var end = range['end'] as Map<String, dynamic>;
    return AnalyzerError._(
      severity: diagnostic['severity'] as String? ?? '',
      errorCode: errorCode ?? '',
      file: location['file'] as String,
      message: message,
      line: start['line'] as int,
      column: start['column'] as int,
      length: (end['offset'] as int) - (start['offset'] as int),
    );
  }

  final String severity;
  final String errorCode;
  final String file;
  final String message;
  final int line;
  final int column;
  final int length;

  final List<AnalyzerError> contextMessages = [];

  AnalyzerError._({
    this.severity = '',
    this.errorCode = '',
    required this.file,
    required this.message,
    required this.line,
    required this.column,
    required this.length,
  });

  @override
  int compareTo(AnalyzerError other) {
    if (file != other.file) return file.compareTo(other.file);
    if (line != other.line) return line.compareTo(other.line);
    if (column != other.column) return column.compareTo(other.column);
    if (length != other.length) return length.compareTo(other.length);
    if (severity != other.severity) return severity.compareTo(other.severity);
    if (errorCode != other.errorCode) {
      return errorCode.compareTo(other.errorCode);
    }
    return message.compareTo(other.message);
  }
}

class AnalysisCommandOutput extends CommandOutput with _StaticErrorOutput {
  static void parseErrors(
    String stdout,
    List<StaticError> errors, [
    List<StaticError>? warnings,
  ]) {
    StaticError convert(AnalyzerError error) {
      var staticError = StaticError(
        ErrorSource.analyzer,
        error.errorCode,
        path: error.file,
        line: error.line,
        column: error.column,
        length: error.length,
      );

      for (var context in error.contextMessages) {
        staticError.contextMessages.add(
          StaticError(
            ErrorSource.context,
            context.message,
            path: context.file,
            line: context.line,
            column: context.column,
            length: context.length,
          ),
        );
      }

      return staticError;
    }

    // Parse as Analyzer errors and then convert them to the StaticError objects
    // the static error tests expect.
    for (var diagnostic in AnalyzerError.parseStdout(stdout)) {
      if (diagnostic.severity == 'ERROR') {
        errors.add(convert(diagnostic));
      } else if (warnings != null &&
          (diagnostic.severity == 'WARNING' || diagnostic.severity == 'INFO')) {
        warnings.add(convert(diagnostic));
      }
    }
  }

  /// If the stdout of analyzer could not be parsed as valid JSON, this will be
  /// the stdout as a string instead. Otherwise it will be null.
  String? get invalidJsonStdout {
    if (!_parsedErrors) {
      _parseErrors();
      _parsedErrors = true;
    }

    return _invalidJsonStdout;
  }

  String? _invalidJsonStdout;

  AnalysisCommandOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped,
  ) : super(
        command,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        compilationSkipped,
        0,
      );

  @override
  Expectation result(TestCase testCase) {
    // TODO(kustermann): If we run the analyzer not in batch mode, make sure
    // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings,
    // no errors)

    // Handle crashes and timeouts first.
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    if (invalidJsonStdout != null) return Expectation.fail;

    // If it's a static error test, validate the exact errors.
    if (testCase.testFile.isStaticErrorTest) {
      return _validateExpectedErrors(testCase);
    }

    if (errors.isNotEmpty) {
      return Expectation.compileTimeError;
    }
    if (warnings.isNotEmpty) {
      return Expectation.staticWarning;
    }
    return Expectation.pass;
  }

  @override
  void describe(TestCase testCase, Progress progress, OutputWriter output) {
    if (invalidJsonStdout != null) {
      output.subsection("analyzer json parse result");
      output.write("- parse failed");
      output.subsection("invalid analyzer json");
      super.describe(testCase, progress, output);
      return;
    }

    // Handle static error test output specially. We don't want to show the raw
    // stdout if we can give the user the parsed expectations instead.
    if (testCase.testFile.isStaticErrorTest || hasCrashed || hasTimedOut) {
      super.describe(testCase, progress, output);
    } else {
      // Parse and sort the errors.
      var errorsByFile = <String?, List<AnalyzerError>>{};
      for (var error in AnalyzerError.parseStdout(decodeUtf8(stdout))) {
        errorsByFile.putIfAbsent(error.file, () => []).add(error);
      }

      var files = errorsByFile.keys.toList();
      files.sort();

      for (var file in files) {
        var path = Path(file!).toString();
        output.subsection("unexpected analysis errors in $path");

        var errors = errorsByFile[file]!;
        errors.sort();

        for (var error in errors) {
          var line = error.line.toString();
          var column = error.column.toString();
          var message = wordWrap(error.message.trim(), prefix: "  ");
          output.write("- Line $line, column $column: ${error.errorCode}");
          output.write("  $message");
          output.separator();
        }
      }
    }
  }

  /// Parses the JSON output of the analyzer.
  @override
  void _parseErrors() {
    var stdoutString = decodeUtf8(stdout);
    try {
      var errors = <StaticError>[];
      var warnings = <StaticError>[];
      parseErrors(stdoutString, errors, warnings);
      errors.forEach(addError);
      warnings.forEach(addWarning);
    } on FormatException {
      // It wasn't JSON. This can happen if analyzer instead prints:
      // "No dart files found at: ..."
      _invalidJsonStdout = stdoutString;
    }
  }
}

class CompareAnalyzerCfeCommandOutput extends CommandOutput {
  CompareAnalyzerCfeCommandOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped,
  ) : super(
        command,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        compilationSkipped,
        0,
      );

  @override
  Expectation result(TestCase testCase) {
    // Handle crashes and timeouts first
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    if (exitCode != 0) return Expectation.fail;
    for (var line in decodeUtf8(stdout).split('\n')) {
      if (line.contains('No differences found')) return Expectation.pass;
      if (line.contains('Differences found')) return Expectation.fail;
    }
    return Expectation.fail;
  }
}

class SpecParseCommandOutput extends CommandOutput with _StaticErrorOutput {
  SpecParseCommandOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped,
  ) : super(
        command,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        compilationSkipped,
        0,
      );

  bool get hasSyntaxError => exitCode == parseFailExitCode;

  @override
  Expectation result(TestCase testCase) {
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;
    if (testCase.testFile.isStaticErrorTest) {
      return _validateExpectedErrors(testCase);
    }
    if (hasSyntaxError || exitCode != 0) return Expectation.syntaxError;
    return Expectation.pass;
  }

  /// Parses the ANTLR parser's diagnostic output.
  ///
  /// For example: `void main() {(}` in 'foo.dart' yields
  ///   Syntax error in foo.dart:
  ///   line 1:14 no viable alternative at input '(}'
  ///   Parsing failed
  ///
  /// The 'Syntax error' line is emitted once for each file with
  /// a syntax error, and each error gets a 'line ...' message.
  @override
  void _parseErrors() {
    var output = decodeUtf8(stderr);
    var lines = output.split('\n');
    String? currentPath;
    var processCommand = command as ProcessCommand;
    var fallbackPath = processCommand.arguments.firstWhere(
      (arg) => arg.endsWith('.dart'),
      orElse: () => '',
    );
    for (var line in lines) {
      if (_pathRegExp.firstMatch(line) case var match?) {
        currentPath = match[1];
      } else if (_errorRegExp.firstMatch(line) case var match?) {
        var lineNum = int.parse(match[1]!);
        var column = int.parse(match[2]!) + 1; // ANTLR is 0-based.
        var message = match[3]!;
        addError(
          StaticError(
            ErrorSource.specParser,
            message,
            path: currentPath ?? fallbackPath,
            line: lineNum,
            column: column,
          ),
        );
      }
    }
  }

  static final RegExp _pathRegExp = .new(r"^Syntax error in (.*):$");
  static final RegExp _errorRegExp = .new(r"^line (\d+):(\d+) (.*)$");
}

class VMCommandOutput extends CommandOutput with _UnittestSuiteMessagesMixin {
  static const _dfeErrorExitCode = 252;
  static const _compileErrorExitCode = 254;
  static const _uncaughtExceptionExitCode = 255;
  static const _adbInfraFailureCodes = [10];
  static const _adbFailureExitCode = 3;
  static const _frontEndTestExitCode = 1;

  VMCommandOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    int pid,
  ) : super(command, exitCode, timedOut, stdout, stderr, time, false, pid);

  @override
  Expectation result(TestCase testCase) {
    // `ffx test` isn't preserving exit codes.
    // TODO(38752): Plumb exit codes through something else?
    if (testCase.configuration.system == System.fuchsia) {
      if (utf8.decode(stdout).contains("completed with result: PASSED")) {
        return Expectation.pass;
      }
      return Expectation.fail;
    }

    // Handle crashes and timeouts first.
    if (exitCode == _dfeErrorExitCode) return Expectation.dartkCrash;
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    // The actual outcome depends on the exitCode.
    if (exitCode == _compileErrorExitCode) return Expectation.compileTimeError;
    if (exitCode == _uncaughtExceptionExitCode) return Expectation.runtimeError;
    if (exitCode == _frontEndTestExitCode &&
        testCase.displayName.startsWith('pkg/front_end/test/')) {
      return Expectation.runtimeError;
    }
    if (testCase.configuration.system == System.android &&
        _adbInfraFailureCodes.contains(exitCode)) {
      print('Android device failed to run test');
      print(command);
      print(decodeUtf8(stdout));
      print(decodeUtf8(stderr));
      io.exit(_adbFailureExitCode);
    }
    if (exitCode != 0) {
      // This is a general fail, in case we get an unknown nonzero exitcode.
      return Expectation.fail;
    }
    var testOutput = decodeUtf8(stdout);
    if (_isAsyncTest(testOutput) && !_isAsyncTestSuccessful(testOutput)) {
      return Expectation.fail;
    }
    return Expectation.pass;
  }
}

class CompilationCommandOutput extends CommandOutput {
  static const _crashExitCode = 253;

  CompilationCommandOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped,
  ) : super(
        command,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        compilationSkipped,
        0,
      );

  @override
  Expectation result(TestCase testCase) {
    // Handle general crash/timeout detection.
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) {
      var isWindows = io.Platform.operatingSystem == 'windows';
      var isBrowserTestCase = testCase.commands.any(
        (command) => command is BrowserTestCommand,
      );
      // TODO(26060) Dart2js batch mode hangs on Windows under heavy load.
      return (isWindows && isBrowserTestCase)
          ? Expectation.ignore
          : Expectation.timeout;
    }
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    // Handle dart2js specific crash detection
    if (exitCode == _crashExitCode ||
        exitCode == VMCommandOutput._compileErrorExitCode ||
        exitCode == VMCommandOutput._uncaughtExceptionExitCode) {
      return Expectation.crash;
    }
    if (exitCode != 0) return Expectation.compileTimeError;
    return Expectation.pass;
  }
}

class Dart2jsCompilerCommandOutput extends CompilationCommandOutput
    with _StaticErrorOutput {
  static void parseErrors(
    String stdout,
    List<StaticError> errors, [
    List<StaticError>? warnings,
  ]) {
    _StaticErrorOutput._parseCfeErrors(
      ErrorSource.web,
      _errorRegexp,
      stdout,
      errors,
      warnings,
    );
  }

  /// Matches the location and message of a dart2js error message, which looks
  /// like:
  ///
  ///     tests/language/some_test.dart:9:3:
  ///     Error: Some message.
  ///       BadThing();
  ///       ^
  ///
  /// The test runner only validates the main error message, and not the
  /// suggested fixes, so we only parse the first line.
  // TODO(rnystrom): Support validating context messages.
  static final _errorRegexp = RegExp(
    r"^([^:\n\r]+):(\d+):(\d+):\n(Error|Warning): (.*)$",
    multiLine: true,
  );

  Dart2jsCompilerCommandOutput(
    super.command,
    super.exitCode,
    super.timedOut,
    super.stdout,
    super.stderr,
    super.time,
    super.compilationSkipped,
  );

  @override
  void _parseErrors() {
    var errors = <StaticError>[];
    var warnings = <StaticError>[];
    parseErrors(decodeUtf8(stdout), errors, warnings);
    errors.forEach(addError);
    warnings.forEach(addWarning);
  }
}

class Dart2WasmCompilerCommandOutput extends CompilationCommandOutput
    with _StaticErrorOutput {
  static void parseErrors(
    String stdout,
    List<StaticError> errors, [
    List<StaticError>? warnings,
  ]) {
    _StaticErrorOutput._parseCfeErrors(
      ErrorSource.web,
      _errorRegexp,
      stdout,
      errors,
      warnings,
    );
  }

  /// Matches the location and message of a dart2wasm error message, which looks
  /// like:
  ///
  ///     tests/language/some_test.dart:9:3: Error: Some message.
  ///       BadThing();
  ///       ^
  ///
  /// The test runner only validates the main error message, and not the
  /// suggested fixes, so we only parse the first line.
  // TODO(rnystrom): Support validating context messages.
  static final _errorRegexp = RegExp(
    r"^([^:\n\r]+):(\d+):(\d+): (Error|Warning): (.*)$",
    multiLine: true,
  );

  Dart2WasmCompilerCommandOutput(
    super.command,
    super.exitCode,
    super.timedOut,
    super.stdout,
    super.stderr,
    super.time,
    super.compilationSkipped,
  );

  @override
  Expectation result(TestCase testCase) {
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    switch (exitCode) {
      case VMCommandOutput._dfeErrorExitCode:
        return Expectation.dartkCrash;
      case VMCommandOutput._compileErrorExitCode:
        if (testCase.testFile.isStaticErrorTest) {
          return _validateExpectedErrors(testCase);
        }
        return Expectation.compileTimeError;
      case VMCommandOutput._uncaughtExceptionExitCode:
        return Expectation.crash;
      default:
        return exitCode != 0 ? Expectation.fail : Expectation.pass;
    }
  }

  @override
  void _parseErrors() {
    var errors = <StaticError>[];
    var warnings = <StaticError>[];
    // We expect errors to be printed to `stderr` for dart2wasm.
    parseErrors(decodeUtf8(stderr), errors, warnings);
    errors.forEach(addError);
    warnings.forEach(addWarning);
  }
}

class DevCompilerCommandOutput extends CommandOutput with _StaticErrorOutput {
  static void parseErrors(
    String stdout,
    List<StaticError> errors, [
    List<StaticError>? warnings,
  ]) {
    _StaticErrorOutput._parseCfeErrors(
      ErrorSource.web,
      _errorRegexp,
      stdout,
      errors,
      warnings,
    );
  }

  /// Matches the first line of a DDC error message. DDC prints errors to
  /// stdout that look like:
  ///
  ///     org-dartlang-app:/tests/language/some_test.dart:7:21: Error: Some message.
  ///     Try fixing the code to be less bad.
  ///       var _ = <int>[if (1) 2];
  ///                    ^
  ///
  /// The test runner only validates the main error message, and not the
  /// suggested fixes, so we only parse the first line.
  // TODO(rnystrom): Support validating context messages.
  static final _errorRegexp = RegExp(
    r"^org-dartlang-app:/([^\n\r]+):(\d+):(\d+): (Error|Warning): (.*)$",
    multiLine: true,
  );

  DevCompilerCommandOutput(
    super.command,
    super.exitCode,
    super.timedOut,
    super.stdout,
    super.stderr,
    super.time,
    super.compilationSkipped,
    super.pid,
  );

  @override
  Expectation result(TestCase testCase) {
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    // If it's a static error test, validate the exact errors.
    if (testCase.testFile.isStaticErrorTest) {
      return _validateExpectedErrors(testCase);
    }

    if (exitCode != 0) return Expectation.compileTimeError;

    return Expectation.pass;
  }

  @override
  void _parseErrors() {
    var errors = <StaticError>[];
    var warnings = <StaticError>[];
    parseErrors(decodeUtf8(stdout), errors, warnings);
    errors.forEach(addError);
    warnings.forEach(addWarning);
  }
}

class VMKernelCompilationCommandOutput extends CompilationCommandOutput {
  VMKernelCompilationCommandOutput(
    super.command,
    super.exitCode,
    super.timedOut,
    super.stdout,
    super.stderr,
    super.time,
    super.compilationSkipped,
  );

  @override
  bool get canRunDependentCommands {
    // See [BatchRunnerProcess]: 0 means success, 1 means compile-time error.
    // TODO(asgerf): When the frontend supports it, continue running even if
    // there were compile-time errors. See kernel_sdk issue #18.
    return !hasCrashed && !hasTimedOut && exitCode == 0;
  }

  @override
  Expectation result(TestCase testCase) {
    // TODO(kustermann): Currently the batch mode runner (which can be found
    // in `test_runner.dart:BatchRunnerProcess`) does not really distinguish
    // between different kinds of failures and will mark a failed
    // compilation to just an exit code of "1".  So we treat all `exitCode ==
    // 1`s as compile-time errors as well.
    const batchModeCompileTimeErrorExit = 1;

    // Handle crashes and timeouts first.
    if (hasCrashed) return Expectation.dartkCrash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    // If the frontend had an uncaught exception, then we'll consider this a
    // crash.
    if (exitCode == VMCommandOutput._uncaughtExceptionExitCode) {
      return Expectation.dartkCrash;
    }

    // Multitests are handled specially.

    if (exitCode == VMCommandOutput._compileErrorExitCode ||
        exitCode == batchModeCompileTimeErrorExit) {
      return Expectation.compileTimeError;
    }
    if (exitCode != 0) {
      // This is a general fail, in case we get an unknown nonzero exitcode.
      return Expectation.fail;
    }
    return Expectation.pass;
  }

  /// If the compiler was able to produce a Kernel IR file we want to run the
  /// result on the Dart VM. We therefore mark the [VMKernelCompilationCommand]
  /// as successful.
  ///
  /// This ensures we test that the DartVM produces correct CompileTime errors
  /// as it is supposed to for our test suites.
  @override
  bool get successful => canRunDependentCommands;
}

class JSCommandLineOutput extends CommandOutput
    with _UnittestSuiteMessagesMixin {
  JSCommandLineOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
  ) : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);

  @override
  Expectation result(TestCase testCase) {
    // Handle crashes and timeouts first.
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    if (exitCode != 0) return Expectation.runtimeError;
    var output = decodeUtf8(stdout);
    if (_isAsyncTest(output) && !_isAsyncTestSuccessful(output)) {
      return Expectation.fail;
    }
    return Expectation.pass;
  }

  @override
  void describe(TestCase testCase, Progress progress, OutputWriter output) {
    super.describe(testCase, progress, output);
    var decodedOut = decodeUtf8(
      stdout,
    ).replaceAll('\r\n', '\n').replaceAll('\r', '\n').trim();

    _deobfuscateAndWriteStack(decodedOut, output);
  }
}

class Dart2WasmCommandLineOutput extends CommandOutput
    with _UnittestSuiteMessagesMixin {
  Dart2WasmCommandLineOutput(
    Command command,
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
  ) : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);

  @override
  Expectation result(TestCase testCase) {
    // Handle crashes and timeouts first.
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    if (exitCode != 0) return Expectation.runtimeError;
    var output = decodeUtf8(stdout);
    if (_isAsyncTest(output) && !_isAsyncTestSuccessful(output)) {
      return Expectation.fail;
    }
    return Expectation.pass;
  }
}

class ScriptCommandOutput extends CommandOutput {
  final Expectation _result;

  ScriptCommandOutput(
    ScriptCommand command,
    this._result,
    String scriptExecutionInformation,
    Duration time,
  ) : super(command, 0, false, [], [], time, false, 0) {
    var lines = scriptExecutionInformation.split("\n");
    diagnostics.addAll(lines);
  }

  @override
  Expectation result(TestCase testCase) => _result;

  @override
  bool get canRunDependentCommands => _result == Expectation.pass;

  @override
  bool get successful => _result == Expectation.pass;
}

class FastaCommandOutput extends CompilationCommandOutput
    with _StaticErrorOutput {
  static void parseErrors(
    String stdout,
    List<StaticError> errors,
    List<StaticError> warnings,
  ) {
    _StaticErrorOutput._parseCfeErrors(
      ErrorSource.cfe,
      _errorRegexp,
      stdout,
      errors,
      warnings,
    );
  }

  /// Matches the first line of a Fasta error, warning, or context message.
  /// Fasta prints to stdout like:
  ///
  ///     tests/language/some_test.dart:7:21: Error: Some message.
  ///     Try fixing the code to be less bad.
  ///       var _ = <int>[if (1) 2];
  ///                    ^
  ///
  /// The test runner only validates the first line of the message, and not the
  /// suggested fixes.
  static final _errorRegexp = RegExp(
    r"^(?:([^:\n\r]+):(\d+):(\d+): )?(Context|Error|Warning): (.*)$",
    multiLine: true,
  );

  FastaCommandOutput(
    super.command,
    super.exitCode,
    super.hasTimedOut,
    super.stdout,
    super.stderr,
    super.time,
    super.compilationSkipped,
  );

  @override
  void _parseErrors() {
    var errors = <StaticError>[];
    var warnings = <StaticError>[];
    parseErrors(decodeUtf8(stdout), errors, warnings);
    errors.forEach(addError);
    warnings.forEach(addWarning);
  }
}

/// Mixin for outputs from a command that implement a Dart front end which
/// reports static errors.
mixin _StaticErrorOutput on CommandOutput {
  /// Parses compile errors reported by CFE using the given [regExp] and adds
  /// them to [errors] as coming from [errorSource].
  static void _parseCfeErrors(
    ErrorSource errorSource,
    RegExp regExp,
    String stdout,
    List<StaticError> errors, [
    List<StaticError>? warnings,
  ]) {
    StaticError? previousError;
    for (var match in regExp.allMatches(stdout)) {
      // These three are either all present or all null.
      var path = match[1];
      var line = _parseNullableInt(match[2]);
      var column = _parseNullableInt(match[3]);

      var severity = match[4];
      var message = match[5];

      if (path == null) {
        // No location information.
        if (severity == 'Context' && previousError != null) {
          // We can use the location information from the error message
          path = previousError.path;
          line = previousError.line;
          column = previousError.column;
        } else {
          // No good default location information, so disregard the error.
          // TODO(45558): we should do something smarter here.
          continue;
        }
      }
      // Line and column information should have been present or it should have
      // been filled in by the code above.
      assert(line != null);
      assert(column != null);

      var error = StaticError(
        severity == "Context" ? ErrorSource.context : errorSource,
        message!,
        path: path,
        line: line!,
        column: column!,
      );

      if (severity == "Context") {
        // Attach context messages to the preceding error/warning.
        if (previousError == null) {
          DebugLogger.error(
            "Got context message in CFE output before "
            "error to attach it to.",
          );
        } else {
          previousError.contextMessages.add(error);
        }
      } else {
        if (severity == "Error") {
          errors.add(error);
        } else {
          warnings?.add(error);
        }
        previousError = error;
      }
    }
  }

  /// Same as `int.parse`, but allows nulls to simply pass through.
  static int? _parseNullableInt(String? s) {
    if (s == null) {
      return null;
    }
    return int.parse(s);
  }

  /// Reported static errors, parsed from [stderr].
  List<StaticError> get errors {
    if (!_parsedErrors) {
      _parseErrors();
      _parsedErrors = true;
    }
    return _errors;
  }

  /// Don't access this from outside of the mixin. It gets populated lazily by
  /// going through the [errors] getter.
  final List<StaticError> _errors = [];

  /// Reported static warnings, parsed from [stderr].
  List<StaticError> get warnings {
    if (!_parsedErrors) {
      _parseErrors();
      _parsedErrors = true;
    }
    return _warnings;
  }

  /// Don't access this from outside of the mixin. It gets populated lazily by
  /// going through the [warnings] getter.
  final List<StaticError> _warnings = [];

  bool _parsedErrors = false;

  @override
  void describe(TestCase testCase, Progress progress, OutputWriter output) {
    // Handle static error test output specially. We don't want to show the raw
    // stdout if we can give the user the parsed expectations instead.
    if (testCase.testFile.isStaticErrorTest &&
        !hasCrashed &&
        !hasTimedOut &&
        !hasNonUtf8 &&
        !truncatedOutput) {
      try {
        _validateExpectedErrors(testCase, output);
      } catch (_) {
        // In the event of a crash trying to compute errors, go ahead and give
        // the raw output.
        super.describe(testCase, progress, output);
        return;
      }

      // Always show the raw output when specifically requested.
      if (progress == Progress.verbose) {
        super.describe(testCase, progress, output);
      }
    } else {
      // Something strange happened, so show the raw output.
      super.describe(testCase, progress, output);
    }
  }

  @override
  Expectation result(TestCase testCase) {
    if (hasCrashed) return Expectation.crash;
    if (hasTimedOut) return Expectation.timeout;
    if (hasNonUtf8) return Expectation.nonUtf8Error;
    if (truncatedOutput) return Expectation.truncatedOutput;

    // If it's a static error test, validate the exact errors.
    if (testCase.testFile.isStaticErrorTest) {
      return _validateExpectedErrors(testCase);
    }

    return super.result(testCase);
  }

  /// A subclass should override this to parse the command's output for any
  /// reported errors and warnings.
  ///
  /// It should read [stderr] and [stdout] and call [addError] and [addWarning].
  void _parseErrors();

  void addError(StaticError error) {
    _errors.add(error);
  }

  void addWarning(StaticError error) {
    _warnings.add(error);
  }

  /// Compare the actual errors produced to the expected static errors parsed
  /// from the test file.
  ///
  /// Returns [Expectation.pass] if all expected errors were correctly
  /// reported.
  ///
  /// If [writer] is given, outputs a description of any error mismatches.
  Expectation _validateExpectedErrors(
    TestCase testCase, [
    OutputWriter? writer,
  ]) {
    // Filter out errors that aren't for this configuration.
    var errorSource = const {
      Compiler.dart2analyzer: ErrorSource.analyzer,
      Compiler.dart2js: ErrorSource.web,
      Compiler.dart2wasm: ErrorSource.web,
      Compiler.ddc: ErrorSource.web,
      Compiler.fasta: ErrorSource.cfe,
      Compiler.specParser: ErrorSource.specParser,
    }[testCase.configuration.compiler]!;

    var expected = testCase.testFile.expectedErrors.where(
      (error) => error.source == errorSource,
    );

    var validation = StaticError.validateExpectations(expected, [
      ...errors,
      ...warnings,
    ]);
    if (validation == null) return Expectation.pass;

    writer?.subsection("static error failures");
    writer?.write(validation);

    return Expectation.missingCompileTimeError;
  }
}

mixin _UnittestSuiteMessagesMixin {
  bool _isAsyncTest(String testOutput) {
    return testOutput.contains("unittest-suite-wait-for-done");
  }

  bool _isAsyncTestSuccessful(String testOutput) {
    return testOutput.contains("unittest-suite-success");
  }
}

void _deobfuscateAndWriteStack(String stack, OutputWriter output) {
  try {
    var deobfuscatedStack = deobfuscateStackTrace(stack);
    if (deobfuscatedStack == stack) return;
    output.subsection('Deobfuscated error and stack');
    output.write(deobfuscatedStack);
  } catch (e, st) {
    output.subsection('Warning: not able to deobfuscate stack');
    output.writeAll(['input: $stack', 'error: $e', 'stack trace: $st']);
    return;
  }
}
