diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index 31a321d5f2..bc742ee74d 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -231,7 +231,7 @@ Future _evalCommand(String executable, List arguments, { } printProgress('RUNNING', relativeWorkingDir, commandDescription); - final DateTime start = DateTime.now(); + final Stopwatch time = Stopwatch()..start(); final Process process = await Process.start(executable, arguments, workingDirectory: workingDirectory, environment: environment, @@ -246,7 +246,7 @@ Future _evalCommand(String executable, List arguments, { exitCode: exitCode, ); - print('$clock ELAPSED TIME: $bold${elapsedTime(start)}$reset for $commandDescription in $relativeWorkingDir: '); + print('$clock ELAPSED TIME: $bold${prettyPrintDuration(time.elapsed)}$reset for $commandDescription in $relativeWorkingDir'); if (exitCode != 0 && !allowNonZeroExit) { stderr.write(result.stderr); diff --git a/dev/bots/run_command.dart b/dev/bots/run_command.dart index a5a371997c..634a23230a 100644 --- a/dev/bots/run_command.dart +++ b/dev/bots/run_command.dart @@ -10,24 +10,37 @@ import 'package:path/path.dart' as path; final bool hasColor = stdout.supportsAnsiEscapes; -final String bold = hasColor ? '\x1B[1m' : ''; -final String red = hasColor ? '\x1B[31m' : ''; -final String green = hasColor ? '\x1B[32m' : ''; -final String yellow = hasColor ? '\x1B[33m' : ''; -final String cyan = hasColor ? '\x1B[36m' : ''; +final String bold = hasColor ? '\x1B[1m' : ''; // used for shard titles +final String red = hasColor ? '\x1B[31m' : ''; // used for errors +final String green = hasColor ? '\x1B[32m' : ''; // used for section titles, commands +final String yellow = hasColor ? '\x1B[33m' : ''; // unused +final String cyan = hasColor ? '\x1B[36m' : ''; // used for paths +final String reverse = hasColor ? '\x1B[7m' : ''; // used for clocks final String reset = hasColor ? '\x1B[0m' : ''; final String redLine = '$red━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$reset'; -const String arrow = '⏩'; -const String clock = '🕐'; -const Duration _kLongTimeout = Duration(minutes: 45); +String get clock { + final DateTime now = DateTime.now(); + return '$reverse▌' + '${now.hour.toString().padLeft(2, "0")}:' + '${now.minute.toString().padLeft(2, "0")}:' + '${now.second.toString().padLeft(2, "0")}' + '▐$reset'; +} -String elapsedTime(DateTime start) { - return DateTime.now().difference(start).toString(); +String prettyPrintDuration(Duration duration) { + String result = ''; + final int minutes = duration.inMinutes; + if (minutes > 0) + result += '${minutes}min '; + final int seconds = duration.inSeconds - minutes * 60; + final int milliseconds = duration.inMilliseconds - (seconds * 1000 + minutes * 60 * 1000); + result += '$seconds.${milliseconds.toString().padLeft(3, "0")}s'; + return result; } void printProgress(String action, String workingDir, String command) { - print('$arrow $action: cd $cyan$workingDir$reset; $yellow$command$reset'); + print('$clock $action: cd $cyan$workingDir$reset; $green$command$reset'); } Stream runAndGetStdout(String executable, List arguments, { @@ -36,7 +49,6 @@ Stream runAndGetStdout(String executable, List arguments, { bool expectNonZeroExit = false, int expectedExitCode, String failureMessage, - Duration timeout = _kLongTimeout, Function beforeExit, }) async* { final String commandDescription = '${path.relative(executable, from: workingDirectory)} ${arguments.join(' ')}'; @@ -44,7 +56,7 @@ Stream runAndGetStdout(String executable, List arguments, { printProgress('RUNNING', relativeWorkingDir, commandDescription); - final DateTime start = DateTime.now(); + final Stopwatch time = Stopwatch()..start(); final Process process = await Process.start(executable, arguments, workingDirectory: workingDirectory, environment: environment, @@ -56,21 +68,18 @@ Stream runAndGetStdout(String executable, List arguments, { yield line; } - final int exitCode = await process.exitCode.timeout(timeout, onTimeout: () { - stderr.writeln('Process timed out after $timeout'); - return expectNonZeroExit ? 0 : 1; - }); - print('$clock ELAPSED TIME: $bold${elapsedTime(start)}$reset for $commandDescription in $relativeWorkingDir: '); + final int exitCode = await process.exitCode; + print('$clock ELAPSED TIME: ${prettyPrintDuration(time.elapsed)} for $green$commandDescription$reset in $cyan$relativeWorkingDir$reset'); if ((exitCode == 0) == expectNonZeroExit || (expectedExitCode != null && exitCode != expectedExitCode)) { if (failureMessage != null) { print(failureMessage); } print( '$redLine\n' - '${bold}ERROR:$red Last command exited with $exitCode (expected: ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'}).$reset\n' - '${bold}Command:$cyan $commandDescription$reset\n' - '${bold}Relative working directory:$red $relativeWorkingDir$reset\n' - '$redLine' + '${bold}ERROR: ${red}Last command exited with $exitCode (expected: ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'}).$reset\n' + '${bold}Command: $green$commandDescription$reset\n' + '${bold}Relative working directory: $cyan$relativeWorkingDir$reset\n' + '$redLine' ); beforeExit?.call(); exit(1); @@ -87,7 +96,6 @@ Future runCommand(String executable, List arguments, { CapturedOutput output, bool skip = false, bool expectFlaky = false, - Duration timeout = _kLongTimeout, bool Function(String) removeLine, }) async { assert((outputMode == OutputMode.capture) == (output != null), @@ -102,7 +110,7 @@ Future runCommand(String executable, List arguments, { } printProgress('RUNNING', relativeWorkingDir, commandDescription); - final DateTime start = DateTime.now(); + final Stopwatch time = Stopwatch()..start(); final Process process = await Process.start(executable, arguments, workingDirectory: workingDirectory, environment: environment, @@ -129,11 +137,8 @@ Future runCommand(String executable, List arguments, { break; } - final int exitCode = await process.exitCode.timeout(timeout, onTimeout: () { - stderr.writeln('Process timed out after $timeout'); - return (expectNonZeroExit || expectFlaky) ? 0 : 1; - }); - print('$clock ELAPSED TIME: $bold${elapsedTime(start)}$reset for $commandDescription in $relativeWorkingDir: '); + final int exitCode = await process.exitCode; + print('$clock ELAPSED TIME: ${prettyPrintDuration(time.elapsed)} for $green$commandDescription$reset in $cyan$relativeWorkingDir$reset'); if (output != null) { output.stdout = _flattenToString(await savedStdout); @@ -141,9 +146,9 @@ Future runCommand(String executable, List arguments, { } // If the test is flaky we don't care about the actual exit. - if (expectFlaky) { + if (expectFlaky) return; - } + if ((exitCode == 0) == expectNonZeroExit || (expectedExitCode != null && exitCode != expectedExitCode)) { if (failureMessage != null) { print(failureMessage); @@ -162,10 +167,10 @@ Future runCommand(String executable, List arguments, { } print( '$redLine\n' - '${bold}ERROR:$red Last command exited with $exitCode (expected: ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'}).$reset\n' - '${bold}Command:$cyan $commandDescription$reset\n' - '${bold}Relative working directory:$red $relativeWorkingDir$reset\n' - '$redLine' + '${bold}ERROR: ${red}Last command exited with $exitCode (expected: ${expectNonZeroExit ? (expectedExitCode ?? 'non-zero') : 'zero'}).$reset\n' + '${bold}Command: $green$commandDescription$reset\n' + '${bold}Relative working directory: $cyan$relativeWorkingDir$reset\n' + '$redLine' ); exit(1); } diff --git a/dev/bots/test.dart b/dev/bots/test.dart index 48a729f5ba..657ba529ea 100644 --- a/dev/bots/test.dart +++ b/dev/bots/test.dart @@ -46,9 +46,6 @@ const Map _kShards = { 'add2app_test': _runAdd2AppTest, }; -const Duration _kLongTimeout = Duration(minutes: 45); -const Duration _kShortTimeout = Duration(minutes: 5); - /// When you call this, you can pass additional arguments to pass custom /// arguments to flutter test. For example, you might want to call this /// script with the parameter --local-engine=host_debug_unopt to @@ -90,26 +87,22 @@ Future _runSmokeTests() async { await _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'pass_test.dart'), printOutput: false, - timeout: _kShortTimeout, ); await _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'fail_test.dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ); // We run the timeout tests individually because they are timing-sensitive. await _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'timeout_pass_test.dart'), expectFailure: false, printOutput: false, - timeout: _kShortTimeout, ); await _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'timeout_fail_test.dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ); await _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'pending_timer_fail_test.dart'), @@ -119,7 +112,6 @@ Future _runSmokeTests() async { output.stdout.contains('failingPendingTimerTest') ? null : 'Failed to find the stack trace for the pending Timer.', - timeout: _kShortTimeout, ); // We run the remaining smoketests in parallel, because they each take some // time to run (e.g. compiling), so we don't want to run them in series, @@ -130,38 +122,32 @@ Future _runSmokeTests() async { script: path.join('test_smoke_test', 'crash1_test.dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ), _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'crash2_test.dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ), _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'syntax_error_test.broken_dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ), _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'missing_import_test.broken_dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ), _runFlutterTest(automatedTests, script: path.join('test_smoke_test', 'disallow_error_reporter_modification_test.dart'), expectFailure: true, printOutput: false, - timeout: _kShortTimeout, ), runCommand(flutter, ['drive', '--use-existing-app', '-t', path.join('test_driver', 'failure.dart')], workingDirectory: path.join(flutterRoot, 'packages', 'flutter_driver'), expectNonZeroExit: true, outputMode: OutputMode.discard, - timeout: _kShortTimeout, ), ], ); @@ -306,7 +292,6 @@ Future _flutterBuildDart2js(String relativePathToApplication) async { ['build', 'web', '-v'], workingDirectory: path.join(flutterRoot, relativePathToApplication), expectNonZeroExit: false, - timeout: _kShortTimeout, environment: { 'FLUTTER_WEB': 'true', } @@ -320,7 +305,6 @@ Future _flutterBuildAot(String relativePathToApplication) async { ['build', 'aot', '-v'], workingDirectory: path.join(flutterRoot, relativePathToApplication), expectNonZeroExit: false, - timeout: _kShortTimeout, ); print('Done.'); } @@ -336,7 +320,6 @@ Future _flutterBuildApk(String relativePathToApplication) async { ['build', 'apk', '--debug', '-v'], workingDirectory: path.join(flutterRoot, relativePathToApplication), expectNonZeroExit: false, - timeout: _kShortTimeout, ); print('Done.'); } @@ -354,14 +337,12 @@ Future _flutterBuildIpa(String relativePathToApplication) async { ['install'], workingDirectory: podfile.parent.path, expectNonZeroExit: false, - timeout: _kShortTimeout, ); } await runCommand(flutter, ['build', 'ios', '--no-codesign', '--debug', '-v'], workingDirectory: path.join(flutterRoot, relativePathToApplication), expectNonZeroExit: false, - timeout: _kShortTimeout, ); print('Done.'); } @@ -376,7 +357,6 @@ Future _runAdd2AppTest() async { [], workingDirectory: add2AppDir, expectNonZeroExit: false, - timeout: _kShortTimeout, ); print('Done.'); } @@ -783,7 +763,6 @@ class EvalResult { } Future _runFlutterWebTest(String workingDirectory, { - Duration timeout = _kLongTimeout, List tests, }) async { final List args = [ @@ -803,7 +782,6 @@ Future _runFlutterWebTest(String workingDirectory, { args, workingDirectory: workingDirectory, expectFlaky: true, - timeout: timeout, environment: { 'FLUTTER_WEB': 'true', 'FLUTTER_LOW_RESOURCE_MODE': 'true', @@ -821,7 +799,6 @@ Future _runFlutterTest(String workingDirectory, { OutputChecker outputChecker, List options = const [], bool skip = false, - Duration timeout = _kLongTimeout, bq.TabledataResourceApi tableData, Map environment, List tests = const [], @@ -876,7 +853,6 @@ Future _runFlutterTest(String workingDirectory, { outputMode: outputMode, output: output, skip: skip, - timeout: timeout, environment: environment, ); @@ -899,7 +875,6 @@ Future _runFlutterTest(String workingDirectory, { args, workingDirectory: workingDirectory, expectNonZeroExit: expectFailure, - timeout: timeout, beforeExit: formatter.finish, environment: environment, ); @@ -910,7 +885,6 @@ Future _runFlutterTest(String workingDirectory, { args, workingDirectory: workingDirectory, expectNonZeroExit: expectFailure, - timeout: timeout, ); } }