blob: a80d853795187aa67a2ce180a8bfa6f9aa23e3fe [file] [log] [blame] [edit]
// Copyright (c) 2024, 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 file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import '../tool/coverage_merger.dart' as coverageMerger;
import 'utils/io_utils.dart';
final Uri repoDirUri = computeRepoDirUri();
Future<void> main() async {
Directory coverageTmpDir = await runAllCoverageTests(silent: false);
// Don't include the not-compiled stuff as we've (mostly) asked the VM to
// force compile everything and that the remaining stuff is (mostly) mixins
// and const classes etc that shouldn't (necessarily) be compiled but is
// potentially covered in other ways.
await coverageMerger.mergeFromDirUri(
repoDirUri.resolve(".dart_tool/package_config.json"),
coverageTmpDir.uri,
silent: false,
extraCoverageIgnores: const [],
extraCoverageBlockIgnores: const [],
);
}
Future<Directory> runAllCoverageTests({required bool silent}) async {
String dartExtension = "";
if (Platform.isWindows) {
dartExtension = ".exe";
}
Uri dart = repoDirUri.resolve(
"out/ReleaseX64/dart-sdk/bin/dart$dartExtension",
);
if (!File.fromUri(dart).existsSync()) throw "Didn't find dart at $dart";
Directory coverageTmpDir = Directory.systemTemp.createTempSync(
"cfe_coverage",
);
print("Using $coverageTmpDir for coverage.");
List<List<String>> runTheseSeveralAtATime = [];
List<List<String>> runTheseOneAtATime = [];
void addSuiteSkipVm(String suitePath, {required int shards}) {
for (int shard = 1; shard <= shards; shard++) {
runTheseSeveralAtATime.add([
dart.toFilePath(),
"--enable-asserts",
suitePath,
"-DskipVm=true",
"--coverage=${coverageTmpDir.path}/",
"--shards=$shards",
"--shard=$shard",
]);
}
}
void addWithCoverageArgument(String script) {
runTheseSeveralAtATime.add([
dart.toFilePath(),
"--enable-asserts",
script,
"--coverage=${coverageTmpDir.path}/",
]);
}
addSuiteSkipVm("pkg/front_end/test/strong_suite.dart", shards: 4);
addSuiteSkipVm("pkg/front_end/test/modular_suite.dart", shards: 1);
addWithCoverageArgument("pkg/front_end/test/messages_suite.dart");
addWithCoverageArgument("pkg/front_end/test/outline_suite.dart");
addWithCoverageArgument("pkg/front_end/test/textual_outline_suite.dart");
addWithCoverageArgument("pkg/front_end/test/expression_suite.dart");
addWithCoverageArgument("pkg/front_end/test/incremental_dartino_suite.dart");
addWithCoverageArgument("pkg/front_end/test/dartdoctest_suite.dart");
addWithCoverageArgument(
"pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart",
);
addWithCoverageArgument("pkg/front_end/test/incremental_suite.dart");
addWithCoverageArgument("pkg/front_end/test/lint_suite.dart");
addWithCoverageArgument("pkg/front_end/test/outline_extractor_suite.dart");
addWithCoverageArgument("pkg/front_end/test/parser_all_suite.dart");
addWithCoverageArgument("pkg/front_end/test/parser_equivalence_suite.dart");
addWithCoverageArgument("pkg/front_end/test/parser_suite.dart");
addWithCoverageArgument(
"pkg/front_end/test/spelling_test_not_src_suite.dart",
);
addWithCoverageArgument("pkg/front_end/test/spelling_test_src_suite.dart");
addWithCoverageArgument("pkg/front_end/test/compile_platform_coverage.dart");
// These two each use all available CPUs.
runTheseOneAtATime.add([
"python3",
"tools/test.py",
"-cfasta",
"-mrelease",
"-rnone",
"language",
]);
runTheseOneAtATime.add([
dart.toFilePath(),
repoDirUri
.resolve("pkg/front_end/test/run_our_tests_with_coverage.dart")
.toFilePath(),
]);
Map<String, String> environment = new Map<String, String>.of(
Platform.environment,
);
environment["CFE_COVERAGE"] = "${coverageTmpDir.path}/";
final int processes = Platform.numberOfProcessors;
int processesLeft = processes;
int processesRunning = 0;
Completer<void> completer = new Completer();
for (List<String> runThis in runTheseSeveralAtATime) {
while (processesLeft <= 0) {
await completer.future;
}
processesLeft--;
processesRunning++;
print("Starting $runThis");
unawaited(
_run(silent, runThis, environment).then((runExitCode) {
print("$runThis finished with exit code $runExitCode.");
processesRunning--;
processesLeft++;
Completer<void> oldCompleter = completer;
completer = new Completer();
oldCompleter.complete();
}),
);
}
while (processesRunning > 0) {
await completer.future;
}
for (List<String> runThis in runTheseOneAtATime) {
print("Starting $runThis");
print(
"Finished with exit code "
"${await _run(silent, runThis, environment)}",
);
}
return coverageTmpDir;
}
Future<int> _run(
bool silent,
List<String> runThis,
Map<String, String> environment,
) async {
Process p = await Process.start(
runThis.first,
runThis.skip(1).toList(),
environment: environment,
);
p.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen((
String line,
) {
if (!silent) print("stdout> $line");
});
p.stderr.transform(utf8.decoder).transform(const LineSplitter()).listen((
String line,
) {
print("stderr> $line");
});
return await p.exitCode;
}