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

Side by Side Diff: runtime/vm/message_queue_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/port.h" 6 #include "vm/message_queue.h"
7 #include "vm/unit_test.h" 7 #include "vm/unit_test.h"
8 8
9 namespace dart { 9 namespace dart {
10 10
11 TEST_CASE(Port) { 11
12 const char* msg_data = "Hallo Velo!"; 12 // Provide access to private members of MessageQueue for testing.
13 13 class MessageQueueTestPeer {
14 intptr_t port1 = PortMap::CreatePort(); 14 public:
15 intptr_t port2 = PortMap::CreatePort(); 15 explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {}
16 EXPECT(port1 != port2); 16
17 17 bool HasMessage() const { return queue_->head_ != NULL; }
18 PortMessage* msg1 = new PortMessage(port1, 0, strdup(msg_data)); 18
19 EXPECT_EQ(true, PortMap::PostMessage(msg1)); 19 private:
20 PortMessage* msg = PortMap::ReceiveMessage(10); 20 MessageQueue* queue_;
21 EXPECT_EQ(port1, msg->dest_id()); 21 };
22 EXPECT_EQ(msg1, msg); 22
23
24 TEST_CASE(MessageQueue_BasicOperations) {
25 MessageQueue queue;
26 MessageQueueTestPeer queue_peer(&queue);
27 EXPECT(!queue_peer.HasMessage());
28
29 Dart_Port port = 1;
30
31 // Add two messages.
32 PortMessage* msg1 = new PortMessage(port, 0, strdup("msg1"));
33 queue.Enqueue(msg1);
34 EXPECT(queue_peer.HasMessage());
35
36 PortMessage* msg2 = new PortMessage(port, 0, strdup("msg2"));
37 queue.Enqueue(msg2);
38 EXPECT(queue_peer.HasMessage());
39
40 // Remove two messages.
41 PortMessage* msg = queue.Dequeue(0);
42 EXPECT(msg != NULL);
43 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data()));
44 EXPECT(queue_peer.HasMessage());
45
46 msg = queue.Dequeue(0);
47 EXPECT(msg != NULL);
48 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
49 EXPECT(!queue_peer.HasMessage());
50
23 delete msg1; 51 delete msg1;
24 52 delete msg2;
25 msg1 = new PortMessage(port2, 0, strdup(msg_data)); 53 }
26 EXPECT_EQ(true, PortMap::PostMessage(msg1)); 54
27 msg = PortMap::ReceiveMessage(10); 55
28 EXPECT_EQ(port2, msg->dest_id()); 56 // A thread which receives an expected sequence of messages.
29 EXPECT_EQ(msg1, msg); 57 static Monitor* sync = NULL;
30 delete msg1; 58 static MessageQueue* shared_queue = NULL;
31 59 void MessageReceiver_start(uword unused) {
32 PortMap::ClosePort(port1); 60 // We only need an isolate here because the MonitorLocker in the
33 EXPECT_EQ(false, PortMap::IsActivePort(port1)); 61 // MessageQueue expects it.
34 msg1 = new PortMessage(port1, 0, strdup(msg_data));
35 EXPECT_EQ(false, PortMap::PostMessage(msg1));
36 delete msg1;
37 EXPECT(PortMap::ReceiveMessage(10) == NULL);
38
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);
43 EXPECT(PortMap::ReceiveMessage(10) == NULL);
44
45 for (int i = 0; i < 32; i++) {
46 intptr_t port = PortMap::CreatePort();
47 PortMap::ClosePort(port);
48 }
49 }
50
51
52 // End-of-test marker.
53 static const intptr_t kEOT = 0xFFFF;
54
55 void* AllocIntData(intptr_t payload) {
56 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload)));
57 *result = payload;
58 return result;
59 }
60
61
62 intptr_t GetIntData(void* data) {
63 return *reinterpret_cast<intptr_t*>(data);
64 }
65
66
67 void ThreadedPort_start(uword parameter) {
68 Dart::CreateIsolate(NULL, NULL); 62 Dart::CreateIsolate(NULL, NULL);
69 63
70 intptr_t remote = parameter; 64 // Create a message queue and share it.
71 intptr_t local = PortMap::CreatePort(); 65 MessageQueue* queue = new MessageQueue();
72 66 shared_queue = queue;
73 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(local))); 67
74 68 // Tell the other thread to fill the queue a bit.
75 intptr_t count = 0; 69 {
76 while (true) { 70 MonitorLocker ml(sync);
77 PortMessage* msg = PortMap::ReceiveMessage(0); 71 ml.Notify();
78 EXPECT_EQ(local, msg->dest_id()); 72 }
73
74 // Wait for the other thread to fill the queue a bit.
75 {
76 MonitorLocker ml(sync);
77 ml.Wait(0);
78 }
79
80 for (int i = 0; i < 3; i++) {
81 PortMessage* msg = queue->Dequeue(0);
79 EXPECT(msg != NULL); 82 EXPECT(msg != NULL);
80 if (GetIntData(msg->data()) == kEOT) { 83 EXPECT_EQ(i+10, msg->dest_port());
81 break; 84 EXPECT_EQ(i+100, msg->reply_port());
82 } 85 EXPECT_EQ(i+1000, *(reinterpret_cast<int*>(msg->data())));
83 EXPECT(GetIntData(msg->data()) == count);
84 delete msg; 86 delete msg;
85 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(count * 2))); 87 }
86 count++; 88 for (int i = 0; i < 3; i++) {
87 } 89 PortMessage* msg = queue->Dequeue(0);
88 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 90 EXPECT(msg != NULL);
89 91 EXPECT_EQ(i+20, msg->dest_port());
92 EXPECT_EQ(i+200, msg->reply_port());
93 EXPECT_EQ(i+2000, *(reinterpret_cast<int*>(msg->data())));
94 delete msg;
95 }
96 shared_queue = NULL;
97 delete queue;
90 Dart::ShutdownIsolate(); 98 Dart::ShutdownIsolate();
91 } 99 }
92 100
93 101
94 TEST_CASE(ThreadedPort) { 102 TEST_CASE(MessageQueue_WaitNotify) {
95 intptr_t local = PortMap::CreatePort(); 103 Thread* thread = new Thread(MessageReceiver_start, 0);
96 104 EXPECT(thread != NULL);
97 Thread* thr = new Thread(ThreadedPort_start, local); 105
98 EXPECT(thr != NULL); 106 // Wait for the shared queue to be created.
99 107 sync = new Monitor();
100 PortMessage* msg = PortMap::ReceiveMessage(0); 108 {
101 EXPECT_EQ(local, msg->dest_id()); 109 MonitorLocker ml(sync);
110 ml.Wait(0);
111 }
112 ASSERT(shared_queue != NULL);
113
114 // Pile up three messages before the other thread runs.
115 for (int i = 0; i < 3; i++) {
116 int* data = reinterpret_cast<int*>(malloc(sizeof(*data)));
117 *data = i+1000;
118 PortMessage* msg = new PortMessage(i+10, i+100, data);
119 shared_queue->Enqueue(msg);
120 }
121
122 // Wake the other thread and have it start consuming messages.
123 {
124 MonitorLocker ml(sync);
125 ml.Notify();
126 }
127
128 // Add a few more messages after sleeping to allow the other thread
129 // to potentially exercise the blocking code path in Dequeue.
130 OS::Sleep(5);
131 for (int i = 0; i < 3; i++) {
132 int* data = reinterpret_cast<int*>(malloc(sizeof(*data)));
133 *data = i+2000;
134 PortMessage* msg = new PortMessage(i+20, i+200, data);
135 shared_queue->Enqueue(msg);
136 }
137
138 sync = NULL;
139 delete sync;
140 }
141
142
143 TEST_CASE(MessageQueue_FlushAll) {
144 MessageQueue queue;
145 MessageQueueTestPeer queue_peer(&queue);
146 Dart_Port port1 = 1;
147 Dart_Port port2 = 2;
148
149 // Add two messages.
150 PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
151 queue.Enqueue(msg1);
152 PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2"));
153 queue.Enqueue(msg2);
154
155 EXPECT(queue_peer.HasMessage());
156 queue.FlushAll();
157 EXPECT(!queue_peer.HasMessage());
158
159 // msg1 and msg2 already delete by FlushAll.
160 }
161
162
163 TEST_CASE(MessageQueue_Flush) {
164 MessageQueue queue;
165 MessageQueueTestPeer queue_peer(&queue);
166 Dart_Port port1 = 1;
167 Dart_Port port2 = 2;
168
169 // Add two messages on different ports.
170 PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
171 queue.Enqueue(msg1);
172 PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2"));
173 queue.Enqueue(msg2);
174 EXPECT(queue_peer.HasMessage());
175
176 queue.Flush(port1);
177
178 // One message is left in the queue.
179 EXPECT(queue_peer.HasMessage());
180 PortMessage* msg = queue.Dequeue(0);
102 EXPECT(msg != NULL); 181 EXPECT(msg != NULL);
103 intptr_t remote = GetIntData(msg->data()); // Get the remote port. 182 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
104 delete msg; 183
105 184 EXPECT(!queue_peer.HasMessage());
106 for (intptr_t i = 0; i < 10; i++) { 185
107 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(i))); 186 // msg1 is already deleted by Flush.
108 PortMessage* msg = PortMap::ReceiveMessage(0); 187 delete msg2;
109 EXPECT_EQ(local, msg->dest_id()); 188 }
110 EXPECT(msg != NULL); 189
111 EXPECT_EQ(i * 2, GetIntData(msg->data())); 190
112 delete msg; 191 TEST_CASE(MessageQueue_Flush_MultipleMessages) {
113 } 192 MessageQueue queue;
114 193 MessageQueueTestPeer queue_peer(&queue);
115 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); 194 Dart_Port port1 = 1;
116 msg = PortMap::ReceiveMessage(0); 195
117 EXPECT_EQ(local, msg->dest_id()); 196 PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
118 EXPECT(msg != NULL); 197 queue.Enqueue(msg1);
119 EXPECT_EQ(kEOT, GetIntData(msg->data())); 198 PortMessage* msg2 = new PortMessage(port1, 0, strdup("msg2"));
120 delete msg; 199 queue.Enqueue(msg2);
121 200 EXPECT(queue_peer.HasMessage());
122 // Give the spawned thread enough time to properly exit. 201
123 Monitor* waiter = new Monitor(); 202 queue.Flush(port1);
124 { 203
125 MonitorLocker ml(waiter); 204 // Queue is empty.
126 ml.Wait(20); 205 EXPECT(!queue_peer.HasMessage());
127 } 206 // msg1 and msg2 are already deleted by Flush.
128 delete waiter; 207 }
129 } 208
209
210 TEST_CASE(MessageQueue_Flush_EmptyQueue) {
211 MessageQueue queue;
212 MessageQueueTestPeer queue_peer(&queue);
213 Dart_Port port1 = 1;
214
215 EXPECT(!queue_peer.HasMessage());
216 queue.Flush(port1);
217
218 // Queue is still empty.
219 EXPECT(!queue_peer.HasMessage());
220 }
221
130 222
131 } // namespace dart 223 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698