Skip to content

Add support for hybrid VM/browser tests. #509

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

Merged
merged 2 commits into from
Dec 20, 2016
Merged

Add support for hybrid VM/browser tests. #509

merged 2 commits into from
Dec 20, 2016

Conversation

nex3
Copy link
Member

@nex3 nex3 commented Dec 19, 2016

This adds spawnHybridUri() and spawnHybridCode() methods that spawn
VM isolates even when called from the browser. It still needs some
additional work to close the isolates when the test ends by default.

See #109

This adds `spawnHybridUri()` and `spawnHybridCode()` methods that spawn
VM isolates even when called from the browser. It still needs some
additional work to close the isolates when the test ends by default.

See #109
@nex3 nex3 assigned natebosch and unassigned natebosch Dec 19, 2016
@nex3 nex3 requested a review from natebosch December 19, 2016 23:36
library that communicates over WebSockets. We call tests that run code on both
the browser and the VM **hybrid tests**.

Hybrid tests use one of two functions: [`spawnHybridCode()`][spawnHybridUri] and
Copy link
Member

Choose a reason for hiding this comment

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

Looks like the url references got reversed

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

import '../util/remote_exception.dart';
import '../utils.dart';

/// A transformer that handles messages from the spawned isolate and ensures
Copy link
Member

Choose a reason for hiding this comment

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

can this doc mention the 'print' functionality?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

sink.add(message);
}));

/// Spawns a VM isolate for the given [uri], which may be a [Uri] or a [String].
Copy link
Member

Choose a reason for hiding this comment

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

what is the benefit of having an untyped uri argument?

Copy link
Member

Choose a reason for hiding this comment

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

Can be URI or String.

We need union types. 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

More specifically, in practice URLs are represented as Strings and Uri objects with similar frequency in Dart. I try to make my APIs handle either representation to avoid making my users write lots of annoying .toString() or Uri.parse() calls.

/// easily spawn an isolate.
///
/// The Dart file at [uri] must define a top-level `hybridMain()` function that
/// takes a `StreamChannel` argument and, optionally, an `Object` argument to
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need two ways to pass data? If there is initial data can we send it as the first value through the stream channel?

Copy link
Member Author

Choose a reason for hiding this comment

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

You can, but the Stream API doesn't make it particularly easy to get the first event without also canceling the stream subscription. This also mirrors the Isolate spawn APIs more closely.

throw new ArgumentError.value(uri, "uri", "must be a Uri or a String.");
}

String uriString;
Copy link
Member

Choose a reason for hiding this comment

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

we've already seen a uri which may have been a String. Can this one be absoluteUri so the distinction is more explicit?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

/// that messages sent to it are JSON-encodable.
final _transformer = new StreamChannelTransformer(
new StreamTransformer.fromHandlers(handleData: (message, sink) {
switch (message['type']) {
Copy link
Member

Choose a reason for hiding this comment

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

[nit] line 159 uses double quotes in similar usage

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

/// decoded after being JSON-serialized.
final _transformer = new StreamSinkTransformer.fromHandlers(
handleData: (data, sink) {
ensureJsonEncodable(data);
Copy link
Member

Choose a reason for hiding this comment

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

what happens if this throws? Should we be putting an error on the sink?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is called synchronously from the user's Sink.add() call, so if ensureJsonEncodable() throws here they'll get a helpful stack trace. I'll add a comment to that effect.

}

if (main is! Function) {
_sendError(channel, "Top-level hybridMain getter is not a function.");
Copy link
Member

Choose a reason for hiding this comment

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

[nit] this usage of 'getter' might not match what some readers expect. I might phrase this as "Top-level hybridMain is not a function."

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

///
/// **Note**: If you use this API, be sure to add a dependency on the
/// **`stream_channel` package, since you're using its API as well!
StreamChannel spawnHybridCode(String dartCode, {Object message}) {
Copy link
Member

Choose a reason for hiding this comment

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

DBC: This seems cool – but feel scary.

Is there a strong case for this over just giving folks the URI-based method?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you elaborate on "scary"?

This is useful for the common situation where the hybrid isolate is very simple. It lets users keep the full definition of their test in one file.

sink.add(message);
}));

/// Spawns a VM isolate for the given [uri], which may be a [Uri] or a [String].
Copy link
Member

Choose a reason for hiding this comment

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

Can be URI or String.

We need union types. 😄

@nex3 nex3 merged commit e80252f into master Dec 20, 2016
@nex3 nex3 deleted the hybrid branch December 20, 2016 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants