More helpful test.dart output (#140175)

Each error section is numbered, so you can all be sure you're talking about the same one.
A message is printed at the very end telling you how to find the error blocks in the verbose logs.
This commit is contained in:
Ian Hickson 2023-12-28 15:16:12 -08:00 committed by GitHub
parent b0b0e423d6
commit 11119cff38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 23 deletions

View file

@ -188,15 +188,7 @@ Future<CommandResult> runCommand(String executable, List<String> arguments, {
print(result.flattenedStdout);
print(result.flattenedStderr);
}
String allOutput;
if (failureMessage == null) {
allOutput = '${result.flattenedStdout}\n${result.flattenedStderr}';
if (allOutput.split('\n').length > 10) {
allOutput = '(stdout/stderr output was more than 10 lines)';
}
} else {
allOutput = '';
}
final String allOutput = '${result.flattenedStdout}\n${result.flattenedStderr}';
foundError(<String>[
if (failureMessage != null)
failureMessage,
@ -204,7 +196,7 @@ Future<CommandResult> runCommand(String executable, List<String> arguments, {
if (failureMessage == null)
'$bold${red}Command exited with exit code ${result.exitCode} but expected ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'} exit code.$reset',
'${bold}Working directory: $cyan${path.absolute(relativeWorkingDir)}$reset',
if (allOutput.isNotEmpty)
if (allOutput.isNotEmpty && allOutput.length < 512)
'${bold}stdout and stderr output:\n$allOutput',
]);
} else {

View file

@ -69,7 +69,7 @@ void main() {
})
.join('\n');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'$lines\n'
'║ See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes\n'
'╚═══════════════════════════════════════════════════════════════════════════════\n'
@ -88,7 +88,7 @@ void main() {
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
.toList();
expect(result.length, 4 + lines.length, reason: 'output had unexpected number of lines:\n${result.join('\n')}');
expect(result[0], '╔═╡ERROR═══════════════════════════════════════════════════════════════════════');
expect(result[0], '╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════');
expect(result.getRange(1, result.length - 3).toSet(), lines.toSet());
expect(result[result.length - 3], '║ See: https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter');
expect(result[result.length - 2], '╚═══════════════════════════════════════════════════════════════════════════════');
@ -100,7 +100,7 @@ void main() {
final String file = 'test/analyze-test-input/root/packages/foo/foo.dart'
.replaceAll('/', Platform.isWindows ? r'\' : '/');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'║ The following file does not have the right license header for dart files:\n'
'$file\n'
'║ The expected license header is:\n'
@ -121,7 +121,7 @@ void main() {
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
.join('\n');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'$lines\n'
'╚═══════════════════════════════════════════════════════════════════════════════\n'
);
@ -139,7 +139,7 @@ void main() {
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
.join('\n');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'$lines\n'
'╚═══════════════════════════════════════════════════════════════════════════════\n'
);
@ -152,7 +152,7 @@ void main() {
), shouldHaveErrors: !Platform.isWindows);
if (!Platform.isWindows) {
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'║ test/analyze-test-input/root/packages/foo/serviceaccount.enc:0: file is not valid UTF-8\n'
'║ All files in this repository must be UTF-8. In particular, images and other binaries\n'
'║ must not be checked into this repository. This is because we are very sensitive to the\n'
@ -229,7 +229,7 @@ void main() {
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
.join('\n');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'$lines\n'
'\n'
'║ For performance reasons, we use a custom "clampDouble" function instead of using "double.clamp".\n'
@ -259,7 +259,7 @@ void main() {
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
.join('\n');
expect(result,
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════\n'
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
'$lines\n'
'\n'
'║ Stopwatches introduce flakes by falling out of sync with the FakeAsync used in testing.\n'

View file

@ -119,7 +119,7 @@ void main() {
shouldHaveErrors: true,
);
final String lines = <String>[
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════',
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
'║ The following examples are not linked from any source file API doc comments:',
'║ examples/api/lib/layer/missing_example.0.dart',
'║ Either link them to a source file API doc comment, or remove them.',
@ -142,7 +142,7 @@ void main() {
);
final bool isWindows = Platform.isWindows;
final String lines = <String>[
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════',
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
'║ The following examples are not linked from any source file API doc comments:',
if (!isWindows) '║ examples/api/lib/animation/curves/curve2_d.0.dart',
if (!isWindows) '║ examples/api/lib/layer/foo_example.0.dart',
@ -152,7 +152,7 @@ void main() {
if (isWindows) r'║ examples\api\lib\layer\bar_example.0.dart',
'║ Either link them to a source file API doc comment, or remove them.',
'╚═══════════════════════════════════════════════════════════════════════════════',
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════',
'╔═╡ERROR #2╞════════════════════════════════════════════════════════════════════',
'║ The following malformed links were found in API doc comments:',
if (!isWindows) '║ /flutter sdk/packages/flutter/lib/src/animation/curves.dart:6: ///* see code in examples/api/lib/animation/curves/curve2_d.0.dart *',
if (!isWindows) '║ /flutter sdk/packages/flutter/lib/src/layer/foo.dart:6: ///*See Code *',
@ -178,7 +178,7 @@ void main() {
shouldHaveErrors: true,
);
final String lines = <String>[
'╔═╡ERROR═══════════════════════════════════════════════════════════════════════',
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
'║ The following example test files are missing:',
'║ examples/api/test/layer/bar_example.0_test.dart',
'╚═══════════════════════════════════════════════════════════════════════════════',

View file

@ -0,0 +1,65 @@
// Copyright 2014 The Flutter Authors. 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:io' as io;
import '../run_command.dart';
import '../utils.dart';
import 'common.dart';
void main() {
// These tests only run on Linux. They test platform-agnostic code that is
// triggered by platform-sensitive code. To avoid having to complicate our
// test harness by using a mockable process manager, the tests rely on one
// platform's conventions (Linux having `sh`). The logic being tested is not
// so critical that it matters that we're only testing it on one platform.
test('short output on runCommand failure', () async {
final List<Object?> log = <String>[];
final PrintCallback oldPrint = print;
print = log.add;
try {
await runCommand('/usr/bin/sh', <String>['-c', 'echo test; false']);
expect(log, <Object>[
startsWith('RUNNING:'),
'workingDirectory: null, executable: /usr/bin/sh, arguments: [-c, echo test; false]',
'test',
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
startsWith('║ Command: '),
'║ Command exited with exit code 1 but expected zero exit code.',
startsWith('║ Working directory: '),
'║ stdout and stderr output:',
'║ test',
'',
'╚═══════════════════════════════════════════════════════════════════════════════'
]);
} finally {
print = oldPrint;
resetErrorStatus();
}
}, skip: !io.Platform.isLinux); // [intended] See comments above.
test('long output on runCommand failure', () async {
final List<Object?> log = <String>[];
final PrintCallback oldPrint = print;
print = log.add;
try {
await runCommand('/usr/bin/sh', <String>['-c', 'echo ${"meow" * 1024}; false']);
expect(log, <Object>[
startsWith('RUNNING:'),
'workingDirectory: null, executable: /usr/bin/sh, arguments: [-c, echo ${"meow" * 1024}; false]',
'meow' * 1024,
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
startsWith('║ Command: '),
'║ Command exited with exit code 1 but expected zero exit code.',
startsWith('║ Working directory: '),
'╚═══════════════════════════════════════════════════════════════════════════════'
]);
} finally {
print = oldPrint;
resetErrorStatus();
}
}, skip: !io.Platform.isLinux); // [intended] See comments above.
}

View file

@ -95,7 +95,8 @@ void foundError(List<String> messages) {
// Make the error message easy to notice in the logs by
// wrapping it in a red box.
final int width = math.max(15, (hasColor ? stdout.terminalColumns : 80) - 1);
print('$red╔═╡${bold}ERROR$reset$red╞═${"" * (width - 9)}');
final String title = 'ERROR #${_errorMessages.length + 1}';
print('$red╔═╡$bold$title$reset$red╞═${"" * (width - 4 - title.length)}');
for (final String message in messages.expand((String line) => line.split('\n'))) {
print('$red$reset $message');
}
@ -145,6 +146,7 @@ Never reportErrorsAndExit(String message) {
}
}
print(redLine);
print('You may find the errors by searching for "╡ERROR #" in the logs.');
system.exit(1);
}