OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/system/wait_set.h" | 5 #include "mojo/public/cpp/system/wait_set.h" |
6 | 6 |
| 7 #include <set> |
| 8 #include <vector> |
| 9 |
7 #include "base/bind.h" | 10 #include "base/bind.h" |
8 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/synchronization/waitable_event.h" |
9 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
10 #include "base/threading/simple_thread.h" | 15 #include "base/threading/simple_thread.h" |
11 #include "mojo/public/cpp/system/message_pipe.h" | 16 #include "mojo/public/cpp/system/message_pipe.h" |
| 17 #include "mojo/public/cpp/system/wait.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
13 | 19 |
14 namespace mojo { | 20 namespace mojo { |
15 namespace { | 21 namespace { |
16 | 22 |
17 using WaitSetTest = testing::Test; | 23 using WaitSetTest = testing::Test; |
18 | 24 |
19 void WriteMessage(const ScopedMessagePipeHandle& handle, | 25 void WriteMessage(const ScopedMessagePipeHandle& handle, |
20 const base::StringPiece& message) { | 26 const base::StringPiece& message) { |
21 MojoResult rv = WriteMessageRaw(handle.get(), message.data(), | 27 MojoResult rv = WriteMessageRaw(handle.get(), message.data(), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 67 |
62 // Watch only one handle and write to the other. | 68 // Watch only one handle and write to the other. |
63 | 69 |
64 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); | 70 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
65 WriteMessage(p.handle0, kTestMessage1); | 71 WriteMessage(p.handle0, kTestMessage1); |
66 | 72 |
67 size_t num_ready_handles = 2; | 73 size_t num_ready_handles = 2; |
68 Handle ready_handles[2]; | 74 Handle ready_handles[2]; |
69 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; | 75 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; |
70 HandleSignalsState hss[2]; | 76 HandleSignalsState hss[2]; |
71 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss); | 77 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); |
72 | 78 |
73 EXPECT_EQ(1u, num_ready_handles); | 79 EXPECT_EQ(1u, num_ready_handles); |
74 EXPECT_EQ(p.handle1.get(), ready_handles[0]); | 80 EXPECT_EQ(p.handle1.get(), ready_handles[0]); |
75 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 81 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
76 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); | 82 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); |
77 | 83 |
78 wait_set.RemoveHandle(p.handle1.get()); | 84 wait_set.RemoveHandle(p.handle1.get()); |
79 | 85 |
80 // Now watch only the other handle and write to the first one. | 86 // Now watch only the other handle and write to the first one. |
81 | 87 |
82 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 88 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
83 WriteMessage(p.handle1, kTestMessage1); | 89 WriteMessage(p.handle1, kTestMessage1); |
84 | 90 |
85 num_ready_handles = 2; | 91 num_ready_handles = 2; |
86 ready_results[0] = MOJO_RESULT_UNKNOWN; | 92 ready_results[0] = MOJO_RESULT_UNKNOWN; |
87 ready_results[1] = MOJO_RESULT_UNKNOWN; | 93 ready_results[1] = MOJO_RESULT_UNKNOWN; |
88 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss); | 94 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); |
89 | 95 |
90 EXPECT_EQ(1u, num_ready_handles); | 96 EXPECT_EQ(1u, num_ready_handles); |
91 EXPECT_EQ(p.handle0.get(), ready_handles[0]); | 97 EXPECT_EQ(p.handle0.get(), ready_handles[0]); |
92 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 98 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
93 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); | 99 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); |
94 | 100 |
95 // Now wait on both of them. | 101 // Now wait on both of them. |
96 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); | 102 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
97 | 103 |
98 num_ready_handles = 2; | 104 num_ready_handles = 2; |
99 ready_results[0] = MOJO_RESULT_UNKNOWN; | 105 ready_results[0] = MOJO_RESULT_UNKNOWN; |
100 ready_results[1] = MOJO_RESULT_UNKNOWN; | 106 ready_results[1] = MOJO_RESULT_UNKNOWN; |
101 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss); | 107 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); |
102 EXPECT_EQ(2u, num_ready_handles); | 108 EXPECT_EQ(2u, num_ready_handles); |
103 EXPECT_TRUE((ready_handles[0] == p.handle0.get() && | 109 EXPECT_TRUE((ready_handles[0] == p.handle0.get() && |
104 ready_handles[1] == p.handle1.get()) || | 110 ready_handles[1] == p.handle1.get()) || |
105 (ready_handles[0] == p.handle1.get() && | 111 (ready_handles[0] == p.handle1.get() && |
106 ready_handles[1] == p.handle0.get())); | 112 ready_handles[1] == p.handle0.get())); |
107 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 113 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
108 EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]); | 114 EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]); |
109 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); | 115 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed()); |
110 EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed()); | 116 EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed()); |
111 | 117 |
112 // Wait on both again, but with only enough output space for one result. | 118 // Wait on both again, but with only enough output space for one result. |
113 num_ready_handles = 1; | 119 num_ready_handles = 1; |
114 ready_results[0] = MOJO_RESULT_UNKNOWN; | 120 ready_results[0] = MOJO_RESULT_UNKNOWN; |
115 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss); | 121 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); |
116 EXPECT_EQ(1u, num_ready_handles); | 122 EXPECT_EQ(1u, num_ready_handles); |
117 EXPECT_TRUE(ready_handles[0] == p.handle0.get() || | 123 EXPECT_TRUE(ready_handles[0] == p.handle0.get() || |
118 ready_handles[0] == p.handle1.get()); | 124 ready_handles[0] == p.handle1.get()); |
119 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 125 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
120 | 126 |
121 // Remove the ready handle from the set and wait one more time. | 127 // Remove the ready handle from the set and wait one more time. |
122 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); | 128 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); |
123 | 129 |
124 num_ready_handles = 1; | 130 num_ready_handles = 1; |
125 ready_results[0] = MOJO_RESULT_UNKNOWN; | 131 ready_results[0] = MOJO_RESULT_UNKNOWN; |
126 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss); | 132 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss); |
127 EXPECT_EQ(1u, num_ready_handles); | 133 EXPECT_EQ(1u, num_ready_handles); |
128 EXPECT_TRUE(ready_handles[0] == p.handle0.get() || | 134 EXPECT_TRUE(ready_handles[0] == p.handle0.get() || |
129 ready_handles[0] == p.handle1.get()); | 135 ready_handles[0] == p.handle1.get()); |
130 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 136 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
131 | 137 |
132 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); | 138 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0])); |
133 | 139 |
134 // The wait set should be empty now. Nothing to wait on. | 140 // The wait set should be empty now. Nothing to wait on. |
135 num_ready_handles = 2; | 141 num_ready_handles = 2; |
136 wait_set.Wait(&num_ready_handles, ready_handles, ready_results); | 142 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); |
137 EXPECT_EQ(0u, num_ready_handles); | 143 EXPECT_EQ(0u, num_ready_handles); |
138 } | 144 } |
139 | 145 |
140 TEST_F(WaitSetTest, Unsatisfiable) { | 146 TEST_F(WaitSetTest, Unsatisfiable) { |
141 MessagePipe p, q; | 147 MessagePipe p, q; |
142 WaitSet wait_set; | 148 WaitSet wait_set; |
143 | 149 |
144 wait_set.AddHandle(q.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 150 wait_set.AddHandle(q.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
145 wait_set.AddHandle(q.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); | 151 wait_set.AddHandle(q.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
146 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 152 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
147 | 153 |
148 size_t num_ready_handles = 2; | 154 size_t num_ready_handles = 2; |
149 Handle ready_handles[2]; | 155 Handle ready_handles[2]; |
150 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; | 156 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; |
151 | 157 |
152 p.handle1.reset(); | 158 p.handle1.reset(); |
153 wait_set.Wait(&num_ready_handles, ready_handles, ready_results); | 159 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); |
154 EXPECT_EQ(1u, num_ready_handles); | 160 EXPECT_EQ(1u, num_ready_handles); |
155 EXPECT_EQ(p.handle0.get(), ready_handles[0]); | 161 EXPECT_EQ(p.handle0.get(), ready_handles[0]); |
156 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); | 162 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); |
157 } | 163 } |
158 | 164 |
159 TEST_F(WaitSetTest, CloseWhileWaiting) { | 165 TEST_F(WaitSetTest, CloseWhileWaiting) { |
160 MessagePipe p; | 166 MessagePipe p; |
161 WaitSet wait_set; | 167 WaitSet wait_set; |
162 | 168 |
163 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 169 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
164 | 170 |
165 const Handle handle0_value = p.handle0.get(); | 171 const Handle handle0_value = p.handle0.get(); |
166 ThreadedRunner close_after_delay(base::Bind( | 172 ThreadedRunner close_after_delay(base::Bind( |
167 [](ScopedMessagePipeHandle* handle) { | 173 [](ScopedMessagePipeHandle* handle) { |
168 // Wait a little while, then close the handle. | 174 // Wait a little while, then close the handle. |
169 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); | 175 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); |
170 handle->reset(); | 176 handle->reset(); |
171 }, | 177 }, |
172 &p.handle0)); | 178 &p.handle0)); |
173 close_after_delay.Start(); | 179 close_after_delay.Start(); |
174 | 180 |
175 size_t num_ready_handles = 2; | 181 size_t num_ready_handles = 2; |
176 Handle ready_handles[2]; | 182 Handle ready_handles[2]; |
177 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; | 183 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; |
178 wait_set.Wait(&num_ready_handles, ready_handles, ready_results); | 184 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); |
179 EXPECT_EQ(1u, num_ready_handles); | 185 EXPECT_EQ(1u, num_ready_handles); |
180 EXPECT_EQ(handle0_value, ready_handles[0]); | 186 EXPECT_EQ(handle0_value, ready_handles[0]); |
181 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]); | 187 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]); |
182 | 188 |
183 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); | 189 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); |
184 } | 190 } |
185 | 191 |
186 TEST_F(WaitSetTest, CloseBeforeWaiting) { | 192 TEST_F(WaitSetTest, CloseBeforeWaiting) { |
187 MessagePipe p; | 193 MessagePipe p; |
188 WaitSet wait_set; | 194 WaitSet wait_set; |
189 | 195 |
190 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 196 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
191 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); | 197 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
192 | 198 |
193 Handle handle0_value = p.handle0.get(); | 199 Handle handle0_value = p.handle0.get(); |
194 Handle handle1_value = p.handle1.get(); | 200 Handle handle1_value = p.handle1.get(); |
195 | 201 |
196 p.handle0.reset(); | 202 p.handle0.reset(); |
197 p.handle1.reset(); | 203 p.handle1.reset(); |
198 | 204 |
199 // Ensure that the WaitSet user is always made aware of all cancellations even | 205 // Ensure that the WaitSet user is always made aware of all cancellations even |
200 // if they happen while not waiting, or they have to be returned over the span | 206 // if they happen while not waiting, or they have to be returned over the span |
201 // of multiple Wait() calls due to insufficient output storage. | 207 // of multiple Wait() calls due to insufficient output storage. |
202 | 208 |
203 size_t num_ready_handles = 1; | 209 size_t num_ready_handles = 1; |
204 Handle ready_handle; | 210 Handle ready_handle; |
205 MojoResult ready_result = MOJO_RESULT_UNKNOWN; | 211 MojoResult ready_result = MOJO_RESULT_UNKNOWN; |
206 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result); | 212 wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); |
207 EXPECT_EQ(1u, num_ready_handles); | 213 EXPECT_EQ(1u, num_ready_handles); |
208 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); | 214 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); |
209 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); | 215 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); |
210 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); | 216 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); |
211 | 217 |
212 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result); | 218 wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); |
213 EXPECT_EQ(1u, num_ready_handles); | 219 EXPECT_EQ(1u, num_ready_handles); |
214 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); | 220 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value); |
215 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); | 221 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result); |
216 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); | 222 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value)); |
217 | 223 |
218 // Nothing more to wait on. | 224 // Nothing more to wait on. |
219 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result); | 225 wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result); |
220 EXPECT_EQ(0u, num_ready_handles); | 226 EXPECT_EQ(0u, num_ready_handles); |
221 } | 227 } |
222 | 228 |
223 TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) { | 229 TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) { |
224 MessagePipe p; | 230 MessagePipe p; |
225 WaitSet wait_set; | 231 WaitSet wait_set; |
226 | 232 |
227 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); | 233 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
228 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); | 234 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
229 | 235 |
230 const char kTestMessage1[] = "testing testing testing"; | 236 const char kTestMessage1[] = "testing testing testing"; |
231 WriteMessage(p.handle0, kTestMessage1); | 237 WriteMessage(p.handle0, kTestMessage1); |
232 | 238 |
233 size_t num_ready_handles = 2; | 239 size_t num_ready_handles = 2; |
234 Handle ready_handles[2]; | 240 Handle ready_handles[2]; |
235 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; | 241 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN}; |
236 wait_set.Wait(&num_ready_handles, ready_handles, ready_results); | 242 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); |
237 EXPECT_EQ(1u, num_ready_handles); | 243 EXPECT_EQ(1u, num_ready_handles); |
238 EXPECT_EQ(p.handle1.get(), ready_handles[0]); | 244 EXPECT_EQ(p.handle1.get(), ready_handles[0]); |
239 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 245 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
240 | 246 |
241 EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1)); | 247 EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1)); |
242 | 248 |
243 ThreadedRunner write_after_delay(base::Bind( | 249 ThreadedRunner write_after_delay(base::Bind( |
244 [](ScopedMessagePipeHandle* handle) { | 250 [](ScopedMessagePipeHandle* handle) { |
245 // Wait a little while, then write a message. | 251 // Wait a little while, then write a message. |
246 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); | 252 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); |
247 WriteMessage(*handle, "wakey wakey"); | 253 WriteMessage(*handle, "wakey wakey"); |
248 }, | 254 }, |
249 &p.handle1)); | 255 &p.handle1)); |
250 write_after_delay.Start(); | 256 write_after_delay.Start(); |
251 | 257 |
252 num_ready_handles = 2; | 258 num_ready_handles = 2; |
253 wait_set.Wait(&num_ready_handles, ready_handles, ready_results); | 259 wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results); |
254 EXPECT_EQ(1u, num_ready_handles); | 260 EXPECT_EQ(1u, num_ready_handles); |
255 EXPECT_EQ(p.handle0.get(), ready_handles[0]); | 261 EXPECT_EQ(p.handle0.get(), ready_handles[0]); |
256 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | 262 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); |
257 } | 263 } |
258 | 264 |
| 265 TEST_F(WaitSetTest, EventOnly) { |
| 266 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, |
| 267 base::WaitableEvent::InitialState::SIGNALED); |
| 268 WaitSet wait_set; |
| 269 wait_set.AddEvent(&event); |
| 270 |
| 271 base::WaitableEvent* ready_event = nullptr; |
| 272 size_t num_ready_handles = 1; |
| 273 Handle ready_handle; |
| 274 MojoResult ready_result = MOJO_RESULT_UNKNOWN; |
| 275 wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); |
| 276 EXPECT_EQ(0u, num_ready_handles); |
| 277 EXPECT_EQ(&event, ready_event); |
| 278 } |
| 279 |
| 280 TEST_F(WaitSetTest, EventAndHandle) { |
| 281 const char kTestMessage[] = "hello hello"; |
| 282 |
| 283 MessagePipe p; |
| 284 WriteMessage(p.handle0, kTestMessage); |
| 285 |
| 286 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, |
| 287 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 288 |
| 289 WaitSet wait_set; |
| 290 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| 291 wait_set.AddEvent(&event); |
| 292 |
| 293 base::WaitableEvent* ready_event = nullptr; |
| 294 size_t num_ready_handles = 1; |
| 295 Handle ready_handle; |
| 296 MojoResult ready_result = MOJO_RESULT_UNKNOWN; |
| 297 wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); |
| 298 EXPECT_EQ(1u, num_ready_handles); |
| 299 EXPECT_EQ(nullptr, ready_event); |
| 300 EXPECT_EQ(p.handle1.get(), ready_handle); |
| 301 EXPECT_EQ(MOJO_RESULT_OK, ready_result); |
| 302 |
| 303 EXPECT_EQ(kTestMessage, ReadMessage(p.handle1)); |
| 304 |
| 305 ThreadedRunner signal_after_delay(base::Bind( |
| 306 [](base::WaitableEvent* event) { |
| 307 // Wait a little while, then close the handle. |
| 308 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200)); |
| 309 event->Signal(); |
| 310 }, |
| 311 &event)); |
| 312 signal_after_delay.Start(); |
| 313 |
| 314 wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result); |
| 315 EXPECT_EQ(0u, num_ready_handles); |
| 316 EXPECT_EQ(&event, ready_event); |
| 317 } |
| 318 |
| 319 TEST_F(WaitSetTest, NoStarvation) { |
| 320 const char kTestMessage[] = "wait for it"; |
| 321 const size_t kNumTestPipes = 50; |
| 322 const size_t kNumTestEvents = 10; |
| 323 |
| 324 // Create a bunch of handles and events which are always ready and add them |
| 325 // to a shared WaitSet. |
| 326 |
| 327 WaitSet wait_set; |
| 328 |
| 329 MessagePipe pipes[kNumTestPipes]; |
| 330 for (size_t i = 0; i < kNumTestPipes; ++i) { |
| 331 WriteMessage(pipes[i].handle0, kTestMessage); |
| 332 Wait(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| 333 |
| 334 WriteMessage(pipes[i].handle1, kTestMessage); |
| 335 Wait(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| 336 |
| 337 wait_set.AddHandle(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| 338 wait_set.AddHandle(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE); |
| 339 } |
| 340 |
| 341 std::vector<std::unique_ptr<base::WaitableEvent>> events(kNumTestEvents); |
| 342 for (auto& event_ptr : events) { |
| 343 event_ptr = base::MakeUnique<base::WaitableEvent>( |
| 344 base::WaitableEvent::ResetPolicy::MANUAL, |
| 345 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 346 event_ptr->Signal(); |
| 347 wait_set.AddEvent(event_ptr.get()); |
| 348 } |
| 349 |
| 350 // Now verify that all handle and event signals are deteceted within a finite |
| 351 // number of consecutive Wait() calls. Do it a few times for good measure. |
| 352 for (size_t i = 0; i < 3; ++i) { |
| 353 std::set<base::WaitableEvent*> ready_events; |
| 354 std::set<Handle> ready_handles; |
| 355 while (ready_events.size() < kNumTestEvents || |
| 356 ready_handles.size() < kNumTestPipes * 2) { |
| 357 base::WaitableEvent* ready_event = nullptr; |
| 358 size_t num_ready_handles = 1; |
| 359 Handle ready_handle; |
| 360 MojoResult ready_result = MOJO_RESULT_UNKNOWN; |
| 361 wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, |
| 362 &ready_result); |
| 363 if (ready_event) |
| 364 ready_events.insert(ready_event); |
| 365 |
| 366 if (num_ready_handles) { |
| 367 EXPECT_EQ(1u, num_ready_handles); |
| 368 EXPECT_EQ(MOJO_RESULT_OK, ready_result); |
| 369 ready_handles.insert(ready_handle); |
| 370 } |
| 371 } |
| 372 } |
| 373 } |
| 374 |
259 } // namespace | 375 } // namespace |
260 } // namespace mojo | 376 } // namespace mojo |
OLD | NEW |