[test_runner] Fix error parsing: paths do not contain newlines.

This stops over-matching which was causing paths to be incorrect when there were multiple errors, breaking the expectation updater.

R=srujzs@google.com

Change-Id: I357d0c96ed2d5bc3658d6cc2eb9ca82f86860818
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/357700
Commit-Queue: Morgan :) <davidmorgan@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Auto-Submit: Morgan :) <davidmorgan@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 476b45d..dd5fdb6 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -1108,7 +1108,7 @@
   /// suggested fixes, so we only parse the first line.
   // TODO(rnystrom): Support validating context messages.
   static final _errorRegexp =
-      RegExp(r"^([^:]+):(\d+):(\d+):\n(Error): (.*)$", multiLine: true);
+      RegExp(r"^([^:\n\r]+):(\d+):(\d+):\n(Error): (.*)$", multiLine: true);
 
   Dart2jsCompilerCommandOutput(super.command, super.exitCode, super.timedOut,
       super.stdout, super.stderr, super.time, super.compilationSkipped);
@@ -1139,7 +1139,7 @@
   /// suggested fixes, so we only parse the first line.
   // TODO(rnystrom): Support validating context messages.
   static final _errorRegexp =
-      RegExp(r"^([^:]+):(\d+):(\d+): (Error): (.*)$", multiLine: true);
+      RegExp(r"^([^:\n\r]+):(\d+):(\d+): (Error): (.*)$", multiLine: true);
 
   Dart2WasmCompilerCommandOutput(super.command, super.exitCode, super.timedOut,
       super.stdout, super.stderr, super.time, super.compilationSkipped);
@@ -1154,6 +1154,11 @@
 }
 
 class DevCompilerCommandOutput extends CommandOutput with _StaticErrorOutput {
+  static void parseErrors(String stdout, List<StaticError> errors) {
+    _StaticErrorOutput._parseCfeErrors(
+        ErrorSource.web, _errorRegexp, stdout, errors);
+  }
+
   /// Matches the first line of a DDC error message. DDC prints errors to
   /// stdout that look like:
   ///
@@ -1166,7 +1171,7 @@
   /// suggested fixes, so we only parse the first line.
   // TODO(rnystrom): Support validating context messages.
   static final _errorRegexp = RegExp(
-      r"^org-dartlang-app:/([^:]+):(\d+):(\d+): (Error): (.*)$",
+      r"^org-dartlang-app:/([^\n\r]+):(\d+):(\d+): (Error): (.*)$",
       multiLine: true);
 
   DevCompilerCommandOutput(
@@ -1223,8 +1228,7 @@
   @override
   void _parseErrors() {
     var errors = <StaticError>[];
-    _StaticErrorOutput._parseCfeErrors(
-        ErrorSource.web, _errorRegexp, decodeUtf8(stdout), errors);
+    parseErrors(decodeUtf8(stdout), errors);
     errors.forEach(addError);
   }
 }
diff --git a/pkg/test_runner/test/parse_error_test.dart b/pkg/test_runner/test/parse_error_test.dart
index 426196d..be1baee 100644
--- a/pkg/test_runner/test/parse_error_test.dart
+++ b/pkg/test_runner/test/parse_error_test.dart
@@ -23,6 +23,9 @@
 void main() {
   // TODO(55202): Add general testing of CFE and analyzer error parsing.
   testCfeErrors();
+  testDart2jsCompilerErrors();
+  testDart2WasmCompilerErrors();
+  testDevCompilerErrors();
 }
 
 void testCfeErrors() {
@@ -185,3 +188,110 @@
       message:
           "Operand of null-aware operation '!' has type 'Type' which excludes null.");
 }
+
+void testDart2jsCompilerErrors() {
+  _testMultipleDart2jsCompilerErrors();
+}
+
+void _testMultipleDart2jsCompilerErrors() {
+  var errors = <StaticError>[];
+  Dart2jsCompilerCommandOutput.parseErrors('''
+tests/language/explicit_type_instantiation_parsing_test.dart:171:26:
+Error: Cannot access static member on an instantiated generic class.
+Try removing the type arguments or placing them after the member name.
+  expect1<Class>(Z<X, X>.instance);
+                         ^^^^^^^^
+tests/language/explicit_type_instantiation_parsing_test.dart:232:6:
+Error: A comparison expression can't be an operand of another comparison expression.
+Try putting parentheses around one of the comparisons.
+  X<2>(2);
+     ^
+''', errors);
+
+  var path = 'tests/language/explicit_type_instantiation_parsing_test.dart';
+
+  Expect.equals(2, errors.length);
+
+  _checkError(errors[0],
+      path: path,
+      line: 171,
+      column: 26,
+      message: "Cannot access static member on an instantiated generic class.");
+
+  _checkError(errors[1],
+      path: path,
+      line: 232,
+      column: 6,
+      message:
+          "A comparison expression can't be an operand of another comparison expression.");
+}
+
+void testDart2WasmCompilerErrors() {
+  _testMultipleDart2WasmCompilerErrors();
+}
+
+void _testMultipleDart2WasmCompilerErrors() {
+  var errors = <StaticError>[];
+  Dart2WasmCompilerCommandOutput.parseErrors('''
+tests/language/explicit_type_instantiation_parsing_test.dart:171:26: Error: Cannot access static member on an instantiated generic class.
+Try removing the type arguments or placing them after the member name.
+  expect1<Class>(Z<X, X>.instance);
+                         ^^^^^^^^
+tests/language/explicit_type_instantiation_parsing_test.dart:232:6: Error: A comparison expression can't be an operand of another comparison expression.
+Try putting parentheses around one of the comparisons.
+  X<2>(2);
+     ^
+''', errors);
+
+  var path = 'tests/language/explicit_type_instantiation_parsing_test.dart';
+
+  Expect.equals(2, errors.length);
+
+  _checkError(errors[0],
+      path: path,
+      line: 171,
+      column: 26,
+      message: "Cannot access static member on an instantiated generic class.");
+
+  _checkError(errors[1],
+      path: path,
+      line: 232,
+      column: 6,
+      message:
+          "A comparison expression can't be an operand of another comparison expression.");
+}
+
+void testDevCompilerErrors() {
+  _testMultipleDevCompilerErrors();
+}
+
+void _testMultipleDevCompilerErrors() {
+  var errors = <StaticError>[];
+  DevCompilerCommandOutput.parseErrors('''
+org-dartlang-app:/tests/language/explicit_type_instantiation_parsing_test.dart:171:26: Error: Cannot access static member on an instantiated generic class.
+Try removing the type arguments or placing them after the member name.
+  expect1<Class>(Z<X, X>.instance);
+                         ^^^^^^^^
+org-dartlang-app:/tests/language/explicit_type_instantiation_parsing_test.dart:232:6: Error: A comparison expression can't be an operand of another comparison expression.
+Try putting parentheses around one of the comparisons.
+  X<2>(2);
+     ^
+''', errors);
+
+  var path = 'tests/language/explicit_type_instantiation_parsing_test.dart';
+
+  Expect.equals(2, errors.length);
+
+  _checkError(errors[0],
+      path: path,
+      line: 171,
+      column: 26,
+      message: "Cannot access static member on an instantiated generic class.");
+
+  _checkError(errors[1],
+      path: path,
+      line: 232,
+      column: 6,
+      message:
+          "A comparison expression can't be an operand of another comparison expression.");
+}