OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This file tests the C++ wrappers in mojo/public/cpp/system/message_pipe.h. |
| 6 |
| 7 #include "mojo/public/cpp/system/message_pipe.h" |
| 8 |
| 9 #include <vector> |
| 10 |
| 11 #include "mojo/public/cpp/system/handle.h" |
| 12 #include "mojo/public/cpp/system/wait.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 namespace mojo { |
| 16 namespace { |
| 17 |
| 18 TEST(MessagePipeTest, InvalidArgs) { |
| 19 MessagePipeHandle h_invalid; |
| 20 EXPECT_FALSE(h_invalid.is_valid()); |
| 21 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| 22 WriteMessageRaw(h_invalid, nullptr, 0, nullptr, 0, |
| 23 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 24 char buffer[10] = {0}; |
| 25 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| 26 WriteMessageRaw(h_invalid, buffer, sizeof(buffer), nullptr, 0, |
| 27 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 28 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| 29 ReadMessageRaw(h_invalid, nullptr, nullptr, nullptr, nullptr, |
| 30 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 31 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
| 32 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| 33 ReadMessageRaw(h_invalid, buffer, &buffer_size, nullptr, nullptr, |
| 34 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 35 } |
| 36 |
| 37 TEST(MessagePipeTest, BasicWaitingAndClosing) { |
| 38 // Cursory compilation test of |MakeScopedHandle()| with message pipe handles. |
| 39 EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid()); |
| 40 |
| 41 MojoHandle hv0 = kInvalidHandleValue; |
| 42 { |
| 43 ScopedMessagePipeHandle h0; |
| 44 ScopedMessagePipeHandle h1; |
| 45 EXPECT_FALSE(h0.get().is_valid()); |
| 46 EXPECT_FALSE(h1.get().is_valid()); |
| 47 |
| 48 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h0, &h1)); |
| 49 EXPECT_TRUE(h0.get().is_valid()); |
| 50 EXPECT_TRUE(h1.get().is_valid()); |
| 51 EXPECT_NE(h0.get().value(), h1.get().value()); |
| 52 // Save the handle values, so we can check that things got closed |
| 53 // correctly. |
| 54 hv0 = h0.get().value(); |
| 55 MojoHandle hv1 = h1.get().value(); |
| 56 MojoHandleSignalsState state; |
| 57 |
| 58 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, |
| 59 Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); |
| 60 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
| 61 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 62 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 63 state.satisfiable_signals); |
| 64 |
| 65 std::vector<Handle> wh; |
| 66 wh.push_back(h0.get()); |
| 67 wh.push_back(h1.get()); |
| 68 std::vector<MojoHandleSignals> sigs; |
| 69 sigs.push_back(MOJO_HANDLE_SIGNAL_READABLE); |
| 70 sigs.push_back(MOJO_HANDLE_SIGNAL_WRITABLE); |
| 71 std::vector<MojoHandleSignalsState> states(sigs.size()); |
| 72 WaitManyResult wait_many_result = WaitMany(wh, sigs, 1000, &states); |
| 73 EXPECT_EQ(MOJO_RESULT_OK, wait_many_result.result); |
| 74 EXPECT_EQ(1u, wait_many_result.index); |
| 75 EXPECT_TRUE(wait_many_result.IsIndexValid()); |
| 76 EXPECT_TRUE(wait_many_result.AreSignalsStatesValid()); |
| 77 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals); |
| 78 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 79 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 80 states[0].satisfiable_signals); |
| 81 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[1].satisfied_signals); |
| 82 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 83 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 84 states[1].satisfiable_signals); |
| 85 |
| 86 // Test closing |h1| explicitly. |
| 87 Close(h1.Pass()); |
| 88 EXPECT_FALSE(h1.get().is_valid()); |
| 89 |
| 90 // Make sure |h1| is closed. |
| 91 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| 92 Wait(Handle(hv1), ~MOJO_HANDLE_SIGNAL_NONE, |
| 93 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 94 |
| 95 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 96 Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 97 MOJO_DEADLINE_INDEFINITE, &state)); |
| 98 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); |
| 99 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); |
| 100 } |
| 101 // |hv0| should have been closed when |h0| went out of scope, so this close |
| 102 // should fail. |
| 103 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); |
| 104 } |
| 105 |
| 106 TEST(MessagePipeTest, BasicWritingAndReading) { |
| 107 MojoHandle hv0 = kInvalidHandleValue; |
| 108 { |
| 109 ScopedMessagePipeHandle h0; |
| 110 ScopedMessagePipeHandle h1; |
| 111 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h0, &h1)); |
| 112 |
| 113 const char kHello[] = "hello"; |
| 114 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); |
| 115 EXPECT_EQ(MOJO_RESULT_OK, |
| 116 WriteMessageRaw(h0.get(), kHello, kHelloSize, nullptr, 0, |
| 117 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 118 |
| 119 MojoHandleSignalsState state; |
| 120 EXPECT_EQ(MOJO_RESULT_OK, Wait(h1.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 121 MOJO_DEADLINE_INDEFINITE, &state)); |
| 122 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
| 123 state.satisfied_signals); |
| 124 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 125 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 126 state.satisfiable_signals); |
| 127 |
| 128 char buffer[10] = {0}; |
| 129 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
| 130 EXPECT_EQ(MOJO_RESULT_OK, |
| 131 ReadMessageRaw(h1.get(), buffer, &buffer_size, nullptr, nullptr, |
| 132 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 133 EXPECT_EQ(kHelloSize, buffer_size); |
| 134 EXPECT_STREQ(kHello, buffer); |
| 135 |
| 136 // Send a handle over the previously-establish message pipe. Use the |
| 137 // |MessagePipe| wrapper (to test it), which automatically creates a |
| 138 // message pipe. |
| 139 MessagePipe mp; |
| 140 |
| 141 // Write a message to |mp.handle0|, before we send |mp.handle1|. |
| 142 const char kWorld[] = "world!"; |
| 143 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); |
| 144 EXPECT_EQ(MOJO_RESULT_OK, |
| 145 WriteMessageRaw(mp.handle0.get(), kWorld, kWorldSize, nullptr, 0, |
| 146 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 147 |
| 148 // Send |mp.handle1| over |h1| to |h0|. |
| 149 MojoHandle handles[5]; |
| 150 handles[0] = mp.handle1.release().value(); |
| 151 EXPECT_NE(kInvalidHandleValue, handles[0]); |
| 152 EXPECT_FALSE(mp.handle1.get().is_valid()); |
| 153 uint32_t handles_count = 1; |
| 154 EXPECT_EQ(MOJO_RESULT_OK, |
| 155 WriteMessageRaw(h1.get(), kHello, kHelloSize, handles, |
| 156 handles_count, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 157 // |handles[0]| should actually be invalid now. |
| 158 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0])); |
| 159 |
| 160 // Read "hello" and the sent handle. |
| 161 EXPECT_EQ(MOJO_RESULT_OK, Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 162 MOJO_DEADLINE_INDEFINITE, &state)); |
| 163 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
| 164 state.satisfied_signals); |
| 165 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 166 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 167 state.satisfiable_signals); |
| 168 |
| 169 memset(buffer, 0, sizeof(buffer)); |
| 170 buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
| 171 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) |
| 172 handles[i] = kInvalidHandleValue; |
| 173 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); |
| 174 EXPECT_EQ(MOJO_RESULT_OK, |
| 175 ReadMessageRaw(h0.get(), buffer, &buffer_size, handles, |
| 176 &handles_count, MOJO_READ_MESSAGE_FLAG_NONE)); |
| 177 EXPECT_EQ(kHelloSize, buffer_size); |
| 178 EXPECT_STREQ(kHello, buffer); |
| 179 EXPECT_EQ(1u, handles_count); |
| 180 EXPECT_NE(kInvalidHandleValue, handles[0]); |
| 181 |
| 182 // Read from the sent/received handle. |
| 183 mp.handle1.reset(MessagePipeHandle(handles[0])); |
| 184 // Save |handles[0]| to check that it gets properly closed. |
| 185 hv0 = handles[0]; |
| 186 |
| 187 EXPECT_EQ(MOJO_RESULT_OK, |
| 188 Wait(mp.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| 189 MOJO_DEADLINE_INDEFINITE, &state)); |
| 190 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
| 191 state.satisfied_signals); |
| 192 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | |
| 193 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 194 state.satisfiable_signals); |
| 195 |
| 196 memset(buffer, 0, sizeof(buffer)); |
| 197 buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
| 198 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) |
| 199 handles[i] = kInvalidHandleValue; |
| 200 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); |
| 201 EXPECT_EQ(MOJO_RESULT_OK, |
| 202 ReadMessageRaw(mp.handle1.get(), buffer, &buffer_size, handles, |
| 203 &handles_count, MOJO_READ_MESSAGE_FLAG_NONE)); |
| 204 EXPECT_EQ(kWorldSize, buffer_size); |
| 205 EXPECT_STREQ(kWorld, buffer); |
| 206 EXPECT_EQ(0u, handles_count); |
| 207 } |
| 208 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); |
| 209 } |
| 210 |
| 211 // TODO(vtl): This is not the right level to test this at. |
| 212 TEST(MessagePipeTest, TearDownWithMessagesEnqueued) { |
| 213 // Tear down a message pipe which still has a message enqueued, with the |
| 214 // message also having a valid message pipe handle. |
| 215 { |
| 216 ScopedMessagePipeHandle h0; |
| 217 ScopedMessagePipeHandle h1; |
| 218 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h0, &h1)); |
| 219 |
| 220 // Send a handle over the previously-establish message pipe. |
| 221 ScopedMessagePipeHandle h2; |
| 222 ScopedMessagePipeHandle h3; |
| 223 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h2, &h3)); |
| 224 |
| 225 // Write a message to |h2|, before we send |h3|. |
| 226 const char kWorld[] = "world!"; |
| 227 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); |
| 228 EXPECT_EQ(MOJO_RESULT_OK, |
| 229 WriteMessageRaw(h2.get(), kWorld, kWorldSize, nullptr, 0, |
| 230 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 231 // And also a message to |h3|. |
| 232 EXPECT_EQ(MOJO_RESULT_OK, |
| 233 WriteMessageRaw(h3.get(), kWorld, kWorldSize, nullptr, 0, |
| 234 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 235 |
| 236 // Send |h3| over |h1| to |h0|. |
| 237 const char kHello[] = "hello"; |
| 238 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); |
| 239 MojoHandle h3_value; |
| 240 h3_value = h3.release().value(); |
| 241 EXPECT_NE(kInvalidHandleValue, h3_value); |
| 242 EXPECT_FALSE(h3.get().is_valid()); |
| 243 EXPECT_EQ(MOJO_RESULT_OK, |
| 244 WriteMessageRaw(h1.get(), kHello, kHelloSize, &h3_value, 1, |
| 245 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 246 // |h3_value| should actually be invalid now. |
| 247 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); |
| 248 |
| 249 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); |
| 250 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); |
| 251 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); |
| 252 } |
| 253 |
| 254 // Do this in a different order: make the enqueued message pipe handle only |
| 255 // half-alive. |
| 256 { |
| 257 ScopedMessagePipeHandle h0; |
| 258 ScopedMessagePipeHandle h1; |
| 259 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h0, &h1)); |
| 260 |
| 261 // Send a handle over the previously-establish message pipe. |
| 262 ScopedMessagePipeHandle h2; |
| 263 ScopedMessagePipeHandle h3; |
| 264 ASSERT_EQ(MOJO_RESULT_OK, CreateMessagePipe(nullptr, &h2, &h3)); |
| 265 |
| 266 // Write a message to |h2|, before we send |h3|. |
| 267 const char kWorld[] = "world!"; |
| 268 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); |
| 269 EXPECT_EQ(MOJO_RESULT_OK, |
| 270 WriteMessageRaw(h2.get(), kWorld, kWorldSize, nullptr, 0, |
| 271 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 272 // And also a message to |h3|. |
| 273 EXPECT_EQ(MOJO_RESULT_OK, |
| 274 WriteMessageRaw(h3.get(), kWorld, kWorldSize, nullptr, 0, |
| 275 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 276 |
| 277 // Send |h3| over |h1| to |h0|. |
| 278 const char kHello[] = "hello"; |
| 279 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); |
| 280 MojoHandle h3_value; |
| 281 h3_value = h3.release().value(); |
| 282 EXPECT_NE(kInvalidHandleValue, h3_value); |
| 283 EXPECT_FALSE(h3.get().is_valid()); |
| 284 EXPECT_EQ(MOJO_RESULT_OK, |
| 285 WriteMessageRaw(h1.get(), kHello, kHelloSize, &h3_value, 1, |
| 286 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 287 // |h3_value| should actually be invalid now. |
| 288 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); |
| 289 |
| 290 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); |
| 291 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); |
| 292 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); |
| 293 } |
| 294 } |
| 295 |
| 296 } // namespace |
| 297 } // namespace mojo |
OLD | NEW |