| 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 |