OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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 "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/message.h" | 6 #include "vm/message_handler.h" |
7 #include "vm/os.h" | 7 #include "vm/os.h" |
8 #include "vm/port.h" | 8 #include "vm/port.h" |
9 #include "vm/unit_test.h" | 9 #include "vm/unit_test.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 // Provides private access to PortMap for testing. | 13 // Provides private access to PortMap for testing. |
14 class PortMapTestPeer { | 14 class PortMapTestPeer { |
15 public: | 15 public: |
16 static bool IsActivePort(Dart_Port port) { | 16 static bool IsActivePort(Dart_Port port) { |
17 MutexLocker ml(PortMap::mutex_); | 17 MutexLocker ml(PortMap::mutex_); |
18 return (PortMap::FindPort(port) >= 0); | 18 return (PortMap::FindPort(port) >= 0); |
19 } | 19 } |
20 | 20 |
21 static bool IsLivePort(Dart_Port port) { | 21 static bool IsLivePort(Dart_Port port) { |
22 MutexLocker ml(PortMap::mutex_); | 22 MutexLocker ml(PortMap::mutex_); |
23 intptr_t index = PortMap::FindPort(port); | 23 intptr_t index = PortMap::FindPort(port); |
24 if (index < 0) { | 24 if (index < 0) { |
25 return false; | 25 return false; |
26 } | 26 } |
27 return PortMap::map_[index].live; | 27 return PortMap::map_[index].live; |
28 } | 28 } |
29 }; | 29 }; |
30 | 30 |
31 | 31 |
32 class TestMessageHandler : public MessageHandler { | 32 class PortTestMessageHandler : public MessageHandler { |
33 public: | 33 public: |
34 TestMessageHandler() : notify_count(0) {} | 34 PortTestMessageHandler() : notify_count(0) {} |
35 | 35 |
36 void MessageNotify(Message::Priority priority) { | 36 void MessageNotify(Message::Priority priority) { |
37 notify_count++; | 37 notify_count++; |
38 } | 38 } |
39 | 39 |
| 40 bool HandleMessage(Message* message) { return true; } |
| 41 |
40 int notify_count; | 42 int notify_count; |
41 }; | 43 }; |
42 | 44 |
43 | 45 |
44 TEST_CASE(PortMap_CreateAndCloseOnePort) { | 46 TEST_CASE(PortMap_CreateAndCloseOnePort) { |
45 TestMessageHandler handler; | 47 PortTestMessageHandler handler; |
46 intptr_t port = PortMap::CreatePort(&handler); | 48 intptr_t port = PortMap::CreatePort(&handler); |
47 EXPECT_NE(0, port); | 49 EXPECT_NE(0, port); |
48 EXPECT(PortMapTestPeer::IsActivePort(port)); | 50 EXPECT(PortMapTestPeer::IsActivePort(port)); |
49 | 51 |
50 PortMap::ClosePort(port); | 52 PortMap::ClosePort(port); |
51 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 53 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
52 } | 54 } |
53 | 55 |
54 | 56 |
55 TEST_CASE(PortMap_CreateAndCloseTwoPorts) { | 57 TEST_CASE(PortMap_CreateAndCloseTwoPorts) { |
56 TestMessageHandler handler; | 58 PortTestMessageHandler handler; |
57 Dart_Port port1 = PortMap::CreatePort(&handler); | 59 Dart_Port port1 = PortMap::CreatePort(&handler); |
58 Dart_Port port2 = PortMap::CreatePort(&handler); | 60 Dart_Port port2 = PortMap::CreatePort(&handler); |
59 EXPECT(PortMapTestPeer::IsActivePort(port1)); | 61 EXPECT(PortMapTestPeer::IsActivePort(port1)); |
60 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 62 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
61 | 63 |
62 // Uniqueness. | 64 // Uniqueness. |
63 EXPECT_NE(port1, port2); | 65 EXPECT_NE(port1, port2); |
64 | 66 |
65 PortMap::ClosePort(port1); | 67 PortMap::ClosePort(port1); |
66 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 68 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
67 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 69 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
68 | 70 |
69 PortMap::ClosePort(port2); | 71 PortMap::ClosePort(port2); |
70 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 72 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
71 EXPECT(!PortMapTestPeer::IsActivePort(port2)); | 73 EXPECT(!PortMapTestPeer::IsActivePort(port2)); |
72 } | 74 } |
73 | 75 |
74 | 76 |
75 TEST_CASE(PortMap_ClosePorts) { | 77 TEST_CASE(PortMap_ClosePorts) { |
76 TestMessageHandler handler; | 78 PortTestMessageHandler handler; |
77 Dart_Port port1 = PortMap::CreatePort(&handler); | 79 Dart_Port port1 = PortMap::CreatePort(&handler); |
78 Dart_Port port2 = PortMap::CreatePort(&handler); | 80 Dart_Port port2 = PortMap::CreatePort(&handler); |
79 EXPECT(PortMapTestPeer::IsActivePort(port1)); | 81 EXPECT(PortMapTestPeer::IsActivePort(port1)); |
80 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 82 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
81 | 83 |
82 // Close all ports at once. | 84 // Close all ports at once. |
83 PortMap::ClosePorts(&handler); | 85 PortMap::ClosePorts(&handler); |
84 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 86 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
85 EXPECT(!PortMapTestPeer::IsActivePort(port2)); | 87 EXPECT(!PortMapTestPeer::IsActivePort(port2)); |
86 } | 88 } |
87 | 89 |
88 | 90 |
89 TEST_CASE(PortMap_CreateManyPorts) { | 91 TEST_CASE(PortMap_CreateManyPorts) { |
90 TestMessageHandler handler; | 92 PortTestMessageHandler handler; |
91 for (int i = 0; i < 32; i++) { | 93 for (int i = 0; i < 32; i++) { |
92 Dart_Port port = PortMap::CreatePort(&handler); | 94 Dart_Port port = PortMap::CreatePort(&handler); |
93 EXPECT(PortMapTestPeer::IsActivePort(port)); | 95 EXPECT(PortMapTestPeer::IsActivePort(port)); |
94 PortMap::ClosePort(port); | 96 PortMap::ClosePort(port); |
95 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 97 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
96 } | 98 } |
97 } | 99 } |
98 | 100 |
99 | 101 |
100 TEST_CASE(PortMap_SetLive) { | 102 TEST_CASE(PortMap_SetLive) { |
101 TestMessageHandler handler; | 103 PortTestMessageHandler handler; |
102 intptr_t port = PortMap::CreatePort(&handler); | 104 intptr_t port = PortMap::CreatePort(&handler); |
103 EXPECT_NE(0, port); | 105 EXPECT_NE(0, port); |
104 EXPECT(PortMapTestPeer::IsActivePort(port)); | 106 EXPECT(PortMapTestPeer::IsActivePort(port)); |
105 EXPECT(!PortMapTestPeer::IsLivePort(port)); | 107 EXPECT(!PortMapTestPeer::IsLivePort(port)); |
106 | 108 |
107 PortMap::SetLive(port); | 109 PortMap::SetLive(port); |
108 EXPECT(PortMapTestPeer::IsActivePort(port)); | 110 EXPECT(PortMapTestPeer::IsActivePort(port)); |
109 EXPECT(PortMapTestPeer::IsLivePort(port)); | 111 EXPECT(PortMapTestPeer::IsLivePort(port)); |
110 | 112 |
111 PortMap::ClosePort(port); | 113 PortMap::ClosePort(port); |
112 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 114 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
113 EXPECT(!PortMapTestPeer::IsLivePort(port)); | 115 EXPECT(!PortMapTestPeer::IsLivePort(port)); |
114 } | 116 } |
115 | 117 |
116 | 118 |
117 TEST_CASE(PortMap_PostMessage) { | 119 TEST_CASE(PortMap_PostMessage) { |
118 TestMessageHandler handler; | 120 PortTestMessageHandler handler; |
119 Dart_Port port = PortMap::CreatePort(&handler); | 121 Dart_Port port = PortMap::CreatePort(&handler); |
120 EXPECT_EQ(0, handler.notify_count); | 122 EXPECT_EQ(0, handler.notify_count); |
121 | 123 |
122 EXPECT(PortMap::PostMessage(new Message( | 124 EXPECT(PortMap::PostMessage(new Message( |
123 port, 0, reinterpret_cast<uint8_t*>(strdup("msg")), | 125 port, 0, reinterpret_cast<uint8_t*>(strdup("msg")), |
124 Message::kNormalPriority))); | 126 Message::kNormalPriority))); |
125 | 127 |
126 // Check that the message notify callback was called. | 128 // Check that the message notify callback was called. |
127 EXPECT_EQ(1, handler.notify_count); | 129 EXPECT_EQ(1, handler.notify_count); |
128 PortMap::ClosePorts(&handler); | 130 PortMap::ClosePorts(&handler); |
129 } | 131 } |
130 | 132 |
131 | 133 |
132 TEST_CASE(PortMap_PostMessageInvalidPort) { | 134 TEST_CASE(PortMap_PostMessageInvalidPort) { |
133 EXPECT(!PortMap::PostMessage(new Message( | 135 EXPECT(!PortMap::PostMessage(new Message( |
134 0, 0, reinterpret_cast<uint8_t*>(strdup("msg")), | 136 0, 0, reinterpret_cast<uint8_t*>(strdup("msg")), |
135 Message::kNormalPriority))); | 137 Message::kNormalPriority))); |
136 } | 138 } |
137 | 139 |
138 | |
139 // End-of-test marker. | |
140 static const intptr_t kEOT = 0xFFFF; | |
141 | |
142 | |
143 uint8_t* AllocIntData(intptr_t payload) { | |
144 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); | |
145 *result = payload; | |
146 return reinterpret_cast<uint8_t*>(result); | |
147 } | |
148 | |
149 | |
150 intptr_t GetIntData(uint8_t* data) { | |
151 return *reinterpret_cast<intptr_t*>(data); | |
152 } | |
153 | |
154 | |
155 static Message* NextMessage() { | |
156 Isolate* isolate = Isolate::Current(); | |
157 Message* result = isolate->message_handler()->queue()->Dequeue(0); | |
158 return result; | |
159 } | |
160 | |
161 | |
162 void ThreadedPort_start(uword parameter) { | |
163 // TODO(turnidge): We only use the isolate to get access to its | |
164 // message handler. I should rewrite this test to use a | |
165 // TestMessageHandler instead. | |
166 Isolate* isolate = Dart::CreateIsolate(NULL); | |
167 | |
168 intptr_t remote = parameter; | |
169 intptr_t local = PortMap::CreatePort(isolate->message_handler()); | |
170 | |
171 PortMap::PostMessage(new Message( | |
172 remote, 0, AllocIntData(local), Message::kNormalPriority)); | |
173 intptr_t count = 0; | |
174 while (true) { | |
175 Message* msg = NextMessage(); | |
176 EXPECT_EQ(local, msg->dest_port()); | |
177 EXPECT(msg != NULL); | |
178 if (GetIntData(msg->data()) == kEOT) { | |
179 break; | |
180 } | |
181 EXPECT(GetIntData(msg->data()) == count); | |
182 delete msg; | |
183 PortMap::PostMessage(new Message( | |
184 remote, 0, AllocIntData(count * 2), Message::kNormalPriority)); | |
185 count++; | |
186 } | |
187 PortMap::PostMessage(new Message( | |
188 remote, 0, AllocIntData(kEOT), Message::kNormalPriority)); | |
189 Dart::ShutdownIsolate(); | |
190 } | |
191 | |
192 | |
193 TEST_CASE(ThreadedPort) { | |
194 intptr_t local = PortMap::CreatePort(Isolate::Current()->message_handler()); | |
195 | |
196 int result = Thread::Start(ThreadedPort_start, local); | |
197 EXPECT_EQ(0, result); | |
198 | |
199 Message* msg = NextMessage(); | |
200 EXPECT_EQ(local, msg->dest_port()); | |
201 EXPECT(msg != NULL); | |
202 intptr_t remote = GetIntData(msg->data()); // Get the remote port. | |
203 delete msg; | |
204 | |
205 for (intptr_t i = 0; i < 10; i++) { | |
206 PortMap::PostMessage( | |
207 new Message(remote, 0, AllocIntData(i), Message::kNormalPriority)); | |
208 Message* msg = NextMessage(); | |
209 EXPECT_EQ(local, msg->dest_port()); | |
210 EXPECT(msg != NULL); | |
211 EXPECT_EQ(i * 2, GetIntData(msg->data())); | |
212 delete msg; | |
213 } | |
214 | |
215 PortMap::PostMessage( | |
216 new Message(remote, 0, AllocIntData(kEOT), Message::kNormalPriority)); | |
217 msg = NextMessage(); | |
218 EXPECT_EQ(local, msg->dest_port()); | |
219 EXPECT(msg != NULL); | |
220 EXPECT_EQ(kEOT, GetIntData(msg->data())); | |
221 delete msg; | |
222 | |
223 // Give the spawned thread enough time to properly exit. | |
224 Monitor* waiter = new Monitor(); | |
225 { | |
226 MonitorLocker ml(waiter); | |
227 ml.Wait(20); | |
228 } | |
229 delete waiter; | |
230 } | |
231 | |
232 } // namespace dart | 140 } // namespace dart |
OLD | NEW |