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