[infra] Make test.py --build fail fast.

Currently, running `test.py --build` will attempt to build
the necessary files, before running the tests specified.
However, the tests are run even if this build fails, which
usually means old build artefacts are used for running the tests.
This can lead to some very confusing results if you do not yourself
catch that the build failed half-way through the run.

This change makes `test.py` exit with an error code and a message,
and does not proceed with the tests, if the build fails.

TEST=Manual testing locally.
Change-Id: I4e0f1d3f8d695219f2e4c0d7b474542af136aca9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241740
Reviewed-by: William Hesse <whesse@google.com>
Commit-Queue: Clement Skau <cskau@google.com>
This commit is contained in:
Clement Skau 2022-04-20 13:55:58 +00:00 committed by Commit Bot
parent f2c6a374e1
commit 1320e644d5
2 changed files with 32 additions and 9 deletions

View file

@ -29,17 +29,25 @@ import "package:test_runner/src/test_configurations.dart";
/// Runs all of the tests specified by the given command line [arguments].
void main(List<String> arguments) async {
// Parse the command line arguments to a configuration.
var parser = OptionsParser();
var configurations = <TestConfiguration>[];
final parser = OptionsParser();
List<TestConfiguration> configurations;
try {
configurations = parser.parse(arguments);
} on OptionParseException catch (exception) {
print(exception.message);
exit(1);
}
if (configurations == null) {
return;
}
final build_success = await buildConfigurations(configurations);
if (!build_success) {
print("ERROR: Build failed.");
exit(1);
}
if (configurations.isEmpty) return;
await buildConfigurations(configurations);
// Run all of the configured tests.
await testConfigurations(configurations);
}

View file

@ -8,25 +8,35 @@ import 'dart:io';
import 'configuration.dart';
import 'utils.dart';
Future buildConfigurations(List<TestConfiguration> configurations) async {
var startTime = DateTime.now();
if (!configurations.first.build) return;
// Returns false if build failed.
Future<bool> buildConfigurations(List<TestConfiguration> configurations) async {
final startTime = DateTime.now();
final buildTargets = <String>{};
final modes = <Mode>{};
final architectures = <Architecture>{};
final systems = <System>{};
for (final configuration in configurations) {
if (!configuration.build) {
continue;
}
final inner = configuration.configuration;
buildTargets.addAll(_selectBuildTargets(inner));
modes.add(inner.mode);
architectures.add(inner.architecture);
systems.add(inner.system);
}
if (buildTargets.isEmpty) return;
if (buildTargets.isEmpty) {
print('No build targets found.');
return true;
}
if (systems.length > 1) {
print('Unimplemented: building for multiple systems ${systems.join(',')}');
exit(1);
}
final system = systems.single;
final osFlags = <String>[];
if (system == System.android) {
@ -40,6 +50,7 @@ Future buildConfigurations(List<TestConfiguration> configurations) async {
exit(1);
}
}
final command = [
'tools/build.py',
'-m',
@ -50,6 +61,7 @@ Future buildConfigurations(List<TestConfiguration> configurations) async {
...buildTargets
];
print('Running command: python3 ${command.join(' ')}');
final process = await Process.start('python3', command);
stdout.nonBlocking.addStream(process.stdout);
stderr.nonBlocking.addStream(process.stderr);
@ -57,8 +69,11 @@ Future buildConfigurations(List<TestConfiguration> configurations) async {
if (exitCode != 0) {
print('exit code: $exitCode');
}
var buildTime = niceTime(DateTime.now().difference(startTime));
final buildTime = niceTime(DateTime.now().difference(startTime));
print('--- Build time: $buildTime ---');
return exitCode == 0;
}
List<String> _selectBuildTargets(Configuration inner) {