Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support targeting compilers via platform selectors #1911

Merged
merged 2 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions pkgs/test/test/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ SuiteConfiguration suiteConfiguration(
bool? runSkipped,
Iterable<String>? dart2jsArgs,
String? precompiledPath,
Iterable<CompilerSelection>? compilers,
Iterable<CompilerSelection>? compilerSelections,
Iterable<RuntimeSelection>? runtimes,
Map<BooleanSelector, SuiteConfiguration>? tags,
Map<PlatformSelector, SuiteConfiguration>? onPlatform,
Expand All @@ -244,7 +244,7 @@ SuiteConfiguration suiteConfiguration(
runSkipped: runSkipped,
dart2jsArgs: dart2jsArgs,
precompiledPath: precompiledPath,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
tags: tags,
onPlatform: onPlatform,
Expand Down Expand Up @@ -293,7 +293,7 @@ Configuration configuration(
Iterable<String>? dart2jsArgs,
String? precompiledPath,
Iterable<Pattern>? globalPatterns,
Iterable<CompilerSelection>? compilers,
Iterable<CompilerSelection>? compilerSelections,
Iterable<RuntimeSelection>? runtimes,
BooleanSelector? includeTags,
BooleanSelector? excludeTags,
Expand Down Expand Up @@ -343,7 +343,7 @@ Configuration configuration(
dart2jsArgs: dart2jsArgs,
precompiledPath: precompiledPath,
globalPatterns: globalPatterns,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
includeTags: includeTags,
excludeTags: excludeTags,
Expand Down
41 changes: 11 additions & 30 deletions pkgs/test_core/lib/src/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'package:stack_trace/stack_trace.dart';
// ignore: deprecated_member_use
import 'package:test_api/backend.dart'
show PlatformSelector, Runtime, SuitePlatform;
import 'package:test_api/src/backend/compiler.dart'; //ignore: implementation_imports
import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/group_entry.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/operating_system.dart'; // ignore: implementation_imports
Expand Down Expand Up @@ -167,21 +166,12 @@ class Runner {
var testOn = _config.suiteDefaults.metadata.testOn;
if (testOn == PlatformSelector.all) return;

var runtimes = _config.suiteDefaults.runtimes
var unsupportedRuntimes = _config.suiteDefaults.runtimes
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually just a revert of what I had tried to do earlier, it should match the original logic now. What I was trying to do no longer makes sense with the fallback to a default compiler on any runtime that has no compiler specified.

.map(_loader.findRuntime)
.whereType<Runtime>();

Iterable<Compiler?> compilers = _config.suiteDefaults.compilers?.map(
(identifier) => Compiler.builtIn
.firstWhere((compiler) => compiler.identifier == identifier)) ??
[null];
var unsupportedRuntimes = [
for (var runtime in runtimes)
if (!compilers.any((compiler) =>
!runtime.supportedCompilers.contains(compiler) ||
!testOn.evaluate(currentPlatform(runtime, compiler))))
runtime,
];
.whereType<Runtime>()
.where((runtime) => !testOn.evaluate(currentPlatform(runtime, null)))
.toList();

if (unsupportedRuntimes.isEmpty) return;

// Human-readable names for all unsupported runtimes.
Expand All @@ -195,9 +185,7 @@ class Runner {
if (unsupportedBrowsers.isNotEmpty) {
var supportsAnyBrowser = _loader.allRuntimes
.where((runtime) => runtime.isBrowser)
.any((runtime) => compilers.any((compiler) =>
runtime.supportedCompilers.contains(compiler) &&
testOn.evaluate(currentPlatform(runtime, compiler))));
.any((runtime) => testOn.evaluate(currentPlatform(runtime, null)));

if (supportsAnyBrowser) {
unsupportedNames
Expand All @@ -210,9 +198,9 @@ class Runner {
// If the user tried to run on the VM and it's not supported, figure out if
// that's because of the current OS or whether the VM is unsupported.
if (unsupportedRuntimes.contains(Runtime.vm)) {
var supportsAnyOS = OperatingSystem.all.any((os) => compilers.any(
(compiler) => testOn.evaluate(SuitePlatform(Runtime.vm,
compiler: compiler, os: os, inGoogle: inGoogle))));
var supportsAnyOS = OperatingSystem.all.any((os) => testOn.evaluate(
SuitePlatform(Runtime.vm,
compiler: null, os: os, inGoogle: inGoogle)));

if (supportsAnyOS) {
unsupportedNames.add(currentOS.name);
Expand All @@ -221,15 +209,8 @@ class Runner {
}
}

var message = StringBuffer("this package doesn't support running tests on ")
..write(toSentence(unsupportedNames, conjunction: 'or'));
if (_config.suiteDefaults.compilers != null) {
message
..write(' with any of the given compilers: ')
..write(toSentence(compilers, conjunction: 'or'));
}

warn(message.toString());
warn("this package doesn't support running tests on "
'${toSentence(unsupportedNames, conjunction: 'or')}.');
}

/// Closes the runner.
Expand Down
49 changes: 44 additions & 5 deletions pkgs/test_core/lib/src/runner/compiler_selection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,61 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:source_span/source_span.dart';
// ignore: deprecated_member_use
import 'package:test_api/backend.dart' show Compiler;
import 'package:test_core/backend.dart';

/// A compiler with which the user has chosen to run tests.
class CompilerSelection {
/// The name of the compiler.
final String name;
/// The chosen compiler to use.
final Compiler compiler;

/// The location in the configuration file of this compiler string, or `null`
/// if it was defined outside a configuration file (for example, on the
/// command line).
final SourceSpan? span;

CompilerSelection(this.name, [this.span]);
/// The platform selector for which platforms this compiler should apply to,
/// if specified. Defaults to all platforms where the compiler is supported.
final PlatformSelector? platformSelector;

CompilerSelection(String compiler,
{required this.platformSelector, required this.span})
: compiler = Compiler.builtIn.firstWhere((c) => c.identifier == compiler);

factory CompilerSelection.parse(String option, {SourceSpan? parentSpan}) {
var parts = option.split(':');
switch (parts.length) {
case 1:
_checkValidCompiler(option, parentSpan);
return CompilerSelection(option,
platformSelector: null, span: parentSpan);
case 2:
var compiler = parts[1];
_checkValidCompiler(compiler, parentSpan);
return CompilerSelection(compiler,
platformSelector: PlatformSelector.parse(parts[0]),
span: parentSpan);
default:
throw ArgumentError.value(
option,
'--compiler',
'Must be of the format [<boolean-selector>:]<compiler>, but got '
'more than one `:`.');
}
}

@override
bool operator ==(other) => other is CompilerSelection && other.name == name;
bool operator ==(other) =>
other is CompilerSelection && other.compiler == compiler;

@override
int get hashCode => name.hashCode;
int get hashCode => compiler.hashCode;
}

void _checkValidCompiler(String compiler, SourceSpan? span) {
if (Compiler.builtIn.any((c) => c.identifier == compiler)) return;
throw SourceSpanFormatException(
'Invalid compiler `$compiler`, must be one of ${Compiler.builtIn.map((c) => c.identifier).join(', ')}',
span);
}
18 changes: 9 additions & 9 deletions pkgs/test_core/lib/src/runner/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class Configuration {
required Iterable<String>? dart2jsArgs,
required String? precompiledPath,
required Iterable<Pattern>? globalPatterns,
required Iterable<CompilerSelection>? compilers,
required Iterable<CompilerSelection>? compilerSelections,
required Iterable<RuntimeSelection>? runtimes,
required BooleanSelector? includeTags,
required BooleanSelector? excludeTags,
Expand Down Expand Up @@ -347,7 +347,7 @@ class Configuration {
runSkipped: runSkipped,
dart2jsArgs: dart2jsArgs,
precompiledPath: precompiledPath,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
tags: tags,
onPlatform: onPlatform,
Expand Down Expand Up @@ -404,7 +404,7 @@ class Configuration {
Iterable<String>? dart2jsArgs,
String? precompiledPath,
Iterable<Pattern>? globalPatterns,
Iterable<CompilerSelection>? compilers,
Iterable<CompilerSelection>? compilerSelections,
Iterable<RuntimeSelection>? runtimes,
BooleanSelector? includeTags,
BooleanSelector? excludeTags,
Expand Down Expand Up @@ -454,7 +454,7 @@ class Configuration {
dart2jsArgs: dart2jsArgs,
precompiledPath: precompiledPath,
globalPatterns: globalPatterns,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
includeTags: includeTags,
excludeTags: excludeTags,
Expand Down Expand Up @@ -521,7 +521,7 @@ class Configuration {
dart2jsArgs: null,
precompiledPath: null,
globalPatterns: null,
compilers: null,
compilerSelections: null,
runtimes: null,
includeTags: null,
excludeTags: null,
Expand Down Expand Up @@ -587,7 +587,7 @@ class Configuration {
dart2jsArgs: null,
precompiledPath: null,
globalPatterns: null,
compilers: null,
compilerSelections: null,
runtimes: null,
includeTags: null,
excludeTags: null,
Expand All @@ -614,7 +614,7 @@ class Configuration {
required String? reporter,
required Map<String, String>? fileReporters,
required int? concurrency,
required Iterable<CompilerSelection>? compilers,
required Iterable<CompilerSelection>? compilerSelections,
required Iterable<RuntimeSelection>? runtimes,
required Iterable<String>? chosenPresets,
required Map<String, RuntimeSettings>? overrideRuntimes}) =>
Expand All @@ -625,7 +625,7 @@ class Configuration {
reporter: reporter,
fileReporters: fileReporters,
concurrency: concurrency,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
chosenPresets: chosenPresets,
overrideRuntimes: overrideRuntimes,
Expand Down Expand Up @@ -716,7 +716,7 @@ class Configuration {
runSkipped: null,
dart2jsArgs: null,
precompiledPath: null,
compilers: null,
compilerSelections: null,
runtimes: null,
tags: null,
onPlatform: null,
Expand Down
26 changes: 12 additions & 14 deletions pkgs/test_core/lib/src/runner/configuration/args.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,14 @@ final ArgParser _parser = (() {
});
parser.addMultiOption('compiler',
abbr: 'c',
help:
'The compiler(s) to use to run tests. Each platform chooses its default and supported compilers.',
defaultsTo: [],
allowed: [
for (var compiler in Compiler.builtIn) compiler.identifier,
],
allowedHelp: {
for (var compiler in Compiler.builtIn)
compiler.identifier: compiler.description,
});
help: 'The compiler(s) to use to run tests, supported compilers are '
'[${Compiler.builtIn.map((c) => c.identifier).join(', ')}].\n\n'
'Each platform has a default compiler but may support other '
'compilers.\n\n'
'You can target a compiler to a specific platform using arguments '
'of the following form [<platform-selector>:]<compiler>.\n\n'
'If a platform is specified but no given compiler is supported for '
'that platform, then it will use its default compiler.');
parser.addMultiOption('preset',
abbr: 'P', help: 'The configuration preset(s) to use.');
parser.addOption('concurrency',
Expand Down Expand Up @@ -308,8 +306,8 @@ class _Parser {
var runtimes = _ifParsed<List<String>>('platform')
?.map((runtime) => RuntimeSelection(runtime))
.toList();
var compilers = _ifParsed<List<String>>('compiler')
?.map((compiler) => CompilerSelection(compiler))
var compilerSelections = _ifParsed<List<String>>('compiler')
?.map(CompilerSelection.parse)
.toList();

final paths = _options.rest.isEmpty ? null : _options.rest;
Expand Down Expand Up @@ -341,9 +339,9 @@ class _Parser {
concurrency: _parseOption('concurrency', int.parse),
shardIndex: shardIndex,
totalShards: totalShards,
timeout: _parseOption('timeout', (value) => Timeout.parse(value)),
timeout: _parseOption('timeout', Timeout.parse),
globalPatterns: patterns,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
runSkipped: _ifParsed('run-skipped'),
chosenPresets: _ifParsed('preset'),
Expand Down
11 changes: 7 additions & 4 deletions pkgs/test_core/lib/src/runner/configuration/load.dart
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,13 @@ class _ConfigurationLoader {
_parseIdentifierLike(runtimeNode, 'Platform name'),
runtimeNode.span));

var compilers = _getList(
var compilerSelections = _getList(
'compilers',
(compiler) => CompilerSelection(
_parseIdentifierLike(compiler, 'Compiler name'), compiler.span));
(node) => _parseNode(
node,
'compiler',
(option) =>
CompilerSelection.parse(option, parentSpan: node.span)));

var chosenPresets = _getList('add_presets',
(presetNode) => _parseIdentifierLike(presetNode, 'Preset name'));
Expand All @@ -292,7 +295,7 @@ class _ConfigurationLoader {
reporter: reporter,
fileReporters: fileReporters,
concurrency: concurrency,
compilers: compilers,
compilerSelections: compilerSelections,
runtimes: runtimes,
chosenPresets: chosenPresets,
overrideRuntimes: overrideRuntimes);
Expand Down
30 changes: 17 additions & 13 deletions pkgs/test_core/lib/src/runner/loader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import 'dart:io';
import 'package:async/async.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:test_api/src/backend/compiler.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/compiler_selection.dart';
import 'package:yaml/yaml.dart';

import '../util/io.dart';
Expand Down Expand Up @@ -182,18 +182,22 @@ class Loader {
}

for (var runtimeName in suiteConfig.runtimes) {
for (var compilerName in suiteConfig.compilers ?? [null]) {
var runtime = findRuntime(runtimeName);
if (runtime == null) {
throw ArgumentError.value(
runtimeName, 'platform', 'Unknown platform');
}
var compiler = compilerName == null
? runtime.defaultCompiler
: Compiler.builtIn
.firstWhere((compiler) => compiler.identifier == compilerName);
if (!runtime.supportedCompilers.contains(compiler)) continue;

var runtime = findRuntime(runtimeName);
if (runtime == null) {
throw ArgumentError.value(runtimeName, 'platform', 'Unknown platform');
}
final compilers = [
for (var selection
in suiteConfig.compilerSelections ?? <CompilerSelection>[])
if (runtime.supportedCompilers.contains(selection.compiler) &&
(selection.platformSelector == null ||
selection.platformSelector!
.evaluate(currentPlatform(runtime, selection.compiler))))
selection.compiler,
];
if (compilers.isEmpty) compilers.add(runtime.defaultCompiler);

for (var compiler in compilers) {
var platform = currentPlatform(runtime, compiler);
if (!suiteConfig.metadata.testOn.evaluate(platform)) continue;

Expand Down
3 changes: 2 additions & 1 deletion pkgs/test_core/lib/src/runner/reporter/compact.dart
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,8 @@ class CompactReporter implements Reporter {
}

if (_printPlatform) {
name = '[${liveTest.suite.platform.runtime.name}] $name';
name = '[${liveTest.suite.platform.runtime.name}, '
'${liveTest.suite.platform.compiler.name}] $name';
}

if (liveTest.suite is LoadSuite) name = '$_bold$_gray$name$_noColor';
Expand Down
Loading