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

Add a SuitePlatform class #778

Merged
merged 4 commits into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 5 additions & 6 deletions lib/src/backend/group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import 'package:stack_trace/stack_trace.dart';

import 'group_entry.dart';
import 'metadata.dart';
import 'operating_system.dart';
import 'suite_platform.dart';
import 'test.dart';
import 'test_platform.dart';

/// A group contains one or more tests and subgroups.
///
Expand Down Expand Up @@ -52,10 +51,10 @@ class Group implements GroupEntry {
: entries = new List<GroupEntry>.unmodifiable(entries),
metadata = metadata == null ? new Metadata() : metadata;

Group forPlatform(TestPlatform platform, {OperatingSystem os}) {
if (!metadata.testOn.evaluate(platform, os: os)) return null;
var newMetadata = metadata.forPlatform(platform, os: os);
var filtered = _map((entry) => entry.forPlatform(platform, os: os));
Group forPlatform(SuitePlatform platform) {
if (!metadata.testOn.evaluate(platform)) return null;
var newMetadata = metadata.forPlatform(platform);
var filtered = _map((entry) => entry.forPlatform(platform));
if (filtered.isEmpty && entries.isNotEmpty) return null;
return new Group(name, filtered,
metadata: newMetadata,
Expand Down
8 changes: 3 additions & 5 deletions lib/src/backend/group_entry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
import 'package:stack_trace/stack_trace.dart';

import 'metadata.dart';
import 'operating_system.dart';
import 'suite_platform.dart';
import 'test.dart';
import 'test_platform.dart';

/// A [Test] or [Group].
abstract class GroupEntry {
Expand All @@ -28,9 +27,8 @@ abstract class GroupEntry {
/// Returns a copy of [this] with all platform-specific metadata resolved.
///
/// Removes any tests and groups with [Metadata.testOn] selectors that don't
/// match [platform] and [selector]. Returns `null` if this entry's selector
/// doesn't match.
GroupEntry forPlatform(TestPlatform platform, {OperatingSystem os});
/// match [platform]. Returns `null` if this entry's selector doesn't match.
GroupEntry forPlatform(SuitePlatform platform);

/// Returns a copy of [this] with all tests that don't match [callback]
/// removed.
Expand Down
11 changes: 5 additions & 6 deletions lib/src/backend/invoker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ import 'live_test.dart';
import 'live_test_controller.dart';
import 'message.dart';
import 'metadata.dart';
import 'operating_system.dart';
import 'outstanding_callback_counter.dart';
import 'state.dart';
import 'suite.dart';
import 'suite_platform.dart';
import 'test.dart';
import 'test_platform.dart';

/// A test in this isolate.
class LocalTest extends Test {
Expand Down Expand Up @@ -57,10 +56,10 @@ class LocalTest extends Test {
return invoker.liveTest;
}

Test forPlatform(TestPlatform platform, {OperatingSystem os}) {
if (!metadata.testOn.evaluate(platform, os: os)) return null;
return new LocalTest._(name, metadata.forPlatform(platform, os: os), _body,
trace, _guarded, isScaffoldAll);
Test forPlatform(SuitePlatform platform) {
if (!metadata.testOn.evaluate(platform)) return null;
return new LocalTest._(name, metadata.forPlatform(platform), _body, trace,
_guarded, isScaffoldAll);
}
}

Expand Down
7 changes: 3 additions & 4 deletions lib/src/backend/metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import 'package:collection/collection.dart';
import '../frontend/skip.dart';
import '../frontend/timeout.dart';
import '../utils.dart';
import 'operating_system.dart';
import 'platform_selector.dart';
import 'test_platform.dart';
import 'suite_platform.dart';

/// Metadata for a test or test suite.
///
Expand Down Expand Up @@ -353,12 +352,12 @@ class Metadata {

/// Returns a copy of [this] with all platform-specific metadata from
/// [onPlatform] resolved.
Metadata forPlatform(TestPlatform platform, {OperatingSystem os}) {
Metadata forPlatform(SuitePlatform platform) {
if (onPlatform.isEmpty) return this;

var metadata = this;
onPlatform.forEach((platformSelector, platformMetadata) {
if (!platformSelector.evaluate(platform, os: os)) return;
if (!platformSelector.evaluate(platform)) return;
metadata = metadata.merge(platformMetadata);
});
return metadata.change(onPlatform: {});
Expand Down
27 changes: 13 additions & 14 deletions lib/src/backend/platform_selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import 'package:boolean_selector/boolean_selector.dart';
import 'package:source_span/source_span.dart';

import 'operating_system.dart';
import 'test_platform.dart';
import 'runtime.dart';
import 'suite_platform.dart';

/// The set of variable names that are valid for all platform selectors.
final _universalValidVariables =
new Set<String>.from(["posix", "dart-vm", "browser", "js", "blink"])
..addAll(TestPlatform.builtIn.map((platform) => platform.identifier))
..addAll(Runtime.builtIn.map((runtime) => runtime.identifier))
..addAll(OperatingSystem.all.map((os) => os.identifier));

/// An expression for selecting certain platforms, including operating systems
Expand Down Expand Up @@ -68,27 +69,25 @@ class PlatformSelector {
_span);
}

/// Returns whether the selector matches the given [platform] and [os].
/// Returns whether the selector matches the given [platform].
///
/// [os] defaults to [OperatingSystem.none].
bool evaluate(TestPlatform platform, {OperatingSystem os}) {
os ??= OperatingSystem.none;

bool evaluate(SuitePlatform platform) {
return _inner.evaluate((variable) {
if (variable == platform.identifier) return true;
if (variable == platform.parent?.identifier) return true;
if (variable == os.identifier) return true;
if (variable == platform.runtime.identifier) return true;
if (variable == platform.runtime.parent?.identifier) return true;
if (variable == platform.os.identifier) return true;
switch (variable) {
case "dart-vm":
return platform.isDartVM;
return platform.runtime.isDartVM;
case "browser":
return platform.isBrowser;
return platform.runtime.isBrowser;
case "js":
return platform.isJS;
return platform.runtime.isJS;
case "blink":
return platform.isBlink;
return platform.runtime.isBlink;
case "posix":
return os.isPosix;
return platform.os.isPosix;
default:
return false;
}
Expand Down
78 changes: 37 additions & 41 deletions lib/src/backend/test_platform.dart → lib/src/backend/runtime.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,57 @@
// 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.

// TODO(nweiz): support pluggable platforms.
/// An enum of all platforms on which tests can run.
class TestPlatform {
// When adding new platforms, be sure to update the baseline and derived
/// An enum of all Dart runtimes supported by the test runner.
class Runtime {
// When adding new runtimes, be sure to update the baseline and derived
// variable tests in test/backend/platform_selector/evaluate_test.

/// The command-line Dart VM.
static const TestPlatform vm = const TestPlatform("VM", "vm", isDartVM: true);
static const Runtime vm = const Runtime("VM", "vm", isDartVM: true);

/// Dartium.
static const TestPlatform dartium = const TestPlatform("Dartium", "dartium",
static const Runtime dartium = const Runtime("Dartium", "dartium",
isBrowser: true, isBlink: true, isDartVM: true);

/// Dartium content shell.
static const TestPlatform contentShell = const TestPlatform(
static const Runtime contentShell = const Runtime(
"Dartium Content Shell", "content-shell",
isBrowser: true, isBlink: true, isDartVM: true, isHeadless: true);

/// Google Chrome.
static const TestPlatform chrome = const TestPlatform("Chrome", "chrome",
static const Runtime chrome = const Runtime("Chrome", "chrome",
isBrowser: true, isJS: true, isBlink: true);

/// PhantomJS.
static const TestPlatform phantomJS = const TestPlatform(
"PhantomJS", "phantomjs",
static const Runtime phantomJS = const Runtime("PhantomJS", "phantomjs",
isBrowser: true, isJS: true, isBlink: true, isHeadless: true);

/// Mozilla Firefox.
static const TestPlatform firefox =
const TestPlatform("Firefox", "firefox", isBrowser: true, isJS: true);
static const Runtime firefox =
const Runtime("Firefox", "firefox", isBrowser: true, isJS: true);

/// Apple Safari.
static const TestPlatform safari =
const TestPlatform("Safari", "safari", isBrowser: true, isJS: true);
static const Runtime safari =
const Runtime("Safari", "safari", isBrowser: true, isJS: true);

/// Microsoft Internet Explorer.
static const TestPlatform internetExplorer = const TestPlatform(
"Internet Explorer", "ie",
isBrowser: true, isJS: true);
static const Runtime internetExplorer =
const Runtime("Internet Explorer", "ie", isBrowser: true, isJS: true);

/// The command-line Node.js VM.
static const TestPlatform nodeJS =
const TestPlatform("Node.js", "node", isJS: true);
static const Runtime nodeJS = const Runtime("Node.js", "node", isJS: true);

/// The platforms that are supported by the test runner by default.
static const List<TestPlatform> builtIn = const [
TestPlatform.vm,
TestPlatform.dartium,
TestPlatform.contentShell,
TestPlatform.chrome,
TestPlatform.phantomJS,
TestPlatform.firefox,
TestPlatform.safari,
TestPlatform.internetExplorer,
TestPlatform.nodeJS
static const List<Runtime> builtIn = const [
Runtime.vm,
Runtime.dartium,
Runtime.contentShell,
Runtime.chrome,
Runtime.phantomJS,
Runtime.firefox,
Runtime.safari,
Runtime.internetExplorer,
Runtime.nodeJS
];

/// The human-friendly name of the platform.
Expand All @@ -67,7 +63,7 @@ class TestPlatform {

/// The parent platform that this is based on, or `null` if there is no
/// parent.
final TestPlatform parent;
final Runtime parent;

/// Returns whether this is a child of another platform.
bool get isChild => parent != null;
Expand All @@ -91,26 +87,26 @@ class TestPlatform {
/// anything.
///
/// That is, returns [parent] if it's non-`null` or [this] if it's `null`.
TestPlatform get root => parent ?? this;
Runtime get root => parent ?? this;

const TestPlatform(this.name, this.identifier,
const Runtime(this.name, this.identifier,
{this.isDartVM: false,
this.isBrowser: false,
this.isJS: false,
this.isBlink: false,
this.isHeadless: false})
: parent = null;

TestPlatform._child(this.name, this.identifier, this.parent)
Runtime._child(this.name, this.identifier, this.parent)
: isDartVM = parent.isDartVM,
isBrowser = parent.isBrowser,
isJS = parent.isJS,
isBlink = parent.isBlink,
isHeadless = parent.isHeadless;

/// Converts a JSON-safe representation generated by [serialize] back into a
/// [TestPlatform].
factory TestPlatform.deserialize(Object serialized) {
/// [Runtime].
factory Runtime.deserialize(Object serialized) {
if (serialized is String) {
return builtIn
.firstWhere((platform) => platform.identifier == serialized);
Expand All @@ -123,11 +119,11 @@ class TestPlatform {
// a separately-deserialized parent platform. This should be fine, though,
// since we only deserialize platforms in the remote execution context
// where they're only used to evaluate platform selectors.
return new TestPlatform._child(
map["name"], map["identifier"], new TestPlatform.deserialize(parent));
return new Runtime._child(
map["name"], map["identifier"], new Runtime.deserialize(parent));
}

return new TestPlatform(map["name"], map["identifier"],
return new Runtime(map["name"], map["identifier"],
isDartVM: map["isDartVM"],
isBrowser: map["isBrowser"],
isJS: map["isJS"],
Expand All @@ -136,7 +132,7 @@ class TestPlatform {
}

/// Converts [this] into a JSON-safe object that can be converted back to a
/// [TestPlatform] using [new TestPlatform.deserialize].
/// [Runtime] using [new Runtime.deserialize].
Object serialize() {
if (builtIn.contains(this)) return identifier;

Expand All @@ -163,8 +159,8 @@ class TestPlatform {
/// and the new [identifier].
///
/// This may not be called on a platform that's already a child.
TestPlatform extend(String name, String identifier) {
if (parent == null) return new TestPlatform._child(name, identifier, this);
Runtime extend(String name, String identifier) {
if (parent == null) return new Runtime._child(name, identifier, this);
throw new StateError("A child platform may not be extended.");
}

Expand Down
33 changes: 8 additions & 25 deletions lib/src/backend/suite.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,16 @@

import 'group.dart';
import 'metadata.dart';
import 'operating_system.dart';
import 'suite_platform.dart';
import 'test.dart';
import 'test_platform.dart';

/// A test suite.
///
/// A test suite is a set of tests that are intended to be run together and that
/// share default configuration.
class Suite {
/// The platform on which the suite is running, or `null` if that platform is
/// unknown.
final TestPlatform platform;

/// The operating system on which the suite is running, or `null` if that
/// operating system is unknown.
///
/// This will always be `null` if [platform] is `null`.
final OperatingSystem os;
/// The platform on which the suite is running.
final SuitePlatform platform;

/// The path to the Dart test suite, or `null` if that path is unknown.
final String path;
Expand All @@ -40,23 +32,14 @@ class Suite {
/// platform information.
///
/// If [os] is passed without [platform], throws an [ArgumentError].
Suite(Group group, {this.path, TestPlatform platform, OperatingSystem os})
: platform = platform,
os = os,
group = _filterGroup(group, platform, os);
Suite(Group group, this.platform, {this.path})
: group = _filterGroup(group, platform);

/// Returns [entries] filtered according to [platform] and [os].
///
/// Gracefully handles [platform] being null.
static Group _filterGroup(
Group group, TestPlatform platform, OperatingSystem os) {
if (platform == null && os != null) {
throw new ArgumentError.value(
null, "os", "If os is passed, platform must be passed as well");
}

if (platform == null) return group;
var filtered = group.forPlatform(platform, os: os);
static Group _filterGroup(Group group, SuitePlatform platform) {
var filtered = group.forPlatform(platform);
if (filtered != null) return filtered;
return new Group.root([], metadata: group.metadata);
}
Expand All @@ -68,6 +51,6 @@ class Suite {
Suite filter(bool callback(Test test)) {
var filtered = group.filter(callback);
if (filtered == null) filtered = new Group.root([], metadata: metadata);
return new Suite(filtered, platform: platform, os: os, path: path);
return new Suite(filtered, platform, path: path);
}
}
Loading