Skip to content

Commit 0a3f688

Browse files
authored
Send test platforms to the remote listener (flutter#694)
This ensures that the remote listener has access to any platforms that are dynamically loaded in the test runner, so they can be used in platform selectors. See flutter#99 See flutter#391
1 parent 7f7d218 commit 0a3f688

File tree

8 files changed

+87
-35
lines changed

8 files changed

+87
-35
lines changed

lib/src/backend/test_platform.dart

+43-11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ class TestPlatform {
6060
all.firstWhere((platform) => platform.identifier == identifier,
6161
orElse: () => null);
6262

63+
static Set<TestPlatform> _builtIn = new Set.from([
64+
TestPlatform.vm,
65+
TestPlatform.dartium,
66+
TestPlatform.contentShell,
67+
TestPlatform.chrome,
68+
TestPlatform.phantomJS,
69+
TestPlatform.firefox,
70+
TestPlatform.safari,
71+
TestPlatform.internetExplorer,
72+
TestPlatform.nodeJS
73+
]);
74+
6375
/// The human-friendly name of the platform.
6476
final String name;
6577

@@ -88,20 +100,40 @@ class TestPlatform {
88100
this.isBlink: false,
89101
this.isHeadless: false});
90102

103+
/// Converts a JSON-safe representation generated by [serialize] back into a
104+
/// [TestPlatform].
105+
factory TestPlatform.deserialize(Object serialized) {
106+
if (serialized is String) return find(serialized);
107+
108+
var map = serialized as Map;
109+
return new TestPlatform._(map["name"], map["identifier"],
110+
isDartVM: map["isDartVM"],
111+
isBrowser: map["isBrowser"],
112+
isJS: map["isJS"],
113+
isBlink: map["isBlink"],
114+
isHeadless: map["isHeadless"]);
115+
}
116+
117+
/// Converts [this] into a JSON-safe object that can be converted back to a
118+
/// [TestPlatform] using [new TestPlatform.deserialize].
119+
Object serialize() {
120+
if (_builtIn.contains(this)) return identifier;
121+
122+
return {
123+
"name": name,
124+
"identifier": identifier,
125+
"isDartVM": isDartVM,
126+
"isBrowser": isBrowser,
127+
"isJS": isJS,
128+
"isBlink": isBlink,
129+
"isHeadless": isHeadless
130+
};
131+
}
132+
91133
String toString() => name;
92134
}
93135

94-
final List<TestPlatform> _allPlatforms = [
95-
TestPlatform.vm,
96-
TestPlatform.dartium,
97-
TestPlatform.contentShell,
98-
TestPlatform.chrome,
99-
TestPlatform.phantomJS,
100-
TestPlatform.firefox,
101-
TestPlatform.safari,
102-
TestPlatform.internetExplorer,
103-
TestPlatform.nodeJS
104-
];
136+
final List<TestPlatform> _allPlatforms = TestPlatform._builtIn.toList();
105137

106138
/// **Do not call this function without express permission from the test package
107139
/// authors**.

lib/src/runner/browser/browser_manager.dart

