blob: 2d31d15d0b053a8346560d7aa6a9b2acb2df0ef2 [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 file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:io' as io;
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import '../vm/dart/snapshot_test_helper.dart';
void forwardStream(Stream<List<int>> input, IOSink output) {
// Print the information line-by-line.
input
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((String line) {
output.writeln(line);
});
}
Future<bool> run(String executable, List<String> args) async {
print('Running "$executable ${args.join(' ')}"');
final Process process = await Process.start(executable, args);
forwardStream(process.stdout, stdout);
forwardStream(process.stderr, stderr);
final int exitCode = await process.exitCode;
if (exitCode != 0) {
print('=> Running "$executable ${args.join(' ')}" failed with $exitCode');
io.exitCode = 255; // Make this shard fail.
return false;
}
return true;
}
abstract class TestRunner {
Future runTest();
}
class JitTestRunner extends TestRunner {
final String buildDir;
final List<String> arguments;
JitTestRunner(this.buildDir, this.arguments);
Future runTest() async {
await run('$buildDir/dart', arguments);
}
}
class AotTestRunner extends TestRunner {
final String buildDir;
final List<String> arguments;
final List<String> aotArguments;
AotTestRunner(this.buildDir, this.arguments, this.aotArguments);
Future runTest() async {
await withTempDir((String dir) async {
final elfFile = path.join(dir, 'app.elf');
if (await run('$buildDir/gen_snapshot',
['--snapshot-kind=app-aot-elf', '--elf=$elfFile', ...arguments])) {
await run(
'$buildDir/dart_precompiled_runtime', [...aotArguments, elfFile]);
}
});
}
}
const int tsanShards = 200;
final configurations = <TestRunner>[
JitTestRunner('out/DebugX64', [
'--disable-dart-dev',
'--no-sound-null-safety',
'--enable-isolate-groups',
'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
]),
JitTestRunner('out/ReleaseX64', [
'--disable-dart-dev',
'--no-sound-null-safety',
'--enable-isolate-groups',
'--no-inline-alloc',
'--use-slow-path',
'--deoptimize-on-runtime-call-every=3',
'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
]),
for (int i = 0; i < tsanShards; ++i)
JitTestRunner('out/ReleaseTSANX64', [
'--disable-dart-dev',
'-Drepeat=4',
'-Dshard=$i',
'-Dshards=$tsanShards',
'--no-sound-null-safety',
'--enable-isolate-groups',
'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
]),
AotTestRunner('out/ReleaseX64', [
'--no-sound-null-safety',
'runtime/tests/concurrency/generated_stress_test.dart.aot.dill',
], [
'--no-sound-null-safety',
'--enable-isolate-groups',
]),
AotTestRunner('out/DebugX64', [
'--no-sound-null-safety',
'runtime/tests/concurrency/generated_stress_test.dart.aot.dill',
], [
'--no-sound-null-safety',
'--enable-isolate-groups',
]),
];
main(List<String> arguments) async {
final parser = ArgParser()
..addOption('shards', help: 'number of shards used', defaultsTo: '1')
..addOption('shard', help: 'shard id', defaultsTo: '1')
..addOption('output-directory',
help: 'unused parameter to make sharding infra work', defaultsTo: '');
final options = parser.parse(arguments);
final shards = int.parse(options['shards']);
final shard = int.parse(options['shard']) - 1;
// Tasks will eventually be killed if they do not have any output for some
// time. So we'll explicitly print something every 4 minutes.
final sw = Stopwatch()..start();
final timer = Timer.periodic(const Duration(minutes: 4), (_) {
print('[${sw.elapsed}] ... still working ...');
});
try {
final thisShardsConfigurations = [];
for (int i = 0; i < configurations.length; i++) {
if ((i % shards) == shard) {
thisShardsConfigurations.add(configurations[i]);
}
}
for (final config in thisShardsConfigurations) {
await config.runTest();
}
} finally {
timer.cancel();
}
}