Files
sdk/pkg/modular_test/lib/src/runner.dart
T
Jens Johansen a757154d93 [infra] Shard dart2js modular tests
* Shard dart2js modular tests (and decrease the shards of the
  unit tests)
* Remove folders we look for dart files in --- the remove folders
  doesn't contain any anyway and would have to be copied if keeping
  these lines.
* Fix sharding, previously trying to shard in 2 shards would only allow
  you to run ~50% of the tests:

```
$ out/ReleaseX64/dart-sdk/bin/dart pkg/compiler/tool/modular_test_suite.dart -nweb-unittest-asserts-linux --verbose --use-sdk --shards=2 --shard=0
Error: shard should be between 0 and 1, but got 0

$ out/ReleaseX64/dart-sdk/bin/dart pkg/compiler/tool/modular_test_suite.dart -nweb-unittest-asserts-linux --verbose --use-sdk --shards=2 --shard=2
Error: shard should be between 0 and 1, but got 2
```

  This has been corrected to allow from `1..n` for `n` shards to fit
  with what the testing system sends when specifying `shards` in
  `tools/bots/test_matrix.json`.

For previous try runs I extracted this:

Build 60615:
Shard #1: --- Total time: 04:27 ---
Shard #2: --- Total time: 05:19 ---
Shard #3: --- Total time: 04:23 ---
Shard #4: --- Total time: 10:29 ---
 => A total of 24:35 --- combined finish of 10:29
Modular tests: 32:19
Total bot runtime: 35:48

Build 60614:
Shard #1: --- Total time: 03:57 ---
Shard #2: --- Total time: 05:18 ---
Shard #3: --- Total time: 05:21 ---
Shard #4: --- Total time: 05:34 ---
 => A total of 20:10 --- combined finish of 5:34
Modular tests: 29:41 secs
Total bot runtime: 35:55

Build: 60613
Shard #1: --- Total time: 03:56 ---
Shard #2: --- Total time: 05:15 ---
Shard #3: --- Total time: 04:32 ---
Shard #4: --- Total time: 05:34 ---
 => A total of 19:17 --- combined finish of 5:34
Modular tests: 33:39
Total bot runtime: 38:51

With the new sharding I'd estimate that the unit tests and modular tests
would have finished in less than 13 minutes, making the bots finish in
~17 minutes, ~20 minutes and ~19 minutes instead.
The try-run with this ran in 17:06

Possibly a follow-up could do more stuff on the "main bot".

Change-Id: Ie5c96206deb9c0c6db3385bbca04ae6f4eab4c3a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448381
Reviewed-by: Nate Biggs <natebiggs@google.com>
Reviewed-by: Ivan Inozemtsev <iinozemtsev@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
2025-09-04 23:11:30 -07:00

121 lines
4.1 KiB
Dart

// Copyright (c) 2019, 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.
/// A runner that executes a pipeline on a folder containing modular tests.
library;
import 'dart:io';
import 'package:args/args.dart';
import 'package:modular_test/src/io_pipeline.dart';
import 'package:modular_test/src/loader.dart';
import 'package:modular_test/src/suite.dart';
import 'generic_runner.dart' as generic;
Uri relativize(Uri uri, Uri base) {
return Uri.parse(uri.path.substring(base.path.length));
}
Future<void> runSuite(Uri suiteFolder, String suiteName, Options options,
IOPipeline pipeline) async {
var dir = Directory.fromUri(suiteFolder);
var entries = (await dir.list(recursive: false).toList())
.whereType<Directory>()
.map((e) => _PipelineTest(e.uri, suiteFolder, options, pipeline))
.toList();
await generic.runSuite(
entries,
generic.RunnerOptions(
suiteName: suiteName,
configurationName: options.configurationName,
filter: options.filter,
logDir: options.outputDirectory,
shard: options.shard,
shards: options.shards,
verbose: options.verbose,
reproTemplate: '%executable %script --verbose --filter %name'));
await pipeline.cleanup();
}
class _PipelineTest implements generic.Test {
@override
final String name;
final Uri uri;
final Options options;
final IOPipeline pipeline;
_PipelineTest(this.uri, Uri suiteFolder, this.options, this.pipeline)
// Use the name of the folder as the test name by trimming out the prefix
// from the suite and the trailing `/`.
: name = uri.path.substring(suiteFolder.path.length, uri.path.length - 1);
@override
Future<void> run() async {
ModularTest test = await loadTest(uri);
if (options.verbose) print(test.debugString());
await pipeline.run(test);
}
}
class Options {
bool showSkipped = false;
bool verbose = false;
String? filter;
int shards = 1;
int shard = 1;
String? configurationName;
Uri? outputDirectory;
bool useSdk = false;
static Options parse(List<String> args) {
var parser = ArgParser()
..addFlag('verbose',
abbr: 'v',
defaultsTo: false,
help: 'print detailed information about the test and modular steps')
..addFlag('show-skipped',
defaultsTo: false,
help: 'print the name of the tests skipped by the filtering option')
..addFlag('use-sdk',
defaultsTo: false, help: 'whether to use snapshots from a built sdk')
..addOption('filter',
help: 'only run tests containing this filter as a substring')
..addOption('shards',
help: 'total number of shards a suite is going to be split into.',
defaultsTo: '1')
..addOption('shard',
help: 'which shard this script is executing. This should be between 1'
' and `shards`.')
..addOption('output-directory',
help: 'location where to emit the jsonl result and log files')
..addOption('named-configuration',
abbr: 'n',
help: 'configuration name to use for emitting jsonl result files.');
ArgResults argResults = parser.parse(args);
int shards = int.tryParse(argResults['shards']) ?? 1;
int shard = 1;
if (shards > 1) {
shard = int.tryParse(argResults['shard']) ?? 1;
if (shard <= 0 || shard > shards) {
print('Error: shard should be between 1 and $shards,'
' but got $shard');
exit(1);
}
}
Uri? toUri(s) => s == null ? null : Uri.base.resolveUri(Uri.file(s));
return Options()
..showSkipped = argResults['show-skipped']
..verbose = argResults['verbose']
..useSdk = argResults['use-sdk']
..filter = argResults['filter']
..shards = shards
// Turn shard from [1..shards] into [0..shards-1]
..shard = shard - 1
..configurationName = argResults['named-configuration']
..outputDirectory = toUri(argResults['output-directory']);
}
}