More flexible timeout logic in flutter_test (#18256)
This should reduce the number of flakes without actually increasing
the timeout, so we'll still find out quickly if a test is hanging.
The numbers here might need tweaking. Maybe the default two seconds is
too short for CI bots.
diff --git a/dev/bots/test.dart b/dev/bots/test.dart
index ab8f030..7bbd571 100644
--- a/dev/bots/test.dart
+++ b/dev/bots/test.dart
@@ -50,8 +50,11 @@
final String shard = Platform.environment['SHARD'];
if (shard != null) {
- if (!_kShards.containsKey(shard))
- throw new ArgumentError('Invalid shard: $shard');
+ if (!_kShards.containsKey(shard)) {
+ print('Invalid shard: $shard');
+ print('The available shards are: ${_kShards.keys.join(", ")}');
+ exit(1);
+ }
print('${bold}SHARD=$shard$reset');
await _kShards[shard]();
} else {
@@ -132,55 +135,79 @@
}
Future<Null> _runTests() async {
- // Verify that the tests actually return failure on failure and success on success.
+ // Verify that the tests actually return failure on failure and success on
+ // success.
final String automatedTests = path.join(flutterRoot, 'dev', 'automated_tests');
- await _runFlutterTest(automatedTests,
- script: path.join('test_smoke_test', 'fail_test.dart'),
- expectFailure: true,
- printOutput: false,
- timeout: _kShortTimeout,
- );
+ // We run the "pass" and "fail" smoke tests first, and alone, because those
+ // are particularly critical and sensitive. If one of these fails, there's no
+ // point even trying the others.
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', 'crash1_test.dart'),
+ 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', 'crash2_test.dart'),
+ 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', 'syntax_error_test.broken_dart'),
- expectFailure: true,
- printOutput: false,
- timeout: _kShortTimeout,
- );
- await _runFlutterTest(automatedTests,
- script: path.join('test_smoke_test', 'missing_import_test.broken_dart'),
- expectFailure: true,
- printOutput: false,
- timeout: _kShortTimeout,
- );
- await _runFlutterTest(automatedTests,
- script: path.join('test_smoke_test', 'disallow_error_reporter_modification_test.dart'),
- expectFailure: true,
- printOutput: false,
- timeout: _kShortTimeout,
- );
- await _runCommand(flutter,
- <String>['drive', '--use-existing-app', '-t', path.join('test_driver', 'failure.dart')],
- workingDirectory: path.join(flutterRoot, 'packages', 'flutter_driver'),
- expectFailure: true,
- printOutput: false,
- 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,
+ // especially on 20-core machines...
+ await Future.wait<void>(
+ <Future<void>>[
+ _runFlutterTest(automatedTests,
+ 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,
+ <String>['drive', '--use-existing-app', '-t', path.join('test_driver', 'failure.dart')],
+ workingDirectory: path.join(flutterRoot, 'packages', 'flutter_driver'),
+ expectFailure: true,
+ printOutput: false,
+ timeout: _kShortTimeout,
+ ),
+ ],
);
// Verify that we correctly generated the version file.
@@ -369,8 +396,20 @@
final List<String> args = <String>['test']..addAll(options);
if (flutterTestArgs != null && flutterTestArgs.isNotEmpty)
args.addAll(flutterTestArgs);
- if (script != null)
+ if (script != null) {
+ final String fullScriptPath = path.join(workingDirectory, script);
+ if (!FileSystemEntity.isFileSync(fullScriptPath)) {
+ print('Could not find test: $fullScriptPath');
+ print('Working directory: $workingDirectory');
+ print('Script: $script');
+ if (!printOutput)
+ print('This is one of the tests that does not normally print output.');
+ if (skip)
+ print('This is one of the tests that is normally skipped in this configuration.');
+ exit(1);
+ }
args.add(script);
+ }
return _runCommand(flutter, args,
workingDirectory: workingDirectory,
expectFailure: expectFailure,