+4-3
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ class BrowserManager {
201201
///
202202
/// If [mapper] is passed, it's used to map stack traces for errors coming
203203
/// from this test suite.
204-
Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
204+
Future<RunnerSuite> load(
205+
String path, Uri url, SuiteConfiguration suiteConfig, Object message,
205206
{StackTraceMapper mapper}) async {
206207
url = url.replace(
207208
fragment: Uri.encodeFull(JSON.encode({
@@ -236,8 +237,8 @@ class BrowserManager {
236237
});
237238

238239
try {
239-
controller = await deserializeSuite(
240-
path, _platform, suiteConfig, await _environment, suiteChannel,
240+
controller = await deserializeSuite(path, _platform, suiteConfig,
241+
await _environment, suiteChannel, message,
241242
mapper: mapper);
242243
_controllers.add(controller);
243244
return controller.suite;

lib/src/runner/browser/platform.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ class BrowserPlatform extends PlatformPlugin {
192192
///
193193
/// This will start a browser to load the suite if one isn't already running.
194194
/// Throws an [ArgumentError] if [browser] isn't a browser platform.
195-
Future<RunnerSuite> load(
196-
String path, TestPlatform browser, SuiteConfiguration suiteConfig) async {
195+
Future<RunnerSuite> load(String path, TestPlatform browser,
196+
SuiteConfiguration suiteConfig, Object message) async {
197197
assert(suiteConfig.platforms.contains(browser.identifier));
198198

199199
if (!browser.isBrowser) {
@@ -271,7 +271,7 @@ class BrowserPlatform extends PlatformPlugin {
271271
var browserManager = await _browserManagerFor(browser);
272272
if (_closed || browserManager == null) return null;
273273

274-
var suite = await browserManager.load(path, suiteUrl, suiteConfig,
274+
var suite = await browserManager.load(path, suiteUrl, suiteConfig, message,
275275
mapper: browser.isJS ? _mappers[path] : null);
276276
if (_closed) return null;
277277
return suite;

lib/src/runner/loader.dart

+16-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ class Loader {
4747
List<TestPlatform> get allPlatforms =>
4848
new List.unmodifiable(_platformCallbacks.keys);
4949

50+
List<Map<String, Object>> get _allPlatformsSerialized {
51+
if (__allPlatformsSerialized != null &&
52+
__allPlatformsSerialized.length == _platformCallbacks.length) {
53+
return __allPlatformsSerialized;
54+
}
55+
56+
__allPlatformsSerialized = _platformCallbacks.keys
57+
.map((platform) => platform.serialize())
58+
.toList();
59+
return __allPlatformsSerialized;
60+
}
61+
62+
List<Map<String, Object>> __allPlatformsSerialized;
63+
5064
/// Creates a new loader that loads tests on platforms defined in
5165
/// [Configuration.current].
5266
///
@@ -169,7 +183,8 @@ class Loader {
169183

170184
try {
171185
var plugin = await memo.runOnce(_platformCallbacks[platform]);
172-
var suite = await plugin.load(path, platform, platformConfig);
186+
var suite = await plugin.load(path, platform, platformConfig,
187+
{"testPlatforms": _allPlatformsSerialized});
173188
if (suite != null) _suites.add(suite);
174189
return suite;
175190
} catch (error, stackTrace) {

lib/src/runner/node/platform.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ class NodePlatform extends PlatformPlugin {
5151
throw new UnimplementedError();
5252

5353
Future<RunnerSuite> load(String path, TestPlatform platform,
54-
SuiteConfiguration suiteConfig) async {
54+
SuiteConfiguration suiteConfig, Object message) async {
5555
assert(platform == TestPlatform.nodeJS);
5656

5757
var pair = await _loadChannel(path, suiteConfig);
58-
var controller = await deserializeSuite(
59-
path, platform, suiteConfig, new PluginEnvironment(), pair.first,
58+
var controller = await deserializeSuite(path, platform, suiteConfig,
59+
new PluginEnvironment(), pair.first, message,
6060
mapper: pair.last);
6161
return controller.suite;
6262
}

lib/src/runner/plugin/platform.dart

+7-7
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import 'platform_helpers.dart';
2323
/// In order to support interactive debugging, a plugin must override [load] as
2424
/// well, which returns a [RunnerSuite] that can contain a custom [Environment]
2525
/// and control debugging metadata such as [RunnerSuite.isDebugging] and
26-
/// [RunnerSuite.onDebugging]. To make this easier, implementations can call
27-
/// [deserializeSuite] in `platform_helpers.dart`.
26+
/// [RunnerSuite.onDebugging]. The plugin must create this suite by calling the
27+
/// [deserializeSuite] helper function.
2828
///
2929
/// A platform plugin can be registered with [Loader.registerPlatformPlugin].
3030
abstract class PlatformPlugin {
@@ -52,16 +52,16 @@ abstract class PlatformPlugin {
5252
/// fine-grained control over the [RunnerSuite], including providing a custom
5353
/// implementation of [Environment].
5454
///
55-
/// It's recommended that subclasses overriding this method call
56-
/// [deserializeSuite] in `platform_helpers.dart` to obtain a
57-
/// [RunnerSuiteController].
55+
/// Subclasses overriding this method must call [deserializeSuite] in
56+
/// `platform_helpers.dart` to obtain a [RunnerSuiteController]. They must
57+
/// pass the opaque [message] parameter to the [deserializeSuite] call.
5858
Future<RunnerSuite> load(String path, TestPlatform platform,
59-
SuiteConfiguration suiteConfig) async {
59+
SuiteConfiguration suiteConfig, Object message) async {
6060
// loadChannel may throw an exception. That's fine; it will cause the
6161
// LoadSuite to emit an error, which will be presented to the user.
6262
var channel = loadChannel(path, platform);
6363
var controller = await deserializeSuite(
64-
path, platform, suiteConfig, new PluginEnvironment(), channel);
64+
path, platform, suiteConfig, new PluginEnvironment(), channel, message);
6565
return controller.suite;
6666
}
6767

lib/src/runner/plugin/platform_helpers.dart

+7-6
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,19 @@ final _deserializeTimeout = new Duration(minutes: 8);
3333
///
3434
/// If the suite is closed, this will close [channel].
3535
///
36-
/// If [mapTrace] is passed, it will be used to adjust stack traces for any
37-
/// errors emitted by tests.
36+
/// The [message] parameter is an opaque object passed from the runner to
37+
/// [PlatformPlugin.load]. Plugins shouldn't interact with it other than to pass
38+
/// it on to [deserializeSuite].
3839
///
39-
/// If [asciiSymbols] is passed, it controls whether the `symbol` package is
40-
/// configured to use plain ASCII or Unicode symbols. It defaults to `true` on
41-
/// Windows and `false` elsewhere.
40+
/// If [mapper] is passed, it will be used to adjust stack traces for any errors
41+
/// emitted by tests.
4242
Future<RunnerSuiteController> deserializeSuite(
4343
String path,
4444
TestPlatform platform,
4545
SuiteConfiguration suiteConfig,
4646
Environment environment,
4747
StreamChannel channel,
48+
Object message,
4849
{StackTraceMapper mapper}) async {
4950
var disconnector = new Disconnector();
5051
var suiteChannel = new MultiChannel(channel.transform(disconnector));
@@ -60,7 +61,7 @@ Future<RunnerSuiteController> deserializeSuite(
6061
'stackTraceMapper': mapper?.serialize(),
6162
'foldTraceExcept': Configuration.current.foldTraceExcept.toList(),
6263
'foldTraceOnly': Configuration.current.foldTraceOnly.toList(),
63-
});
64+
}..addAll(message as Map));
6465

6566
var completer = new Completer();
6667

lib/src/runner/remote_listener.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ class RemoteListener {
7777
if (message['asciiGlyphs'] ?? false) glyph.ascii = true;
7878
var metadata = new Metadata.deserialize(message['metadata']);
7979
verboseChain = metadata.verboseTrace;
80-
var declarer = new Declarer(TestPlatform.all,
80+
var declarer = new Declarer(
81+
message['testPlatforms']
82+
.map((platform) => new TestPlatform.deserialize(platform))
83+
.toList(),
8184
metadata: metadata,
8285
collectTraces: message['collectTraces'],
8386
noRetry: message['noRetry']);

0 commit comments

Comments
 (0)