Skip to content

Commit 8460fa9

Browse files
committed
Factor out a SuiteConfiguration object.
This tracks configuration that makes sense to apply to test suites, as opposed to Configuration which applies to an entire run and Metadata which applies to individual tests. This is intended to make it easier for load separate configurations for separate targets in a live test runner.
1 parent 6c880f5 commit 8460fa9

26 files changed

+1079
-826
lines changed

lib/src/backend/metadata.dart

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,29 @@ import 'test_platform.dart';
1919
/// This metadata comes from declarations on the test itself; it doesn't include
2020
/// configuration from the user.
2121
class Metadata {
22+
/// Empty metadata with only default values.
23+
///
24+
/// Using this is slightly more efficient than manually constructing a new
25+
/// metadata with no arguments.
26+
static final empty = new Metadata._();
27+
2228
/// The selector indicating which platforms the suite supports.
2329
final PlatformSelector testOn;
2430

2531
/// The modification to the timeout for the test or suite.
2632
final Timeout timeout;
2733

2834
/// Whether the test or suite should be skipped.
29-
final bool skip;
30-
31-
/// Whether to use verbose stack traces.
32-
final bool verboseTrace;
35+
bool get skip => _skip ?? false;
36+
final bool _skip;
3337

3438
/// The reason the test or suite should be skipped, if given.
3539
final String skipReason;
3640

41+
/// Whether to use verbose stack traces.
42+
bool get verboseTrace => _verboseTrace ?? false;
43+
final bool _verboseTrace;
44+
3745
/// The user-defined tags attached to the test or suite.
3846
final Set<String> tags;
3947

@@ -122,8 +130,8 @@ class Metadata {
122130
/// If [forTag] contains metadata that applies to [tags], that metadata is
123131
/// included inline in the returned value. The values directly passed to the
124132
/// constructor take precedence over tag-specific metadata.
125-
factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false,
126-
bool verboseTrace: false, String skipReason, Iterable<String> tags,
133+
factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip,
134+
bool verboseTrace, String skipReason, Iterable<String> tags,
127135
Map<PlatformSelector, Metadata> onPlatform,
128136
Map<BooleanSelector, Metadata> forTag}) {
129137
// Returns metadata without forTag resolved at all.
@@ -159,13 +167,14 @@ class Metadata {
159167
/// Creates new Metadata.
160168
///
161169
/// Unlike [new Metadata], this assumes [forTag] is already resolved.
162-
Metadata._({PlatformSelector testOn, Timeout timeout, bool skip: false,
163-
this.verboseTrace: false, this.skipReason, Iterable<String> tags,
170+
Metadata._({PlatformSelector testOn, Timeout timeout, bool skip,
171+
this.skipReason, bool verboseTrace, Iterable<String> tags,
164172
Map<PlatformSelector, Metadata> onPlatform,
165173
Map<BooleanSelector, Metadata> forTag})
166174
: testOn = testOn == null ? PlatformSelector.all : testOn,
167175
timeout = timeout == null ? const Timeout.factor(1) : timeout,
168-
skip = skip,
176+
_skip = skip,
177+
_verboseTrace = verboseTrace,
169178
tags = new UnmodifiableSetView(
170179
tags == null ? new Set() : tags.toSet()),
171180
onPlatform = onPlatform == null
@@ -182,13 +191,14 @@ class Metadata {
182191
///
183192
/// Throws a [FormatException] if any field is invalid.
184193
Metadata.parse({String testOn, Timeout timeout, skip,
185-
this.verboseTrace: false, Map<String, dynamic> onPlatform,
194+
bool verboseTrace, Map<String, dynamic> onPlatform,
186195
tags})
187196
: testOn = testOn == null
188197
? PlatformSelector.all
189198
: new PlatformSelector.parse(testOn),
190199
timeout = timeout == null ? const Timeout.factor(1) : timeout,
191-
skip = skip != null && skip != false,
200+
_skip = skip == null ? null : skip != false,
201+
_verboseTrace = verboseTrace,
192202
skipReason = skip is String ? skip : null,
193203
onPlatform = _parseOnPlatform(onPlatform),
194204
tags = _parseTags(tags),
@@ -207,9 +217,9 @@ class Metadata {
207217
? PlatformSelector.all
208218
: new PlatformSelector.parse(serialized['testOn']),
209219
timeout = _deserializeTimeout(serialized['timeout']),
210-
skip = serialized['skip'],
220+
_skip = serialized['skip'],
211221
skipReason = serialized['skipReason'],
212-
verboseTrace = serialized['verboseTrace'],
222+
_verboseTrace = serialized['verboseTrace'],
213223
tags = new Set.from(serialized['tags']),
214224
onPlatform = new Map.fromIterable(serialized['onPlatform'],
215225
key: (pair) => new PlatformSelector.parse(pair.first),
@@ -252,9 +262,9 @@ class Metadata {
252262
new Metadata(
253263
testOn: testOn.intersection(other.testOn),
254264
timeout: timeout.merge(other.timeout),
255-
skip: skip || other.skip,
265+
skip: other._skip ?? _skip ,
256266
skipReason: other.skipReason == null ? skipReason : other.skipReason,
257-
verboseTrace: verboseTrace || other.verboseTrace,
267+
verboseTrace: other._verboseTrace ?? _verboseTrace,
258268
tags: tags.union(other.tags),
259269
onPlatform: mergeMaps(onPlatform, other.onPlatform,
260270
value: (metadata1, metadata2) => metadata1.merge(metadata2)),
@@ -273,8 +283,8 @@ class Metadata {
273283
Map<BooleanSelector, Metadata> forTag}) {
274284
testOn ??= this.testOn;
275285
timeout ??= this.timeout;
276-
skip ??= this.skip;
277-
verboseTrace ??= this.verboseTrace;
286+
skip ??= this._skip;
287+
verboseTrace ??= this._verboseTrace;
278288
skipReason ??= this.skipReason;
279289
onPlatform ??= this.onPlatform;
280290
tags ??= this.tags;

lib/src/runner.dart

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,17 @@ class Runner {
6767

6868
/// Creates a new runner based on [configuration].
6969
factory Runner(Configuration config) => config.asCurrent(() {
70-
var engine = new Engine(
71-
concurrency: config.concurrency,
72-
runSkipped: config.runSkipped);
70+
var engine = new Engine(concurrency: config.concurrency);
7371

7472
var reporter;
7573
switch (config.reporter) {
7674
case "expanded":
7775
reporter = ExpandedReporter.watch(
7876
engine,
7977
color: config.color,
80-
verboseTrace: config.verboseTrace,
8178
printPath: config.paths.length > 1 ||
8279
new Directory(config.paths.single).existsSync(),
83-
printPlatform: config.platforms.length > 1);
80+
printPlatform: config.suiteDefaults.platforms.length > 1);
8481
break;
8582

8683
case "compact":
@@ -124,9 +121,11 @@ class Runner {
124121

125122
if (_closed) return false;
126123

127-
if (_engine.passed.length == 0 && _engine.failed.length == 0 &&
128-
_engine.skipped.length == 0 && _config.patterns.isNotEmpty) {
129-
var patterns = toSentence(_config.patterns.map(
124+
if (_engine.passed.length == 0 &&
125+
_engine.failed.length == 0 &&
126+
_engine.skipped.length == 0 &&
127+
_config.suiteDefaults.patterns.isNotEmpty) {
128+
var patterns = toSentence(_config.suiteDefaults.patterns.map(
130129
(pattern) => pattern is RegExp
131130
? 'regular expression "${pattern.pattern}"'
132131
: '"$pattern"'));
@@ -142,11 +141,12 @@ class Runner {
142141
/// Emits a warning if the user is trying to run on a platform that's
143142
/// unsupported for the entire package.
144143
void _warnForUnsupportedPlatforms() {
145-
if (_config.testOn == PlatformSelector.all) return;
144+
var testOn = _config.suiteDefaults.metadata.testOn;
145+
if (testOn == PlatformSelector.all) return;
146146

147-
var unsupportedPlatforms = _config.platforms.where((platform) {
148-
return !_config.testOn.evaluate(platform, os: currentOS);
149-
}).toList();
147+
var unsupportedPlatforms = _config.suiteDefaults.platforms
148+
.where((platform) => !testOn.evaluate(platform, os: currentOS))
149+
.toList();
150150
if (unsupportedPlatforms.isEmpty) return;
151151

152152
// Human-readable names for all unsupported platforms.
@@ -160,7 +160,7 @@ class Runner {
160160
if (unsupportedBrowsers.isNotEmpty) {
161161
var supportsAnyBrowser = TestPlatform.all
162162
.where((platform) => platform.isBrowser)
163-
.any((platform) => _config.testOn.evaluate(platform));
163+
.any((platform) => testOn.evaluate(platform));
164164

165165
if (supportsAnyBrowser) {
166166
unsupportedNames.addAll(
@@ -174,7 +174,7 @@ class Runner {
174174
// that's because of the current OS or whether the VM is unsupported.
175175
if (unsupportedPlatforms.contains(TestPlatform.vm)) {
176176
var supportsAnyOS = OperatingSystem.all.any((os) =>
177-
_config.testOn.evaluate(TestPlatform.vm, os: os));
177+
testOn.evaluate(TestPlatform.vm, os: os));
178178

179179
if (supportsAnyOS) {
180180
unsupportedNames.add(currentOS.name);
@@ -232,29 +232,37 @@ class Runner {
232232
/// suites once they're loaded.
233233
Stream<LoadSuite> _loadSuites() {
234234
return StreamGroup.merge(_config.paths.map((path) {
235-
if (new Directory(path).existsSync()) return _loader.loadDir(path);
236-
if (new File(path).existsSync()) return _loader.loadFile(path);
237-
238-
return new Stream.fromIterable([
239-
new LoadSuite.forLoadException(
240-
new LoadException(path, 'Does not exist.'))
241-
]);
235+
if (new Directory(path).existsSync()) {
236+
return _loader.loadDir(path, _config.suiteDefaults);
237+
} else if (new File(path).existsSync()) {
238+
return _loader.loadFile(path, _config.suiteDefaults);
239+
} else {
240+
return new Stream.fromIterable([
241+
new LoadSuite.forLoadException(
242+
new LoadException(path, 'Does not exist.'),
243+
_config.suiteDefaults)
244+
]);
245+
}
242246
})).map((loadSuite) {
243247
return loadSuite.changeSuite((suite) {
244248
_warnForUnknownTags(suite);
245249

246250
return _shardSuite(suite.filter((test) {
247251
// Skip any tests that don't match all the given patterns.
248-
if (!_config.patterns
252+
if (!suite.config.patterns
249253
.every((pattern) => test.name.contains(pattern))) {
250254
return false;
251255
}
252256

253257
// If the user provided tags, skip tests that don't match all of them.
254-
if (!_config.includeTags.evaluate(test.metadata.tags)) return false;
258+
if (!suite.config.includeTags.evaluate(test.metadata.tags)) {
259+
return false;
260+
}
255261

256262
// Skip tests that do match any tags the user wants to exclude.
257-
if (_config.excludeTags.evaluate(test.metadata.tags)) return false;
263+
if (suite.config.excludeTags.evaluate(test.metadata.tags)) {
264+
return false;
265+
}
258266

259267
return true;
260268
}));
@@ -363,7 +371,7 @@ class Runner {
363371
/// Loads each suite in [suites] in order, pausing after load for platforms
364372
/// that support debugging.
365373
Future<bool> _loadThenPause(Stream<LoadSuite> suites) async {
366-
if (_config.platforms.contains(TestPlatform.vm)) {
374+
if (_config.suiteDefaults.platforms.contains(TestPlatform.vm)) {
367375
warn("Debugging is currently unsupported on the Dart VM.",
368376
color: _config.color);
369377
}

lib/src/runner/browser/browser_manager.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import 'package:pool/pool.dart';
1010
import 'package:stream_channel/stream_channel.dart';
1111
import 'package:web_socket_channel/web_socket_channel.dart';
1212

13-
import '../../backend/metadata.dart';
1413
import '../../backend/test_platform.dart';
1514
import '../../util/stack_trace_mapper.dart';
1615
import '../application_exception.dart';
16+
import '../configuration/suite.dart';
1717
import '../environment.dart';
1818
import '../plugin/platform_helpers.dart';
1919
import '../runner_suite.dart';
@@ -193,14 +193,14 @@ class BrowserManager {
193193
///
194194
/// [url] should be an HTML page with a reference to the JS-compiled test
195195
/// suite. [path] is the path of the original test suite file, which is used
196-
/// for reporting. [metadata] is the parsed metadata for the test suite.
196+
/// for reporting. [suiteConfig] is the configuration for the test suite.
197197
///
198198
/// If [mapper] is passed, it's used to map stack traces for errors coming
199199
/// from this test suite.
200-
Future<RunnerSuite> load(String path, Uri url, Metadata metadata,
200+
Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
201201
{StackTraceMapper mapper}) async {
202202
url = url.replace(fragment: Uri.encodeFull(JSON.encode({
203-
"metadata": metadata.serialize(),
203+
"metadata": suiteConfig.metadata.serialize(),
204204
"browser": _platform.identifier
205205
})));
206206

@@ -235,7 +235,7 @@ class BrowserManager {
235235

236236
try {
237237
controller = await deserializeSuite(
238-
path, _platform, metadata, await _environment, suiteChannel,
238+
path, _platform, suiteConfig, await _environment, suiteChannel,
239239
mapTrace: mapper?.mapStackTrace);
240240
_controllers.add(controller);
241241
return controller.suite;

lib/src/runner/browser/compiler_pool.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:pool/pool.dart';
1313

1414
import '../../util/io.dart';
1515
import '../configuration.dart';
16+
import '../configuration/suite.dart';
1617
import '../load_exception.dart';
1718

1819
/// A regular expression matching the first status line printed by dart2js.
@@ -47,7 +48,8 @@ class CompilerPool {
4748
///
4849
/// The returned [Future] will complete once the `dart2js` process completes
4950
/// *and* all its output has been printed to the command line.
50-
Future compile(String dartPath, String jsPath) {
51+
Future compile(String dartPath, String jsPath,
52+
SuiteConfiguration suiteConfig) {
5153
return _pool.withResource(() {
5254
if (_closed) return null;
5355

@@ -75,7 +77,7 @@ class CompilerPool {
7577
wrapperPath,
7678
"--out=$jsPath",
7779
await PackageResolver.current.processArgument
78-
]..addAll(_config.dart2jsArgs);
80+
]..addAll(suiteConfig.dart2jsArgs);
7981

8082
if (_config.color) args.add("--enable-diagnostic-colors");
8183

0 commit comments

Comments
 (0)