Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1562)

Unified Diff: runtime/vm/message_queue_test.cc

Issue 8297004: Allow embedders to provide custom message delivery for an isolate. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/message_queue.cc ('k') | runtime/vm/port.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,221 @@
// 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 messages.
+ 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 messages.
+ PortMessage* msg = queue.Dequeue(0);
+ EXPECT(msg != NULL);
+ EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data()));
+ EXPECT(queue_peer.HasMessage());
+ msg = queue.Dequeue(0);
+ 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);
+ delete msg1;
+ delete msg2;
}
-void ThreadedPort_start(uword parameter) {
+// A thread which receives an expected sequence of messages.
+static Monitor* sync = NULL;
+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)));
+ // Tell the other thread to fill the queue a bit.
+ {
+ MonitorLocker ml(sync);
+ ml.Notify();
+ }
- intptr_t count = 0;
- while (true) {
- PortMessage* msg = PortMap::ReceiveMessage(0);
- EXPECT_EQ(local, msg->dest_id());
+ // Wait for the other thread to fill the queue a bit.
+ {
+ MonitorLocker ml(sync);
+ ml.Wait(0);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ PortMessage* msg = queue->Dequeue(0);
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)));
-
+ for (int i = 0; i < 3; i++) {
+ PortMessage* msg = queue->Dequeue(0);
+ EXPECT(msg != NULL);
+ EXPECT_EQ(i+20, msg->dest_port());
+ EXPECT_EQ(i+200, msg->reply_port());
+ EXPECT_EQ(i+2000, *(reinterpret_cast<int*>(msg->data())));
+ delete msg;
+ }
+ 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.
+ sync = new Monitor();
+ {
+ MonitorLocker ml(sync);
+ ml.Wait(0);
+ }
+ ASSERT(shared_queue != NULL);
- 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;
+ // Pile up three messages before the other thread runs.
+ for (int i = 0; i < 3; 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);
+ }
- 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;
+ // Wake the other thread and have it start consuming messages.
+ {
+ MonitorLocker ml(sync);
+ ml.Notify();
}
- PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT)));
- msg = PortMap::ReceiveMessage(0);
- EXPECT_EQ(local, msg->dest_id());
+ // Add a few more messages after sleeping to allow the other thread
+ // to potentially exercise the blocking code path in Dequeue.
+ OS::Sleep(5);
+ for (int i = 0; i < 3; i++) {
+ int* data = reinterpret_cast<int*>(malloc(sizeof(*data)));
+ *data = i+2000;
+ PortMessage* msg = new PortMessage(i+20, i+200, data);
+ shared_queue->Enqueue(msg);
+ }
+
+ sync = NULL;
+ delete sync;
+}
+
+
+TEST_CASE(MessageQueue_FlushAll) {
+ MessageQueue queue;
+ MessageQueueTestPeer queue_peer(&queue);
+ Dart_Port port1 = 1;
+ Dart_Port port2 = 2;
+
+ // Add two messages.
+ 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 messages 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);
+
+ // One message is left in the queue.
+ EXPECT(queue_peer.HasMessage());
+ PortMessage* msg = queue.Dequeue(0);
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.
+ delete msg2;
}
+
+TEST_CASE(MessageQueue_Flush_MultipleMessages) {
+ MessageQueue queue;
+ MessageQueueTestPeer queue_peer(&queue);
+ Dart_Port port1 = 1;
+
+ PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
+ queue.Enqueue(msg1);
+ PortMessage* msg2 = new PortMessage(port1, 0, strdup("msg2"));
+ queue.Enqueue(msg2);
+ EXPECT(queue_peer.HasMessage());
+
+ queue.Flush(port1);
+
+ // Queue is empty.
+ EXPECT(!queue_peer.HasMessage());
+ // msg1 and msg2 are already deleted by Flush.
+}
+
+
+TEST_CASE(MessageQueue_Flush_EmptyQueue) {
+ MessageQueue queue;
+ MessageQueueTestPeer queue_peer(&queue);
+ Dart_Port port1 = 1;
+
+ EXPECT(!queue_peer.HasMessage());
+ queue.Flush(port1);
+
+ // Queue is still empty.
+ EXPECT(!queue_peer.HasMessage());
+}
+
+
} // namespace dart
« no previous file with comments | « runtime/vm/message_queue.cc ('k') | runtime/vm/port.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698