Chromium Code Reviews| Index: runtime/vm/message_queue_test.cc |
| =================================================================== |
| --- runtime/vm/message_queue_test.cc (revision 446) |
| +++ runtime/vm/message_queue_test.cc (working copy) |
| @@ -3,129 +3,157 @@ |
| // BSD-style license that can be found in the LICENSE file. |
| #include "vm/assert.h" |
| -#include "vm/port.h" |
| +#include "vm/message_queue.h" |
| #include "vm/unit_test.h" |
| namespace dart { |
| -TEST_CASE(Port) { |
| - const char* msg_data = "Hallo Velo!"; |
| - intptr_t port1 = PortMap::CreatePort(); |
| - intptr_t port2 = PortMap::CreatePort(); |
| - EXPECT(port1 != port2); |
| +// Provide access to private members of MessageQueue for testing. |
| +class MessageQueueTestPeer { |
| + public: |
| + explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {} |
| - PortMessage* msg1 = new PortMessage(port1, 0, strdup(msg_data)); |
| - EXPECT_EQ(true, PortMap::PostMessage(msg1)); |
| - PortMessage* msg = PortMap::ReceiveMessage(10); |
| - EXPECT_EQ(port1, msg->dest_id()); |
| - EXPECT_EQ(msg1, msg); |
| - delete msg1; |
| + bool HasMessage() const { return queue_->head_ != NULL; } |
| - msg1 = new PortMessage(port2, 0, strdup(msg_data)); |
| - EXPECT_EQ(true, PortMap::PostMessage(msg1)); |
| - msg = PortMap::ReceiveMessage(10); |
| - EXPECT_EQ(port2, msg->dest_id()); |
| - EXPECT_EQ(msg1, msg); |
| - delete msg1; |
| + private: |
| + MessageQueue* queue_; |
| +}; |
| - PortMap::ClosePort(port1); |
| - EXPECT_EQ(false, PortMap::IsActivePort(port1)); |
| - msg1 = new PortMessage(port1, 0, strdup(msg_data)); |
| - EXPECT_EQ(false, PortMap::PostMessage(msg1)); |
| - delete msg1; |
| - EXPECT(PortMap::ReceiveMessage(10) == NULL); |
| - EXPECT_EQ(true, PortMap::IsActivePort(port2)); |
| - msg1 = new PortMessage(port2, 0, strdup(msg_data)); |
| - EXPECT_EQ(true, PortMap::PostMessage(msg1)); |
| - PortMap::ClosePort(port2); |
| - EXPECT(PortMap::ReceiveMessage(10) == NULL); |
| +TEST_CASE(MessageQueue_BasicOperations) { |
| + MessageQueue queue; |
| + MessageQueueTestPeer queue_peer(&queue); |
| + EXPECT(!queue_peer.HasMessage()); |
| - for (int i = 0; i < 32; i++) { |
| - intptr_t port = PortMap::CreatePort(); |
| - PortMap::ClosePort(port); |
| - } |
| -} |
| + Dart_Port port = 1; |
| + // Add two elements. |
| + PortMessage* msg1 = new PortMessage(port, 0, strdup("msg1")); |
| + queue.Enqueue(msg1); |
| + EXPECT(queue_peer.HasMessage()); |
| -// End-of-test marker. |
| -static const intptr_t kEOT = 0xFFFF; |
| + PortMessage* msg2 = new PortMessage(port, 0, strdup("msg2")); |
| + queue.Enqueue(msg2); |
| + EXPECT(queue_peer.HasMessage()); |
| -void* AllocIntData(intptr_t payload) { |
| - intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); |
| - *result = payload; |
| - return result; |
| -} |
| + // Remove two elements. |
| + PortMessage* msg = queue.Dequeue(); |
| + EXPECT(msg != NULL); |
| + EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data())); |
| + EXPECT(queue_peer.HasMessage()); |
| + msg = queue.Dequeue(); |
| + EXPECT(msg != NULL); |
| + EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); |
| + EXPECT(!queue_peer.HasMessage()); |
| -intptr_t GetIntData(void* data) { |
| - return *reinterpret_cast<intptr_t*>(data); |
| + // Remove a message from an empty queue. |
| + msg = queue.Dequeue(); |
| + EXPECT(msg == NULL); |
| + EXPECT(!queue_peer.HasMessage()); |
| + |
| + delete msg1; |
| + delete msg2; |
| } |
| -void ThreadedPort_start(uword parameter) { |
| +// A thread which receives an expected sequence of messages. |
| +static MessageQueue* shared_queue = NULL; |
| +void MessageReceiver_start(uword unused) { |
| + // We only need an isolate here because the MonitorLocker in the |
| + // MessageQueue expects it. |
| Dart::CreateIsolate(NULL, NULL); |
| - intptr_t remote = parameter; |
| - intptr_t local = PortMap::CreatePort(); |
| + // Create a message queue and share it. |
| + MessageQueue* queue = new MessageQueue(); |
| + shared_queue = queue; |
| - PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(local))); |
| - |
| - intptr_t count = 0; |
| - while (true) { |
| - PortMessage* msg = PortMap::ReceiveMessage(0); |
| - EXPECT_EQ(local, msg->dest_id()); |
| + // Receive 5 messages with different payloads. |
| + for (int i = 0; i < 5; i++) { |
| + queue->Wait(0); // Waits on internal monitor |
|
siva
2011/10/14 21:01:52
monitor.
turnidge
2011/10/14 23:08:02
Line removed.
|
| + PortMessage* msg = queue->Dequeue(); |
| EXPECT(msg != NULL); |
| - if (GetIntData(msg->data()) == kEOT) { |
| - break; |
| - } |
| - EXPECT(GetIntData(msg->data()) == count); |
| + EXPECT_EQ(i+10, msg->dest_port()); |
| + EXPECT_EQ(i+100, msg->reply_port()); |
| + EXPECT_EQ(i+1000, *(reinterpret_cast<int*>(msg->data()))); |
| delete msg; |
| - PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(count * 2))); |
| - count++; |
| } |
| - PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); |
| - |
| + shared_queue = NULL; |
| + delete queue; |
| Dart::ShutdownIsolate(); |
| } |
| -TEST_CASE(ThreadedPort) { |
| - intptr_t local = PortMap::CreatePort(); |
| +TEST_CASE(MessageQueue_WaitNotify) { |
| + Thread* thread = new Thread(MessageReceiver_start, 0); |
| + EXPECT(thread != NULL); |
| - Thread* thr = new Thread(ThreadedPort_start, local); |
| - EXPECT(thr != NULL); |
| + // Wait for the shared queue to be created. |
| + Monitor waiter; |
| + while (shared_queue == NULL) { |
| + MonitorLocker ml(&waiter); |
| + ml.Wait(5); |
|
siva
2011/10/14 21:01:52
Instead of a timed wait why not share the waiter m
turnidge
2011/10/14 23:08:02
Done.
|
| + } |
| - PortMessage* msg = PortMap::ReceiveMessage(0); |
| - EXPECT_EQ(local, msg->dest_id()); |
| - EXPECT(msg != NULL); |
| - intptr_t remote = GetIntData(msg->data()); // Get the remote port. |
| - delete msg; |
| - |
| - for (intptr_t i = 0; i < 10; i++) { |
| - PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(i))); |
| - PortMessage* msg = PortMap::ReceiveMessage(0); |
| - EXPECT_EQ(local, msg->dest_id()); |
| - EXPECT(msg != NULL); |
| - EXPECT_EQ(i * 2, GetIntData(msg->data())); |
| - delete msg; |
| + // Send 5 messages with different payloads. |
| + for (int i = 0; i < 5; i++) { |
| + int* data = reinterpret_cast<int*>(malloc(sizeof(*data))); |
| + *data = i+1000; |
| + PortMessage* msg = new PortMessage(i+10, i+100, data); |
| + shared_queue->Enqueue(msg); // Enqueue notifies internal monitor |
| + MonitorLocker ml(&waiter); |
| + ml.Wait(i+1); |
|
siva
2011/10/14 21:01:52
Why do you need this wait here?
turnidge
2011/10/14 23:08:02
I wanted to exercise the path where the monitor is
|
| } |
| +} |
| - PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT))); |
| - msg = PortMap::ReceiveMessage(0); |
| - EXPECT_EQ(local, msg->dest_id()); |
| + |
| +TEST_CASE(MessageQueue_FlushAll) { |
| + MessageQueue queue; |
| + MessageQueueTestPeer queue_peer(&queue); |
| + Dart_Port port1 = 1; |
| + Dart_Port port2 = 2; |
| + |
| + // Add two elements. |
| + PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1")); |
| + queue.Enqueue(msg1); |
| + PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2")); |
| + queue.Enqueue(msg2); |
| + |
| + EXPECT(queue_peer.HasMessage()); |
| + queue.FlushAll(); |
| + EXPECT(!queue_peer.HasMessage()); |
| + |
| + // msg1 and msg2 already delete by FlushAll. |
| +} |
| + |
| + |
| +TEST_CASE(MessageQueue_Flush) { |
| + MessageQueue queue; |
| + MessageQueueTestPeer queue_peer(&queue); |
| + Dart_Port port1 = 1; |
| + Dart_Port port2 = 2; |
| + |
| + // Add two elements on different ports. |
| + PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1")); |
| + queue.Enqueue(msg1); |
| + PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2")); |
| + queue.Enqueue(msg2); |
| + EXPECT(queue_peer.HasMessage()); |
| + |
| + queue.Flush(port1); |
|
siva
2011/10/14 21:01:52
Would be good to have two additional tests
- a por
turnidge
2011/10/14 23:08:02
I added two test cases, but I'm not sure that they
|
| + |
| + // One message is left in the queue. |
| + EXPECT(queue_peer.HasMessage()); |
| + PortMessage* msg = queue.Dequeue(); |
| EXPECT(msg != NULL); |
| - EXPECT_EQ(kEOT, GetIntData(msg->data())); |
| - delete msg; |
| + EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data())); |
| - // Give the spawned thread enough time to properly exit. |
| - Monitor* waiter = new Monitor(); |
| - { |
| - MonitorLocker ml(waiter); |
| - ml.Wait(20); |
| - } |
| - delete waiter; |
| + EXPECT(!queue_peer.HasMessage()); |
| + |
| + // msg1 is already deleted by Flush |
|
siva
2011/10/14 21:01:52
Flush.
turnidge
2011/10/14 23:08:02
Fixed.
|
| + delete msg2; |
| } |
| + |
| } // namespace dart |