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