mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +00:00
831ad5580d
This is follow-up to 2ee771a4f6
to fix iso_stress_linux bot.
TEST=ci
Change-Id: Ic6840481287b5af943252bef9854e0be4049553b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/337003
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
215 lines
6 KiB
Dart
215 lines
6 KiB
Dart
// 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 'package:path/path.dart' as path;
|
|
|
|
final thisDirectory = path.join('runtime', 'tests', 'concurrency');
|
|
final stressTestListJson = path.join(thisDirectory, 'stress_test_list.json');
|
|
final generatedTest =
|
|
path.join(path.join(thisDirectory, 'generated_stress_test.dart'));
|
|
|
|
final List<String> testFiles =
|
|
List<String>.from(json.decode(File(stressTestListJson).readAsStringSync()));
|
|
final dart = 'tools/sdks/dart-sdk/bin/dart';
|
|
|
|
main(List<String> args) async {
|
|
File(generatedTest).writeAsStringSync(await generateStressTest(testFiles));
|
|
}
|
|
|
|
Future<String> generateStressTest(List<String> testFiles) async {
|
|
testFiles = testFiles
|
|
.map((String file) => path.absolute(path.join(thisDirectory, file)))
|
|
.toList();
|
|
|
|
final sb = StringBuffer();
|
|
sb.writeln(r'''
|
|
import 'dart:async';
|
|
import 'dart:isolate';
|
|
import 'dart:io';
|
|
|
|
''');
|
|
for (int i = 0; i < testFiles.length; ++i) {
|
|
final testFile = testFiles[i];
|
|
sb.writeln('import "$testFile" as test$i;');
|
|
}
|
|
for (int i = 0; i < testFiles.length; ++i) {
|
|
final testFile = testFiles[i];
|
|
sb.writeln('''
|
|
wrapper$i(dynamic _) {
|
|
print('[$testFile] starting ...');
|
|
runZoned(() {
|
|
test$i.main();
|
|
}, zoneSpecification: ZoneSpecification(
|
|
handleUncaughtError: (_, ZoneDelegate parent, Zone zone, error, stack) {
|
|
parent.print(zone, 'Error($testFile): \$error \\nstack:\$stack');
|
|
parent.handleUncaughtError(zone, error, stack);
|
|
},
|
|
print: (_, _2, _3, String line) {}));
|
|
}
|
|
''');
|
|
}
|
|
sb.writeln('');
|
|
sb.writeln(r'''
|
|
class Test {
|
|
final String name;
|
|
final dynamic Function(dynamic) fun;
|
|
Test(this.name, this.fun);
|
|
}
|
|
''');
|
|
sb.writeln('final List<Test> tests = [');
|
|
for (int i = 0; i < testFiles.length; ++i) {
|
|
final testFile = testFiles[i];
|
|
sb.writeln(' Test("$testFile", wrapper$i),');
|
|
}
|
|
sb.writeln('];');
|
|
sb.writeln('');
|
|
|
|
sb.writeln('''
|
|
class Runner {
|
|
static const progressEvery = 100;
|
|
|
|
final List<Test> tests;
|
|
late final ReceivePort onExit;
|
|
late final List<ReceivePort> onExits;
|
|
late final List<ReceivePort> onErrors;
|
|
final List<String> errorLog = [];
|
|
|
|
Runner(this.tests) {
|
|
onExit = ReceivePort();
|
|
onExits = List<ReceivePort>.generate(tests.length, (int i) {
|
|
return ReceivePort()..listen((_) {
|
|
print('[\${tests[i].name}] finished');
|
|
onExit.sendPort.send(null);
|
|
});
|
|
});
|
|
onErrors = List<ReceivePort>.generate(tests.length, (int i) {
|
|
return ReceivePort()..listen((error) {
|
|
errorLog.add('[\${tests[i].name}] error: \$error');
|
|
});
|
|
});
|
|
}
|
|
|
|
Future runWithUnlimitedParallelism() async {
|
|
for (int i = 0; i < tests.length; ++i) {
|
|
await Isolate.spawn(
|
|
tests[i].fun,
|
|
null,
|
|
onExit: onExits[i].sendPort,
|
|
onError: onErrors[i].sendPort);
|
|
}
|
|
await waitUntilDone();
|
|
}
|
|
|
|
Future runWithParallelism(int parallelism) async {
|
|
int _current = 0;
|
|
|
|
Future run() async {
|
|
final int current = _current++;
|
|
await Isolate.spawn(
|
|
tests[current].fun,
|
|
null,
|
|
onExit: onExits[current].sendPort,
|
|
onError: onErrors[current].sendPort);
|
|
}
|
|
void scheduleNext() {
|
|
if (_current == tests.length) return;
|
|
run().whenComplete(scheduleNext);
|
|
}
|
|
|
|
for (int i = 0; i < parallelism; ++i) {
|
|
scheduleNext();
|
|
}
|
|
await waitUntilDone();
|
|
}
|
|
|
|
Future waitUntilDone() async {
|
|
final exitSi = StreamIterator(onExit);
|
|
for (int i = 0; i < tests.length; ++i) {
|
|
await exitSi.moveNext();
|
|
}
|
|
await exitSi.cancel();
|
|
onExit.close();
|
|
onExits.forEach((rp) => rp.close());
|
|
onErrors.forEach((rp) => rp.close());
|
|
|
|
if (!errorLog.isEmpty) {
|
|
print('Spawning tests in isolates resulted in the following errors:');
|
|
print('------------------------------------------------------------');
|
|
errorLog.forEach(print);
|
|
print('------------------------------------------------------------');
|
|
print('-> Setting exitCode to 255');
|
|
exitCode = 255;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
main() async {
|
|
final shards = int.fromEnvironment(
|
|
'shards', defaultValue: 1);
|
|
final shard = int.fromEnvironment(
|
|
'shard', defaultValue: 0);
|
|
|
|
final repeat = int.fromEnvironment(
|
|
'repeat', defaultValue: 1);
|
|
|
|
final parallelism = int.fromEnvironment(
|
|
'parallelism', defaultValue: 0);
|
|
|
|
final filteredTests = <Test>[];
|
|
for (int i = 0; i < tests.length; ++i) {
|
|
if ((i % shards) == shard) {
|
|
final test = tests[i];
|
|
for (int j = 0; j < repeat; ++j) {
|
|
filteredTests.add(test);
|
|
}
|
|
}
|
|
}
|
|
|
|
final runner = Runner(filteredTests);
|
|
if (parallelism <= 0) {
|
|
await runner.runWithUnlimitedParallelism();
|
|
} else {
|
|
await runner.runWithParallelism(parallelism);
|
|
}
|
|
}
|
|
''');
|
|
return format(sb.toString());
|
|
}
|
|
|
|
Future<String> format(String generatedSource) async {
|
|
try {
|
|
final result = await Process.start(dart, ['format']);
|
|
result.stdin.writeln(generatedSource);
|
|
|
|
final results = await Future.wait([
|
|
result.stdin.close(),
|
|
result.stdout.transform(utf8.decoder).join(''),
|
|
result.stderr.transform(utf8.decoder).join(''),
|
|
result.exitCode
|
|
]);
|
|
|
|
final exitCode = results[3] as int;
|
|
if (exitCode != 0) {
|
|
print('Note: Failed to format source code. Dart format exited non-0.');
|
|
return generatedSource;
|
|
}
|
|
final stdout = results[1] as String;
|
|
final stderr = results[2] as String;
|
|
if (stderr.trim().length != 0) {
|
|
print('Note: Failed to format source code. Dart format had stderr: '
|
|
'$stderr');
|
|
return generatedSource;
|
|
}
|
|
return stdout;
|
|
} catch (e) {
|
|
print('Note: Failed to format source code: $e');
|
|
return generatedSource;
|
|
}
|
|
}
|