OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/message.h" | 6 #include "vm/message.h" |
7 #include "vm/unit_test.h" | 7 #include "vm/unit_test.h" |
8 | 8 |
9 namespace dart { | 9 namespace dart { |
10 | 10 |
11 | 11 |
12 // Provide access to private members of MessageQueue for testing. | 12 // Provide access to private members of MessageQueue for testing. |
13 class MessageQueueTestPeer { | 13 class MessageQueueTestPeer { |
14 public: | 14 public: |
15 explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {} | 15 explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {} |
16 | 16 |
17 bool HasMessage() const { | 17 bool HasMessage() const { |
18 // We don't really need to grab the monitor during the unit test, | |
19 // but it doesn't hurt. | |
20 queue_->monitor_.Enter(); | |
21 bool result = (queue_->head_[Message::kNormalPriority] != NULL || | 18 bool result = (queue_->head_[Message::kNormalPriority] != NULL || |
22 queue_->head_[Message::kOOBPriority] != NULL); | 19 queue_->head_[Message::kOOBPriority] != NULL); |
23 queue_->monitor_.Exit(); | |
24 return result; | 20 return result; |
25 } | 21 } |
26 | 22 |
27 private: | 23 private: |
28 MessageQueue* queue_; | 24 MessageQueue* queue_; |
29 }; | 25 }; |
30 | 26 |
31 | 27 |
| 28 class MessageHandlerTestPeer { |
| 29 public: |
| 30 explicit MessageHandlerTestPeer(MessageHandler* handler) |
| 31 : handler_(handler) {} |
| 32 |
| 33 MessageQueue* queue() { return handler_->queue_; } |
| 34 |
| 35 private: |
| 36 MessageHandler* handler_; |
| 37 }; |
| 38 |
| 39 |
32 static uint8_t* AllocMsg(const char* str) { | 40 static uint8_t* AllocMsg(const char* str) { |
33 return reinterpret_cast<uint8_t*>(strdup(str)); | 41 return reinterpret_cast<uint8_t*>(strdup(str)); |
34 } | 42 } |
35 | 43 |
36 | 44 |
37 TEST_CASE(MessageQueue_BasicOperations) { | 45 TEST_CASE(MessageQueue_BasicOperations) { |
38 MessageQueue queue; | 46 MessageQueue queue; |
39 MessageQueueTestPeer queue_peer(&queue); | 47 MessageQueueTestPeer queue_peer(&queue); |
40 EXPECT(!queue_peer.HasMessage()); | 48 EXPECT(!queue_peer.HasMessage()); |
41 | 49 |
42 Dart_Port port = 1; | 50 Dart_Port port = 1; |
43 | 51 |
44 // Add two messages. | 52 // Add two messages. |
45 Message* msg1 = | 53 Message* msg1 = |
46 new Message(port, 0, AllocMsg("msg1"), Message::kNormalPriority); | 54 new Message(port, 0, AllocMsg("msg1"), Message::kNormalPriority); |
47 queue.Enqueue(msg1); | 55 queue.Enqueue(msg1); |
48 EXPECT(queue_peer.HasMessage()); | 56 EXPECT(queue_peer.HasMessage()); |
49 | 57 |
50 Message* msg2 = | 58 Message* msg2 = |
51 new Message(port, 0, AllocMsg("msg2"), Message::kNormalPriority); | 59 new Message(port, 0, AllocMsg("msg2"), Message::kNormalPriority); |
52 | 60 |
53 queue.Enqueue(msg2); | 61 queue.Enqueue(msg2); |
54 EXPECT(queue_peer.HasMessage()); | 62 EXPECT(queue_peer.HasMessage()); |
55 | 63 |
56 // Remove two messages. | 64 // Remove two messages. |
57 Message* msg = queue.Dequeue(0); | 65 Message* msg = queue.Dequeue(); |
58 EXPECT(msg != NULL); | 66 EXPECT(msg != NULL); |
59 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data())); | 67 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data())); |
60 EXPECT(queue_peer.HasMessage()); | 68 EXPECT(queue_peer.HasMessage()); |
61 | 69 |
62 msg = queue.Dequeue(0); | 70 msg = queue.Dequeue(); |
63 EXPECT(msg != NULL); | 71 EXPECT(msg != NULL); |
64 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); | 72 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); |
65 EXPECT(!queue_peer.HasMessage()); | 73 EXPECT(!queue_peer.HasMessage()); |
66 | 74 |
67 delete msg1; | 75 delete msg1; |
68 delete msg2; | 76 delete msg2; |
69 } | 77 } |
70 | 78 |
71 | 79 |
72 TEST_CASE(MessageQueue_Priorities) { | 80 TEST_CASE(MessageQueue_Priorities) { |
73 MessageQueue queue; | 81 MessageQueue queue; |
74 MessageQueueTestPeer queue_peer(&queue); | 82 MessageQueueTestPeer queue_peer(&queue); |
75 EXPECT(!queue_peer.HasMessage()); | 83 EXPECT(!queue_peer.HasMessage()); |
76 | 84 |
77 Dart_Port port = 1; | 85 Dart_Port port = 1; |
78 | 86 |
79 // Add two messages. | 87 // Add two messages. |
80 Message* msg1 = | 88 Message* msg1 = |
81 new Message(port, 0, AllocMsg("msg1"), Message::kNormalPriority); | 89 new Message(port, 0, AllocMsg("msg1"), Message::kNormalPriority); |
82 queue.Enqueue(msg1); | 90 queue.Enqueue(msg1); |
83 EXPECT(queue_peer.HasMessage()); | 91 EXPECT(queue_peer.HasMessage()); |
84 | 92 |
85 Message* msg2 = | 93 Message* msg2 = |
86 new Message(port, 0, AllocMsg("msg2"), Message::kOOBPriority); | 94 new Message(port, 0, AllocMsg("msg2"), Message::kOOBPriority); |
87 | 95 |
88 queue.Enqueue(msg2); | 96 queue.Enqueue(msg2); |
89 EXPECT(queue_peer.HasMessage()); | 97 EXPECT(queue_peer.HasMessage()); |
90 | 98 |
91 // The higher priority message is delivered first. | 99 // The higher priority message is delivered first. |
92 Message* msg = queue.Dequeue(0); | 100 Message* msg = queue.Dequeue(); |
93 EXPECT(msg != NULL); | 101 EXPECT(msg != NULL); |
94 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); | 102 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); |
95 EXPECT(queue_peer.HasMessage()); | 103 EXPECT(queue_peer.HasMessage()); |
96 | 104 |
97 msg = queue.Dequeue(0); | 105 msg = queue.Dequeue(); |
98 EXPECT(msg != NULL); | 106 EXPECT(msg != NULL); |
99 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data())); | 107 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data())); |
100 EXPECT(!queue_peer.HasMessage()); | 108 EXPECT(!queue_peer.HasMessage()); |
101 | 109 |
102 delete msg1; | 110 delete msg1; |
103 delete msg2; | 111 delete msg2; |
104 } | 112 } |
105 | 113 |
106 | 114 |
107 // A thread which receives an expected sequence of messages. | 115 // A thread which receives an expected sequence of messages. |
108 static Monitor* sync = NULL; | 116 static Monitor* sync = NULL; |
109 static MessageQueue* shared_queue = NULL; | 117 static MessageHandler* shared_handler = NULL; |
110 void MessageReceiver_start(uword unused) { | 118 void MessageReceiver_start(uword unused) { |
111 // We only need an isolate here because the MonitorLocker in the | 119 // We only need an isolate here because the MonitorLocker in the |
112 // MessageQueue expects it, we don't need to initialize the isolate | 120 // MessageQueue expects it, we don't need to initialize the isolate |
113 // as it does not run any dart code. | 121 // as it does not run any dart code. |
114 Dart::CreateIsolate(NULL); | 122 Dart::CreateIsolate(NULL); |
115 | 123 |
116 // Create a message queue and share it. | 124 // Create a message handler and share it. |
117 MessageQueue* queue = new MessageQueue(); | 125 MessageHandler* handler = new MessageHandler(); |
118 MessageQueueTestPeer peer(queue); | 126 MessageHandlerTestPeer handler_peer(handler); |
119 shared_queue = queue; | 127 MessageQueueTestPeer queue_peer(handler_peer.queue()); |
| 128 shared_handler = handler; |
120 | 129 |
121 // Tell the other thread that the shared queue is ready. | 130 // Tell the other thread that the shared queue is ready. |
122 { | 131 { |
123 MonitorLocker ml(sync); | 132 MonitorLocker ml(sync); |
124 ml.Notify(); | 133 ml.Notify(); |
125 } | 134 } |
126 | 135 |
127 // Wait for the other thread to fill the queue a bit. | 136 // Wait for the other thread to fill the queue a bit. |
128 while (!peer.HasMessage()) { | 137 while (!queue_peer.HasMessage()) { |
129 MonitorLocker ml(sync); | 138 MonitorLocker ml(sync); |
130 ml.Wait(5); | 139 ml.Wait(5); |
131 } | 140 } |
132 | 141 |
133 for (int i = 0; i < 3; i++) { | 142 for (int i = 0; i < 3; i++) { |
134 Message* msg = queue->Dequeue(0); | 143 Message* msg = handler->Dequeue(0); |
135 EXPECT(msg != NULL); | 144 EXPECT(msg != NULL); |
136 EXPECT_EQ(i + 10, msg->dest_port()); | 145 EXPECT_EQ(i + 10, msg->dest_port()); |
137 EXPECT_EQ(i + 100, msg->reply_port()); | 146 EXPECT_EQ(i + 100, msg->reply_port()); |
138 EXPECT_EQ(i + 1000, *(reinterpret_cast<int*>(msg->data()))); | 147 EXPECT_EQ(i + 1000, *(reinterpret_cast<int*>(msg->data()))); |
139 delete msg; | 148 delete msg; |
140 } | 149 } |
141 for (int i = 0; i < 3; i++) { | 150 for (int i = 0; i < 3; i++) { |
142 Message* msg = queue->Dequeue(0); | 151 Message* msg = handler->Dequeue(0); |
143 EXPECT(msg != NULL); | 152 EXPECT(msg != NULL); |
144 EXPECT_EQ(i + 20, msg->dest_port()); | 153 EXPECT_EQ(i + 20, msg->dest_port()); |
145 EXPECT_EQ(i + 200, msg->reply_port()); | 154 EXPECT_EQ(i + 200, msg->reply_port()); |
146 EXPECT_EQ(i + 2000, *(reinterpret_cast<int*>(msg->data()))); | 155 EXPECT_EQ(i + 2000, *(reinterpret_cast<int*>(msg->data()))); |
147 delete msg; | 156 delete msg; |
148 } | 157 } |
149 shared_queue = NULL; | 158 shared_handler = NULL; |
150 delete queue; | 159 delete handler; |
151 Dart::ShutdownIsolate(); | 160 Dart::ShutdownIsolate(); |
152 } | 161 } |
153 | 162 |
154 | 163 |
155 TEST_CASE(MessageQueue_WaitNotify) { | 164 TEST_CASE(MessageHandler_WaitNotify) { |
156 sync = new Monitor(); | 165 sync = new Monitor(); |
157 | 166 |
158 int result = Thread::Start(MessageReceiver_start, 0); | 167 int result = Thread::Start(MessageReceiver_start, 0); |
159 EXPECT_EQ(0, result); | 168 EXPECT_EQ(0, result); |
160 | 169 |
161 // Wait for the shared queue to be created. | 170 // Wait for the shared handler to be created. |
162 while (shared_queue == NULL) { | 171 while (shared_handler == NULL) { |
163 MonitorLocker ml(sync); | 172 MonitorLocker ml(sync); |
164 ml.Wait(5); | 173 ml.Wait(5); |
165 } | 174 } |
166 ASSERT(shared_queue != NULL); | 175 ASSERT(shared_handler != NULL); |
167 | 176 |
168 // Pile up three messages before the other thread runs. | 177 // Pile up three messages before the other thread runs. |
169 for (int i = 0; i < 3; i++) { | 178 for (int i = 0; i < 3; i++) { |
170 int* data = reinterpret_cast<int*>(malloc(sizeof(*data))); | 179 int* data = reinterpret_cast<int*>(malloc(sizeof(*data))); |
171 *data = i + 1000; | 180 *data = i + 1000; |
172 Message* msg = | 181 Message* msg = |
173 new Message(i + 10, i + 100, reinterpret_cast<uint8_t*>(data), | 182 new Message(i + 10, i + 100, reinterpret_cast<uint8_t*>(data), |
174 Message::kNormalPriority); | 183 Message::kNormalPriority); |
175 shared_queue->Enqueue(msg); | 184 shared_handler->PostMessage(msg); |
176 } | 185 } |
177 | 186 |
178 // Wake the other thread and have it start consuming messages. | 187 // Wake the other thread and have it start consuming messages. |
179 { | 188 { |
180 MonitorLocker ml(sync); | 189 MonitorLocker ml(sync); |
181 ml.Notify(); | 190 ml.Notify(); |
182 } | 191 } |
183 | 192 |
184 // Add a few more messages after sleeping to allow the other thread | 193 // Add a few more messages after sleeping to allow the other thread |
185 // to potentially exercise the blocking code path in Dequeue. | 194 // to potentially exercise the blocking code path in Dequeue. |
186 OS::Sleep(5); | 195 OS::Sleep(5); |
187 for (int i = 0; i < 3; i++) { | 196 for (int i = 0; i < 3; i++) { |
188 int* data = reinterpret_cast<int*>(malloc(sizeof(*data))); | 197 int* data = reinterpret_cast<int*>(malloc(sizeof(*data))); |
189 *data = i + 2000; | 198 *data = i + 2000; |
190 Message* msg = | 199 Message* msg = |
191 new Message(i + 20, i + 200, reinterpret_cast<uint8_t*>(data), | 200 new Message(i + 20, i + 200, reinterpret_cast<uint8_t*>(data), |
192 Message::kNormalPriority); | 201 Message::kNormalPriority); |
193 shared_queue->Enqueue(msg); | 202 shared_handler->PostMessage(msg); |
194 } | 203 } |
195 | 204 |
196 sync = NULL; | 205 sync = NULL; |
197 delete sync; | 206 delete sync; |
198 | 207 |
199 // Give the spawned thread enough time to properly exit. | 208 // Give the spawned thread enough time to properly exit. |
200 OS::Sleep(20); | 209 OS::Sleep(20); |
201 } | 210 } |
202 | 211 |
203 | 212 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 queue.Enqueue(msg1); | 244 queue.Enqueue(msg1); |
236 Message* msg2 = | 245 Message* msg2 = |
237 new Message(port2, 0, AllocMsg("msg2"), Message::kNormalPriority); | 246 new Message(port2, 0, AllocMsg("msg2"), Message::kNormalPriority); |
238 queue.Enqueue(msg2); | 247 queue.Enqueue(msg2); |
239 EXPECT(queue_peer.HasMessage()); | 248 EXPECT(queue_peer.HasMessage()); |
240 | 249 |
241 queue.Flush(port1); | 250 queue.Flush(port1); |
242 | 251 |
243 // One message is left in the queue. | 252 // One message is left in the queue. |
244 EXPECT(queue_peer.HasMessage()); | 253 EXPECT(queue_peer.HasMessage()); |
245 Message* msg = queue.Dequeue(0); | 254 Message* msg = queue.Dequeue(); |
246 EXPECT(msg != NULL); | 255 EXPECT(msg != NULL); |
247 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); | 256 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); |
248 | 257 |
249 EXPECT(!queue_peer.HasMessage()); | 258 EXPECT(!queue_peer.HasMessage()); |
250 | 259 |
251 // msg1 is already deleted by Flush. | 260 // msg1 is already deleted by Flush. |
252 delete msg2; | 261 delete msg2; |
253 } | 262 } |
254 | 263 |
255 | 264 |
(...skipping 24 matching lines...) Expand all Loading... |
280 Dart_Port port1 = 1; | 289 Dart_Port port1 = 1; |
281 | 290 |
282 EXPECT(!queue_peer.HasMessage()); | 291 EXPECT(!queue_peer.HasMessage()); |
283 queue.Flush(port1); | 292 queue.Flush(port1); |
284 | 293 |
285 // Queue is still empty. | 294 // Queue is still empty. |
286 EXPECT(!queue_peer.HasMessage()); | 295 EXPECT(!queue_peer.HasMessage()); |
287 } | 296 } |
288 | 297 |
289 } // namespace dart | 298 } // namespace dart |
OLD | NEW |