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 |