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_queue.h" | 6 #include "vm/message.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 // Intercept the post message callback and just store a copy of the message. | 32 class TestMessageHandler : public MessageHandler { |
33 static int notify_count = 0; | 33 public: |
34 static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) { | 34 TestMessageHandler() : notify_count(0) {} |
35 notify_count++; | |
36 } | |
37 | 35 |
| 36 void MessageNotify(Message::Priority priority) { |
| 37 notify_count++; |
| 38 } |
38 | 39 |
39 static void InitPortMapTest() { | 40 int notify_count; |
40 Dart_SetMessageNotifyCallback(&MyMessageNotifyCallback); | 41 }; |
41 notify_count = 0; | |
42 } | |
43 | 42 |
44 | 43 |
45 TEST_CASE(PortMap_CreateAndCloseOnePort) { | 44 TEST_CASE(PortMap_CreateAndCloseOnePort) { |
46 InitPortMapTest(); | 45 TestMessageHandler handler; |
47 intptr_t port = PortMap::CreatePort(); | 46 intptr_t port = PortMap::CreatePort(&handler); |
48 EXPECT_NE(0, port); | 47 EXPECT_NE(0, port); |
49 EXPECT(PortMapTestPeer::IsActivePort(port)); | 48 EXPECT(PortMapTestPeer::IsActivePort(port)); |
50 | 49 |
51 PortMap::ClosePort(port); | 50 PortMap::ClosePort(port); |
52 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 51 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
53 } | 52 } |
54 | 53 |
55 | 54 |
56 TEST_CASE(PortMap_CreateAndCloseTwoPorts) { | 55 TEST_CASE(PortMap_CreateAndCloseTwoPorts) { |
57 InitPortMapTest(); | 56 TestMessageHandler handler; |
58 Dart_Port port1 = PortMap::CreatePort(); | 57 Dart_Port port1 = PortMap::CreatePort(&handler); |
59 Dart_Port port2 = PortMap::CreatePort(); | 58 Dart_Port port2 = PortMap::CreatePort(&handler); |
60 EXPECT(PortMapTestPeer::IsActivePort(port1)); | 59 EXPECT(PortMapTestPeer::IsActivePort(port1)); |
61 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 60 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
62 | 61 |
63 // Uniqueness. | 62 // Uniqueness. |
64 EXPECT_NE(port1, port2); | 63 EXPECT_NE(port1, port2); |
65 | 64 |
66 PortMap::ClosePort(port1); | 65 PortMap::ClosePort(port1); |
67 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 66 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
68 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 67 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
69 | 68 |
70 PortMap::ClosePort(port2); | 69 PortMap::ClosePort(port2); |
71 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 70 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
72 EXPECT(!PortMapTestPeer::IsActivePort(port2)); | 71 EXPECT(!PortMapTestPeer::IsActivePort(port2)); |
73 } | 72 } |
74 | 73 |
75 | 74 |
76 TEST_CASE(PortMap_ClosePorts) { | 75 TEST_CASE(PortMap_ClosePorts) { |
77 InitPortMapTest(); | 76 TestMessageHandler handler; |
78 Dart_Port port1 = PortMap::CreatePort(); | 77 Dart_Port port1 = PortMap::CreatePort(&handler); |
79 Dart_Port port2 = PortMap::CreatePort(); | 78 Dart_Port port2 = PortMap::CreatePort(&handler); |
80 EXPECT(PortMapTestPeer::IsActivePort(port1)); | 79 EXPECT(PortMapTestPeer::IsActivePort(port1)); |
81 EXPECT(PortMapTestPeer::IsActivePort(port2)); | 80 EXPECT(PortMapTestPeer::IsActivePort(port2)); |
82 | 81 |
83 // Close all ports at once. | 82 // Close all ports at once. |
84 PortMap::ClosePorts(); | 83 PortMap::ClosePorts(&handler); |
85 EXPECT(!PortMapTestPeer::IsActivePort(port1)); | 84 EXPECT(!PortMapTestPeer::IsActivePort(port1)); |
86 EXPECT(!PortMapTestPeer::IsActivePort(port2)); | 85 EXPECT(!PortMapTestPeer::IsActivePort(port2)); |
87 } | 86 } |
88 | 87 |
89 | 88 |
90 TEST_CASE(PortMap_CreateManyPorts) { | 89 TEST_CASE(PortMap_CreateManyPorts) { |
91 InitPortMapTest(); | 90 TestMessageHandler handler; |
92 for (int i = 0; i < 32; i++) { | 91 for (int i = 0; i < 32; i++) { |
93 Dart_Port port = PortMap::CreatePort(); | 92 Dart_Port port = PortMap::CreatePort(&handler); |
94 EXPECT(PortMapTestPeer::IsActivePort(port)); | 93 EXPECT(PortMapTestPeer::IsActivePort(port)); |
95 PortMap::ClosePort(port); | 94 PortMap::ClosePort(port); |
96 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 95 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
97 } | 96 } |
98 } | 97 } |
99 | 98 |
100 | 99 |
101 TEST_CASE(PortMap_SetLive) { | 100 TEST_CASE(PortMap_SetLive) { |
102 InitPortMapTest(); | 101 TestMessageHandler handler; |
103 intptr_t port = PortMap::CreatePort(); | 102 intptr_t port = PortMap::CreatePort(&handler); |
104 EXPECT_NE(0, port); | 103 EXPECT_NE(0, port); |
105 EXPECT(PortMapTestPeer::IsActivePort(port)); | 104 EXPECT(PortMapTestPeer::IsActivePort(port)); |
106 EXPECT(!PortMapTestPeer::IsLivePort(port)); | 105 EXPECT(!PortMapTestPeer::IsLivePort(port)); |
107 | 106 |
108 PortMap::SetLive(port); | 107 PortMap::SetLive(port); |
109 EXPECT(PortMapTestPeer::IsActivePort(port)); | 108 EXPECT(PortMapTestPeer::IsActivePort(port)); |
110 EXPECT(PortMapTestPeer::IsLivePort(port)); | 109 EXPECT(PortMapTestPeer::IsLivePort(port)); |
111 | 110 |
112 PortMap::ClosePort(port); | 111 PortMap::ClosePort(port); |
113 EXPECT(!PortMapTestPeer::IsActivePort(port)); | 112 EXPECT(!PortMapTestPeer::IsActivePort(port)); |
114 EXPECT(!PortMapTestPeer::IsLivePort(port)); | 113 EXPECT(!PortMapTestPeer::IsLivePort(port)); |
115 } | 114 } |
116 | 115 |
117 | 116 |
118 TEST_CASE(PortMap_PostMessage) { | 117 TEST_CASE(PortMap_PostMessage) { |
119 InitPortMapTest(); | 118 TestMessageHandler handler; |
120 Dart_Port port = PortMap::CreatePort(); | 119 Dart_Port port = PortMap::CreatePort(&handler); |
| 120 EXPECT_EQ(0, handler.notify_count); |
| 121 |
121 EXPECT(PortMap::PostMessage(new Message( | 122 EXPECT(PortMap::PostMessage(new Message( |
122 port, 0, reinterpret_cast<uint8_t*>(strdup("msg")), | 123 port, 0, reinterpret_cast<uint8_t*>(strdup("msg")), |
123 Message::kNormalPriority))); | 124 Message::kNormalPriority))); |
124 | 125 |
125 // Check that the message notify callback was called. | 126 // Check that the message notify callback was called. |
126 EXPECT_EQ(1, notify_count); | 127 EXPECT_EQ(1, handler.notify_count); |
127 PortMap::ClosePorts(); | 128 PortMap::ClosePorts(&handler); |
128 } | 129 } |
129 | 130 |
130 | 131 |
131 TEST_CASE(PortMap_PostMessageInvalidPort) { | 132 TEST_CASE(PortMap_PostMessageInvalidPort) { |
132 InitPortMapTest(); | |
133 EXPECT(!PortMap::PostMessage(new Message( | 133 EXPECT(!PortMap::PostMessage(new Message( |
134 0, 0, reinterpret_cast<uint8_t*>(strdup("msg")), | 134 0, 0, reinterpret_cast<uint8_t*>(strdup("msg")), |
135 Message::kNormalPriority))); | 135 Message::kNormalPriority))); |
136 | |
137 // Check that the message notifycallback was not called. | |
138 EXPECT_STREQ(0, notify_count); | |
139 } | 136 } |
140 | 137 |
141 | 138 |
142 // End-of-test marker. | 139 // End-of-test marker. |
143 static const intptr_t kEOT = 0xFFFF; | 140 static const intptr_t kEOT = 0xFFFF; |
144 | 141 |
145 | 142 |
146 uint8_t* AllocIntData(intptr_t payload) { | 143 uint8_t* AllocIntData(intptr_t payload) { |
147 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); | 144 intptr_t* result = reinterpret_cast<intptr_t*>(malloc(sizeof(payload))); |
148 *result = payload; | 145 *result = payload; |
149 return reinterpret_cast<uint8_t*>(result); | 146 return reinterpret_cast<uint8_t*>(result); |
150 } | 147 } |
151 | 148 |
152 | 149 |
153 intptr_t GetIntData(uint8_t* data) { | 150 intptr_t GetIntData(uint8_t* data) { |
154 return *reinterpret_cast<intptr_t*>(data); | 151 return *reinterpret_cast<intptr_t*>(data); |
155 } | 152 } |
156 | 153 |
157 | 154 |
158 static Message* NextMessage() { | 155 static Message* NextMessage() { |
159 Isolate* isolate = Isolate::Current(); | 156 Isolate* isolate = Isolate::Current(); |
160 Message* result = isolate->message_queue()->Dequeue(0); | 157 Message* result = isolate->message_handler()->queue()->Dequeue(0); |
161 return result; | 158 return result; |
162 } | 159 } |
163 | 160 |
164 | 161 |
165 void ThreadedPort_start(uword parameter) { | 162 void ThreadedPort_start(uword parameter) { |
166 // We only need an isolate here because the MutexLocker in | 163 // TODO(turnidge): We only use the isolate to get access to its |
167 // PortMap::CreatePort expects it, we don't need to initialize | 164 // message handler. I should rewrite this test to use a |
168 // the isolate as it does not run any dart code. | 165 // TestMessageHandler instead. |
169 Dart::CreateIsolate(NULL); | 166 Isolate* isolate = Dart::CreateIsolate(NULL); |
170 | 167 |
171 intptr_t remote = parameter; | 168 intptr_t remote = parameter; |
172 intptr_t local = PortMap::CreatePort(); | 169 intptr_t local = PortMap::CreatePort(isolate->message_handler()); |
173 | 170 |
174 PortMap::PostMessage(new Message( | 171 PortMap::PostMessage(new Message( |
175 remote, 0, AllocIntData(local), Message::kNormalPriority)); | 172 remote, 0, AllocIntData(local), Message::kNormalPriority)); |
176 intptr_t count = 0; | 173 intptr_t count = 0; |
177 while (true) { | 174 while (true) { |
178 Message* msg = NextMessage(); | 175 Message* msg = NextMessage(); |
179 EXPECT_EQ(local, msg->dest_port()); | 176 EXPECT_EQ(local, msg->dest_port()); |
180 EXPECT(msg != NULL); | 177 EXPECT(msg != NULL); |
181 if (GetIntData(msg->data()) == kEOT) { | 178 if (GetIntData(msg->data()) == kEOT) { |
182 break; | 179 break; |
183 } | 180 } |
184 EXPECT(GetIntData(msg->data()) == count); | 181 EXPECT(GetIntData(msg->data()) == count); |
185 delete msg; | 182 delete msg; |
186 PortMap::PostMessage(new Message( | 183 PortMap::PostMessage(new Message( |
187 remote, 0, AllocIntData(count * 2), Message::kNormalPriority)); | 184 remote, 0, AllocIntData(count * 2), Message::kNormalPriority)); |
188 count++; | 185 count++; |
189 } | 186 } |
190 PortMap::PostMessage(new Message( | 187 PortMap::PostMessage(new Message( |
191 remote, 0, AllocIntData(kEOT), Message::kNormalPriority)); | 188 remote, 0, AllocIntData(kEOT), Message::kNormalPriority)); |
192 Dart::ShutdownIsolate(); | 189 Dart::ShutdownIsolate(); |
193 } | 190 } |
194 | 191 |
195 | 192 |
196 TEST_CASE(ThreadedPort) { | 193 TEST_CASE(ThreadedPort) { |
197 intptr_t local = PortMap::CreatePort(); | 194 intptr_t local = PortMap::CreatePort(Isolate::Current()->message_handler()); |
198 | 195 |
199 Thread* thr = new Thread(ThreadedPort_start, local); | 196 Thread* thr = new Thread(ThreadedPort_start, local); |
200 EXPECT(thr != NULL); | 197 EXPECT(thr != NULL); |
201 | 198 |
202 Message* msg = NextMessage(); | 199 Message* msg = NextMessage(); |
203 EXPECT_EQ(local, msg->dest_port()); | 200 EXPECT_EQ(local, msg->dest_port()); |
204 EXPECT(msg != NULL); | 201 EXPECT(msg != NULL); |
205 intptr_t remote = GetIntData(msg->data()); // Get the remote port. | 202 intptr_t remote = GetIntData(msg->data()); // Get the remote port. |
206 delete msg; | 203 delete msg; |
207 | 204 |
(...skipping 18 matching lines...) Expand all Loading... |
226 // Give the spawned thread enough time to properly exit. | 223 // Give the spawned thread enough time to properly exit. |
227 Monitor* waiter = new Monitor(); | 224 Monitor* waiter = new Monitor(); |
228 { | 225 { |
229 MonitorLocker ml(waiter); | 226 MonitorLocker ml(waiter); |
230 ml.Wait(20); | 227 ml.Wait(20); |
231 } | 228 } |
232 delete waiter; | 229 delete waiter; |
233 } | 230 } |
234 | 231 |
235 } // namespace dart | 232 } // namespace dart |
OLD | NEW |