Add filtering to "--list-configurations".
I got tired of wading through the giant list and guessing at which one
matches the options I want to run the tests on, so I added filtering.
If you pass any of the common options like "-m", "-r", etc. when also
passing "--list-configurations", then it only prints configurations
that match those options.
Also, by default it only prints configurations that match the current
host OS.
Eventually, I would like *running* tests to work the same way, where
passing "-c" means "find me a config in the test matrix with this
compiler. But this seems like a good start.
Also, I removed the slow way that test.dart calls test.py to handle
--list-configurations now that those are all in the same package.
Change-Id: Ifabb415a9fad889afc12cfcd7dd81bd02c918612
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158980
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Karl Klose <karlklose@google.com>
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 79222af..14eb334 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -155,7 +155,7 @@
hide: true),
_Option('system', 'The operating system to run tests on.',
abbr: 's',
- values: System.names,
+ values: ['all', ...System.names],
defaultsTo: Platform.operatingSystem,
hide: true),
_Option('sanitizer', 'Sanitizer in which to run the tests.',
@@ -228,6 +228,7 @@
_Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
hide: true),
_Option.bool('list', 'List tests only, do not run them.'),
+ _Option.bool('find-configurations', 'Find matching configurations.'),
_Option.bool('list-configurations', 'Output list of configurations.'),
_Option.bool('list_status_files',
'List status files for test-suites. Do not run any test suites.',
@@ -406,21 +407,8 @@
return null;
}
- if (arguments.contains("--list-configurations")) {
- var testMatrixFile = "tools/bots/test_matrix.json";
- var testMatrix = TestMatrix.fromPath(testMatrixFile);
- for (var configuration in testMatrix.configurations
- .map((configuration) => configuration.name)
- .toList()
- ..sort()) {
- print(configuration);
- }
- return null;
- }
-
- var configuration = <String, dynamic>{};
-
- // Fill in configuration with arguments passed to the test script.
+ // Parse the command line arguments to a map.
+ var options = <String, dynamic>{};
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
@@ -458,7 +446,7 @@
} else {
// The argument does not start with "-" or "--" and is therefore not an
// option. Use it as a test selector pattern.
- var patterns = configuration.putIfAbsent("selectors", () => <String>[]);
+ var patterns = options.putIfAbsent("selectors", () => <String>[]);
// Allow passing in the full relative path to a test or directory and
// infer the selector from it. This lets users use tab completion on
@@ -492,7 +480,7 @@
// Multiple uses of a flag are an error, because there is no naturally
// correct way to handle conflicting options.
- if (configuration.containsKey(option.name)) {
+ if (options.containsKey(option.name)) {
_fail('Already have value for command line option "$command".');
}
@@ -503,12 +491,12 @@
_fail('Boolean flag "$command" does not take a value.');
}
- configuration[option.name] = true;
+ options[option.name] = true;
break;
case _OptionValueType.int:
try {
- configuration[option.name] = int.parse(value);
+ options[option.name] = int.parse(value);
} on FormatException {
_fail('Integer value expected for option "$command".');
}
@@ -535,17 +523,27 @@
// TODO(rnystrom): Store as a list instead of a comma-delimited
// string.
- configuration[option.name] = value;
+ options[option.name] = value;
break;
}
}
+ if (options.containsKey('find-configurations')) {
+ findConfigurations(options);
+ return null;
+ }
+
+ if (options.containsKey('list-configurations')) {
+ listConfigurations(options);
+ return null;
+ }
+
// If a named configuration was specified ensure no other options, which are
// implied by the named configuration, were specified.
- if (configuration['named_configuration'] is String) {
+ if (options['named_configuration'] is String) {
for (var optionName in _namedConfigurationOptions) {
- if (configuration.containsKey(optionName)) {
- var namedConfig = configuration['named_configuration'];
+ if (options.containsKey(optionName)) {
+ var namedConfig = options['named_configuration'];
_fail("The named configuration '$namedConfig' implies "
"'$optionName'. Try removing '$optionName'.");
}
@@ -554,26 +552,26 @@
// Apply default values for unspecified options.
for (var option in _options) {
- if (!configuration.containsKey(option.name)) {
- configuration[option.name] = option.defaultValue;
+ if (!options.containsKey(option.name)) {
+ options[option.name] = option.defaultValue;
}
}
// Fetch list of tests to run, if option is present.
- var testList = configuration['test_list'];
+ var testList = options['test_list'];
if (testList is String) {
- configuration['test_list_contents'] = File(testList).readAsLinesSync();
+ options['test_list_contents'] = File(testList).readAsLinesSync();
}
- var tests = configuration['tests'];
+ var tests = options['tests'];
if (tests is String) {
- if (configuration.containsKey('test_list_contents')) {
+ if (options.containsKey('test_list_contents')) {
_fail('--tests and --test-list cannot be used together');
}
- configuration['test_list_contents'] = LineSplitter.split(tests).toList();
+ options['test_list_contents'] = LineSplitter.split(tests).toList();
}
- return _createConfigurations(configuration);
+ return _createConfigurations(options);
}
/// Given a set of parsed option values, returns the list of command line
@@ -682,6 +680,12 @@
data['progress'] = 'verbose';
}
+ var systemName = data["system"] as String;
+ if (systemName == "all") {
+ _fail("Can only use '--system=all' with '--find-configurations'.");
+ }
+ var system = System.find(systemName);
+
var runtimeNames = data["runtime"] as String;
var runtimes = [
if (runtimeNames != null) ...runtimeNames.split(",").map(Runtime.find)
@@ -813,7 +817,6 @@
}
for (var sanitizerName in sanitizers.split(",")) {
var sanitizer = Sanitizer.find(sanitizerName);
- var system = System.find(data["system"] as String);
var configuration = Configuration("custom configuration",
architecture, compiler, mode, runtime, system,
nnbdMode: nnbdMode,
@@ -996,6 +999,101 @@
OptionParseException(this.message);
}
+/// Prints the names of the configurations in the test matrix that match the
+/// given filter options.
+///
+/// If any of the options `--system`, `--arch`, `--mode`, `--compiler`,
+/// `--nnbd`, or `--runtime` (or their abbreviations) are passed, then only
+/// configurations matching those are shown.
+void findConfigurations(Map<String, dynamic> options) {
+ var testMatrix = TestMatrix.fromPath('tools/bots/test_matrix.json');
+
+ // Default to only showing configurations for the current machine.
+ var systemOption = options['system'] as String;
+ var system = System.host;
+ if (systemOption == 'all') {
+ system = null;
+ } else if (systemOption != null) {
+ system = System.find(systemOption);
+ }
+
+ var architectureOption = options['arch'] as String;
+ var architectures = const [Architecture.x64];
+ if (architectureOption == 'all') {
+ architectures = null;
+ } else if (architectureOption != null) {
+ architectures =
+ architectureOption.split(',').map(Architecture.find).toList();
+ }
+
+ var mode = Mode.release;
+ if (options.containsKey('mode')) {
+ mode = Mode.find(options['mode'] as String);
+ }
+
+ Compiler compiler;
+ if (options.containsKey('compiler')) {
+ compiler = Compiler.find(options['compiler'] as String);
+ }
+
+ Runtime runtime;
+ if (options.containsKey('runtime')) {
+ runtime = Runtime.find(options['runtime'] as String);
+ }
+
+ NnbdMode nnbdMode;
+ if (options.containsKey('nnbd')) {
+ nnbdMode = NnbdMode.find(options['nnbd'] as String);
+ }
+
+ var names = <String>[];
+ for (var configuration in testMatrix.configurations) {
+ if (system != null && configuration.system != system) continue;
+ if (architectures != null &&
+ !architectures.contains(configuration.architecture)) {
+ continue;
+ }
+ if (mode != null && configuration.mode != mode) continue;
+ if (compiler != null && configuration.compiler != compiler) continue;
+ if (runtime != null && configuration.runtime != runtime) continue;
+ if (nnbdMode != null && configuration.nnbdMode != nnbdMode) continue;
+
+ names.add(configuration.name);
+ }
+
+ names.sort();
+
+ var filters = [
+ if (system != null) "system=$system",
+ if (architectures != null) "arch=${architectures.join(',')}",
+ if (mode != null) "mode=$mode",
+ if (compiler != null) "compiler=$compiler",
+ if (runtime != null) "runtime=$runtime",
+ if (nnbdMode != null) "nnbd=$nnbdMode",
+ ];
+
+ if (filters.isEmpty) {
+ print("All configurations:");
+ } else {
+ print("Configurations where ${filters.join(', ')}:");
+ }
+
+ for (var name in names) {
+ print("- $name");
+ }
+}
+
+/// Prints the names of the configurations in the test matrix.
+void listConfigurations(Map<String, dynamic> options) {
+ var testMatrix = TestMatrix.fromPath('tools/bots/test_matrix.json');
+
+ var names = testMatrix.configurations
+ .map((configuration) => configuration.name)
+ .toList();
+ names.sort();
+ names.forEach(print);
+}
+
/// Throws an [OptionParseException] with [message].
void _fail(String message) {
throw OptionParseException(message);
diff --git a/pkg/test_runner/lib/test_runner.dart b/pkg/test_runner/lib/test_runner.dart
index 065b840..e0843da 100644
--- a/pkg/test_runner/lib/test_runner.dart
+++ b/pkg/test_runner/lib/test_runner.dart
@@ -12,6 +12,7 @@
import 'package:smith/smith.dart';
import 'bot_results.dart';
+import 'src/options.dart';
const int deflakingCount = 5;
@@ -343,10 +344,7 @@
}
if (options["list-configurations"] as bool) {
- var process = await Process.start(
- "python", ["tools/test.py", "--list-configurations"],
- mode: ProcessStartMode.inheritStdio, runInShell: Platform.isWindows);
- exitCode = await process.exitCode;
+ listConfigurations({"system": "all"});
return;
}