blob: 2fe9bbfe204eb71a604450961753bd9968d6c146 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
import 'dart:async' show Future;
import 'dart:convert' show LineSplitter, utf8;
import 'dart:io' show File, Platform, Process, exitCode;
Future<void> main(List<String> args) async {
// General idea: Launch - in separate processes - whatever we want to run
// concurrently, capturing the stdout and stderr, printing it with some
// prepended identification.
// When all runs are done, fail if any fails.
// Later we might be able to move it to the "testRunner"-system, if that
// offers any advantages.
print("NOTE: This machine has ${Platform.numberOfProcessors} processors!"
"\n\n");
List<WrappedProcess> startedProcesses = [];
WrappedProcess? leakTest;
{
// Very slow: Leak-test.
Uri leakTester =
Platform.script.resolve("flutter_gallery_leak_tester.dart");
if (!new File.fromUri(leakTester).existsSync()) {
exitCode = 1;
print("Couldn't find $leakTester");
} else {
// The tools/bots/flutter/compile_flutter.sh script passes `--path`
// --- we'll just pass everything along.
leakTest = await run(
[
leakTester.toString(),
...args,
],
"leak test",
);
startedProcesses.add(leakTest);
}
}
{
// Slow: Leak-test with alternative invalidation.
Uri leakTester =
Platform.script.resolve("flutter_gallery_leak_tester.dart");
if (!new File.fromUri(leakTester).existsSync()) {
exitCode = 1;
print("Couldn't find $leakTester");
} else {
// Note that the leak test run above will start checking out flutter
// gallery (etc) and that it has to finish before starting this.
// We therefore wait for the observatory line being printed before
// starting. Wait at most 10 minutes though.
// ignore: unawaited_futures
() async {
for (int i = 0; i < 10 * 60; i++) {
if (leakTest == null || leakTest.observatoryLines.isNotEmpty) {
break;
}
await Future.delayed(new Duration(seconds: 1));
}
// The tools/bots/flutter/compile_flutter.sh script passes `--path`
// --- we'll just pass everything along.
startedProcesses.add(await run(
[
leakTester.toString(),
...args,
"--alternativeInvalidation",
],
"leak test alternative invalidation",
));
}();
}
}
{
// Weak suite with fuzzing.
Uri weakSuite = Platform.script.resolve("fasta/weak_suite.dart");
if (!new File.fromUri(weakSuite).existsSync()) {
exitCode = 1;
print("Couldn't find $weakSuite");
} else {
startedProcesses.add(await run(
[
weakSuite.toString(),
"-DsemiFuzz=true",
],
"weak suite",
));
}
}
{
// Strong suite with fuzzing.
Uri strongSuite = Platform.script.resolve("fasta/strong_suite.dart");
if (!new File.fromUri(strongSuite).existsSync()) {
exitCode = 1;
print("Couldn't find $strongSuite");
} else {
startedProcesses.add(await run(
[
strongSuite.toString(),
"-DsemiFuzz=true",
],
"strong suite",
));
}
}
{
// Leak tests of incremental suite tests.
Uri incrementalLeakTest =
Platform.script.resolve("vm_service_for_leak_detection.dart");
if (!new File.fromUri(incrementalLeakTest).existsSync()) {
exitCode = 1;
print("Couldn't find $incrementalLeakTest");
} else {
startedProcesses.add(await run([
incrementalLeakTest.toString(),
"--weekly",
], "incremental leak test"));
}
}
// Wait for everything to finish.
List<int> exitCodes =
await Future.wait(startedProcesses.map((e) => e.process.exitCode));
if (exitCodes.where((e) => e != 0).isNotEmpty) {
print("\n\nFound failures!:\n");
// At least one failed.
for (WrappedProcess p in startedProcesses) {
int pExitCode = await p.process.exitCode;
if (pExitCode != 0) {
print("${p.id} failed with exist-code $pExitCode");
}
}
throw "There were failures!";
}
}
Future<WrappedProcess> run(List<String> args, String id) async {
Stopwatch stopwatch = new Stopwatch()..start();
Process process = await Process.start(
Platform.resolvedExecutable, ["--enable-asserts", ...args]);
List<String> observatoryLines = [];
process.stderr
.transform(utf8.decoder)
.transform(new LineSplitter())
.listen((line) {
print("$id stderr> $line");
if (line.contains("Observatory listening on")) {
observatoryLines.add(line);
}
});
process.stdout
.transform(utf8.decoder)
.transform(new LineSplitter())
.listen((line) {
print("$id stdout> $line");
if (line.contains("Observatory listening on")) {
observatoryLines.add(line);
}
});
// ignore: unawaited_futures
process.exitCode.then((int exitCode) {
stopwatch.stop();
print("$id finished in ${stopwatch.elapsed.toString()} "
"with exit code $exitCode");
});
return new WrappedProcess(process, id, observatoryLines);
}
class WrappedProcess {
final Process process;
final String id;
final List<String> observatoryLines;
WrappedProcess(this.process, this.id, this.observatoryLines);
}