Index: runtime/vm/message_handler_test.cc |
=================================================================== |
--- runtime/vm/message_handler_test.cc (revision 0) |
+++ runtime/vm/message_handler_test.cc (revision 0) |
@@ -0,0 +1,268 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include "vm/message_handler.h" |
+#include "vm/unit_test.h" |
+ |
+namespace dart { |
+ |
+class MessageHandlerTestPeer { |
+ public: |
+ explicit MessageHandlerTestPeer(MessageHandler* handler) |
+ : handler_(handler) {} |
+ |
+ void PostMessage(Message* message) { handler_->PostMessage(message); } |
+ void ClosePort(Dart_Port port) { handler_->ClosePort(port); } |
+ void CloseAllPorts() { handler_->CloseAllPorts(); } |
+ |
+ void increment_live_ports() { handler_->increment_live_ports(); } |
+ void decrement_live_ports() { handler_->decrement_live_ports(); } |
+ |
+ MessageQueue* queue() const { return handler_->queue_; } |
+ MessageQueue* oob_queue() const { return handler_->oob_queue_; } |
+ |
+ private: |
+ MessageHandler* handler_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MessageHandlerTestPeer); |
+}; |
+ |
+ |
+class TestMessageHandler : public MessageHandler { |
+ public: |
+ TestMessageHandler() |
+ : port_buffer_(strdup("")), |
+ notify_count_(0), |
+ message_count_(0), |
+ result_(true) { |
+ } |
+ |
+ ~TestMessageHandler() { |
+ free(port_buffer_); |
+ } |
+ |
+ void MessageNotify(Message::Priority priority) { |
+ notify_count_++; |
+ } |
+ |
+ bool HandleMessage(Message* message) { |
+ // For testing purposes, keep a string with a list of the ports |
+ // for all messages we receive. |
+ intptr_t len = |
+ OS::SNPrint(NULL, 0, "%s %d", port_buffer_, message->dest_port()) + 1; |
+ char* buffer = reinterpret_cast<char*>(malloc(len)); |
+ OS::SNPrint(buffer, len, "%s %d", port_buffer_, message->dest_port()); |
+ free(port_buffer_); |
+ port_buffer_ = buffer; |
+ delete message; |
+ message_count_++; |
+ return result_; |
+ } |
+ |
+ |
+ bool Start() { |
+ intptr_t len = |
+ OS::SNPrint(NULL, 0, "%s start", port_buffer_) + 1; |
+ char* buffer = reinterpret_cast<char*>(malloc(len)); |
+ OS::SNPrint(buffer, len, "%s start", port_buffer_); |
+ free(port_buffer_); |
+ port_buffer_ = buffer; |
+ return true; |
+ } |
+ |
+ |
+ void End() { |
+ intptr_t len = |
+ OS::SNPrint(NULL, 0, "%s end", port_buffer_) + 1; |
+ char* buffer = reinterpret_cast<char*>(malloc(len)); |
+ OS::SNPrint(buffer, len, "%s end", port_buffer_); |
+ free(port_buffer_); |
+ port_buffer_ = buffer; |
+ } |
+ |
+ |
+ const char* port_buffer() const { return port_buffer_; } |
+ int notify_count() const { return notify_count_; } |
+ int message_count() const { return message_count_; } |
+ |
+ void set_result(bool result) { result_ = result; } |
+ |
+ private: |
+ char* port_buffer_; |
+ int notify_count_; |
+ int message_count_; |
+ bool result_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestMessageHandler); |
+}; |
+ |
+ |
+bool TestStartFunction(uword data) { |
+ return (reinterpret_cast<TestMessageHandler*>(data))->Start(); |
+} |
+ |
+ |
+void TestEndFunction(uword data) { |
+ return (reinterpret_cast<TestMessageHandler*>(data))->End(); |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_PostMessage) { |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ EXPECT_EQ(0, handler.notify_count()); |
+ |
+ // Post a message. |
+ Message* message = new Message(0, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message); |
+ |
+ // The notify callback is called. |
+ EXPECT_EQ(1, handler.notify_count()); |
+ |
+ // The message has been added to the correct queue. |
+ EXPECT(message == handler_peer.queue()->Dequeue()); |
+ EXPECT(NULL == handler_peer.oob_queue()->Dequeue()); |
+ delete message; |
+ |
+ // Post an oob message. |
+ message = new Message(0, 0, NULL, Message::kOOBPriority); |
+ handler_peer.PostMessage(message); |
+ |
+ // The notify callback is called. |
+ EXPECT_EQ(2, handler.notify_count()); |
+ |
+ // The message has been added to the correct queue. |
+ EXPECT(message == handler_peer.oob_queue()->Dequeue()); |
+ EXPECT(NULL == handler_peer.queue()->Dequeue()); |
+ delete message; |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_ClosePort) { |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message1); |
+ Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message2); |
+ |
+ handler_peer.ClosePort(1); |
+ |
+ // The message on port 1 is dropped from the queue. |
+ EXPECT(message2 == handler_peer.queue()->Dequeue()); |
+ EXPECT(NULL == handler_peer.queue()->Dequeue()); |
+ delete message2; |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_CloseAllPorts) { |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message1); |
+ Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message2); |
+ |
+ handler_peer.CloseAllPorts(); |
+ |
+ // All messages are dropped from the queue. |
+ EXPECT(NULL == handler_peer.queue()->Dequeue()); |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_HandleNextMessage) { |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message1); |
+ Message* oob_message1 = new Message(3, 0, NULL, Message::kOOBPriority); |
+ handler_peer.PostMessage(oob_message1); |
+ Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message2); |
+ Message* oob_message2 = new Message(4, 0, NULL, Message::kOOBPriority); |
+ handler_peer.PostMessage(oob_message2); |
+ |
+ // We handle both oob messages and a single normal message. |
+ EXPECT(handler.HandleNextMessage()); |
+ EXPECT_STREQ(" 3 4 1", handler.port_buffer()); |
+ handler_peer.CloseAllPorts(); |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_HandleOOBMessages) { |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ Message* message1 = new Message(1, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message1); |
+ Message* message2 = new Message(2, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message2); |
+ Message* oob_message1 = new Message(3, 0, NULL, Message::kOOBPriority); |
+ handler_peer.PostMessage(oob_message1); |
+ Message* oob_message2 = new Message(4, 0, NULL, Message::kOOBPriority); |
+ handler_peer.PostMessage(oob_message2); |
+ |
+ // We handle both oob messages but no normal messages. |
+ EXPECT(handler.HandleOOBMessages()); |
+ EXPECT_STREQ(" 3 4", handler.port_buffer()); |
+ handler_peer.CloseAllPorts(); |
+} |
+ |
+ |
+struct ThreadStartInfo { |
+ MessageHandler* handler; |
+ int count; |
+}; |
+ |
+ |
+static void SendMessages(uword param) { |
+ ThreadStartInfo* info = reinterpret_cast<ThreadStartInfo*>(param); |
+ MessageHandler* handler = info->handler; |
+ MessageHandlerTestPeer handler_peer(handler); |
+ for (int i = 0; i < info->count; i++) { |
+ Message* message = new Message(i + 1, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message); |
+ } |
+} |
+ |
+ |
+UNIT_TEST_CASE(MessageHandler_Run) { |
+ ThreadPool pool; |
+ TestMessageHandler handler; |
+ MessageHandlerTestPeer handler_peer(&handler); |
+ int sleep = 0; |
+ const int kMaxSleep = 20 * 1000; // 20 seconds. |
+ |
+ EXPECT(!handler.HasLivePorts()); |
+ handler_peer.increment_live_ports(); |
+ |
+ handler.Run(&pool, |
+ TestStartFunction, |
+ TestEndFunction, |
+ reinterpret_cast<uword>(&handler)); |
+ Message* message = new Message(100, 0, NULL, Message::kNormalPriority); |
+ handler_peer.PostMessage(message); |
+ |
+ // Wait for the first message to be handled. |
+ while (sleep < kMaxSleep && handler.message_count() < 1) { |
+ OS::Sleep(10); |
+ sleep += 10; |
+ } |
+ EXPECT_STREQ(" start 100", handler.port_buffer()); |
+ |
+ // Start a thread which sends more messages. |
+ ThreadStartInfo info; |
+ info.handler = &handler; |
+ info.count = 10; |
+ Thread::Start(SendMessages, reinterpret_cast<uword>(&info)); |
+ while (sleep < kMaxSleep && handler.message_count() < 11) { |
+ OS::Sleep(10); |
+ sleep += 10; |
+ } |
+ EXPECT_STREQ(" start 100 1 2 3 4 5 6 7 8 9 10", handler.port_buffer()); |
+ |
+ handler_peer.decrement_live_ports(); |
+ EXPECT(!handler.HasLivePorts()); |
+} |
+ |
+} // namespace dart |