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

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

Powered by Google App Engine
This is Rietveld 408576698