| 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 "gtest/gtest.h" | |
| 12 #include "mojo/public/cpp/system/handle.h" | |
| 13 #include "mojo/public/cpp/system/wait.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 |