Index: tests/isolate/remote_unittest_helper.dart |
diff --git a/tests/isolate/remote_unittest_helper.dart b/tests/isolate/remote_unittest_helper.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..68704ce78cd2cd348e241eceece886823b0a57a4 |
--- /dev/null |
+++ b/tests/isolate/remote_unittest_helper.dart |
@@ -0,0 +1,125 @@ |
+// Copyright (c) 2013, 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. |
+ |
+// Helper functions and classes for running a set of unittests in a |
+// remote isolate. |
+// Used to test Isolate.spawn because dartium/drt does not allow it in the DOM |
+// isolate. |
+ |
+import "dart:isolate"; |
+import "package:unittest/unittest.dart"; |
+import "dart:mirrors"; |
+ |
+/** |
+ * Use this function at the beginning of the main method: |
+ * |
+ * void main([args, port]) { |
+ * if (testRemote(main, port)) return; |
+ * // the usual test. |
+ * } |
+ */ |
siva
2013/11/14 17:21:08
I find this a little tricky, you probably did it t
Lasse Reichstein Nielsen
2013/11/15 14:57:45
Minimizing changes was a goal, yes :) Didn't succe
|
+bool testRemote(Function main, SendPort port) { |
+ if (port == null) { |
+ return new LocalTests().run(main); |
+ } else { |
+ unittestConfiguration = new RemoteConfiguration(port); |
+ return false; |
+ } |
+} |
+ |
+ |
+class LocalTests { |
+ final ReceivePort _port = new ReceivePort(); |
+ final Map<String, Function> _testBody = new Map<String, Function>(); |
+ |
+ bool run(Function main) { |
+ ClosureMirror closure = reflect(main); |
+ LibraryMirror library = closure.function.owner; |
+ try { |
+ Isolate.spawnUri(library.uri, null, _port.sendPort); |
+ _port.listen(remoteAction); |
+ return true; |
+ } catch (e) { |
+ // spawnUri is only supported by dart2js if web workers are available. |
+ // If the spawnUri fails, run the tests locally instead, since we are |
+ // not in a browser anyway. |
+ return false; |
+ } |
+ } |
+ |
+ void remoteAction(message) { |
+ switch (message[0]) { |
+ case "testStart": |
+ String name = message[1]; |
+ test(name, () { |
+ _testBody[name] = expectAsync2((result, message) { |
+ if (result == FAIL) { |
+ fail(message); |
+ } else if (result == ERROR) { |
+ throw message; |
+ } |
+ _testBody.remove(name); |
+ }); |
+ }); |
+ break; |
+ case "testResult": |
+ String name = message[1]; |
+ Function completer = _testBody[name]; |
+ completer(message[2], message[3]); |
+ break; |
+ case "testResultChanged": |
+ throw new UnsupportedError("result change after the fact?"); |
+ case "logMessage": |
+ break; // Ignore. |
+ case "summary": |
+ throw message[1]; // Uncaught error. |
+ case "done": |
+ _port.close(); |
+ break; |
+ } |
+ } |
+} |
+ |
+ |
+class RemoteConfiguration implements Configuration { |
+ final SendPort _port; |
+ Duration timeout = const Duration(minutes: 2); |
+ |
+ RemoteConfiguration(this._port); |
+ |
+ bool get autoStart => true; |
+ |
+ void onInit() { } |
+ |
+ void onStart() { } |
+ |
+ void onTestStart(TestCase testCase) { |
+ _port.send(["testStart", testCase.description]); |
+ } |
+ |
+ void onTestResult(TestCase testCase) { |
+ _port.send(["testResult", testCase.description, |
+ testCase.result, testCase.message]); |
+ } |
+ |
+ void onTestResultChanged(TestCase testCase) { |
+ _port.send(["testResultChanged", testCase.description, |
+ testCase.result, testCase.message]); |
+ } |
+ |
+ void onLogMessage(TestCase testCase, String message) { |
+ _port.send(["logMessage", testCase.description, message]); |
+ } |
+ |
+ void onDone(bool success) { |
+ _port.send(["done", success]); |
+ } |
+ |
+ void onSummary(int passed, int failed, int errors, List<TestCase> results, |
+ String uncaughtError) { |
+ if (uncaughtError != null) { |
+ _port.send(["summary", uncaughtError]); |
+ } |
+ } |
+} |