diff --git a/dev/bots/run_command.dart b/dev/bots/run_command.dart index e32b0f8ba1c..f39d89650b0 100644 --- a/dev/bots/run_command.dart +++ b/dev/bots/run_command.dart @@ -188,15 +188,7 @@ Future runCommand(String executable, List 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([ if (failureMessage != null) failureMessage, @@ -204,7 +196,7 @@ Future runCommand(String executable, List 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 { diff --git a/dev/bots/test/analyze_test.dart b/dev/bots/test/analyze_test.dart index 3c06d78a3ca..57bb08c23f9 100644 --- a/dev/bots/test/analyze_test.dart +++ b/dev/bots/test/analyze_test.dart @@ -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' diff --git a/dev/bots/test/check_code_samples_test.dart b/dev/bots/test/check_code_samples_test.dart index 1e748f0210d..c72c39010da 100644 --- a/dev/bots/test/check_code_samples_test.dart +++ b/dev/bots/test/check_code_samples_test.dart @@ -119,7 +119,7 @@ void main() { shouldHaveErrors: true, ); final String lines = [ - '╔═╡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 = [ - '╔═╡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 = [ - '╔═╡ERROR╞═══════════════════════════════════════════════════════════════════════', + '╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════', '║ The following example test files are missing:', '║ examples/api/test/layer/bar_example.0_test.dart', '╚═══════════════════════════════════════════════════════════════════════════════', diff --git a/dev/bots/test/run_command_test.dart b/dev/bots/test/run_command_test.dart new file mode 100644 index 00000000000..9252965e016 --- /dev/null +++ b/dev/bots/test/run_command_test.dart @@ -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 log = []; + final PrintCallback oldPrint = print; + print = log.add; + try { + await runCommand('/usr/bin/sh', ['-c', 'echo test; false']); + expect(log, [ + 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 log = []; + final PrintCallback oldPrint = print; + print = log.add; + try { + await runCommand('/usr/bin/sh', ['-c', 'echo ${"meow" * 1024}; false']); + expect(log, [ + 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. +} diff --git a/dev/bots/utils.dart b/dev/bots/utils.dart index 58bdf5f30b6..165fc379237 100644 --- a/dev/bots/utils.dart +++ b/dev/bots/utils.dart @@ -95,7 +95,8 @@ void foundError(List 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); }