Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: tests/isolate/function_send_test.dart

Issue 584843003: Allow sending static/top-level functions through ports and as isolate (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/_internal/compiler/js_lib/isolate_helper.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/isolate/function_send_test.dart
diff --git a/tests/isolate/function_send_test.dart b/tests/isolate/function_send_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..03767f3ec990fc6d95c1e1a869836126b40596bb
--- /dev/null
+++ b/tests/isolate/function_send_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+void toplevel(port, message) { port.send("toplevel:$message"); }
+void mkToplevelFunc() => (p, m) { p.send(m); };
floitsch 2014/09/19 19:52:45 mkFuncToplevel or funcGeneratorToplevel
Lasse Reichstein Nielsen 2014/09/23 07:25:07 I'll go for createFuncToplevel.
+class C {
+ Function initializer;
+ Function body;
+ C() : initializer = ((p, m) { throw "initializer"; }) {
+ body = (p, m) { throw "body"; };
+ }
+ static void staticFunc(port, message) { port.send("static:$message"); }
+ static Function mkStaticFunc() => (p, m) { throw "static expr"; };
+ void member(p, m) { throw "member"; }
+ void mkFunc() => (p, m) { throw "instance expr"; };
+ void call(n, p) { throw "C"; }
+}
+
+class Callable {
+ void call(p, m) { p.send(["callable", m]); }
+}
+
+
+void main() {
+ asyncStart();
+
+ // Sendables are top-level functions and static functions only.
+ testSendable("toplevel", toplevel);
+ testSendable("static", C.staticFunc);
+
+ // Unsendables are any closure - instance methods or function expression.
+ var c = new C();
+ testUnsendable("instance method", c.member);
+ testUnsendable("static context expression", mkToplevelFunc());
+ testUnsendable("static context expression", C.mkStaticFunc());
+ testUnsendable("initializer context expression", c.initializer);
+ testUnsendable("constructor context expression", c.body);
+ testUnsendable("instance method context expression", c.mkFunc());
+
+ // Actually allowed. Identical in VM, different, but still static, in dart2js.
floitsch 2014/09/19 19:52:45 If it's allowed, why is it commented?
Lasse Reichstein Nielsen 2014/09/23 07:25:07 I can't say whether it should be allowed or not, a
+ // testUnsendable("toplevel.call closure", toplevel.call);
+ // testUnsendable("static.call closure", C.staticFunc.call);
+
+ // Callable objects are sendable if general objects are (VM yes, dart2js no).
+ //testSendable("callable object", new Callable()); /// 01: ok
floitsch 2014/09/19 19:52:45 Why is it commented? Especially with "/// 01: ok".
Lasse Reichstein Nielsen 2014/09/23 07:25:07 Again I can't decide on whether it should be one o
+ testUnsendable("callable object", new Callable()); /// 02: ok
floitsch 2014/09/19 19:52:45 That looks like the same as above...
Lasse Reichstein Nielsen 2014/09/23 07:25:07 This one is test*Un*sendablem the one above is tes
+ testUnsendable("callable object", new Callable().call);
+ asyncEnd();
+ return;
+}
+
+// Create a receive port that expects exactly one message.
+// Pass the message to `callback` and return the sendPort.
+void singleMessagePort(callback) {
+ var p;
+ p = new RawReceivePort((v) { p.close(); callback(v); });
+ return p.sendPort;
+}
+
+// A singleMessagePort that expects the message to be a specific value.
+void expectMessagePort(message) {
+ asyncStart();
+ return singleMessagePort((v) {
+ Expect.equals(message, v);
+ asyncEnd();
+ });
+}
+
+void testSendable(name, func) {
+ // Function as spawn message.
+ Isolate.spawn(callFunc, [func, expectMessagePort("$name:spawn"), "spawn"]);
+
+ // Send function to same isolate.
+ var reply = expectMessagePort("$name:direct");
+ singleMessagePort(callFunc).send([func, reply, "direct"]);
+
+ // Send function to other isolate, call it there.
+ reply = expectMessagePort("$name:other isolate");
+ callPort().then((p) {
+ p.send([func, reply, "other isolate"]);
+ });
+
+ // Round-trip function trough other isolate.
+ echoPort((roundtripFunc) {
+ Expect.identical(func, roundtripFunc, "$name:send through isolate");
+ }).then((port) { port.send(func); });
+}
+
+// Creates a new isolate and a pair of ports that expect a single message
+// to be sent to the other isolate and back to the callback function.
+Future<SendPort> echoPort(callback(value)) {
+ Completer completer = new Completer<SendPort>();
+ SendPort replyPort = singleMessagePort(callback);
+ RawReceivePort initPort;
+ initPort = new RawReceivePort((p) {
+ completer.complete(p);
+ initPort.close();
+ });
+ return Isolate.spawn(_echo, [replyPort, initPort.sendPort])
+ .then((isolate) => completer.future);
+}
+
+void _echo(msg) {
+ var replyPort = msg[0];
+ RawReceivePort requestPort;
+ requestPort = new RawReceivePort((msg) {
+ replyPort.send(msg);
+ requestPort.close(); // Single echo only.
+ });
+ msg[1].send(requestPort.sendPort);
+}
+
+// Creates other isolate that waits for a single message, `msg`, on the returned
+// port, and executes it as `msg[0](msg[1],msg[2])` in the other isolate.
+Future<SendPort> callPort() {
+ Completer completer = new Completer<SendPort>();
+ SendPort initPort = singleMessagePort(completer.complete);
+ return Isolate.spawn(_call, initPort)
+ .then((_) => completer.future);
+}
+
+void _call(initPort) {
+ initPort.send(singleMessagePort(callFunc));
+}
+ // Expect.throws(() {
+ // noReply.sendPort.send([func]);
+ // }, null, "send wrapped");
+
+
+void testUnsendable(name, func) {
+ asyncStart();
+ Isolate.spawn(nop, func).then((v) => throw "allowed spawn direct?",
+ onError: (e,s){ asyncEnd(); });
+ asyncStart();
+ Isolate.spawn(nop, [func]).then((v) => throw "allowed spawn wrapped?",
+ onError: (e,s){ asyncEnd(); });
+
+ asyncStart();
+ var noReply = new RawReceivePort((_) { throw "Unexpected message: $_"; });
+ // Currently succeedes incorrectly in dart2js.
+ // Expect.throws(() {
+ // noReply.sendPort.send(func);
+ // }, null, "send direct");
+ // Expect.throws(() {
+ // noReply.sendPort.send([func]);
+ // }, null, "send wrapped");
+ scheduleMicrotask(() {
+ noReply.close();
+ asyncEnd();
+ });
+
+ // Try sending through other isolate.
+ asyncStart();
+ echoPort((_) => throw "unreachable")
+ .then((p) => p.send(func))
+ .then((p) => throw "unreachable 2",
+ onError: (e, s) {asyncEnd();});
+}
+
+void nop(_) {}
+
+void callFunc(message) {
+ message[0](message[1], message[2]);
+}
« no previous file with comments | « sdk/lib/_internal/compiler/js_lib/isolate_helper.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698