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

Side by Side Diff: runtime/vm/port_test.cc

Issue 8297004: Allow embedders to provide custom message delivery for an isolate. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years, 2 months 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
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/assert.h" 5 #include "vm/assert.h"
6 #include "vm/message_queue.h"
7 #include "vm/os.h"
6 #include "vm/port.h" 8 #include "vm/port.h"
7 #include "vm/unit_test.h" 9 #include "vm/unit_test.h"
8 10
9 namespace dart { 11 namespace dart {
10 12
11 TEST_CASE(Port) {
12 const char* msg_data = "Hallo Velo!";
13 13
14 intptr_t port1 = PortMap::CreatePort(); 14 // Intercept the post message callback and just store a copy of the message.
15 intptr_t port2 = PortMap::CreatePort(); 15 static const int kMaxSavedMsg = 80;
16 EXPECT(port1 != port2); 16 static char saved_msg[kMaxSavedMsg];
17 static bool MyPostMessageCallback(Dart_Isolate dest_isolate,
18 Dart_Port dest_port,
19 Dart_Port reply_port,
20 Dart_Message dart_message) {
21 const char* msg = reinterpret_cast<char*>(dart_message);
22 OS::SNPrint(saved_msg, kMaxSavedMsg, "%s", msg);
23 bool result = (strcmp(msg, "fail") != 0);
24 free(dart_message);
25 return result;
26 }
17 27
18 PortMessage* msg1 = new PortMessage(port1, 0, strdup(msg_data));
19 EXPECT_EQ(true, PortMap::PostMessage(msg1));
20 PortMessage* msg = PortMap::ReceiveMessage(10);
21 EXPECT_EQ(port1, msg->dest_id());
22 EXPECT_EQ(msg1, msg);
23 delete msg1;
24 28
25 msg1 = new PortMessage(port2, 0, strdup(msg_data)); 29 // Intercept the close port callback and remember which port was closed.
26 EXPECT_EQ(true, PortMap::PostMessage(msg1)); 30 static Dart_Port saved_port = 0;
27 msg = PortMap::ReceiveMessage(10); 31 static void MyClosePortCallback(Dart_Isolate dart_isolate,
28 EXPECT_EQ(port2, msg->dest_id()); 32 Dart_Port port) {
29 EXPECT_EQ(msg1, msg); 33 saved_port = port;
30 delete msg1; 34 }
35
36
37 static void InitPortMapTest() {
38 Dart_SetPostMessageCallback(&MyPostMessageCallback);
39 Dart_SetClosePortCallback(&MyClosePortCallback);
40 saved_port = 0;
41 saved_msg[0] = '\0';
42 }
43
44
45 TEST_CASE(PortMap_CreateAndCloseOnePort) {
46 InitPortMapTest();
47 intptr_t port = PortMap::CreatePort();
48 EXPECT_NE(0, port);
49 EXPECT(PortMap::IsActivePort(port));
50
51 PortMap::ClosePort(port);
52 EXPECT(!PortMap::IsActivePort(port));
53
54 // Embedder was notified of port closure.
55 EXPECT_EQ(port, saved_port);
56 }
57
58
59 TEST_CASE(PortMap_CreateAndCloseTwoPorts) {
60 InitPortMapTest();
61 Dart_Port port1 = PortMap::CreatePort();
62 Dart_Port port2 = PortMap::CreatePort();
63 EXPECT(PortMap::IsActivePort(port1));
64 EXPECT(PortMap::IsActivePort(port2));
65
66 // Uniqueness
siva 2011/10/14 21:01:52 '.'
turnidge 2011/10/14 23:08:02 Done.
67 EXPECT_NE(port1, port2);
31 68
32 PortMap::ClosePort(port1); 69 PortMap::ClosePort(port1);
33 EXPECT_EQ(false, PortMap::IsActivePort(port1)); 70 EXPECT(!PortMap::IsActivePort(port1));
34 msg1 = new PortMessage(port1, 0, strdup(msg_data)); 71 EXPECT(PortMap::IsActivePort(port2));
35 EXPECT_EQ(false, PortMap::PostMessage(msg1)); 72 EXPECT_EQ(port1, saved_port);
36 delete msg1;
37 EXPECT(PortMap::ReceiveMessage(10) == NULL);
38 73
39 EXPECT_EQ(true, PortMap::IsActivePort(port2));
40 msg1 = new PortMessage(port2, 0, strdup(msg_data));
41 EXPECT_EQ(true, PortMap::PostMessage(msg1));
42 PortMap::ClosePort(port2); 74 PortMap::ClosePort(port2);
43 EXPECT(PortMap::ReceiveMessage(10) == NULL); 75 EXPECT(!PortMap::IsActivePort(port1));
76 EXPECT(!PortMap::IsActivePort(port2));
77 EXPECT_EQ(port2, saved_port);
78 }
44 79
80
81 TEST_CASE(PortMap_ClosePorts) {
82 InitPortMapTest();
83 Dart_Port port1 = PortMap::CreatePort();
84 Dart_Port port2 = PortMap::CreatePort();
85 EXPECT(PortMap::IsActivePort(port1));
86 EXPECT(PortMap::IsActivePort(port2));
87
88 // Close all ports at once
siva 2011/10/14 21:01:52 once.
turnidge 2011/10/14 23:08:02 Done.
89 PortMap::ClosePorts();
90 EXPECT(!PortMap::IsActivePort(port1));
91 EXPECT(!PortMap::IsActivePort(port2));
92
93 // Embedder is notified to close all ports as well.
94 EXPECT_EQ(kCloseAllPorts, saved_port);
95 }
96
97
98 TEST_CASE(PortMap_CreateManyPorts) {
99 InitPortMapTest();
45 for (int i = 0; i < 32; i++) { 100 for (int i = 0; i < 32; i++) {
46 intptr_t port = PortMap::CreatePort(); 101 Dart_Port port = PortMap::CreatePort();
102 EXPECT(PortMap::IsActivePort(port));
47 PortMap::ClosePort(port); 103 PortMap::ClosePort(port);
104 EXPECT(!PortMap::IsActivePort(port));
48 } 105 }
49 } 106 }
50 107
51 108
109 TEST_CASE(PortMap_PostMessage) {
110 InitPortMapTest();
111 Dart_Port port = PortMap::CreatePort();
112 EXPECT(PortMap::PostMessage(
113 port, 0, reinterpret_cast<Dart_Message>(strdup("msg"))));
114
115 // Check that the post message callback was called.
116 EXPECT_STREQ("msg", saved_msg);
117 PortMap::ClosePorts();
118 }
119
120
121 TEST_CASE(PortMap_PostMessageInvalidPort) {
122 InitPortMapTest();
123 EXPECT(!PortMap::PostMessage(
124 0, 0, reinterpret_cast<Dart_Message>(strdup("msg"))));
125
126 // Check that the post message callback was not called.
127 EXPECT_STREQ("", saved_msg);
siva 2011/10/14 21:01:52 The duped string is leaked in this case.
turnidge 2011/10/14 23:08:02 Ah. Good catch. I have added a call to free() in
128 }
129
130
131 TEST_CASE(PortMap_PostMessageFailureInCallback) {
132 InitPortMapTest();
133 Dart_Port port = PortMap::CreatePort();
134
135 // Our callback is rigged to return false when it sees the message
136 // "fail". This return value is propagated out of PostMessage.
137 EXPECT(!PortMap::PostMessage(
138 port, 0, reinterpret_cast<Dart_Message>(strdup("fail"))));
139
140 // Check that the post message callback was called.
141 EXPECT_STREQ("fail", saved_msg);
142 PortMap::ClosePorts();
143 }
144
145
52 // End-of-test marker. 146 // End-of-test marker.
53 static const intptr_t kEOT = 0xFFFF; 147 static const intptr_t kEOT = 0xFFFF;
54 148
55 void* AllocIntData(intptr_t payload) { 149 void* AllocIntData(intptr_t payload) {
56 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); 150 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload)));
57 *result = payload; 151 *result = payload;
58 return result; 152 return result;
59 } 153 }
60 154
61 155
62 intptr_t GetIntData(void* data) { 156 intptr_t GetIntData(void* data) {
63 return *reinterpret_cast<intptr_t*>(data); 157 return *reinterpret_cast<intptr_t*>(data);
64 } 158 }
65 159
66 160
161 static PortMessage* NextMessage() {
162 // Since only the isolate owning the port can close the port and remove it
163 // from the port map and flush its messages, we can safely assume that the
164 // all messages in the message queue are for active ports.
siva 2011/10/14 21:01:52 "that the all messages ..." => "that all messages
turnidge 2011/10/14 23:08:02 I have just deleted this comment.
165 Isolate* isolate = Isolate::Current();
166 {
167 PortMessage* result = isolate->message_queue()->Dequeue();
168 if (result == NULL) {
169 isolate->message_queue()->Wait(0);
170 result = isolate->message_queue()->Dequeue();
171 }
172 return result;
173 }
174 }
175
176
67 void ThreadedPort_start(uword parameter) { 177 void ThreadedPort_start(uword parameter) {
68 Dart::CreateIsolate(NULL, NULL); 178 Dart::CreateIsolate(NULL, NULL);
69 179
70 intptr_t remote = parameter; 180 intptr_t remote = parameter;
71 intptr_t local = PortMap::CreatePort(); 181 intptr_t local = PortMap::CreatePort();
72 182
73 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(local))); 183 PortMap::PostMessage(remote, 0, AllocIntData(local));
74 184
75 intptr_t count = 0; 185 intptr_t count = 0;
76 while (true) { 186 while (true) {
77 PortMessage* msg = PortMap::ReceiveMessage(0); 187 PortMessage* msg = NextMessage();
78 EXPECT_EQ(local, msg->dest_id()); 188 EXPECT_EQ(local, msg->dest_port());
79 EXPECT(msg != NULL); 189 EXPECT(msg != NULL);
80 if (GetIntData(msg->data()) == kEOT) { 190 if (GetIntData(msg->data()) == kEOT) {
81 break; 191 break;
82 } 192 }
83 EXPECT(GetIntData(msg->data()) == count); 193 EXPECT(GetIntData(msg->data()) == count);
84 delete msg; 194 delete msg;
85 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(count * 2))); 195 PortMap::PostMessage(remote, 0, AllocIntData(count * 2));
86 count++; 196 count++;
87 } 197 }
88 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 198 PortMap::PostMessage(remote, 0, AllocIntData(kEOT));
89 199
90 Dart::ShutdownIsolate(); 200 Dart::ShutdownIsolate();
91 } 201 }
92 202
93 203
94 TEST_CASE(ThreadedPort) { 204 TEST_CASE(ThreadedPort) {
95 intptr_t local = PortMap::CreatePort(); 205 intptr_t local = PortMap::CreatePort();
96 206
97 Thread* thr = new Thread(ThreadedPort_start, local); 207 Thread* thr = new Thread(ThreadedPort_start, local);
98 EXPECT(thr != NULL); 208 EXPECT(thr != NULL);
99 209
100 PortMessage* msg = PortMap::ReceiveMessage(0); 210 PortMessage* msg = NextMessage();
101 EXPECT_EQ(local, msg->dest_id()); 211 EXPECT_EQ(local, msg->dest_port());
102 EXPECT(msg != NULL); 212 EXPECT(msg != NULL);
103 intptr_t remote = GetIntData(msg->data()); // Get the remote port. 213 intptr_t remote = GetIntData(msg->data()); // Get the remote port.
104 delete msg; 214 delete msg;
105 215
106 for (intptr_t i = 0; i < 10; i++) { 216 for (intptr_t i = 0; i < 10; i++) {
107 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(i))); 217 PortMap::PostMessage(remote, 0, AllocIntData(i));
108 PortMessage* msg = PortMap::ReceiveMessage(0); 218 PortMessage* msg = NextMessage();
109 EXPECT_EQ(local, msg->dest_id()); 219 EXPECT_EQ(local, msg->dest_port());
110 EXPECT(msg != NULL); 220 EXPECT(msg != NULL);
111 EXPECT_EQ(i * 2, GetIntData(msg->data())); 221 EXPECT_EQ(i * 2, GetIntData(msg->data()));
112 delete msg; 222 delete msg;
113 } 223 }
114 224
115 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 225 PortMap::PostMessage(remote, 0, AllocIntData(kEOT));
116 msg = PortMap::ReceiveMessage(0); 226 msg = NextMessage();
117 EXPECT_EQ(local, msg->dest_id()); 227 EXPECT_EQ(local, msg->dest_port());
118 EXPECT(msg != NULL); 228 EXPECT(msg != NULL);
119 EXPECT_EQ(kEOT, GetIntData(msg->data())); 229 EXPECT_EQ(kEOT, GetIntData(msg->data()));
120 delete msg; 230 delete msg;
121 231
122 // Give the spawned thread enough time to properly exit. 232 // Give the spawned thread enough time to properly exit.
123 Monitor* waiter = new Monitor(); 233 Monitor* waiter = new Monitor();
124 { 234 {
125 MonitorLocker ml(waiter); 235 MonitorLocker ml(waiter);
126 ml.Wait(20); 236 ml.Wait(20);
127 } 237 }
128 delete waiter; 238 delete waiter;
129 } 239 }
130 240
131 } // namespace dart 241 } // namespace dart
OLDNEW
« runtime/vm/port.cc ('K') | « runtime/vm/port.cc ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698