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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/assert.h" 5 #include "vm/assert.h"
6 #include "vm/port.h" 6 #include "vm/message_queue.h"
7 #include "vm/unit_test.h" 7 #include "vm/unit_test.h"
8 8
9 namespace dart { 9 namespace dart {
10 10
11 TEST_CASE(Port) {
12 const char* msg_data = "Hallo Velo!";
13 11
14 intptr_t port1 = PortMap::CreatePort(); 12 // Provide access to private members of MessageQueue for testing.
15 intptr_t port2 = PortMap::CreatePort(); 13 class MessageQueueTestPeer {
16 EXPECT(port1 != port2); 14 public:
15 explicit MessageQueueTestPeer(MessageQueue* queue) : queue_(queue) {}
17 16
18 PortMessage* msg1 = new PortMessage(port1, 0, strdup(msg_data)); 17 bool HasMessage() const { return queue_->head_ != NULL; }
19 EXPECT_EQ(true, PortMap::PostMessage(msg1)); 18
20 PortMessage* msg = PortMap::ReceiveMessage(10); 19 private:
21 EXPECT_EQ(port1, msg->dest_id()); 20 MessageQueue* queue_;
22 EXPECT_EQ(msg1, msg); 21 };
22
23
24 TEST_CASE(MessageQueue_BasicOperations) {
25 MessageQueue queue;
26 MessageQueueTestPeer queue_peer(&queue);
27 EXPECT(!queue_peer.HasMessage());
28
29 Dart_Port port = 1;
30
31 // Add two elements.
32 PortMessage* msg1 = new PortMessage(port, 0, strdup("msg1"));
33 queue.Enqueue(msg1);
34 EXPECT(queue_peer.HasMessage());
35
36 PortMessage* msg2 = new PortMessage(port, 0, strdup("msg2"));
37 queue.Enqueue(msg2);
38 EXPECT(queue_peer.HasMessage());
39
40 // Remove two elements.
41 PortMessage* msg = queue.Dequeue();
42 EXPECT(msg != NULL);
43 EXPECT_STREQ("msg1", reinterpret_cast<char*>(msg->data()));
44 EXPECT(queue_peer.HasMessage());
45
46 msg = queue.Dequeue();
47 EXPECT(msg != NULL);
48 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
49 EXPECT(!queue_peer.HasMessage());
50
51 // Remove a message from an empty queue.
52 msg = queue.Dequeue();
53 EXPECT(msg == NULL);
54 EXPECT(!queue_peer.HasMessage());
55
23 delete msg1; 56 delete msg1;
57 delete msg2;
58 }
24 59
25 msg1 = new PortMessage(port2, 0, strdup(msg_data));
26 EXPECT_EQ(true, PortMap::PostMessage(msg1));
27 msg = PortMap::ReceiveMessage(10);
28 EXPECT_EQ(port2, msg->dest_id());
29 EXPECT_EQ(msg1, msg);
30 delete msg1;
31 60
32 PortMap::ClosePort(port1); 61 // A thread which receives an expected sequence of messages.
33 EXPECT_EQ(false, PortMap::IsActivePort(port1)); 62 static MessageQueue* shared_queue = NULL;
34 msg1 = new PortMessage(port1, 0, strdup(msg_data)); 63 void MessageReceiver_start(uword unused) {
35 EXPECT_EQ(false, PortMap::PostMessage(msg1)); 64 // We only need an isolate here because the MonitorLocker in the
36 delete msg1; 65 // MessageQueue expects it.
37 EXPECT(PortMap::ReceiveMessage(10) == NULL); 66 Dart::CreateIsolate(NULL, NULL);
38 67
39 EXPECT_EQ(true, PortMap::IsActivePort(port2)); 68 // Create a message queue and share it.
40 msg1 = new PortMessage(port2, 0, strdup(msg_data)); 69 MessageQueue* queue = new MessageQueue();
41 EXPECT_EQ(true, PortMap::PostMessage(msg1)); 70 shared_queue = queue;
42 PortMap::ClosePort(port2);
43 EXPECT(PortMap::ReceiveMessage(10) == NULL);
44 71
45 for (int i = 0; i < 32; i++) { 72 // Receive 5 messages with different payloads.
46 intptr_t port = PortMap::CreatePort(); 73 for (int i = 0; i < 5; i++) {
47 PortMap::ClosePort(port); 74 queue->Wait(0); // Waits on internal monitor
siva 2011/10/14 21:01:52 monitor.
turnidge 2011/10/14 23:08:02 Line removed.
75 PortMessage* msg = queue->Dequeue();
76 EXPECT(msg != NULL);
77 EXPECT_EQ(i+10, msg->dest_port());
78 EXPECT_EQ(i+100, msg->reply_port());
79 EXPECT_EQ(i+1000, *(reinterpret_cast<int*>(msg->data())));
80 delete msg;
81 }
82 shared_queue = NULL;
83 delete queue;
84 Dart::ShutdownIsolate();
85 }
86
87
88 TEST_CASE(MessageQueue_WaitNotify) {
89 Thread* thread = new Thread(MessageReceiver_start, 0);
90 EXPECT(thread != NULL);
91
92 // Wait for the shared queue to be created.
93 Monitor waiter;
94 while (shared_queue == NULL) {
95 MonitorLocker ml(&waiter);
96 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.
97 }
98
99 // Send 5 messages with different payloads.
100 for (int i = 0; i < 5; i++) {
101 int* data = reinterpret_cast<int*>(malloc(sizeof(*data)));
102 *data = i+1000;
103 PortMessage* msg = new PortMessage(i+10, i+100, data);
104 shared_queue->Enqueue(msg); // Enqueue notifies internal monitor
105 MonitorLocker ml(&waiter);
106 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
48 } 107 }
49 } 108 }
50 109
51 110
52 // End-of-test marker. 111 TEST_CASE(MessageQueue_FlushAll) {
53 static const intptr_t kEOT = 0xFFFF; 112 MessageQueue queue;
113 MessageQueueTestPeer queue_peer(&queue);
114 Dart_Port port1 = 1;
115 Dart_Port port2 = 2;
54 116
55 void* AllocIntData(intptr_t payload) { 117 // Add two elements.
56 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); 118 PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
57 *result = payload; 119 queue.Enqueue(msg1);
58 return result; 120 PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2"));
121 queue.Enqueue(msg2);
122
123 EXPECT(queue_peer.HasMessage());
124 queue.FlushAll();
125 EXPECT(!queue_peer.HasMessage());
126
127 // msg1 and msg2 already delete by FlushAll.
59 } 128 }
60 129
61 130
62 intptr_t GetIntData(void* data) { 131 TEST_CASE(MessageQueue_Flush) {
63 return *reinterpret_cast<intptr_t*>(data); 132 MessageQueue queue;
133 MessageQueueTestPeer queue_peer(&queue);
134 Dart_Port port1 = 1;
135 Dart_Port port2 = 2;
136
137 // Add two elements on different ports.
138 PortMessage* msg1 = new PortMessage(port1, 0, strdup("msg1"));
139 queue.Enqueue(msg1);
140 PortMessage* msg2 = new PortMessage(port2, 0, strdup("msg2"));
141 queue.Enqueue(msg2);
142 EXPECT(queue_peer.HasMessage());
143
144 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
145
146 // One message is left in the queue.
147 EXPECT(queue_peer.HasMessage());
148 PortMessage* msg = queue.Dequeue();
149 EXPECT(msg != NULL);
150 EXPECT_STREQ("msg2", reinterpret_cast<char*>(msg->data()));
151
152 EXPECT(!queue_peer.HasMessage());
153
154 // msg1 is already deleted by Flush
siva 2011/10/14 21:01:52 Flush.
turnidge 2011/10/14 23:08:02 Fixed.
155 delete msg2;
64 } 156 }
65 157
66 158
67 void ThreadedPort_start(uword parameter) {
68 Dart::CreateIsolate(NULL, NULL);
69
70 intptr_t remote = parameter;
71 intptr_t local = PortMap::CreatePort();
72
73 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(local)));
74
75 intptr_t count = 0;
76 while (true) {
77 PortMessage* msg = PortMap::ReceiveMessage(0);
78 EXPECT_EQ(local, msg->dest_id());
79 EXPECT(msg != NULL);
80 if (GetIntData(msg->data()) == kEOT) {
81 break;
82 }
83 EXPECT(GetIntData(msg->data()) == count);
84 delete msg;
85 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(count * 2)));
86 count++;
87 }
88 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT)));
89
90 Dart::ShutdownIsolate();
91 }
92
93
94 TEST_CASE(ThreadedPort) {
95 intptr_t local = PortMap::CreatePort();
96
97 Thread* thr = new Thread(ThreadedPort_start, local);
98 EXPECT(thr != NULL);
99
100 PortMessage* msg = PortMap::ReceiveMessage(0);
101 EXPECT_EQ(local, msg->dest_id());
102 EXPECT(msg != NULL);
103 intptr_t remote = GetIntData(msg->data()); // Get the remote port.
104 delete msg;
105
106 for (intptr_t i = 0; i < 10; i++) {
107 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(i)));
108 PortMessage* msg = PortMap::ReceiveMessage(0);
109 EXPECT_EQ(local, msg->dest_id());
110 EXPECT(msg != NULL);
111 EXPECT_EQ(i * 2, GetIntData(msg->data()));
112 delete msg;
113 }
114
115 PortMap::PostMessage(new PortMessage(remote, 0, AllocIntData(kEOT)));
116 msg = PortMap::ReceiveMessage(0);
117 EXPECT_EQ(local, msg->dest_id());
118 EXPECT(msg != NULL);
119 EXPECT_EQ(kEOT, GetIntData(msg->data()));
120 delete msg;
121
122 // Give the spawned thread enough time to properly exit.
123 Monitor* waiter = new Monitor();
124 {
125 MonitorLocker ml(waiter);
126 ml.Wait(20);
127 }
128 delete waiter;
129 }
130
131 } // namespace dart 159 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698