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

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 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/lib/isolate.dart ('k') | runtime/vm/dart.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>();\n"
43 " SendPort port = _start(_entry);\n"
44 " completer.complete(port);\n"
45 " return completer.future;\n"
46 " }\n"
47 "\n"
48 " static SendPort _start(entry)\n"
49 " native \"CustomIsolateImpl_start\";\n"
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 "}\n";
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 virtual bool IsShutdownEvent(Dart_Isolate isolate) {
89 return false;
90 }
91 virtual bool IsMessageEvent(Dart_Isolate isolate, Dart_Port port) {
92 return false;
93 }
94
95 private:
96 friend class EventQueue;
97 Event* next_;
98 };
99
100
101 // Start an isolate.
102 class StartEvent : public Event {
103 public:
104 StartEvent(Dart_Isolate isolate, const char* main)
105 : isolate_(isolate), main_(main) {}
106
107 virtual void Process();
108 private:
109 Dart_Isolate isolate_;
110 const char* main_;
111 };
112
113
114 void StartEvent::Process() {
115 OS::Print(">> StartEvent with isolate(%p)--\n", isolate_);
116 Dart_EnterIsolate(isolate_);
117 Dart_EnterScope();
118 Dart_Handle result;
119
120 // Reload all the test classes here.
121 //
122 // TODO(turnidge): Use the create isolate callback instead?
123 Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
124 NativeLookup);
125 EXPECT_VALID(lib);
126 EXPECT_VALID(Dart_CompileAll());
127
128 Dart_Handle recv_port = Dart_GetReceivePort(Dart_GetMainPortId());
129 EXPECT_VALID(recv_port);
130
131 // TODO(turnidge): Provide a way to set a top-level variable from
132 // the dart embedding api.
133 Dart_Handle hidden = Dart_GetClass(lib, Dart_NewString("GlobalsHack"));
134 EXPECT_VALID(hidden);
135 result = Dart_SetStaticField(hidden, Dart_NewString("_receivePort"),
136 recv_port);
137 EXPECT_VALID(result);
138
139 result = Dart_InvokeStatic(lib,
140 Dart_NewString(""),
141 Dart_NewString(main_),
142 0,
143 NULL);
144 EXPECT_VALID(result);
145 free(const_cast<char*>(main_));
146 main_ = NULL;
147
148 Dart_ExitScope();
149 Dart_ExitIsolate();
150 }
151
152
153 // Shutdown an isolate.
154 class ShutdownEvent : public Event {
155 public:
156 explicit ShutdownEvent(Dart_Isolate isolate) : isolate_(isolate) {}
157
158 virtual bool IsShutdownEvent(Dart_Isolate isolate) {
159 return isolate == isolate_;
160 }
161
162 virtual void Process();
163 private:
164 Dart_Isolate isolate_;
165 };
166
167
168 void ShutdownEvent::Process() {
169 OS::Print("<< ShutdownEvent with isolate(%p)--\n", isolate_);
170 Dart_EnterIsolate(isolate_);
171 Dart_ShutdownIsolate();
172 }
173
174
175 // Deliver a message to an isolate.
176 class MessageEvent : public Event {
177 public:
178 MessageEvent(Dart_Isolate isolate, Dart_Port dest, Dart_Port reply,
179 Dart_Message msg)
180 : isolate_(isolate), dest_(dest), reply_(reply), msg_(msg) {}
181
182 ~MessageEvent() {
183 free(msg_);
184 msg_ = NULL;
185 }
186
187 virtual bool IsMessageEvent(Dart_Isolate isolate, Dart_Port port) {
188 return isolate == isolate_ && (port == kCloseAllPorts || port == dest_);
189 }
190
191 virtual void Process();
192 private:
193 Dart_Isolate isolate_;
194 Dart_Port dest_;
195 Dart_Port reply_;
196 Dart_Message msg_;
197 };
198
199
200 void MessageEvent::Process() {
201 OS::Print("$$ MessageEvent with dest port %lld--\n", dest_);
202 Dart_EnterIsolate(isolate_);
203 Dart_EnterScope();
204
205 Dart_Handle result = Dart_HandleMessage(dest_, reply_, msg_);
206 EXPECT_VALID(result);
207
208 Dart_ExitScope();
209 Dart_ExitIsolate();
210 }
211
212
213 // A simple event queue for our test.
214 class EventQueue {
215 public:
216 EventQueue() {
217 head_ = NULL;
218 }
219
220 void Add(Event* event) {
221 if (head_ == NULL) {
222 head_ = event;
223 tail_ = event;
224 } else {
225 tail_->next_ = event;
226 tail_ = event;
227 }
228 }
229
230 Event* Get() {
231 if (head_ == NULL) {
232 return NULL;
233 }
234 Event* tmp = head_;
235 head_ = head_->next_;
236 if (head_ == NULL) {
237 tail_ = NULL;
238 }
239
240 return tmp;
241 }
242
243 void ClosePort(Dart_Isolate isolate, Dart_Port port) {
244 Event* cur = head_;
245 Event* prev = NULL;
246 while (cur != NULL) {
247 Event* next = cur->next_;
248 if (cur->IsMessageEvent(isolate, port)) {
249 // Remove matching event.
250 if (prev != NULL) {
251 prev->next_ = next;
252 } else {
253 head_ = next;
254 }
255 delete cur;
256 } else {
257 // Advance.
258 prev = cur;
259 }
260 cur = next;
261 }
262 tail_ = prev;
263 }
264
265 private:
266 Event* head_;
267 Event* tail_;
268 };
269 EventQueue* event_queue;
270 Event* current_event;
271
272 static bool PostMessage(Dart_Isolate dest_isolate,
273 Dart_Port dest_port,
274 Dart_Port reply_port,
275 Dart_Message message) {
276 OS::Print("-- Posting message dest(%d) reply(%d) --\n",
277 dest_port, reply_port);
278 OS::Print("-- Adding MessageEvent to queue --\n");
279 event_queue->Add(
280 new MessageEvent(dest_isolate, dest_port, reply_port, message));
281 }
282
283
284 static void ClosePort(Dart_Isolate isolate,
285 Dart_Port port) {
286 OS::Print("-- Closing port (%lld) for isolate(%p) --\n",
287 port, isolate);
288
289 // Remove any pending events for the isolate/port.
290 event_queue->ClosePort(isolate, port);
291
292 Dart_Isolate current = Dart_CurrentIsolate();
293 if (current) {
294 Dart_ExitIsolate();
295 }
296 Dart_EnterIsolate(isolate);
297 if (!Dart_HasLivePorts() &&
298 (current_event == NULL || !current_event->IsShutdownEvent(isolate))) {
299 OS::Print("-- Adding ShutdownEvent to queue --\n");
300 event_queue->Add(new ShutdownEvent(isolate));
301 }
302 Dart_ExitIsolate();
303 if (current) {
304 Dart_EnterIsolate(current);
305 }
306 }
307
308
309 static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc) {
310 const char* name_str = NULL;
311 EXPECT(Dart_IsString(name));
312 EXPECT_VALID(Dart_StringToCString(name, &name_str));
313 if (strcmp(name_str, "native_echo") == 0) {
314 return &native_echo;
315 } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) {
316 return &CustomIsolateImpl_start;
317 }
318 return NULL;
319 }
320
321
322 const char* saved_echo = NULL;
323 static void native_echo(Dart_NativeArguments args) {
324 Dart_EnterScope();
325 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
326 Dart_Handle toString = Dart_ToString(arg);
327 EXPECT_VALID(toString);
328 const char* c_str = NULL;
329 EXPECT_VALID(Dart_StringToCString(toString, &c_str));
330 if (saved_echo) {
331 free(const_cast<char*>(saved_echo));
332 }
333 saved_echo = strdup(c_str);
334 OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
335 Dart_ExitScope();
336 }
337
338
339 static void CustomIsolateImpl_start(Dart_NativeArguments args) {
340 OS::Print("-- Enter: CustomIsolateImpl_start --\n");
341 Dart_Handle result;
342
343 // We would probably want to pass in the this pointer too, so we
344 // could associate the CustomIsolateImpl instance with the
345 // Dart_Isolate by storing it in a native field.
346 EXPECT_EQ(1, Dart_GetNativeArgumentCount(args));
347 Dart_Handle param = Dart_GetNativeArgument(args, 0);
348 EXPECT_VALID(param);
349 EXPECT(Dart_IsString(param));
350 const char* isolate_main = NULL;
351 EXPECT_VALID(Dart_StringToCString(param, &isolate_main));
352 isolate_main = strdup(isolate_main);
353
354 // Save current isolate.
355 Dart_Isolate saved_isolate = Dart_CurrentIsolate();
356 Dart_ExitIsolate();
357
358 // Create a new Dart_Isolate.
359 Dart_Isolate new_isolate = Dart_CreateIsolate(NULL, NULL);
360 Dart_SetMessageCallbacks(&PostMessage, &ClosePort);
361 Dart_Port new_port = Dart_GetMainPortId();
362
363 OS::Print("-- Adding StartEvent to queue --\n");
364 event_queue->Add(new StartEvent(new_isolate, isolate_main));
365
366 // Restore the original isolate.
367 Dart_ExitIsolate();
368 Dart_EnterIsolate(saved_isolate);
369 Dart_EnterScope();
370
371 Dart_Handle send_port = Dart_NewSendPort(new_port);
372 EXPECT_VALID(send_port);
373 Dart_SetReturnValue(args, send_port);
374
375 OS::Print("-- Exit: CustomIsolateImpl_start --\n");
376 Dart_ExitScope();
377 }
378
379
380 UNIT_TEST_CASE(CustomIsolates) {
381 event_queue = new EventQueue();
382 current_event = NULL;
383
384 Dart_Isolate main_isolate = Dart_CreateIsolate(NULL, NULL);
385 Dart_SetMessageCallbacks(&PostMessage, &ClosePort);
386 Dart_EnterScope();
387 Dart_Handle result;
388
389 // Create a test library.
390 Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars,
391 NativeLookup);
392 EXPECT_VALID(lib);
393
394 // Run main.
395 result = Dart_InvokeStatic(lib,
396 Dart_NewString(""),
397 Dart_NewString("main"),
398 0,
399 NULL);
400 EXPECT_VALID(result);
401 EXPECT(Dart_IsString(result));
402 const char* result_str = NULL;
403 EXPECT_VALID(Dart_StringToCString(result, &result_str));
404 EXPECT_STREQ("success", result_str);
405
406 Dart_ExitScope();
407 Dart_ExitIsolate();
408
409 OS::Print("-- Starting event loop --\n");
410 Event* event = event_queue->Get();
411 while (event) {
412 current_event = event;
413 event->Process();
414 current_event = NULL;
415 delete event;
416 event = event_queue->Get();
417 }
418 OS::Print("-- Finished event loop --\n");
419 EXPECT_STREQ("Received: 43", saved_echo);
420 free(const_cast<char*>(saved_echo));
421
422 delete event_queue;
423 }
424
425 #endif // TARGET_ARCH_IA32.
426
427 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/lib/isolate.dart ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698