OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include "vm/message_handler.h" |
| 6 #include "vm/unit_test.h" |
| 7 |
| 8 namespace dart { |
| 9 |
| 10 class MessageHandlerTestPeer { |
| 11 public: |
| 12 explicit MessageHandlerTestPeer(MessageHandler* handler) |
| 13 : handler_(handler) {} |
| 14 |
| 15 void PostMessage(Message* message) { handler_->PostMessage(message); } |
| 16 void ClosePort(Dart_Port port) { handler_->ClosePort(port); } |
| 17 void CloseAllPorts() { handler_->CloseAllPorts(); } |
| 18 |
| 19 void increment_live_ports() { handler_->increment_live_ports(); } |
| 20 void decrement_live_ports() { handler_->decrement_live_ports(); } |
| 21 |
| 22 MessageQueue* queue() const { return handler_->queue_; } |
| 23 MessageQueue* oob_queue() const { return handler_->oob_queue_; } |
| 24 |
| 25 private: |
| 26 MessageHandler* handler_; |
| 27 |
| 28 DISALLOW_COPY_AND_ASSIGN(MessageHandlerTestPeer); |
| 29 }; |
| 30 |
| 31 |
| 32 class TestMessageHandler : public MessageHandler { |
| 33 public: |
| 34 TestMessageHandler() |
| 35 : port_buffer_(strdup("")), |
| 36 notify_count_(0), |
| 37 message_count_(0), |
| 38 result_(true) { |
| 39 } |
| 40 |
| 41 ~TestMessageHandler() { |
| 42 free(port_buffer_); |
| 43 } |
| 44 |
| 45 void MessageNotify(Message::Priority priority) { |
| 46 notify_count_++; |
| 47 } |
| 48 |
| 49 bool HandleMessage(Message* message) { |
| 50 // For testing purposes, keep a string with a list of the ports |
| 51 // for all messages we receive. |
| 52 intptr_t len = |
| 53 OS::SNPrint(NULL, 0, "%s %d", port_buffer_, message->dest_port()) + 1; |
| 54 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 55 OS::SNPrint(buffer, len, "%s %d", port_buffer_, message->dest_port()); |
| 56 free(port_buffer_); |
| 57 port_buffer_ = buffer; |
| 58 delete message; |
| 59 message_count_++; |
| 60 return result_; |
| 61 } |
| 62 |
| 63 |
| 64 bool Start() { |
| 65 intptr_t len = |
| 66 OS::SNPrint(NULL, 0, "%s start", port_buffer_) + 1; |
| 67 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 68 OS::SNPrint(buffer, len, "%s start", port_buffer_); |
| 69 free(port_buffer_); |
| 70 port_buffer_ = buffer; |
| 71 return true; |
| 72 } |
| 73 |
| 74 |
| 75 void End() { |
| 76 intptr_t len = |
| 77 OS::SNPrint(NULL, 0, "%s end", port_buffer_) + 1; |
| 78 char* buffer = reinterpret_cast<char*>(malloc(len)); |
| 79 OS::SNPrint(buffer, len, "%s end", port_buffer_); |
| 80 free(port_buffer_); |
| 81 port_buffer_ = buffer; |
| 82 } |
| 83 |
| 84 |
| 85 const char* port_buffer() const { return port_buffer_; } |
| 86 int notify_count() const { return notify_count_; } |
| 87 int message_count() const { return message_count_; } |
| 88 |
| 89 void set_result(bool result) { result_ = result; } |
| 90 |
| 91 private: |
| 92 char* port_buffer_; |
| 93 int notify_count_; |
| 94 int message_count_; |
| 95 bool result_; |
| 96 |
| 97 DISALLOW_COPY_AND_ASSIGN(TestMessageHandler); |
| 98 }; |
| 99 |
| 100 |
| 101 bool TestStartFunction(uword data) { |
| 102 return (reinterpret_cast<TestMessageHandler*>(data))->Start(); |
| 103 } |
| 104 |
| 105 |
| 106 void TestEndFunction(uword data) { |
| 107 return (reinterpret_cast<TestMessageHandler*>(data))->End(); |
| 108 } |
| 109 |
| 110 |
| 111 UNIT_TEST_CASE(MessageHandler_PostMessage) { |
| 112 TestMessageHandler handler; |
| 113 MessageHandlerTestPeer handler_peer(&handler); |
| 114 EXPECT_EQ(0, handler.notify_count()); |
| 115 |
| 116 // Post a message. |
| 117 Message* message = new Message(0, 0, NULL, Message::kNormalPriority); |
| 118 handler_peer.PostMessage(message); |
| 119 |
| 120 // The notify callback is called. |
| 121 EXPECT_EQ(1, handler.notify_count()); |
| 122 |
| 123 // The message has been added to the correct queue. |
| 124 EXPECT(message == handler_peer.queue()->Dequeue()); |
| 125 EXPECT(NULL == handler_peer.oob_queue()->Dequeue()); |
| 126 delete message; |
| 127 |
| 128 // Post an oob message. |
| 129 message = new Message(0, 0, NULL, Message::kOOBPriority); |
| 130 handler_peer.PostMessage(message); |
| 131 |
| 132 // The notify callback is called. |
| 133 EXPECT_EQ(2, handler.notify_count()); |
| 134 |
| 135 // The message has been added to the correct queue. |
| 136 EXPECT(message == handler_peer.oob_queue()->Dequeue()); |
| 137 EXPECT(NULL == handler_peer.queue()->Dequeue()); |
| 138 delete message; |
| 139 } |
| 140 |
| 141 |
| 142 UNIT_TEST_CASE(MessageHandler_ClosePort) { |
| 143 TestMessageHandler handler; |
| 144 MessageHandlerTestPeer handler_peer(&handler); |
| 145 Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
| 146 handler_peer.PostMessage(message1); |
| 147 Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
| 148 handler_peer.PostMessage(message2); |
| 149 |
| 150 handler_peer.ClosePort(1); |
| 151 |
| 152 // The message on port 1 is dropped from the queue. |
| 153 EXPECT(message2 == handler_peer.queue()->Dequeue()); |
| 154 EXPECT(NULL == handler_peer.queue()->Dequeue()); |
| 155 delete message2; |
| 156 } |
| 157 |
| 158 |
| 159 UNIT_TEST_CASE(MessageHandler_CloseAllPorts) { |
| 160 TestMessageHandler handler; |
| 161 MessageHandlerTestPeer handler_peer(&handler); |
| 162 Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
| 163 handler_peer.PostMessage(message1); |
| 164 Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
| 165 handler_peer.PostMessage(message2); |
| 166 |
| 167 handler_peer.CloseAllPorts(); |
| 168 |
| 169 // All messages are dropped from the queue. |
| 170 EXPECT(NULL == handler_peer.queue()->Dequeue()); |
| 171 } |
| 172 |
| 173 |
| 174 UNIT_TEST_CASE(MessageHandler_HandleNextMessage) { |
| 175 TestMessageHandler handler; |
| 176 MessageHandlerTestPeer handler_peer(&handler); |
| 177 Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
| 178 handler_peer.PostMessage(message1); |
| 179 Message* oob_message1 = new Message(3, 0, NULL, Message::kOOBPriority); |
| 180 handler_peer.PostMessage(oob_message1); |
| 181 Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
| 182 handler_peer.PostMessage(message2); |
| 183 Message* oob_message2 = new Message(4, 0, NULL, Message::kOOBPriority); |
| 184 handler_peer.PostMessage(oob_message2); |
| 185 |
| 186 // We handle both oob messages and a single normal message. |
| 187 EXPECT(handler.HandleNextMessage()); |
| 188 EXPECT_STREQ(" 3 4 1", handler.port_buffer()); |
| 189 handler_peer.CloseAllPorts(); |
| 190 } |
| 191 |
| 192 |
| 193 UNIT_TEST_CASE(MessageHandler_HandleOOBMessages) { |
| 194 TestMessageHandler handler; |
| 195 MessageHandlerTestPeer handler_peer(&handler); |
| 196 Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
| 197 handler_peer.PostMessage(message1); |
| 198 Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
| 199 handler_peer.PostMessage(message2); |
| 200 Message* oob_message1 = new Message(3, 0, NULL, Message::kOOBPriority); |
| 201 handler_peer.PostMessage(oob_message1); |
| 202 Message* oob_message2 = new Message(4, 0, NULL, Message::kOOBPriority); |
| 203 handler_peer.PostMessage(oob_message2); |
| 204 |
| 205 // We handle both oob messages but no normal messages. |
| 206 EXPECT(handler.HandleOOBMessages()); |
| 207 EXPECT_STREQ(" 3 4", handler.port_buffer()); |
| 208 handler_peer.CloseAllPorts(); |
| 209 } |
| 210 |
| 211 |
| 212 struct ThreadStartInfo { |
| 213 MessageHandler* handler; |
| 214 int count; |
| 215 }; |
| 216 |
| 217 |
| 218 static void SendMessages(uword param) { |
| 219 ThreadStartInfo* info = reinterpret_cast<ThreadStartInfo*>(param); |
| 220 MessageHandler* handler = info->handler; |
| 221 MessageHandlerTestPeer handler_peer(handler); |
| 222 for (int i = 0; i < info->count; i++) { |
| 223 Message* message = new Message(i + 1, 0, NULL, Message::kNormalPriority); |
| 224 handler_peer.PostMessage(message); |
| 225 } |
| 226 } |
| 227 |
| 228 |
| 229 UNIT_TEST_CASE(MessageHandler_Run) { |
| 230 ThreadPool pool; |
| 231 TestMessageHandler handler; |
| 232 MessageHandlerTestPeer handler_peer(&handler); |
| 233 int sleep = 0; |
| 234 const int kMaxSleep = 20 * 1000; // 20 seconds. |
| 235 |
| 236 EXPECT(!handler.HasLivePorts()); |
| 237 handler_peer.increment_live_ports(); |
| 238 |
| 239 handler.Run(&pool, |
| 240 TestStartFunction, |
| 241 TestEndFunction, |
| 242 reinterpret_cast<uword>(&handler)); |
| 243 Message* message = new Message(100, 0, NULL, Message::kNormalPriority); |
| 244 handler_peer.PostMessage(message); |
| 245 |
| 246 // Wait for the first message to be handled. |
| 247 while (sleep < kMaxSleep && handler.message_count() < 1) { |
| 248 OS::Sleep(10); |
| 249 sleep += 10; |
| 250 } |
| 251 EXPECT_STREQ(" start 100", handler.port_buffer()); |
| 252 |
| 253 // Start a thread which sends more messages. |
| 254 ThreadStartInfo info; |
| 255 info.handler = &handler; |
| 256 info.count = 10; |
| 257 Thread::Start(SendMessages, reinterpret_cast<uword>(&info)); |
| 258 while (sleep < kMaxSleep && handler.message_count() < 11) { |
| 259 OS::Sleep(10); |
| 260 sleep += 10; |
| 261 } |
| 262 EXPECT_STREQ(" start 100 1 2 3 4 5 6 7 8 9 10", handler.port_buffer()); |
| 263 |
| 264 handler_peer.decrement_live_ports(); |
| 265 EXPECT(!handler.HasLivePorts()); |
| 266 } |
| 267 |
| 268 } // namespace dart |
OLD | NEW |