• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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/multiplex_router.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
16 #include "mojo/public/cpp/bindings/message.h"
17 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
18 #include "mojo/public/cpp/bindings/tests/message_queue.h"
19 #include "mojo/public/cpp/bindings/tests/router_test_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace mojo {
23 namespace test {
24 namespace {
25 
26 using mojo::internal::MultiplexRouter;
27 
28 class MultiplexRouterTest : public testing::Test {
29  public:
MultiplexRouterTest()30   MultiplexRouterTest() {}
31 
SetUp()32   void SetUp() override {
33     MessagePipe pipe;
34     router0_ = new MultiplexRouter(std::move(pipe.handle0),
35                                    MultiplexRouter::MULTI_INTERFACE, false,
36                                    base::ThreadTaskRunnerHandle::Get());
37     router1_ = new MultiplexRouter(std::move(pipe.handle1),
38                                    MultiplexRouter::MULTI_INTERFACE, true,
39                                    base::ThreadTaskRunnerHandle::Get());
40     ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&endpoint0_,
41                                                                 &endpoint1_);
42     auto id = router0_->AssociateInterface(std::move(endpoint1_));
43     endpoint1_ = router1_->CreateLocalEndpointHandle(id);
44   }
45 
TearDown()46   void TearDown() override {
47     endpoint1_.reset();
48     endpoint0_.reset();
49     router1_ = nullptr;
50     router0_ = nullptr;
51   }
52 
PumpMessages()53   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
54 
55  protected:
56   scoped_refptr<MultiplexRouter> router0_;
57   scoped_refptr<MultiplexRouter> router1_;
58   ScopedInterfaceEndpointHandle endpoint0_;
59   ScopedInterfaceEndpointHandle endpoint1_;
60 
61  private:
62   base::MessageLoop loop_;
63 };
64 
TEST_F(MultiplexRouterTest,BasicRequestResponse)65 TEST_F(MultiplexRouterTest, BasicRequestResponse) {
66   InterfaceEndpointClient client0(std::move(endpoint0_), nullptr,
67                                   std::make_unique<PassThroughFilter>(), false,
68                                   base::ThreadTaskRunnerHandle::Get(), 0u);
69   ResponseGenerator generator;
70   InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
71                                   std::make_unique<PassThroughFilter>(), false,
72                                   base::ThreadTaskRunnerHandle::Get(), 0u);
73 
74   Message request;
75   AllocRequestMessage(1, "hello", &request);
76 
77   MessageQueue message_queue;
78   base::RunLoop run_loop;
79   client0.AcceptWithResponder(
80       &request, std::make_unique<MessageAccumulator>(&message_queue,
81                                                      run_loop.QuitClosure()));
82 
83   run_loop.Run();
84 
85   EXPECT_FALSE(message_queue.IsEmpty());
86 
87   Message response;
88   message_queue.Pop(&response);
89 
90   EXPECT_EQ(std::string("hello world!"),
91             std::string(reinterpret_cast<const char*>(response.payload())));
92 
93   // Send a second message on the pipe.
94   Message request2;
95   AllocRequestMessage(1, "hello again", &request2);
96 
97   base::RunLoop run_loop2;
98   client0.AcceptWithResponder(
99       &request2, std::make_unique<MessageAccumulator>(&message_queue,
100                                                       run_loop2.QuitClosure()));
101 
102   run_loop2.Run();
103 
104   EXPECT_FALSE(message_queue.IsEmpty());
105 
106   message_queue.Pop(&response);
107 
108   EXPECT_EQ(std::string("hello again world!"),
109             std::string(reinterpret_cast<const char*>(response.payload())));
110 }
111 
TEST_F(MultiplexRouterTest,BasicRequestResponse_Synchronous)112 TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) {
113   InterfaceEndpointClient client0(std::move(endpoint0_), nullptr,
114                                   std::make_unique<PassThroughFilter>(), false,
115                                   base::ThreadTaskRunnerHandle::Get(), 0u);
116   ResponseGenerator generator;
117   InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
118                                   std::make_unique<PassThroughFilter>(), false,
119                                   base::ThreadTaskRunnerHandle::Get(), 0u);
120 
121   Message request;
122   AllocRequestMessage(1, "hello", &request);
123 
124   MessageQueue message_queue;
125   client0.AcceptWithResponder(
126       &request, std::make_unique<MessageAccumulator>(&message_queue));
127 
128   router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
129   router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
130 
131   EXPECT_FALSE(message_queue.IsEmpty());
132 
133   Message response;
134   message_queue.Pop(&response);
135 
136   EXPECT_EQ(std::string("hello world!"),
137             std::string(reinterpret_cast<const char*>(response.payload())));
138 
139   // Send a second message on the pipe.
140   Message request2;
141   AllocRequestMessage(1, "hello again", &request2);
142 
143   client0.AcceptWithResponder(
144       &request2, std::make_unique<MessageAccumulator>(&message_queue));
145 
146   router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
147   router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
148 
149   EXPECT_FALSE(message_queue.IsEmpty());
150 
151   message_queue.Pop(&response);
152 
153   EXPECT_EQ(std::string("hello again world!"),
154             std::string(reinterpret_cast<const char*>(response.payload())));
155 }
156 
157 // Tests MultiplexRouter using the LazyResponseGenerator. The responses will not
158 // be sent until after the requests have been accepted.
TEST_F(MultiplexRouterTest,LazyResponses)159 TEST_F(MultiplexRouterTest, LazyResponses) {
160   InterfaceEndpointClient client0(
161       std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()),
162       false, base::ThreadTaskRunnerHandle::Get(), 0u);
163   base::RunLoop run_loop;
164   LazyResponseGenerator generator(run_loop.QuitClosure());
165   InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
166                                   base::WrapUnique(new PassThroughFilter()),
167                                   false, base::ThreadTaskRunnerHandle::Get(),
168                                   0u);
169 
170   Message request;
171   AllocRequestMessage(1, "hello", &request);
172 
173   MessageQueue message_queue;
174   base::RunLoop run_loop2;
175   client0.AcceptWithResponder(
176       &request, std::make_unique<MessageAccumulator>(&message_queue,
177                                                      run_loop2.QuitClosure()));
178   run_loop.Run();
179 
180   // The request has been received but the response has not been sent yet.
181   EXPECT_TRUE(message_queue.IsEmpty());
182 
183   // Send the response.
184   EXPECT_TRUE(generator.responder_is_valid());
185   generator.CompleteWithResponse();
186   run_loop2.Run();
187 
188   // Check the response.
189   EXPECT_FALSE(message_queue.IsEmpty());
190   Message response;
191   message_queue.Pop(&response);
192   EXPECT_EQ(std::string("hello world!"),
193             std::string(reinterpret_cast<const char*>(response.payload())));
194 
195   // Send a second message on the pipe.
196   base::RunLoop run_loop3;
197   generator.set_closure(run_loop3.QuitClosure());
198   Message request2;
199   AllocRequestMessage(1, "hello again", &request2);
200 
201   base::RunLoop run_loop4;
202   client0.AcceptWithResponder(
203       &request2, std::make_unique<MessageAccumulator>(&message_queue,
204                                                       run_loop4.QuitClosure()));
205   run_loop3.Run();
206 
207   // The request has been received but the response has not been sent yet.
208   EXPECT_TRUE(message_queue.IsEmpty());
209 
210   // Send the second response.
211   EXPECT_TRUE(generator.responder_is_valid());
212   generator.CompleteWithResponse();
213   run_loop4.Run();
214 
215   // Check the second response.
216   EXPECT_FALSE(message_queue.IsEmpty());
217   message_queue.Pop(&response);
218   EXPECT_EQ(std::string("hello again world!"),
219             std::string(reinterpret_cast<const char*>(response.payload())));
220 }
221 
ForwardErrorHandler(bool * called,const base::Closure & callback)222 void ForwardErrorHandler(bool* called, const base::Closure& callback) {
223   *called = true;
224   callback.Run();
225 }
226 
227 // Tests that if the receiving application destroys the responder_ without
228 // sending a response, then we trigger connection error at both sides. Moreover,
229 // both sides still appear to have a valid message pipe handle bound.
TEST_F(MultiplexRouterTest,MissingResponses)230 TEST_F(MultiplexRouterTest, MissingResponses) {
231   base::RunLoop run_loop0, run_loop1;
232   InterfaceEndpointClient client0(
233       std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()),
234       false, base::ThreadTaskRunnerHandle::Get(), 0u);
235   bool error_handler_called0 = false;
236   client0.set_connection_error_handler(
237       base::Bind(&ForwardErrorHandler, &error_handler_called0,
238                  run_loop0.QuitClosure()));
239 
240   base::RunLoop run_loop3;
241   LazyResponseGenerator generator(run_loop3.QuitClosure());
242   InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
243                                   base::WrapUnique(new PassThroughFilter()),
244                                   false, base::ThreadTaskRunnerHandle::Get(),
245                                   0u);
246   bool error_handler_called1 = false;
247   client1.set_connection_error_handler(
248       base::Bind(&ForwardErrorHandler, &error_handler_called1,
249                  run_loop1.QuitClosure()));
250 
251   Message request;
252   AllocRequestMessage(1, "hello", &request);
253 
254   MessageQueue message_queue;
255   client0.AcceptWithResponder(
256       &request, std::make_unique<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(client0.encountered_error());
276   EXPECT_TRUE(client1.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(MultiplexRouterTest,LateResponse)283 TEST_F(MultiplexRouterTest, 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     InterfaceEndpointClient client0(
292         std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(),
293         false, base::ThreadTaskRunnerHandle::Get(), 0u);
294     InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
295                                     std::make_unique<PassThroughFilter>(),
296                                     false, base::ThreadTaskRunnerHandle::Get(),
297                                     0u);
298 
299     Message request;
300     AllocRequestMessage(1, "hello", &request);
301 
302     MessageQueue message_queue;
303     client0.AcceptWithResponder(
304         &request, std::make_unique<MessageAccumulator>(&message_queue));
305 
306     run_loop.Run();
307 
308     EXPECT_TRUE(generator.has_responder());
309   }
310 
311   EXPECT_FALSE(generator.responder_is_valid());
312   generator.CompleteWithResponse();  // This should end up doing nothing.
313 }
314 
315 // TODO(yzshen): add more tests.
316 
317 }  // namespace
318 }  // namespace test
319 }  // namespace mojo
320