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

Unified Diff: runtime/vm/custom_isolate_test.cc

Issue 8588040: Add a mid-sized integration test for the Dart Embedding Api which (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years, 1 month 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 | « runtime/include/dart_api.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/custom_isolate_test.cc
===================================================================
--- runtime/vm/custom_isolate_test.cc (revision 0)
+++ runtime/vm/custom_isolate_test.cc (revision 0)
@@ -0,0 +1,406 @@
+// Copyright (c) 2011, 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.
+
+#include "include/dart_api.h"
+
+#include "vm/unit_test.h"
+
+// Custom Isolate Test.
+//
+// This mid-size test uses the Dart Embedding Api to create a custom
+// isolate abstraction. Instead of having a dedicated thread for each
+// isolate, as is the case normally, this implementation shares a
+// single thread among the isolates using an event queue.
+
+namespace dart {
+
+#if defined(TARGET_ARCH_IA32) // only ia32 can run execution tests.
+
+static void native_echo(Dart_NativeArguments args);
+static void CustomIsolateImpl_start(Dart_NativeArguments args);
+static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc);
+
+
+static const char* kCustomIsolateScriptChars =
+ "class GlobalsHack {\n"
+ " static ReceivePort _receivePort;\n"
+ "}\n"
+ "\n"
+ "ReceivePort get receivePort() {\n"
+ " return GlobalsHack._receivePort;\n"
+ "}\n"
+ "\n"
+ "echo(arg) native \"native_echo\";\n"
+ "\n"
+ "class CustomIsolateImpl implements CustomIsolate {\n"
+ " CustomIsolateImpl(String entry) : _entry = entry{\n"
+ " echo('Constructing isolate');\n"
+ " }\n"
+ "\n"
+ " Future<SendPort> spawn() {\n"
+ " Completer<SendPort> completer = new Completer<SendPort>();"
+ " SendPort port = _start(_entry);"
+ " completer.complete(port);"
+ " return completer.future;"
+ " }"
+ "\n"
+ " static SendPort _start(entry)\n"
+ " native \"CustomIsolateImpl_start\";"
+ "\n"
+ " String _entry;\n"
+ "}\n"
+ "\n"
+ "interface CustomIsolate factory CustomIsolateImpl {\n"
+ " CustomIsolate(String entry);\n"
+ "\n"
+ " Future<SendPort> spawn();\n"
+ "}\n"
+ "\n"
+ "isolateMain() {\n"
+ " echo('Running isolateMain');\n"
+ " receivePort.receive((message, SendPort replyTo) {\n"
+ " echo('Received: ' + message);\n"
+ " replyTo.send((message + 1), null);\n"
+ " });\n"
+ "}\n"
+ "\n"
+ "main() {\n"
+ " Isolate isolate = new CustomIsolate(\"isolateMain\");\n"
+ " isolate.spawn().then((SendPort port) {\n"
+ " port.call(42).receive((message, replyTo) {\n"
+ " echo('Received: ' + message);\n"
+ " });\n"
+ " });\n"
+ " return 'success';\n"
+ "}";
+
+
+// An entry in our event queue.
+class Event {
+ protected:
+ Event() : next_(NULL) {}
+
+ public:
+ virtual ~Event() {}
+ virtual void Process() = 0;
+
+ private:
+ friend class EventQueue;
+ Event* next_;
+};
+
+
+// Start an isolate.
+class StartEvent : public Event {
+ public:
+ StartEvent(Dart_Isolate isolate, const char* main, Dart_Port port)
+ : isolate_(isolate), main_(main), port_(port) {}
+
+ virtual void Process();
+ private:
+ Dart_Isolate isolate_;
+ const char* main_;
+ Dart_Port port_;
+};
+
+
+void StartEvent::Process() {
+ OS::Print(">> StartEvent with isolate(%p)--\n", isolate_);
+ Dart_EnterIsolate(isolate_);
+ Dart_EnterScope();
+ Dart_Handle result;
+
+ // Reload all the test classes here.
+ //
+ // TODO(turnidge): Use the create isolate callback instead?
+ Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
+ NativeLookup);
+ EXPECT_VALID(lib);
+
+ Dart_Handle core_lib = Dart_LookupLibrary(Dart_NewString("dart:coreimpl"));
+ EXPECT_VALID(core_lib);
+
+ Dart_Handle rp_args[1];
+ rp_args[0] = Dart_NewInteger(port_);
+ Dart_Handle recv_port = Dart_InvokeStatic(core_lib,
Anton Muhin 2011/11/18 14:56:42 shouldn't we have an embedder API for this?
turnidge 2011/11/21 18:19:08 I've added Dart_NewSendPort and Dart_NewReceivePor
+ Dart_NewString("ReceivePortImpl"),
+ Dart_NewString("create_"),
+ 1,
+ rp_args);
+ EXPECT_VALID(recv_port);
+
+ // TODO(turnidge): Provide a way to set a top-level variable from
+ // the dart embedding api.
+ Dart_Handle hidden = Dart_GetClass(lib, Dart_NewString("GlobalsHack"));
+ EXPECT_VALID(hidden);
+ result = Dart_SetStaticField(hidden, Dart_NewString("_receivePort"),
+ recv_port);
+ EXPECT_VALID(result);
+
+ result = Dart_InvokeStatic(lib,
+ Dart_NewString(""),
+ Dart_NewString(main_),
+ 0,
+ NULL);
+ EXPECT_VALID(result);
+ free(const_cast<char*>(main_));
+ main_ = NULL;
+
+ Dart_ExitScope();
+ Dart_ExitIsolate();
+}
+
+
+// Shutdown an isolate.
+class ShutdownEvent : public Event {
+ public:
+ explicit ShutdownEvent(Dart_Isolate isolate) : isolate_(isolate) {}
+
+ virtual void Process();
+ private:
+ Dart_Isolate isolate_;
+};
+
+
+void ShutdownEvent::Process() {
+ OS::Print("<< ShutdownEvent with isolate(%p)--\n", isolate_);
+ Dart_EnterIsolate(isolate_);
+ Dart_ShutdownIsolate();
+}
+
+
+// Deliver a message to an isolate.
+class MessageEvent : public Event {
+ public:
+ MessageEvent(Dart_Isolate isolate, Dart_Port dest, Dart_Port reply,
+ Dart_Message msg)
+ : isolate_(isolate), dest_(dest), reply_(reply), msg_(msg) {}
+
+ ~MessageEvent() {
+ free(msg_);
+ msg_ = NULL;
+ }
+
+ virtual void Process();
+ private:
+ Dart_Isolate isolate_;
+ Dart_Port dest_;
+ Dart_Port reply_;
+ Dart_Message msg_;
+};
+
+
+void MessageEvent::Process() {
+ OS::Print("$$ MessageEvent with dest port %lld--\n", dest_);
+ Dart_EnterIsolate(isolate_);
+ Dart_EnterScope();
+
+ Dart_Handle result = Dart_HandleMessage(dest_, reply_, msg_);
+ EXPECT_VALID(result);
+
+ Dart_ExitScope();
+ Dart_ExitIsolate();
+}
+
+
+// A simple event queue for our test.
+class EventQueue {
+ public:
+ EventQueue() {
+ head_ = NULL;
+ }
+
+ void Add(Event* event) {
+ if (head_ == NULL) {
+ head_ = event;
+ tail_ = event;
+ } else {
+ tail_->next_ = event;
+ tail_ = event;
+ }
+ }
+
+ Event* Get() {
+ if (head_ == NULL) {
+ return NULL;
+ }
+ Event* tmp = head_;
+ head_ = head_->next_;
+ if (head_ == NULL) {
+ tail_ = NULL;
+ }
+
+ return tmp;
+ }
+
+ private:
+ Event* head_;
+ Event* tail_;
+};
+EventQueue* event_queue;
+
+
+static void CreatePort(Dart_Isolate isolate,
+ Dart_Port port) {
+ OS::Print("-- Adding port (%llu) -> isolate (%p) --\n",
+ port, isolate);
+}
+
+
+static bool PostMessage(Dart_Isolate dest_isolate,
+ Dart_Port dest_port,
+ Dart_Port reply_port,
+ Dart_Message message) {
+ OS::Print("-- Posting message dest(%d) reply(%d) --\n",
+ dest_port, reply_port);
+ OS::Print("-- Adding MessageEvent to queue --\n");
+ event_queue->Add(
+ new MessageEvent(dest_isolate, dest_port, reply_port, message));
+}
+
+
+static void ClosePort(Dart_Isolate isolate,
Anton Muhin 2011/11/18 14:56:42 do we need port create/close callbacks? what's th
turnidge 2011/11/21 18:19:08 Got rid of the create port callbacks. The close p
+ Dart_Port port) {
+ OS::Print("-- Closing port (%lld) --\n", port);
+ Dart_Isolate current = Dart_CurrentIsolate();
+ if (current) {
+ Dart_ExitIsolate();
+ }
+ Dart_EnterIsolate(isolate);
+ if (!Dart_IsolateHasActivePorts()) {
+ OS::Print("-- Adding ShutdownEvent to queue --\n");
+ event_queue->Add(new ShutdownEvent(isolate));
+ }
+ Dart_ExitIsolate();
+ if (current) {
+ Dart_EnterIsolate(current);
+ }
+}
+
+
+static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc) {
+ const char* name_str = NULL;
+ EXPECT(Dart_IsString(name));
+ EXPECT_VALID(Dart_StringToCString(name, &name_str));
+ if (strcmp(name_str, "native_echo") == 0) {
+ return &native_echo;
+ } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) {
+ return &CustomIsolateImpl_start;
+ }
+ return NULL;
+}
+
+
+const char* saved_echo = NULL;
+static void native_echo(Dart_NativeArguments args) {
+ Dart_EnterScope();
+ Dart_Handle arg = Dart_GetNativeArgument(args, 0);
+ Dart_Handle toString = Dart_ToString(arg);
+ EXPECT_VALID(toString);
+ const char* c_str = NULL;
+ EXPECT_VALID(Dart_StringToCString(toString, &c_str));
+ if (saved_echo) {
+ free(const_cast<char*>(saved_echo));
+ }
+ saved_echo = strdup(c_str);
+ OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
+ Dart_ExitScope();
+}
+
+
+static void CustomIsolateImpl_start(Dart_NativeArguments args) {
+ OS::Print("-- Enter: CustomIsolateImpl_start --\n");
+ Dart_Handle result;
+
+ // We would probably want to pass in the this pointer too, so we
+ // could associate the CustomIsolateImpl instance with the
+ // Dart_Isolate by storing it in a native field.
+ EXPECT_EQ(1, Dart_GetNativeArgumentCount(args));
+ Dart_Handle param = Dart_GetNativeArgument(args, 0);
+ EXPECT_VALID(param);
+ EXPECT(Dart_IsString(param));
+ const char* isolate_main = NULL;
+ EXPECT_VALID(Dart_StringToCString(param, &isolate_main));
+ isolate_main = strdup(isolate_main);
+
+ // Save current isolate.
+ Dart_Isolate saved_isolate = Dart_CurrentIsolate();
+ Dart_ExitIsolate();
+
+ // Create a new Dart_Isolate and store it in the CustomIsolateImpl.
+ Dart_Isolate new_isolate = Dart_CreateIsolate(NULL, NULL);
+ Dart_SetMessageCallbacks(&CreatePort, &PostMessage, &ClosePort);
+ Dart_Port port = Dart_CreatePort();
+
+ OS::Print("-- Adding StartEvent to queue --\n");
+ event_queue->Add(new StartEvent(new_isolate, isolate_main, port));
+
+ // Restore the original isolate.
+ Dart_ExitIsolate();
+ Dart_EnterIsolate(saved_isolate);
+ Dart_EnterScope();
+
+ Dart_Handle lib = Dart_LookupLibrary(Dart_NewString("dart:coreimpl"));
+ EXPECT_VALID(lib);
+
+ Dart_Handle sp_args[1];
+ sp_args[0] = Dart_NewInteger(port);
+ Dart_Handle send_port = Dart_InvokeStatic(lib,
Anton Muhin 2011/11/18 14:56:42 ditto here for embedder's API. Overall, cannot Da
turnidge 2011/11/21 18:19:08 Intriguing idea. I will discuss with vm team when
turnidge 2011/11/23 01:52:46 Ok, I've played around a bit with this idea. I ca
+ Dart_NewString("SendPortImpl"),
+ Dart_NewString("create_"),
+ 1,
+ sp_args);
+ EXPECT_VALID(send_port);
+ Dart_SetReturnValue(args, send_port);
+
+ OS::Print("-- Exit: CustomIsolateImpl_start --\n");
+ Dart_ExitScope();
+}
+
+
+UNIT_TEST_CASE(CustomIsolates) {
+ event_queue = new EventQueue();
+
+ Dart_Isolate main_isolate = Dart_CreateIsolate(NULL, NULL);
+ Dart_SetMessageCallbacks(&CreatePort, &PostMessage, &ClosePort);
+ Dart_EnterScope();
+ Dart_Handle result;
+
+ // Create a test library.
+ Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
+ NativeLookup);
+ EXPECT_VALID(lib);
+
+ // Run main.
+ result = Dart_InvokeStatic(lib,
+ Dart_NewString(""),
+ Dart_NewString("main"),
+ 0,
+ NULL);
+ EXPECT_VALID(result);
+ EXPECT(Dart_IsString(result));
+ const char* result_str = NULL;
+ EXPECT_VALID(Dart_StringToCString(result, &result_str));
+ EXPECT_STREQ("success", result_str);
+
+ Dart_ExitScope();
+ Dart_ExitIsolate();
+
+ OS::Print("-- Starting event loop --\n");
+ Event* event = event_queue->Get();
+ while (event) {
+ event->Process();
+ delete event;
+ event = event_queue->Get();
+ }
+ OS::Print("-- Finished event loop --\n");
+ EXPECT_STREQ("Received: 43", saved_echo);
+ free(const_cast<char*>(saved_echo));
+
+ delete event_queue;
+}
+
+#endif // TARGET_ARCH_IA32.
+
+} // namespace dart
« no previous file with comments | « runtime/include/dart_api.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698