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 "vm/message_handler.h" | 5 #include "vm/message_handler.h" |
6 #include "vm/port.h" | |
7 #include "vm/unit_test.h" | 6 #include "vm/unit_test.h" |
8 | 7 |
9 namespace dart { | 8 namespace dart { |
10 | 9 |
11 class MessageHandlerTestPeer { | 10 class MessageHandlerTestPeer { |
12 public: | 11 public: |
13 explicit MessageHandlerTestPeer(MessageHandler* handler) | 12 explicit MessageHandlerTestPeer(MessageHandler* handler) |
14 : handler_(handler) {} | 13 : handler_(handler) {} |
15 | 14 |
16 void PostMessage(Message* message) { handler_->PostMessage(message); } | 15 void PostMessage(Message* message) { handler_->PostMessage(message); } |
17 void ClosePort(Dart_Port port) { handler_->ClosePort(port); } | 16 void ClosePort(Dart_Port port) { handler_->ClosePort(port); } |
18 void CloseAllPorts() { handler_->CloseAllPorts(); } | 17 void CloseAllPorts() { handler_->CloseAllPorts(); } |
19 | 18 |
20 void increment_live_ports() { handler_->increment_live_ports(); } | 19 void increment_live_ports() { handler_->increment_live_ports(); } |
21 void decrement_live_ports() { handler_->decrement_live_ports(); } | 20 void decrement_live_ports() { handler_->decrement_live_ports(); } |
22 | 21 |
23 MessageQueue* queue() const { return handler_->queue_; } | 22 MessageQueue* queue() const { return handler_->queue_; } |
24 MessageQueue* oob_queue() const { return handler_->oob_queue_; } | 23 MessageQueue* oob_queue() const { return handler_->oob_queue_; } |
25 | 24 |
26 private: | 25 private: |
27 MessageHandler* handler_; | 26 MessageHandler* handler_; |
28 | 27 |
29 DISALLOW_COPY_AND_ASSIGN(MessageHandlerTestPeer); | 28 DISALLOW_COPY_AND_ASSIGN(MessageHandlerTestPeer); |
30 }; | 29 }; |
31 | 30 |
32 | 31 |
33 class TestMessageHandler : public MessageHandler { | 32 class TestMessageHandler : public MessageHandler { |
34 public: | 33 public: |
35 TestMessageHandler() | 34 TestMessageHandler() |
36 : port_buffer_(NULL), | 35 : port_buffer_(strdup("")), |
37 port_buffer_size_(0), | |
38 notify_count_(0), | 36 notify_count_(0), |
39 message_count_(0), | 37 message_count_(0), |
40 start_called_(false), | |
41 end_called_(false), | |
42 result_(true) { | 38 result_(true) { |
43 } | 39 } |
44 | 40 |
45 ~TestMessageHandler() { | 41 ~TestMessageHandler() { |
46 delete[] port_buffer_; | 42 free(port_buffer_); |
47 } | 43 } |
48 | 44 |
49 void MessageNotify(Message::Priority priority) { | 45 void MessageNotify(Message::Priority priority) { |
50 notify_count_++; | 46 notify_count_++; |
51 } | 47 } |
52 | 48 |
53 bool HandleMessage(Message* message) { | 49 bool HandleMessage(Message* message) { |
54 // For testing purposes, keep a list of the ports | 50 // For testing purposes, keep a string with a list of the ports |
55 // for all messages we receive. | 51 // for all messages we receive. |
56 AddPortToBuffer(message->dest_port()); | 52 intptr_t len = |
| 53 OS::SNPrint(NULL, 0, "%s %"Pd64"", |
| 54 port_buffer_, |
| 55 message->dest_port()) + 1; |
| 56 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 57 OS::SNPrint(buffer, len, "%s %"Pd64"", |
| 58 port_buffer_, |
| 59 message->dest_port()); |
| 60 free(port_buffer_); |
| 61 port_buffer_ = buffer; |
57 delete message; | 62 delete message; |
58 message_count_++; | 63 message_count_++; |
59 return result_; | 64 return result_; |
60 } | 65 } |
61 | 66 |
| 67 |
62 bool Start() { | 68 bool Start() { |
63 start_called_ = true; | 69 intptr_t len = |
| 70 OS::SNPrint(NULL, 0, "%s start", port_buffer_) + 1; |
| 71 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 72 OS::SNPrint(buffer, len, "%s start", port_buffer_); |
| 73 free(port_buffer_); |
| 74 port_buffer_ = buffer; |
64 return true; | 75 return true; |
65 } | 76 } |
66 | 77 |
| 78 |
67 void End() { | 79 void End() { |
68 end_called_ = true; | 80 intptr_t len = |
69 AddPortToBuffer(-2); | 81 OS::SNPrint(NULL, 0, "%s end", port_buffer_) + 1; |
| 82 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 83 OS::SNPrint(buffer, len, "%s end", port_buffer_); |
| 84 free(port_buffer_); |
| 85 port_buffer_ = buffer; |
70 } | 86 } |
71 | 87 |
72 Dart_Port* port_buffer() const { return port_buffer_; } | 88 |
| 89 const char* port_buffer() const { return port_buffer_; } |
73 int notify_count() const { return notify_count_; } | 90 int notify_count() const { return notify_count_; } |
74 int message_count() const { return message_count_; } | 91 int message_count() const { return message_count_; } |
75 bool start_called() const { return start_called_; } | |
76 bool end_called() const { return end_called_; } | |
77 | 92 |
78 void set_result(bool result) { result_ = result; } | 93 void set_result(bool result) { result_ = result; } |
79 | 94 |
80 private: | 95 private: |
81 void AddPortToBuffer(Dart_Port port) { | 96 char* port_buffer_; |
82 if (port_buffer_ == NULL) { | |
83 port_buffer_ = new Dart_Port[10]; | |
84 port_buffer_size_ = 10; | |
85 } else if (message_count_ == port_buffer_size_) { | |
86 port_buffer_size_ = 2 * port_buffer_size_; | |
87 delete[] port_buffer_; | |
88 port_buffer_ = new Dart_Port[port_buffer_size_]; | |
89 } | |
90 port_buffer_[message_count_] = port; | |
91 } | |
92 | |
93 Dart_Port* port_buffer_; | |
94 int port_buffer_size_; | |
95 int notify_count_; | 97 int notify_count_; |
96 int message_count_; | 98 int message_count_; |
97 bool start_called_; | |
98 bool end_called_; | |
99 bool result_; | 99 bool result_; |
100 | 100 |
101 DISALLOW_COPY_AND_ASSIGN(TestMessageHandler); | 101 DISALLOW_COPY_AND_ASSIGN(TestMessageHandler); |
102 }; | 102 }; |
103 | 103 |
104 | 104 |
105 bool TestStartFunction(uword data) { | 105 bool TestStartFunction(uword data) { |
106 return (reinterpret_cast<TestMessageHandler*>(data))->Start(); | 106 return (reinterpret_cast<TestMessageHandler*>(data))->Start(); |
107 } | 107 } |
108 | 108 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 UNIT_TEST_CASE(MessageHandler_ClosePort) { | 146 UNIT_TEST_CASE(MessageHandler_ClosePort) { |
147 TestMessageHandler handler; | 147 TestMessageHandler handler; |
148 MessageHandlerTestPeer handler_peer(&handler); | 148 MessageHandlerTestPeer handler_peer(&handler); |
149 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); | 149 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); |
150 handler_peer.PostMessage(message1); | 150 handler_peer.PostMessage(message1); |
151 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); | 151 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); |
152 handler_peer.PostMessage(message2); | 152 handler_peer.PostMessage(message2); |
153 | 153 |
154 handler_peer.ClosePort(1); | 154 handler_peer.ClosePort(1); |
155 | 155 |
156 // Closing the port does not drop the messages from the queue. | 156 // The message on port 1 is dropped from the queue. |
157 EXPECT(message1 == handler_peer.queue()->Dequeue()); | |
158 EXPECT(message2 == handler_peer.queue()->Dequeue()); | 157 EXPECT(message2 == handler_peer.queue()->Dequeue()); |
159 delete message1; | 158 EXPECT(NULL == handler_peer.queue()->Dequeue()); |
160 delete message2; | 159 delete message2; |
161 } | 160 } |
162 | 161 |
163 | 162 |
164 UNIT_TEST_CASE(MessageHandler_CloseAllPorts) { | 163 UNIT_TEST_CASE(MessageHandler_CloseAllPorts) { |
165 TestMessageHandler handler; | 164 TestMessageHandler handler; |
166 MessageHandlerTestPeer handler_peer(&handler); | 165 MessageHandlerTestPeer handler_peer(&handler); |
167 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); | 166 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); |
168 handler_peer.PostMessage(message1); | 167 handler_peer.PostMessage(message1); |
169 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); | 168 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); |
170 handler_peer.PostMessage(message2); | 169 handler_peer.PostMessage(message2); |
171 | 170 |
172 handler_peer.CloseAllPorts(); | 171 handler_peer.CloseAllPorts(); |
173 | 172 |
174 // All messages are dropped from the queue. | 173 // All messages are dropped from the queue. |
175 EXPECT(NULL == handler_peer.queue()->Dequeue()); | 174 EXPECT(NULL == handler_peer.queue()->Dequeue()); |
176 } | 175 } |
177 | 176 |
178 | 177 |
179 UNIT_TEST_CASE(MessageHandler_HandleNextMessage) { | 178 UNIT_TEST_CASE(MessageHandler_HandleNextMessage) { |
180 TestMessageHandler handler; | 179 TestMessageHandler handler; |
181 MessageHandlerTestPeer handler_peer(&handler); | 180 MessageHandlerTestPeer handler_peer(&handler); |
182 Dart_Port port1 = PortMap::CreatePort(&handler); | 181 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); |
183 Dart_Port port2 = PortMap::CreatePort(&handler); | |
184 Dart_Port port3 = PortMap::CreatePort(&handler); | |
185 Message* message1 = new Message(port1, 0, NULL, 0, Message::kNormalPriority); | |
186 handler_peer.PostMessage(message1); | 182 handler_peer.PostMessage(message1); |
187 Message* oob_message1 = new Message(port2, 0, NULL, 0, Message::kOOBPriority); | 183 Message* oob_message1 = new Message(3, 0, NULL, 0, Message::kOOBPriority); |
188 handler_peer.PostMessage(oob_message1); | 184 handler_peer.PostMessage(oob_message1); |
189 Message* message2 = new Message(port2, 0, NULL, 0, Message::kNormalPriority); | 185 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); |
190 handler_peer.PostMessage(message2); | 186 handler_peer.PostMessage(message2); |
191 Message* oob_message2 = new Message(port3, 0, NULL, 0, Message::kOOBPriority); | 187 Message* oob_message2 = new Message(4, 0, NULL, 0, Message::kOOBPriority); |
192 handler_peer.PostMessage(oob_message2); | 188 handler_peer.PostMessage(oob_message2); |
193 | 189 |
194 // We handle both oob messages and a single normal message. | 190 // We handle both oob messages and a single normal message. |
195 EXPECT(handler.HandleNextMessage()); | 191 EXPECT(handler.HandleNextMessage()); |
196 EXPECT_EQ(3, handler.message_count()); | 192 EXPECT_STREQ(" 3 4 1", handler.port_buffer()); |
197 Dart_Port* ports = handler.port_buffer(); | 193 handler_peer.CloseAllPorts(); |
198 EXPECT_EQ(port2, ports[0]); | |
199 EXPECT_EQ(port3, ports[1]); | |
200 EXPECT_EQ(port1, ports[2]); | |
201 PortMap::ClosePorts(&handler); | |
202 } | 194 } |
203 | 195 |
204 | 196 |
205 UNIT_TEST_CASE(MessageHandler_HandleOOBMessages) { | 197 UNIT_TEST_CASE(MessageHandler_HandleOOBMessages) { |
206 TestMessageHandler handler; | 198 TestMessageHandler handler; |
207 MessageHandlerTestPeer handler_peer(&handler); | 199 MessageHandlerTestPeer handler_peer(&handler); |
208 Dart_Port port1 = PortMap::CreatePort(&handler); | 200 Message* message1 = new Message(1, 0, NULL, 0, Message::kNormalPriority); |
209 Dart_Port port2 = PortMap::CreatePort(&handler); | |
210 Dart_Port port3 = PortMap::CreatePort(&handler); | |
211 Dart_Port port4 = PortMap::CreatePort(&handler); | |
212 Message* message1 = new Message(port1, 0, NULL, 0, Message::kNormalPriority); | |
213 handler_peer.PostMessage(message1); | 201 handler_peer.PostMessage(message1); |
214 Message* message2 = new Message(port2, 0, NULL, 0, Message::kNormalPriority); | 202 Message* message2 = new Message(2, 0, NULL, 0, Message::kNormalPriority); |
215 handler_peer.PostMessage(message2); | 203 handler_peer.PostMessage(message2); |
216 Message* oob_message1 = new Message(port3, 0, NULL, 0, Message::kOOBPriority); | 204 Message* oob_message1 = new Message(3, 0, NULL, 0, Message::kOOBPriority); |
217 handler_peer.PostMessage(oob_message1); | 205 handler_peer.PostMessage(oob_message1); |
218 Message* oob_message2 = new Message(port4, 0, NULL, 0, Message::kOOBPriority); | 206 Message* oob_message2 = new Message(4, 0, NULL, 0, Message::kOOBPriority); |
219 handler_peer.PostMessage(oob_message2); | 207 handler_peer.PostMessage(oob_message2); |
220 | 208 |
221 // We handle both oob messages but no normal messages. | 209 // We handle both oob messages but no normal messages. |
222 EXPECT(handler.HandleOOBMessages()); | 210 EXPECT(handler.HandleOOBMessages()); |
223 EXPECT_EQ(2, handler.message_count()); | 211 EXPECT_STREQ(" 3 4", handler.port_buffer()); |
224 Dart_Port* ports = handler.port_buffer(); | |
225 EXPECT_EQ(port3, ports[0]); | |
226 EXPECT_EQ(port4, ports[1]); | |
227 handler_peer.CloseAllPorts(); | 212 handler_peer.CloseAllPorts(); |
228 } | 213 } |
229 | 214 |
230 | 215 |
231 struct ThreadStartInfo { | 216 struct ThreadStartInfo { |
232 MessageHandler* handler; | 217 MessageHandler* handler; |
233 Dart_Port* ports; | |
234 int count; | 218 int count; |
235 }; | 219 }; |
236 | 220 |
237 | 221 |
238 static void SendMessages(uword param) { | 222 static void SendMessages(uword param) { |
239 ThreadStartInfo* info = reinterpret_cast<ThreadStartInfo*>(param); | 223 ThreadStartInfo* info = reinterpret_cast<ThreadStartInfo*>(param); |
240 MessageHandler* handler = info->handler; | 224 MessageHandler* handler = info->handler; |
241 MessageHandlerTestPeer handler_peer(handler); | 225 MessageHandlerTestPeer handler_peer(handler); |
242 for (int i = 0; i < info->count; i++) { | 226 for (int i = 0; i < info->count; i++) { |
243 Message* message = | 227 Message* message = new Message(i + 1, 0, NULL, 0, Message::kNormalPriority); |
244 new Message(info->ports[i], 0, NULL, 0, Message::kNormalPriority); | |
245 handler_peer.PostMessage(message); | 228 handler_peer.PostMessage(message); |
246 } | 229 } |
247 } | 230 } |
248 | 231 |
249 | 232 |
250 UNIT_TEST_CASE(MessageHandler_Run) { | 233 UNIT_TEST_CASE(MessageHandler_Run) { |
251 ThreadPool pool; | 234 ThreadPool pool; |
252 TestMessageHandler handler; | 235 TestMessageHandler handler; |
253 MessageHandlerTestPeer handler_peer(&handler); | 236 MessageHandlerTestPeer handler_peer(&handler); |
254 int sleep = 0; | 237 int sleep = 0; |
255 const int kMaxSleep = 20 * 1000; // 20 seconds. | 238 const int kMaxSleep = 20 * 1000; // 20 seconds. |
256 | 239 |
257 EXPECT(!handler.HasLivePorts()); | 240 EXPECT(!handler.HasLivePorts()); |
258 handler_peer.increment_live_ports(); | 241 handler_peer.increment_live_ports(); |
259 | 242 |
260 handler.Run(&pool, | 243 handler.Run(&pool, |
261 TestStartFunction, | 244 TestStartFunction, |
262 TestEndFunction, | 245 TestEndFunction, |
263 reinterpret_cast<uword>(&handler)); | 246 reinterpret_cast<uword>(&handler)); |
264 Dart_Port port = PortMap::CreatePort(&handler); | 247 Message* message = new Message(100, 0, NULL, 0, Message::kNormalPriority); |
265 Message* message = new Message(port, 0, NULL, 0, Message::kNormalPriority); | |
266 handler_peer.PostMessage(message); | 248 handler_peer.PostMessage(message); |
267 | 249 |
268 // Wait for the first message to be handled. | 250 // Wait for the first message to be handled. |
269 while (sleep < kMaxSleep && handler.message_count() < 1) { | 251 while (sleep < kMaxSleep && handler.message_count() < 1) { |
270 OS::Sleep(10); | 252 OS::Sleep(10); |
271 sleep += 10; | 253 sleep += 10; |
272 } | 254 } |
273 EXPECT_EQ(1, handler.message_count()); | 255 EXPECT_STREQ(" start 100", handler.port_buffer()); |
274 EXPECT(handler.start_called()); | |
275 EXPECT(!handler.end_called()); | |
276 Dart_Port* handler_ports = handler.port_buffer(); | |
277 EXPECT_EQ(port, handler_ports[0]); | |
278 | 256 |
279 // Start a thread which sends more messages. | 257 // Start a thread which sends more messages. |
280 Dart_Port* ports = new Dart_Port[10]; | |
281 for (int i = 0; i < 10; i++) { | |
282 ports[i] = PortMap::CreatePort(&handler); | |
283 } | |
284 ThreadStartInfo info; | 258 ThreadStartInfo info; |
285 info.handler = &handler; | 259 info.handler = &handler; |
286 info.ports = ports; | |
287 info.count = 10; | 260 info.count = 10; |
288 Thread::Start(SendMessages, reinterpret_cast<uword>(&info)); | 261 Thread::Start(SendMessages, reinterpret_cast<uword>(&info)); |
289 while (sleep < kMaxSleep && handler.message_count() < 11) { | 262 while (sleep < kMaxSleep && handler.message_count() < 11) { |
290 OS::Sleep(10); | 263 OS::Sleep(10); |
291 sleep += 10; | 264 sleep += 10; |
292 } | 265 } |
293 EXPECT_EQ(11, handler.message_count()); | 266 EXPECT_STREQ(" start 100 1 2 3 4 5 6 7 8 9 10", handler.port_buffer()); |
294 EXPECT(handler.start_called()); | 267 |
295 EXPECT(!handler.end_called()); | |
296 EXPECT_EQ(port, handler_ports[0]); | |
297 for (int i = 1; i < 11; i++) { | |
298 EXPECT_EQ(ports[i - 1], handler_ports[i]); | |
299 } | |
300 handler_peer.decrement_live_ports(); | 268 handler_peer.decrement_live_ports(); |
301 EXPECT(!handler.HasLivePorts()); | 269 EXPECT(!handler.HasLivePorts()); |
302 PortMap::ClosePorts(&handler); | |
303 } | 270 } |
304 | 271 |
305 } // namespace dart | 272 } // namespace dart |
OLD | NEW |