OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 #include <stdlib.h> | |
6 #include <string.h> | |
7 | |
8 #include "gtest/gtest.h" | |
9 #include "mojo/public/cpp/bindings/lib/message_builder.h" | |
10 #include "mojo/public/cpp/bindings/lib/router.h" | |
11 #include "mojo/public/cpp/bindings/tests/message_queue.h" | |
12 #include "mojo/public/cpp/system/macros.h" | |
13 #include "mojo/public/cpp/utility/run_loop.h" | |
14 | |
15 namespace mojo { | |
16 namespace test { | |
17 namespace { | |
18 | |
19 void AllocRequestMessage(uint32_t name, const char* text, Message* message) { | |
20 size_t payload_size = strlen(text) + 1; // Plus null terminator. | |
21 RequestMessageBuilder builder(name, payload_size); | |
22 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); | |
23 | |
24 builder.message()->MoveTo(message); | |
25 } | |
26 | |
27 void AllocResponseMessage(uint32_t name, | |
28 const char* text, | |
29 uint64_t request_id, | |
30 Message* message) { | |
31 size_t payload_size = strlen(text) + 1; // Plus null terminator. | |
32 ResponseMessageBuilder builder(name, payload_size, request_id); | |
33 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); | |
34 | |
35 builder.message()->MoveTo(message); | |
36 } | |
37 | |
38 class MessageAccumulator : public MessageReceiver { | |
39 public: | |
40 explicit MessageAccumulator(MessageQueue* queue) : queue_(queue) {} | |
41 | |
42 bool Accept(Message* message) override { | |
43 queue_->Push(message); | |
44 return true; | |
45 } | |
46 | |
47 private: | |
48 MessageQueue* queue_; | |
49 }; | |
50 | |
51 class ResponseGenerator : public MessageReceiverWithResponderStatus { | |
52 public: | |
53 ResponseGenerator() {} | |
54 | |
55 bool Accept(Message* message) override { return false; } | |
56 | |
57 bool AcceptWithResponder(Message* message, | |
58 MessageReceiverWithStatus* responder) override { | |
59 EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse)); | |
60 | |
61 bool result = SendResponse( | |
62 message->name(), message->request_id(), | |
63 reinterpret_cast<const char*>(message->payload()), responder); | |
64 EXPECT_TRUE(responder->IsValid()); | |
65 delete responder; | |
66 return result; | |
67 } | |
68 | |
69 bool SendResponse(uint32_t name, | |
70 uint64_t request_id, | |
71 const char* request_string, | |
72 MessageReceiver* responder) { | |
73 Message response; | |
74 std::string response_string(request_string); | |
75 response_string += " world!"; | |
76 AllocResponseMessage(name, response_string.c_str(), request_id, &response); | |
77 | |
78 return responder->Accept(&response); | |
79 } | |
80 }; | |
81 | |
82 class LazyResponseGenerator : public ResponseGenerator { | |
83 public: | |
84 LazyResponseGenerator() : responder_(nullptr), name_(0), request_id_(0) {} | |
85 | |
86 ~LazyResponseGenerator() override { delete responder_; } | |
87 | |
88 bool AcceptWithResponder(Message* message, | |
89 MessageReceiverWithStatus* responder) override { | |
90 name_ = message->name(); | |
91 request_id_ = message->request_id(); | |
92 request_string_ = | |
93 std::string(reinterpret_cast<const char*>(message->payload())); | |
94 responder_ = responder; | |
95 return true; | |
96 } | |
97 | |
98 bool has_responder() const { return !!responder_; } | |
99 | |
100 bool responder_is_valid() const { return responder_->IsValid(); } | |
101 | |
102 // Send the response and delete the responder. | |
103 void CompleteWithResponse() { Complete(true); } | |
104 | |
105 // Delete the responder without sending a response. | |
106 void CompleteWithoutResponse() { Complete(false); } | |
107 | |
108 private: | |
109 // Completes the request handling by deleting responder_. Optionally | |
110 // also sends a response. | |
111 void Complete(bool send_response) { | |
112 if (send_response) { | |
113 SendResponse(name_, request_id_, request_string_.c_str(), responder_); | |
114 } | |
115 delete responder_; | |
116 responder_ = nullptr; | |
117 } | |
118 | |
119 MessageReceiverWithStatus* responder_; | |
120 uint32_t name_; | |
121 uint64_t request_id_; | |
122 std::string request_string_; | |
123 }; | |
124 | |
125 class RouterTest : public testing::Test { | |
126 public: | |
127 RouterTest() {} | |
128 | |
129 void SetUp() override { | |
130 CreateMessagePipe(nullptr, &handle0_, &handle1_); | |
131 } | |
132 | |
133 void TearDown() override {} | |
134 | |
135 void PumpMessages() { loop_.RunUntilIdle(); } | |
136 | |
137 protected: | |
138 ScopedMessagePipeHandle handle0_; | |
139 ScopedMessagePipeHandle handle1_; | |
140 | |
141 private: | |
142 RunLoop loop_; | |
143 }; | |
144 | |
145 TEST_F(RouterTest, BasicRequestResponse) { | |
146 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
147 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
148 | |
149 ResponseGenerator generator; | |
150 router1.set_incoming_receiver(&generator); | |
151 | |
152 Message request; | |
153 AllocRequestMessage(1, "hello", &request); | |
154 | |
155 MessageQueue message_queue; | |
156 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
157 | |
158 PumpMessages(); | |
159 | |
160 EXPECT_FALSE(message_queue.IsEmpty()); | |
161 | |
162 Message response; | |
163 message_queue.Pop(&response); | |
164 | |
165 EXPECT_EQ(std::string("hello world!"), | |
166 std::string(reinterpret_cast<const char*>(response.payload()))); | |
167 | |
168 // Send a second message on the pipe. | |
169 Message request2; | |
170 AllocRequestMessage(1, "hello again", &request2); | |
171 | |
172 router0.AcceptWithResponder(&request2, | |
173 new MessageAccumulator(&message_queue)); | |
174 | |
175 PumpMessages(); | |
176 | |
177 EXPECT_FALSE(message_queue.IsEmpty()); | |
178 | |
179 message_queue.Pop(&response); | |
180 | |
181 EXPECT_EQ(std::string("hello again world!"), | |
182 std::string(reinterpret_cast<const char*>(response.payload()))); | |
183 } | |
184 | |
185 TEST_F(RouterTest, BasicRequestResponse_Synchronous) { | |
186 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
187 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
188 | |
189 ResponseGenerator generator; | |
190 router1.set_incoming_receiver(&generator); | |
191 | |
192 Message request; | |
193 AllocRequestMessage(1, "hello", &request); | |
194 | |
195 MessageQueue message_queue; | |
196 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
197 | |
198 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
199 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
200 | |
201 EXPECT_FALSE(message_queue.IsEmpty()); | |
202 | |
203 Message response; | |
204 message_queue.Pop(&response); | |
205 | |
206 EXPECT_EQ(std::string("hello world!"), | |
207 std::string(reinterpret_cast<const char*>(response.payload()))); | |
208 | |
209 // Send a second message on the pipe. | |
210 Message request2; | |
211 AllocRequestMessage(1, "hello again", &request2); | |
212 | |
213 router0.AcceptWithResponder(&request2, | |
214 new MessageAccumulator(&message_queue)); | |
215 | |
216 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
217 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
218 | |
219 EXPECT_FALSE(message_queue.IsEmpty()); | |
220 | |
221 message_queue.Pop(&response); | |
222 | |
223 EXPECT_EQ(std::string("hello again world!"), | |
224 std::string(reinterpret_cast<const char*>(response.payload()))); | |
225 } | |
226 | |
227 TEST_F(RouterTest, BasicRequestResponse_SynchronousTimeout) { | |
228 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
229 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
230 | |
231 ResponseGenerator generator; | |
232 router1.set_incoming_receiver(&generator); | |
233 | |
234 Message request; | |
235 AllocRequestMessage(1, "hello", &request); | |
236 | |
237 EXPECT_FALSE(router1.WaitForIncomingMessage(0)); | |
238 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
239 EXPECT_FALSE(router0.encountered_error()); | |
240 EXPECT_FALSE(router1.encountered_error()); | |
241 | |
242 MessageQueue message_queue; | |
243 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
244 | |
245 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
246 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
247 | |
248 EXPECT_FALSE(message_queue.IsEmpty()); | |
249 | |
250 EXPECT_FALSE(router1.WaitForIncomingMessage(0)); | |
251 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
252 EXPECT_FALSE(router0.encountered_error()); | |
253 EXPECT_FALSE(router1.encountered_error()); | |
254 | |
255 Message response; | |
256 message_queue.Pop(&response); | |
257 | |
258 EXPECT_EQ(std::string("hello world!"), | |
259 std::string(reinterpret_cast<const char*>(response.payload()))); | |
260 | |
261 // Send a second message on the pipe. | |
262 Message request2; | |
263 AllocRequestMessage(1, "hello again", &request2); | |
264 | |
265 router0.AcceptWithResponder(&request2, | |
266 new MessageAccumulator(&message_queue)); | |
267 | |
268 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
269 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
270 | |
271 EXPECT_FALSE(message_queue.IsEmpty()); | |
272 | |
273 message_queue.Pop(&response); | |
274 | |
275 EXPECT_EQ(std::string("hello again world!"), | |
276 std::string(reinterpret_cast<const char*>(response.payload()))); | |
277 } | |
278 | |
279 TEST_F(RouterTest, RequestWithNoReceiver) { | |
280 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
281 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
282 | |
283 // Without an incoming receiver set on router1, we expect router0 to observe | |
284 // an error as a result of sending a message. | |
285 | |
286 Message request; | |
287 AllocRequestMessage(1, "hello", &request); | |
288 | |
289 MessageQueue message_queue; | |
290 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
291 | |
292 PumpMessages(); | |
293 | |
294 EXPECT_TRUE(router0.encountered_error()); | |
295 EXPECT_TRUE(router1.encountered_error()); | |
296 EXPECT_TRUE(message_queue.IsEmpty()); | |
297 } | |
298 | |
299 // Tests Router using the LazyResponseGenerator. The responses will not be | |
300 // sent until after the requests have been accepted. | |
301 TEST_F(RouterTest, LazyResponses) { | |
302 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
303 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
304 | |
305 LazyResponseGenerator generator; | |
306 router1.set_incoming_receiver(&generator); | |
307 | |
308 Message request; | |
309 AllocRequestMessage(1, "hello", &request); | |
310 | |
311 MessageQueue message_queue; | |
312 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
313 PumpMessages(); | |
314 | |
315 // The request has been received but the response has not been sent yet. | |
316 EXPECT_TRUE(message_queue.IsEmpty()); | |
317 | |
318 // Send the response. | |
319 EXPECT_TRUE(generator.responder_is_valid()); | |
320 generator.CompleteWithResponse(); | |
321 PumpMessages(); | |
322 | |
323 // Check the response. | |
324 EXPECT_FALSE(message_queue.IsEmpty()); | |
325 Message response; | |
326 message_queue.Pop(&response); | |
327 EXPECT_EQ(std::string("hello world!"), | |
328 std::string(reinterpret_cast<const char*>(response.payload()))); | |
329 | |
330 // Send a second message on the pipe. | |
331 Message request2; | |
332 AllocRequestMessage(1, "hello again", &request2); | |
333 | |
334 router0.AcceptWithResponder(&request2, | |
335 new MessageAccumulator(&message_queue)); | |
336 PumpMessages(); | |
337 | |
338 // The request has been received but the response has not been sent yet. | |
339 EXPECT_TRUE(message_queue.IsEmpty()); | |
340 | |
341 // Send the second response. | |
342 EXPECT_TRUE(generator.responder_is_valid()); | |
343 generator.CompleteWithResponse(); | |
344 PumpMessages(); | |
345 | |
346 // Check the second response. | |
347 EXPECT_FALSE(message_queue.IsEmpty()); | |
348 message_queue.Pop(&response); | |
349 EXPECT_EQ(std::string("hello again world!"), | |
350 std::string(reinterpret_cast<const char*>(response.payload()))); | |
351 } | |
352 | |
353 // Tests that if the receiving application destroys the responder_ without | |
354 // sending a response, then we close the Pipe as a way of signaling an error | |
355 // condition to the caller. | |
356 TEST_F(RouterTest, MissingResponses) { | |
357 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
358 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
359 | |
360 LazyResponseGenerator generator; | |
361 router1.set_incoming_receiver(&generator); | |
362 | |
363 Message request; | |
364 AllocRequestMessage(1, "hello", &request); | |
365 | |
366 MessageQueue message_queue; | |
367 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
368 PumpMessages(); | |
369 | |
370 // The request has been received but no response has been sent. | |
371 EXPECT_TRUE(message_queue.IsEmpty()); | |
372 | |
373 // Destroy the responder MessagerReceiver but don't send any response. | |
374 // This should close the pipe. | |
375 generator.CompleteWithoutResponse(); | |
376 PumpMessages(); | |
377 | |
378 // Check that no response was received. | |
379 EXPECT_TRUE(message_queue.IsEmpty()); | |
380 | |
381 // There is no direct way to test whether or not the pipe has been closed. | |
382 // The only thing we can do is try to send a second message on the pipe | |
383 // and observe that an error occurs. | |
384 Message request2; | |
385 AllocRequestMessage(1, "hello again", &request2); | |
386 router0.AcceptWithResponder(&request2, | |
387 new MessageAccumulator(&message_queue)); | |
388 PumpMessages(); | |
389 | |
390 // Make sure there was an error. | |
391 EXPECT_TRUE(router0.encountered_error()); | |
392 } | |
393 | |
394 // Tests that if the receiving application destroys the responder_ without | |
395 // sending a response, then we close the Pipe as a way of signaling an error | |
396 // condition to the caller. | |
397 // Tests that timeout-0 calls still work and signal an error. | |
398 TEST_F(RouterTest, MissingResponses_Timeout) { | |
399 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
400 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
401 | |
402 LazyResponseGenerator generator; | |
403 router1.set_incoming_receiver(&generator); | |
404 | |
405 Message request; | |
406 AllocRequestMessage(1, "hello", &request); | |
407 | |
408 MessageQueue message_queue; | |
409 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
410 PumpMessages(); | |
411 | |
412 // The request has been received but no response has been sent. | |
413 EXPECT_TRUE(message_queue.IsEmpty()); | |
414 | |
415 // Destroy the responder MessagerReceiver but don't send any response. | |
416 // This should close the pipe. | |
417 generator.CompleteWithoutResponse(); | |
418 PumpMessages(); | |
419 | |
420 // Check that no response was received. | |
421 EXPECT_TRUE(message_queue.IsEmpty()); | |
422 | |
423 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
424 EXPECT_TRUE(router0.encountered_error()); | |
425 | |
426 PumpMessages(); | |
427 | |
428 // Make sure there was an error. | |
429 EXPECT_TRUE(router0.encountered_error()); | |
430 } | |
431 | |
432 TEST_F(RouterTest, LateResponse) { | |
433 // Test that things won't blow up if we try to send a message to a | |
434 // MessageReceiver, which was given to us via AcceptWithResponder, | |
435 // after the router has gone away. | |
436 | |
437 LazyResponseGenerator generator; | |
438 { | |
439 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
440 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
441 | |
442 router1.set_incoming_receiver(&generator); | |
443 | |
444 Message request; | |
445 AllocRequestMessage(1, "hello", &request); | |
446 | |
447 MessageQueue message_queue; | |
448 router0.AcceptWithResponder(&request, | |
449 new MessageAccumulator(&message_queue)); | |
450 | |
451 PumpMessages(); | |
452 | |
453 EXPECT_TRUE(generator.has_responder()); | |
454 } | |
455 | |
456 EXPECT_FALSE(generator.responder_is_valid()); | |
457 generator.CompleteWithResponse(); // This should end up doing nothing. | |
458 } | |
459 | |
460 } // namespace | |
461 } // namespace test | |
462 } // namespace mojo | |
OLD | NEW |