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 "mojo/public/cpp/bindings/lib/router.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "mojo/public/cpp/bindings/tests/message_queue.h"
14 #include "mojo/public/cpp/bindings/tests/router_test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace mojo {
18 namespace test {
19 namespace {
20 
21 class RouterTest : public testing::Test {
22  public:
RouterTest()23   RouterTest() {}
24 
SetUp()25   void SetUp() override {
26     CreateMessagePipe(nullptr, &handle0_, &handle1_);
27   }
28 
TearDown()29   void TearDown() override {}
30 
PumpMessages()31   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
32 
33  protected:
34   ScopedMessagePipeHandle handle0_;
35   ScopedMessagePipeHandle handle1_;
36 
37  private:
38   base::MessageLoop loop_;
39 };
40 
TEST_F(RouterTest,BasicRequestResponse)41 TEST_F(RouterTest, BasicRequestResponse) {
42   internal::Router router0(std::move(handle0_), internal::FilterChain(), false,
43                            base::ThreadTaskRunnerHandle::Get());
44   internal::Router router1(std::move(handle1_), internal::FilterChain(), false,
45                            base::ThreadTaskRunnerHandle::Get());
46 
47   ResponseGenerator generator;
48   router1.set_incoming_receiver(&generator);
49 
50   Message request;
51   AllocRequestMessage(1, "hello", &request);
52 
53   MessageQueue message_queue;
54   base::RunLoop run_loop;
55   router0.AcceptWithResponder(
56       &request, new MessageAccumulator(&message_queue, run_loop.QuitClosure()));
57 
58   run_loop.Run();
59 
60   EXPECT_FALSE(message_queue.IsEmpty());
61 
62   Message response;
63   message_queue.Pop(&response);
64 
65   EXPECT_EQ(std::string("hello world!"),
66             std::string(reinterpret_cast<const char*>(response.payload())));
67 
68   // Send a second message on the pipe.
69   Message request2;
70   AllocRequestMessage(1, "hello again", &request2);
71 
72   base::RunLoop run_loop2;
73   router0.AcceptWithResponder(
74       &request2,
75       new MessageAccumulator(&message_queue, run_loop2.QuitClosure()));
76 
77   run_loop2.Run();
78 
79   EXPECT_FALSE(message_queue.IsEmpty());
80 
81   message_queue.Pop(&response);
82 
83   EXPECT_EQ(std::string("hello again world!"),
84             std::string(reinterpret_cast<const char*>(response.payload())));
85 }
86 
TEST_F(RouterTest,BasicRequestResponse_Synchronous)87 TEST_F(RouterTest, BasicRequestResponse_Synchronous) {
88   internal::Router router0(std::move(handle0_), internal::FilterChain(), false,
89                            base::ThreadTaskRunnerHandle::Get());
90   internal::Router router1(std::move(handle1_), internal::FilterChain(), false,
91                            base::ThreadTaskRunnerHandle::Get());
92 
93   ResponseGenerator generator;
94   router1.set_incoming_receiver(&generator);
95 
96   Message request;
97   AllocRequestMessage(1, "hello", &request);
98 
99   MessageQueue message_queue;
100   router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
101 
102   router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
103   router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
104 
105   EXPECT_FALSE(message_queue.IsEmpty());
106 
107   Message response;
108   message_queue.Pop(&response);
109 
110   EXPECT_EQ(std::string("hello world!"),
111             std::string(reinterpret_cast<const char*>(response.payload())));
112 
113   // Send a second message on the pipe.
114   Message request2;
115   AllocRequestMessage(1, "hello again", &request2);
116 
117   router0.AcceptWithResponder(&request2,
118                               new MessageAccumulator(&message_queue));
119 
120   router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
121   router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
122 
123   EXPECT_FALSE(message_queue.IsEmpty());
124 
125   message_queue.Pop(&response);
126 
127   EXPECT_EQ(std::string("hello again world!"),
128             std::string(reinterpret_cast<const char*>(response.payload())));
129 }
130 
TEST_F(RouterTest,RequestWithNoReceiver)131 TEST_F(RouterTest, RequestWithNoReceiver) {
132   internal::Router router0(std::move(handle0_), internal::FilterChain(), false,
133                            base::ThreadTaskRunnerHandle::Get());
134   internal::Router router1(std::move(handle1_), internal::FilterChain(), false,
135                            base::ThreadTaskRunnerHandle::Get());
136 
137   // Without an incoming receiver set on router1, we expect router0 to observe
138   // an error as a result of sending a message.
139 
140   Message request;
141   AllocRequestMessage(1, "hello", &request);
142 
143   MessageQueue message_queue;
144   base::RunLoop run_loop, run_loop2;
145   router0.set_connection_error_handler(run_loop.QuitClosure());
146   router1.set_connection_error_handler(run_loop2.QuitClosure());
147   router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
148 
149   run_loop.Run();
150   run_loop2.Run();
151 
152   EXPECT_TRUE(router0.encountered_error());
153   EXPECT_TRUE(router1.encountered_error());
154   EXPECT_TRUE(message_queue.IsEmpty());
155 }
156 
157 // Tests Router using the LazyResponseGenerator. The responses will not be
158 // sent until after the requests have been accepted.
TEST_F(RouterTest,LazyResponses)159 TEST_F(RouterTest, LazyResponses) {
160   internal::Router router0(std::move(handle0_), internal::FilterChain(), false,
161                            base::ThreadTaskRunnerHandle::Get());
162   internal::Router router1(std::move(handle1_), internal::FilterChain(), false,
163                            base::ThreadTaskRunnerHandle::Get());
164 
165   base::RunLoop run_loop;
166   LazyResponseGenerator generator(run_loop.QuitClosure());
167   router1.set_incoming_receiver(&generator);
168 
169   Message request;
170   AllocRequestMessage(1, "hello", &request);
171 
172   MessageQueue message_queue;
173   base::RunLoop run_loop2;
174   router0.AcceptWithResponder(
175       &request,
176       new MessageAccumulator(&message_queue, run_loop2.QuitClosure()));
177   run_loop.Run();
178 
179   // The request has been received but the response has not been sent yet.
180   EXPECT_TRUE(message_queue.IsEmpty());
181 
182   // Send the response.
183   EXPECT_TRUE(generator.responder_is_valid());
184   generator.CompleteWithResponse();
185   run_loop2.Run();
186 
187   // Check the response.
188   EXPECT_FALSE(message_queue.IsEmpty());
189   Message response;
190   message_queue.Pop(&response);
191   EXPECT_EQ(std::string("hello world!"),
192             std::string(reinterpret_cast<const char*>(response.payload())));
193 
194   // Send a second message on the pipe.
195   base::RunLoop run_loop3;
196   LazyResponseGenerator generator2(run_loop3.QuitClosure());
197 
198   router1.set_incoming_receiver(&generator2);
199   Message request2;
200   AllocRequestMessage(1, "hello again", &request2);
201 
202   base::RunLoop run_loop4;
203   router0.AcceptWithResponder(
204       &request2,
205       new MessageAccumulator(&message_queue, run_loop4.QuitClosure()));
206   run_loop3.Run();
207 
208   // The request has been received but the response has not been sent yet.
209   EXPECT_TRUE(message_queue.IsEmpty());
210 
211   // Send the second response.
212   EXPECT_TRUE(generator2.responder_is_valid());
213   generator2.CompleteWithResponse();
214   run_loop4.Run();
215 
216   // Check the second response.
217   EXPECT_FALSE(message_queue.IsEmpty());
218   message_queue.Pop(&response);
219   EXPECT_EQ(std::string("hello again world!"),
220             std::string(reinterpret_cast<const char*>(response.payload())));
221 }
222 
ForwardErrorHandler(bool * called,const base::Closure & callback)223 void ForwardErrorHandler(bool* called, const base::Closure& callback) {
224   *called = true;
225   callback.Run();
226 }
227 
228 // Tests that if the receiving application destroys the responder_ without
229 // sending a response, then we trigger connection error at both sides. Moreover,
230 // both sides still appear to have a valid message pipe handle bound.
TEST_F(RouterTest,MissingResponses)231 TEST_F(RouterTest, MissingResponses) {
232   base::RunLoop run_loop0, run_loop1;
233   internal::Router router0(std::move(handle0_), internal::FilterChain(), false,
234                            base::ThreadTaskRunnerHandle::Get());
235   bool error_handler_called0 = false;
236   router0.set_connection_error_handler(
237       base::Bind(&ForwardErrorHandler, &error_handler_called0,
238                  run_loop0.QuitClosure()));
239 
240   internal::Router router1(std::move(handle1_), internal::FilterChain(), false,
241                            base::ThreadTaskRunnerHandle::Get());
242   bool error_handler_called1 = false;
243   router1.set_connection_error_handler(
244       base::Bind(&ForwardErrorHandler, &error_handler_called1,
245                  run_loop1.QuitClosure()));
246 
247   base::RunLoop run_loop3;
248   LazyResponseGenerator generator(run_loop3.QuitClosure());
249   router1.set_incoming_receiver(&generator);
250   router1.set_incoming_receiver(&generator);
251 
252   Message request;
253   AllocRequestMessage(1, "hello", &request);
254 
255   MessageQueue message_queue;
256   router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
257   run_loop3.Run();
258 
259   // The request has been received but no response has been sent.
260   EXPECT_TRUE(message_queue.IsEmpty());
261 
262   // Destroy the responder MessagerReceiver but don't send any response.
263   generator.CompleteWithoutResponse();
264   run_loop0.Run();
265   run_loop1.Run();
266 
267   // Check that no response was received.
268   EXPECT_TRUE(message_queue.IsEmpty());
269 
270   // Connection error handler is called at both sides.
271   EXPECT_TRUE(error_handler_called0);
272   EXPECT_TRUE(error_handler_called1);
273 
274   // The error flag is set at both sides.
275   EXPECT_TRUE(router0.encountered_error());
276   EXPECT_TRUE(router1.encountered_error());
277 
278   // The message pipe handle is valid at both sides.
279   EXPECT_TRUE(router0.is_valid());
280   EXPECT_TRUE(router1.is_valid());
281 }
282 
TEST_F(RouterTest,LateResponse)283 TEST_F(RouterTest, LateResponse) {
284   // Test that things won't blow up if we try to send a message to a
285   // MessageReceiver, which was given to us via AcceptWithResponder,
286   // after the router has gone away.
287 
288   base::RunLoop run_loop;
289   LazyResponseGenerator generator(run_loop.QuitClosure());
290   {
291     internal::Router router0(std::move(handle0_), internal::FilterChain(),
292                              false, base::ThreadTaskRunnerHandle::Get());
293     internal::Router router1(std::move(handle1_), internal::FilterChain(),
294                              false, base::ThreadTaskRunnerHandle::Get());
295 
296     router1.set_incoming_receiver(&generator);
297 
298     Message request;
299     AllocRequestMessage(1, "hello", &request);
300 
301     MessageQueue message_queue;
302     router0.AcceptWithResponder(&request,
303                                 new MessageAccumulator(&message_queue));
304 
305     run_loop.Run();
306 
307     EXPECT_TRUE(generator.has_responder());
308   }
309 
310   EXPECT_FALSE(generator.responder_is_valid());
311   generator.CompleteWithResponse();  // This should end up doing nothing.
312 }
313 
314 }  // namespace
315 }  // namespace test
316 }  // namespace mojo
317