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

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
« no previous file with comments | « runtime/vm/port.cc ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_SetMessageCallbacks(&MyPostMessageCallback, &MyClosePortCallback);
39 saved_port = 0;
40 saved_msg[0] = '\0';
41 }
42
43
44 TEST_CASE(PortMap_CreateAndCloseOnePort) {
45 InitPortMapTest();
46 intptr_t port = PortMap::CreatePort();
47 EXPECT_NE(0, port);
48 EXPECT(PortMap::IsActivePort(port));
49
50 PortMap::ClosePort(port);
51 EXPECT(!PortMap::IsActivePort(port));
52
53 // Embedder was notified of port closure.
54 EXPECT_EQ(port, saved_port);
55 }
56
57
58 TEST_CASE(PortMap_CreateAndCloseTwoPorts) {
59 InitPortMapTest();
60 Dart_Port port1 = PortMap::CreatePort();
61 Dart_Port port2 = PortMap::CreatePort();
62 EXPECT(PortMap::IsActivePort(port1));
63 EXPECT(PortMap::IsActivePort(port2));
64
65 // Uniqueness.
66 EXPECT_NE(port1, port2);
31 67
32 PortMap::ClosePort(port1); 68 PortMap::ClosePort(port1);
33 EXPECT_EQ(false, PortMap::IsActivePort(port1)); 69 EXPECT(!PortMap::IsActivePort(port1));
34 msg1 = new PortMessage(port1, 0, strdup(msg_data)); 70 EXPECT(PortMap::IsActivePort(port2));
35 EXPECT_EQ(false, PortMap::PostMessage(msg1)); 71 EXPECT_EQ(port1, saved_port);
36 delete msg1;
37 EXPECT(PortMap::ReceiveMessage(10) == NULL);
38 72
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); 73 PortMap::ClosePort(port2);
43 EXPECT(PortMap::ReceiveMessage(10) == NULL); 74 EXPECT(!PortMap::IsActivePort(port1));
75 EXPECT(!PortMap::IsActivePort(port2));
76 EXPECT_EQ(port2, saved_port);
77 }
44 78
79
80 TEST_CASE(PortMap_ClosePorts) {
81 InitPortMapTest();
82 Dart_Port port1 = PortMap::CreatePort();
83 Dart_Port port2 = PortMap::CreatePort();
84 EXPECT(PortMap::IsActivePort(port1));
85 EXPECT(PortMap::IsActivePort(port2));
86
87 // Close all ports at once.
88 PortMap::ClosePorts();
89 EXPECT(!PortMap::IsActivePort(port1));
90 EXPECT(!PortMap::IsActivePort(port2));
91
92 // Embedder is notified to close all ports as well.
93 EXPECT_EQ(kCloseAllPorts, saved_port);
94 }
95
96
97 TEST_CASE(PortMap_CreateManyPorts) {
98 InitPortMapTest();
45 for (int i = 0; i < 32; i++) { 99 for (int i = 0; i < 32; i++) {
46 intptr_t port = PortMap::CreatePort(); 100 Dart_Port port = PortMap::CreatePort();
101 EXPECT(PortMap::IsActivePort(port));
47 PortMap::ClosePort(port); 102 PortMap::ClosePort(port);
103 EXPECT(!PortMap::IsActivePort(port));
48 } 104 }
49 } 105 }
50 106
51 107
108 TEST_CASE(PortMap_PostMessage) {
109 InitPortMapTest();
110 Dart_Port port = PortMap::CreatePort();
111 EXPECT(PortMap::PostMessage(
112 port, 0, reinterpret_cast<Dart_Message>(strdup("msg"))));
113
114 // Check that the post message callback was called.
115 EXPECT_STREQ("msg", saved_msg);
116 PortMap::ClosePorts();
117 }
118
119
120 TEST_CASE(PortMap_PostMessageInvalidPort) {
121 InitPortMapTest();
122 EXPECT(!PortMap::PostMessage(
123 0, 0, reinterpret_cast<Dart_Message>(strdup("msg"))));
124
125 // Check that the post message callback was not called.
126 EXPECT_STREQ("", saved_msg);
127 }
128
129
130 TEST_CASE(PortMap_PostMessageFailureInCallback) {
131 InitPortMapTest();
132 Dart_Port port = PortMap::CreatePort();
133
134 // Our callback is rigged to return false when it sees the message
135 // "fail". This return value is propagated out of PostMessage.
136 EXPECT(!PortMap::PostMessage(
137 port, 0, reinterpret_cast<Dart_Message>(strdup("fail"))));
138
139 // Check that the post message callback was called.
140 EXPECT_STREQ("fail", saved_msg);
141 PortMap::ClosePorts();
142 }
143
144
52 // End-of-test marker. 145 // End-of-test marker.
53 static const intptr_t kEOT = 0xFFFF; 146 static const intptr_t kEOT = 0xFFFF;
54 147
55 void* AllocIntData(intptr_t payload) { 148 void* AllocIntData(intptr_t payload) {
56 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); 149 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload)));
57 *result = payload; 150 *result = payload;
58 return result; 151 return result;
59 } 152 }
60 153
61 154
62 intptr_t GetIntData(void* data) { 155 intptr_t GetIntData(void* data) {
63 return *reinterpret_cast<intptr_t*>(data); 156 return *reinterpret_cast<intptr_t*>(data);
64 } 157 }
65 158
66 159
160 static PortMessage* NextMessage() {
161 Isolate* isolate = Isolate::Current();
162 PortMessage* result = isolate->message_queue()->Dequeue(0);
163 return result;
164 }
165
166
67 void ThreadedPort_start(uword parameter) { 167 void ThreadedPort_start(uword parameter) {
68 Dart::CreateIsolate(NULL, NULL); 168 Dart::CreateIsolate(NULL, NULL);
69 169
70 intptr_t remote = parameter; 170 intptr_t remote = parameter;
71 intptr_t local = PortMap::CreatePort(); 171 intptr_t local = PortMap::CreatePort();
72 172
73 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(local))); 173 PortMap::PostMessage(remote, 0, AllocIntData(local));
74 174
75 intptr_t count = 0; 175 intptr_t count = 0;
76 while (true) { 176 while (true) {
77 PortMessage* msg = PortMap::ReceiveMessage(0); 177 PortMessage* msg = NextMessage();
78 EXPECT_EQ(local, msg->dest_id()); 178 EXPECT_EQ(local, msg->dest_port());
79 EXPECT(msg != NULL); 179 EXPECT(msg != NULL);
80 if (GetIntData(msg->data()) == kEOT) { 180 if (GetIntData(msg->data()) == kEOT) {
81 break; 181 break;
82 } 182 }
83 EXPECT(GetIntData(msg->data()) == count); 183 EXPECT(GetIntData(msg->data()) == count);
84 delete msg; 184 delete msg;
85 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(count * 2))); 185 PortMap::PostMessage(remote, 0, AllocIntData(count * 2));
86 count++; 186 count++;
87 } 187 }
88 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 188 PortMap::PostMessage(remote, 0, AllocIntData(kEOT));
89 189
90 Dart::ShutdownIsolate(); 190 Dart::ShutdownIsolate();
91 } 191 }
92 192
93 193
94 TEST_CASE(ThreadedPort) { 194 TEST_CASE(ThreadedPort) {
95 intptr_t local = PortMap::CreatePort(); 195 intptr_t local = PortMap::CreatePort();
96 196
97 Thread* thr = new Thread(ThreadedPort_start, local); 197 Thread* thr = new Thread(ThreadedPort_start, local);
98 EXPECT(thr != NULL); 198 EXPECT(thr != NULL);
99 199
100 PortMessage* msg = PortMap::ReceiveMessage(0); 200 PortMessage* msg = NextMessage();
101 EXPECT_EQ(local, msg->dest_id()); 201 EXPECT_EQ(local, msg->dest_port());
102 EXPECT(msg != NULL); 202 EXPECT(msg != NULL);
103 intptr_t remote = GetIntData(msg->data()); // Get the remote port. 203 intptr_t remote = GetIntData(msg->data()); // Get the remote port.
104 delete msg; 204 delete msg;
105 205
106 for (intptr_t i = 0; i < 10; i++) { 206 for (intptr_t i = 0; i < 10; i++) {
107 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(i))); 207 PortMap::PostMessage(remote, 0, AllocIntData(i));
108 PortMessage* msg = PortMap::ReceiveMessage(0); 208 PortMessage* msg = NextMessage();
109 EXPECT_EQ(local, msg->dest_id()); 209 EXPECT_EQ(local, msg->dest_port());
110 EXPECT(msg != NULL); 210 EXPECT(msg != NULL);
111 EXPECT_EQ(i * 2, GetIntData(msg->data())); 211 EXPECT_EQ(i * 2, GetIntData(msg->data()));
112 delete msg; 212 delete msg;
113 } 213 }
114 214
115 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 215 PortMap::PostMessage(remote, 0, AllocIntData(kEOT));
116 msg = PortMap::ReceiveMessage(0); 216 msg = NextMessage();
117 EXPECT_EQ(local, msg->dest_id()); 217 EXPECT_EQ(local, msg->dest_port());
118 EXPECT(msg != NULL); 218 EXPECT(msg != NULL);
119 EXPECT_EQ(kEOT, GetIntData(msg->data())); 219 EXPECT_EQ(kEOT, GetIntData(msg->data()));
120 delete msg; 220 delete msg;
121 221
122 // Give the spawned thread enough time to properly exit. 222 // Give the spawned thread enough time to properly exit.
123 Monitor* waiter = new Monitor(); 223 Monitor* waiter = new Monitor();
124 { 224 {
125 MonitorLocker ml(waiter); 225 MonitorLocker ml(waiter);
126 ml.Wait(20); 226 ml.Wait(20);
127 } 227 }
128 delete waiter; 228 delete waiter;
129 } 229 }
130 230
131 } // namespace dart 231 } // namespace dart
OLDNEW
« no previous file with comments | « 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