Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Side by Side Diff: mojo/public/cpp/bindings/tests/router_unittest.cc

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/request_response_unittest.cc ('k') | mojo/public/cpp/bindings/tests/sample_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698