mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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:
parent
b0b0e423d6
commit
11119cff38
@ -188,15 +188,7 @@ Future<CommandResult> runCommand(String executable, List<String> arguments, {
|
|||||||
print(result.flattenedStdout);
|
print(result.flattenedStdout);
|
||||||
print(result.flattenedStderr);
|
print(result.flattenedStderr);
|
||||||
}
|
}
|
||||||
String allOutput;
|
final String allOutput = '${result.flattenedStdout}\n${result.flattenedStderr}';
|
||||||
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 = '';
|
|
||||||
}
|
|
||||||
foundError(<String>[
|
foundError(<String>[
|
||||||
if (failureMessage != null)
|
if (failureMessage != null)
|
||||||
failureMessage,
|
failureMessage,
|
||||||
@ -204,7 +196,7 @@ Future<CommandResult> runCommand(String executable, List<String> arguments, {
|
|||||||
if (failureMessage == null)
|
if (failureMessage == null)
|
||||||
'$bold${red}Command exited with exit code ${result.exitCode} but expected ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'} exit code.$reset',
|
'$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',
|
'${bold}Working directory: $cyan${path.absolute(relativeWorkingDir)}$reset',
|
||||||
if (allOutput.isNotEmpty)
|
if (allOutput.isNotEmpty && allOutput.length < 512)
|
||||||
'${bold}stdout and stderr output:\n$allOutput',
|
'${bold}stdout and stderr output:\n$allOutput',
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -69,7 +69,7 @@ void main() {
|
|||||||
})
|
})
|
||||||
.join('\n');
|
.join('\n');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'$lines\n'
|
'$lines\n'
|
||||||
'║ See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes\n'
|
'║ See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes\n'
|
||||||
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
||||||
@ -88,7 +88,7 @@ void main() {
|
|||||||
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
||||||
.toList();
|
.toList();
|
||||||
expect(result.length, 4 + lines.length, reason: 'output had unexpected number of lines:\n${result.join('\n')}');
|
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.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 - 3], '║ See: https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter');
|
||||||
expect(result[result.length - 2], '╚═══════════════════════════════════════════════════════════════════════════════');
|
expect(result[result.length - 2], '╚═══════════════════════════════════════════════════════════════════════════════');
|
||||||
@ -100,7 +100,7 @@ void main() {
|
|||||||
final String file = 'test/analyze-test-input/root/packages/foo/foo.dart'
|
final String file = 'test/analyze-test-input/root/packages/foo/foo.dart'
|
||||||
.replaceAll('/', Platform.isWindows ? r'\' : '/');
|
.replaceAll('/', Platform.isWindows ? r'\' : '/');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'║ The following file does not have the right license header for dart files:\n'
|
'║ The following file does not have the right license header for dart files:\n'
|
||||||
'║ $file\n'
|
'║ $file\n'
|
||||||
'║ The expected license header is:\n'
|
'║ The expected license header is:\n'
|
||||||
@ -121,7 +121,7 @@ void main() {
|
|||||||
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
||||||
.join('\n');
|
.join('\n');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'$lines\n'
|
'$lines\n'
|
||||||
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
||||||
);
|
);
|
||||||
@ -139,7 +139,7 @@ void main() {
|
|||||||
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
||||||
.join('\n');
|
.join('\n');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'$lines\n'
|
'$lines\n'
|
||||||
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
'╚═══════════════════════════════════════════════════════════════════════════════\n'
|
||||||
);
|
);
|
||||||
@ -152,7 +152,7 @@ void main() {
|
|||||||
), shouldHaveErrors: !Platform.isWindows);
|
), shouldHaveErrors: !Platform.isWindows);
|
||||||
if (!Platform.isWindows) {
|
if (!Platform.isWindows) {
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'║ test/analyze-test-input/root/packages/foo/serviceaccount.enc:0: file is not valid UTF-8\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'
|
'║ 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'
|
'║ 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'\' : '/'))
|
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
||||||
.join('\n');
|
.join('\n');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'$lines\n'
|
'$lines\n'
|
||||||
'║ \n'
|
'║ \n'
|
||||||
'║ For performance reasons, we use a custom "clampDouble" function instead of using "double.clamp".\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'\' : '/'))
|
.map((String line) => line.replaceAll('/', Platform.isWindows ? r'\' : '/'))
|
||||||
.join('\n');
|
.join('\n');
|
||||||
expect(result,
|
expect(result,
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════\n'
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════\n'
|
||||||
'$lines\n'
|
'$lines\n'
|
||||||
'║ \n'
|
'║ \n'
|
||||||
'║ Stopwatches introduce flakes by falling out of sync with the FakeAsync used in testing.\n'
|
'║ Stopwatches introduce flakes by falling out of sync with the FakeAsync used in testing.\n'
|
||||||
|
@ -119,7 +119,7 @@ void main() {
|
|||||||
shouldHaveErrors: true,
|
shouldHaveErrors: true,
|
||||||
);
|
);
|
||||||
final String lines = <String>[
|
final String lines = <String>[
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════',
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
|
||||||
'║ The following examples are not linked from any source file API doc comments:',
|
'║ The following examples are not linked from any source file API doc comments:',
|
||||||
'║ examples/api/lib/layer/missing_example.0.dart',
|
'║ examples/api/lib/layer/missing_example.0.dart',
|
||||||
'║ Either link them to a source file API doc comment, or remove them.',
|
'║ 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 bool isWindows = Platform.isWindows;
|
||||||
final String lines = <String>[
|
final String lines = <String>[
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════',
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
|
||||||
'║ The following examples are not linked from any source file API doc comments:',
|
'║ 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/animation/curves/curve2_d.0.dart',
|
||||||
if (!isWindows) '║ examples/api/lib/layer/foo_example.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',
|
if (isWindows) r'║ examples\api\lib\layer\bar_example.0.dart',
|
||||||
'║ Either link them to a source file API doc comment, or remove them.',
|
'║ 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:',
|
'║ 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/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 *',
|
if (!isWindows) '║ /flutter sdk/packages/flutter/lib/src/layer/foo.dart:6: ///*See Code *',
|
||||||
@ -178,7 +178,7 @@ void main() {
|
|||||||
shouldHaveErrors: true,
|
shouldHaveErrors: true,
|
||||||
);
|
);
|
||||||
final String lines = <String>[
|
final String lines = <String>[
|
||||||
'╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════',
|
'╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════',
|
||||||
'║ The following example test files are missing:',
|
'║ The following example test files are missing:',
|
||||||
'║ examples/api/test/layer/bar_example.0_test.dart',
|
'║ examples/api/test/layer/bar_example.0_test.dart',
|
||||||
'╚═══════════════════════════════════════════════════════════════════════════════',
|
'╚═══════════════════════════════════════════════════════════════════════════════',
|
||||||
|
65
dev/bots/test/run_command_test.dart
Normal file
65
dev/bots/test/run_command_test.dart
Normal 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.
|
||||||
|
}
|
@ -95,7 +95,8 @@ void foundError(List<String> messages) {
|
|||||||
// Make the error message easy to notice in the logs by
|
// Make the error message easy to notice in the logs by
|
||||||
// wrapping it in a red box.
|
// wrapping it in a red box.
|
||||||
final int width = math.max(15, (hasColor ? stdout.terminalColumns : 80) - 1);
|
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'))) {
|
for (final String message in messages.expand((String line) => line.split('\n'))) {
|
||||||
print('$red║$reset $message');
|
print('$red║$reset $message');
|
||||||
}
|
}
|
||||||
@ -145,6 +146,7 @@ Never reportErrorsAndExit(String message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
print(redLine);
|
print(redLine);
|
||||||
|
print('You may find the errors by searching for "╡ERROR #" in the logs.');
|
||||||
system.exit(1);
|
system.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user