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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/include/dart_api.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "include/dart_api.h"
6
7 #include "vm/unit_test.h"
8
9 // Custom Isolate Test.
10 //
11 // This mid-size test uses the Dart Embedding Api to create a custom
12 // isolate abstraction. Instead of having a dedicated thread for each
13 // isolate, as is the case normally, this implementation shares a
14 // single thread among the isolates using an event queue.
15
16 namespace dart {
17
18 #if defined(TARGET_ARCH_IA32) // only ia32 can run execution tests.
19
20 static void native_echo(Dart_NativeArguments args);
21 static void CustomIsolateImpl_start(Dart_NativeArguments args);
22 static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc);
23
24
25 static const char* kCustomIsolateScriptChars =
26 "class GlobalsHack {\n"
27 " static ReceivePort _receivePort;\n"
28 "}\n"
29 "\n"
30 "ReceivePort get receivePort() {\n"
31 " return GlobalsHack._receivePort;\n"
32 "}\n"
33 "\n"
34 "echo(arg) native \"native_echo\";\n"
35 "\n"
36 "class CustomIsolateImpl implements CustomIsolate {\n"
37 " CustomIsolateImpl(String entry) : _entry = entry{\n"
38 " echo('Constructing isolate');\n"
39 " }\n"
40 "\n"
41 " Future<SendPort> spawn() {\n"
42 " Completer<SendPort> completer = new Completer<SendPort>();"
43 " SendPort port = _start(_entry);"
44 " completer.complete(port);"
45 " return completer.future;"
46 " }"
47 "\n"
48 " static SendPort _start(entry)\n"
49 " native \"CustomIsolateImpl_start\";"
50 "\n"
51 " String _entry;\n"
52 "}\n"
53 "\n"
54 "interface CustomIsolate factory CustomIsolateImpl {\n"
55 " CustomIsolate(String entry);\n"
56 "\n"
57 " Future<SendPort> spawn();\n"
58 "}\n"
59 "\n"
60 "isolateMain() {\n"
61 " echo('Running isolateMain');\n"
62 " receivePort.receive((message, SendPort replyTo) {\n"
63 " echo('Received: ' + message);\n"
64 " replyTo.send((message + 1), null);\n"
65 " });\n"
66 "}\n"
67 "\n"
68 "main() {\n"
69 " Isolate isolate = new CustomIsolate(\"isolateMain\");\n"
70 " isolate.spawn().then((SendPort port) {\n"
71 " port.call(42).receive((message, replyTo) {\n"
72 " echo('Received: ' + message);\n"
73 " });\n"
74 " });\n"
75 " return 'success';\n"
76 "}";
77
78
79 // An entry in our event queue.
80 class Event {
81 protected:
82 Event() : next_(NULL) {}
83
84 public:
85 virtual ~Event() {}
86 virtual void Process() = 0;
87
88 private:
89 friend class EventQueue;
90 Event* next_;
91 };
92
93
94 // Start an isolate.
95 class StartEvent : public Event {
96 public:
97 StartEvent(Dart_Isolate isolate, const char* main, Dart_Port port)
98 : isolate_(isolate), main_(main), port_(port) {}
99
100 virtual void Process();
101 private:
102 Dart_Isolate isolate_;
103 const char* main_;
104 Dart_Port port_;
105 };
106
107
108 void StartEvent::Process() {
109 OS::Print(">> StartEvent with isolate(%p)--\n", isolate_);
110 Dart_EnterIsolate(isolate_);
111 Dart_EnterScope();
112 Dart_Handle result;
113
114 // Reload all the test classes here.
115 //
116 // TODO(turnidge): Use the create isolate callback instead?
117 Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
118 NativeLookup);
119 EXPECT_VALID(lib);
120
121 Dart_Handle core_lib = Dart_LookupLibrary(Dart_NewString("dart:coreimpl"));
122 EXPECT_VALID(core_lib);
123
124 Dart_Handle rp_args[1];
125 rp_args[0] = Dart_NewInteger(port_);
126 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
127 Dart_NewString("ReceivePortImpl"),
128 Dart_NewString("create_"),
129 1,
130 rp_args);
131 EXPECT_VALID(recv_port);
132
133 // TODO(turnidge): Provide a way to set a top-level variable from
134 // the dart embedding api.
135 Dart_Handle hidden = Dart_GetClass(lib, Dart_NewString("GlobalsHack"));
136 EXPECT_VALID(hidden);
137 result = Dart_SetStaticField(hidden, Dart_NewString("_receivePort"),
138 recv_port);
139 EXPECT_VALID(result);
140
141 result = Dart_InvokeStatic(lib,
142 Dart_NewString(""),
143 Dart_NewString(main_),
144 0,
145 NULL);
146 EXPECT_VALID(result);
147 free(const_cast<char*>(main_));
148 main_ = NULL;
149
150 Dart_ExitScope();
151 Dart_ExitIsolate();
152 }
153
154
155 // Shutdown an isolate.
156 class ShutdownEvent : public Event {
157 public:
158 explicit ShutdownEvent(Dart_Isolate isolate) : isolate_(isolate) {}
159
160 virtual void Process();
161 private:
162 Dart_Isolate isolate_;
163 };
164
165
166 void ShutdownEvent::Process() {
167 OS::Print("<< ShutdownEvent with isolate(%p)--\n", isolate_);
168 Dart_EnterIsolate(isolate_);
169 Dart_ShutdownIsolate();
170 }
171
172
173 // Deliver a message to an isolate.
174 class MessageEvent : public Event {
175 public:
176 MessageEvent(Dart_Isolate isolate, Dart_Port dest, Dart_Port reply,
177 Dart_Message msg)
178 : isolate_(isolate), dest_(dest), reply_(reply), msg_(msg) {}
179
180 ~MessageEvent() {
181 free(msg_);
182 msg_ = NULL;
183 }
184
185 virtual void Process();
186 private:
187 Dart_Isolate isolate_;
188 Dart_Port dest_;
189 Dart_Port reply_;
190 Dart_Message msg_;
191 };
192
193
194 void MessageEvent::Process() {
195 OS::Print("$$ MessageEvent with dest port %lld--\n", dest_);
196 Dart_EnterIsolate(isolate_);
197 Dart_EnterScope();
198
199 Dart_Handle result = Dart_HandleMessage(dest_, reply_, msg_);
200 EXPECT_VALID(result);
201
202 Dart_ExitScope();
203 Dart_ExitIsolate();
204 }
205
206
207 // A simple event queue for our test.
208 class EventQueue {
209 public:
210 EventQueue() {
211 head_ = NULL;
212 }
213
214 void Add(Event* event) {
215 if (head_ == NULL) {
216 head_ = event;
217 tail_ = event;
218 } else {
219 tail_->next_ = event;
220 tail_ = event;
221 }
222 }
223
224 Event* Get() {
225 if (head_ == NULL) {
226 return NULL;
227 }
228 Event* tmp = head_;
229 head_ = head_->next_;
230 if (head_ == NULL) {
231 tail_ = NULL;
232 }
233
234 return tmp;
235 }
236
237 private:
238 Event* head_;
239 Event* tail_;
240 };
241 EventQueue* event_queue;
242
243
244 static void CreatePort(Dart_Isolate isolate,
245 Dart_Port port) {
246 OS::Print("-- Adding port (%llu) -> isolate (%p) --\n",
247 port, isolate);
248 }
249
250
251 static bool PostMessage(Dart_Isolate dest_isolate,
252 Dart_Port dest_port,
253 Dart_Port reply_port,
254 Dart_Message message) {
255 OS::Print("-- Posting message dest(%d) reply(%d) --\n",
256 dest_port, reply_port);
257 OS::Print("-- Adding MessageEvent to queue --\n");
258 event_queue->Add(
259 new MessageEvent(dest_isolate, dest_port, reply_port, message));
260 }
261
262
263 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
264 Dart_Port port) {
265 OS::Print("-- Closing port (%lld) --\n", port);
266 Dart_Isolate current = Dart_CurrentIsolate();
267 if (current) {
268 Dart_ExitIsolate();
269 }
270 Dart_EnterIsolate(isolate);
271 if (!Dart_IsolateHasActivePorts()) {
272 OS::Print("-- Adding ShutdownEvent to queue --\n");
273 event_queue->Add(new ShutdownEvent(isolate));
274 }
275 Dart_ExitIsolate();
276 if (current) {
277 Dart_EnterIsolate(current);
278 }
279 }
280
281
282 static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc) {
283 const char* name_str = NULL;
284 EXPECT(Dart_IsString(name));
285 EXPECT_VALID(Dart_StringToCString(name, &name_str));
286 if (strcmp(name_str, "native_echo") == 0) {
287 return &native_echo;
288 } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) {
289 return &CustomIsolateImpl_start;
290 }
291 return NULL;
292 }
293
294
295 const char* saved_echo = NULL;
296 static void native_echo(Dart_NativeArguments args) {
297 Dart_EnterScope();
298 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
299 Dart_Handle toString = Dart_ToString(arg);
300 EXPECT_VALID(toString);
301 const char* c_str = NULL;
302 EXPECT_VALID(Dart_StringToCString(toString, &c_str));
303 if (saved_echo) {
304 free(const_cast<char*>(saved_echo));
305 }
306 saved_echo = strdup(c_str);
307 OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
308 Dart_ExitScope();
309 }
310
311
312 static void CustomIsolateImpl_start(Dart_NativeArguments args) {
313 OS::Print("-- Enter: CustomIsolateImpl_start --\n");
314 Dart_Handle result;
315
316 // We would probably want to pass in the this pointer too, so we
317 // could associate the CustomIsolateImpl instance with the
318 // Dart_Isolate by storing it in a native field.
319 EXPECT_EQ(1, Dart_GetNativeArgumentCount(args));
320 Dart_Handle param = Dart_GetNativeArgument(args, 0);
321 EXPECT_VALID(param);
322 EXPECT(Dart_IsString(param));
323 const char* isolate_main = NULL;
324 EXPECT_VALID(Dart_StringToCString(param, &isolate_main));
325 isolate_main = strdup(isolate_main);
326
327 // Save current isolate.
328 Dart_Isolate saved_isolate = Dart_CurrentIsolate();
329 Dart_ExitIsolate();
330
331 // Create a new Dart_Isolate and store it in the CustomIsolateImpl.
332 Dart_Isolate new_isolate = Dart_CreateIsolate(NULL, NULL);
333 Dart_SetMessageCallbacks(&CreatePort, &PostMessage, &ClosePort);
334 Dart_Port port = Dart_CreatePort();
335
336 OS::Print("-- Adding StartEvent to queue --\n");
337 event_queue->Add(new StartEvent(new_isolate, isolate_main, port));
338
339 // Restore the original isolate.
340 Dart_ExitIsolate();
341 Dart_EnterIsolate(saved_isolate);
342 Dart_EnterScope();
343
344 Dart_Handle lib = Dart_LookupLibrary(Dart_NewString("dart:coreimpl"));
345 EXPECT_VALID(lib);
346
347 Dart_Handle sp_args[1];
348 sp_args[0] = Dart_NewInteger(port);
349 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
350 Dart_NewString("SendPortImpl"),
351 Dart_NewString("create_"),
352 1,
353 sp_args);
354 EXPECT_VALID(send_port);
355 Dart_SetReturnValue(args, send_port);
356
357 OS::Print("-- Exit: CustomIsolateImpl_start --\n");
358 Dart_ExitScope();
359 }
360
361
362 UNIT_TEST_CASE(CustomIsolates) {
363 event_queue = new EventQueue();
364
365 Dart_Isolate main_isolate = Dart_CreateIsolate(NULL, NULL);
366 Dart_SetMessageCallbacks(&CreatePort, &PostMessage, &ClosePort);
367 Dart_EnterScope();
368 Dart_Handle result;
369
370 // Create a test library.
371 Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
372 NativeLookup);
373 EXPECT_VALID(lib);
374
375 // Run main.
376 result = Dart_InvokeStatic(lib,
377 Dart_NewString(""),
378 Dart_NewString("main"),
379 0,
380 NULL);
381 EXPECT_VALID(result);
382 EXPECT(Dart_IsString(result));
383 const char* result_str = NULL;
384 EXPECT_VALID(Dart_StringToCString(result, &result_str));
385 EXPECT_STREQ("success", result_str);
386
387 Dart_ExitScope();
388 Dart_ExitIsolate();
389
390 OS::Print("-- Starting event loop --\n");
391 Event* event = event_queue->Get();
392 while (event) {
393 event->Process();
394 delete event;
395 event = event_queue->Get();
396 }
397 OS::Print("-- Finished event loop --\n");
398 EXPECT_STREQ("Received: 43", saved_echo);
399 free(const_cast<char*>(saved_echo));
400
401 delete event_queue;
402 }
403
404 #endif // TARGET_ARCH_IA32.
405
406 } // namespace dart
OLDNEW
« 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