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

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

Issue 1455063004: Mojo C++ bindings: introduce MultiplexRouter and related classes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 1 month 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 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 "base/memory/ref_counted.h"
6 #include "base/message_loop/message_loop.h"
7 #include "mojo/message_pump/message_pump_mojo.h"
8 #include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h"
9 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
10 #include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h"
11 #include "mojo/public/cpp/bindings/message.h"
12 #include "mojo/public/cpp/bindings/message_filter.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 using mojo::internal::InterfaceEndpointClient;
22 using mojo::internal::MultiplexRouter;
23 using mojo::internal::ScopedInterfaceEndpointHandle;
24
25 class MultiplexRouterTest : public testing::Test {
26 public:
27 MultiplexRouterTest() : loop_(common::MessagePumpMojo::Create()) {}
28
29 void SetUp() override {
30 MessagePipe pipe;
31 router0_ = new MultiplexRouter(true, pipe.handle0.Pass());
32 router1_ = new MultiplexRouter(true, pipe.handle1.Pass());
33 router0_->CreateEndpointHandlePair(&endpoint0_, &endpoint1_);
34 endpoint1_ =
35 EmulatePassingEndpointHandle(endpoint1_.Pass(), router1_.get());
36 }
37
38 void TearDown() override {}
39
40 void PumpMessages() { loop_.RunUntilIdle(); }
41
42 ScopedInterfaceEndpointHandle EmulatePassingEndpointHandle(
43 ScopedInterfaceEndpointHandle handle,
44 MultiplexRouter* target) {
45 CHECK(!handle.is_local());
46
47 return target->CreateLocalEndpointHandle(handle.release());
48 }
49
50 protected:
51 scoped_refptr<MultiplexRouter> router0_;
52 scoped_refptr<MultiplexRouter> router1_;
53 ScopedInterfaceEndpointHandle endpoint0_;
54 ScopedInterfaceEndpointHandle endpoint1_;
55
56 private:
57 base::MessageLoop loop_;
58 };
59
60 TEST_F(MultiplexRouterTest, BasicRequestResponse) {
61 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
62 make_scoped_ptr(new PassThroughFilter()));
63 ResponseGenerator generator;
64 InterfaceEndpointClient client1(endpoint1_.Pass(), &generator,
65 make_scoped_ptr(new PassThroughFilter()));
66
67 Message request;
68 AllocRequestMessage(1, "hello", &request);
69
70 MessageQueue message_queue;
71 client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
72
73 PumpMessages();
74
75 EXPECT_FALSE(message_queue.IsEmpty());
76
77 Message response;
78 message_queue.Pop(&response);
79
80 EXPECT_EQ(std::string("hello world!"),
81 std::string(reinterpret_cast<const char*>(response.payload())));
82
83 // Send a second message on the pipe.
84 Message request2;
85 AllocRequestMessage(1, "hello again", &request2);
86
87 client0.AcceptWithResponder(&request2,
88 new MessageAccumulator(&message_queue));
89
90 PumpMessages();
91
92 EXPECT_FALSE(message_queue.IsEmpty());
93
94 message_queue.Pop(&response);
95
96 EXPECT_EQ(std::string("hello again world!"),
97 std::string(reinterpret_cast<const char*>(response.payload())));
98 }
99
100 TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) {
101 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
102 make_scoped_ptr(new PassThroughFilter()));
103 ResponseGenerator generator;
104 InterfaceEndpointClient client1(endpoint1_.Pass(), &generator,
105 make_scoped_ptr(new PassThroughFilter()));
106
107 Message request;
108 AllocRequestMessage(1, "hello", &request);
109
110 MessageQueue message_queue;
111 client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
112
113 router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
114 router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
115
116 EXPECT_FALSE(message_queue.IsEmpty());
117
118 Message response;
119 message_queue.Pop(&response);
120
121 EXPECT_EQ(std::string("hello world!"),
122 std::string(reinterpret_cast<const char*>(response.payload())));
123
124 // Send a second message on the pipe.
125 Message request2;
126 AllocRequestMessage(1, "hello again", &request2);
127
128 client0.AcceptWithResponder(&request2,
129 new MessageAccumulator(&message_queue));
130
131 router1_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
132 router0_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
133
134 EXPECT_FALSE(message_queue.IsEmpty());
135
136 message_queue.Pop(&response);
137
138 EXPECT_EQ(std::string("hello again world!"),
139 std::string(reinterpret_cast<const char*>(response.payload())));
140 }
141
142 TEST_F(MultiplexRouterTest, RequestWithNoReceiver) {
143 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
144 make_scoped_ptr(new PassThroughFilter()));
145 InterfaceEndpointClient client1(endpoint1_.Pass(), nullptr,
146 make_scoped_ptr(new PassThroughFilter()));
147
148 // Without an incoming receiver set on client1, we expect client0 to observe
149 // an error as a result of sending a message.
150
151 Message request;
152 AllocRequestMessage(1, "hello", &request);
153
154 MessageQueue message_queue;
155 client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
156
157 PumpMessages();
158
159 EXPECT_TRUE(client0.encountered_error());
160 EXPECT_TRUE(client1.encountered_error());
161 EXPECT_TRUE(message_queue.IsEmpty());
162 }
163
164 // Tests MultiplexRouter using the LazyResponseGenerator. The responses will not
165 // be sent until after the requests have been accepted.
166 TEST_F(MultiplexRouterTest, LazyResponses) {
167 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
168 make_scoped_ptr(new PassThroughFilter()));
169 LazyResponseGenerator generator;
170 InterfaceEndpointClient client1(endpoint1_.Pass(), &generator,
171 make_scoped_ptr(new PassThroughFilter()));
172
173 Message request;
174 AllocRequestMessage(1, "hello", &request);
175
176 MessageQueue message_queue;
177 client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
178 PumpMessages();
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 PumpMessages();
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 Message request2;
197 AllocRequestMessage(1, "hello again", &request2);
198
199 client0.AcceptWithResponder(&request2,
200 new MessageAccumulator(&message_queue));
201 PumpMessages();
202
203 // The request has been received but the response has not been sent yet.
204 EXPECT_TRUE(message_queue.IsEmpty());
205
206 // Send the second response.
207 EXPECT_TRUE(generator.responder_is_valid());
208 generator.CompleteWithResponse();
209 PumpMessages();
210
211 // Check the second response.
212 EXPECT_FALSE(message_queue.IsEmpty());
213 message_queue.Pop(&response);
214 EXPECT_EQ(std::string("hello again world!"),
215 std::string(reinterpret_cast<const char*>(response.payload())));
216 }
217
218 // Tests that if the receiving application destroys the responder_ without
219 // sending a response, then we trigger connection error at both sides. Moreover,
220 // both sides still appear to have a valid message pipe handle bound.
221 TEST_F(MultiplexRouterTest, MissingResponses) {
222 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
223 make_scoped_ptr(new PassThroughFilter()));
224 bool error_handler_called0 = false;
225 client0.set_connection_error_handler(
226 [&error_handler_called0]() { error_handler_called0 = true; });
227
228 LazyResponseGenerator generator;
229 InterfaceEndpointClient client1(endpoint1_.Pass(), &generator,
230 make_scoped_ptr(new PassThroughFilter()));
231 bool error_handler_called1 = false;
232 client1.set_connection_error_handler(
233 [&error_handler_called1]() { error_handler_called1 = true; });
234
235 Message request;
236 AllocRequestMessage(1, "hello", &request);
237
238 MessageQueue message_queue;
239 client0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
240 PumpMessages();
241
242 // The request has been received but no response has been sent.
243 EXPECT_TRUE(message_queue.IsEmpty());
244
245 // Destroy the responder MessagerReceiver but don't send any response.
246 generator.CompleteWithoutResponse();
247 PumpMessages();
248
249 // Check that no response was received.
250 EXPECT_TRUE(message_queue.IsEmpty());
251
252 // Connection error handler is called at both sides.
253 EXPECT_TRUE(error_handler_called0);
254 EXPECT_TRUE(error_handler_called1);
255
256 // The error flag is set at both sides.
257 EXPECT_TRUE(client0.encountered_error());
258 EXPECT_TRUE(client1.encountered_error());
259
260 // The message pipe handle is valid at both sides.
261 EXPECT_TRUE(router0_->is_valid());
262 EXPECT_TRUE(router1_->is_valid());
263 }
264
265 TEST_F(MultiplexRouterTest, LateResponse) {
266 // Test that things won't blow up if we try to send a message to a
267 // MessageReceiver, which was given to us via AcceptWithResponder,
268 // after the router has gone away.
269
270 LazyResponseGenerator generator;
271 {
272 InterfaceEndpointClient client0(endpoint0_.Pass(), nullptr,
273 make_scoped_ptr(new PassThroughFilter()));
274 InterfaceEndpointClient client1(endpoint1_.Pass(), &generator,
275 make_scoped_ptr(new PassThroughFilter()));
276
277 Message request;
278 AllocRequestMessage(1, "hello", &request);
279
280 MessageQueue message_queue;
281 client0.AcceptWithResponder(&request,
282 new MessageAccumulator(&message_queue));
283
284 PumpMessages();
285
286 EXPECT_TRUE(generator.has_responder());
287 }
288
289 EXPECT_FALSE(generator.responder_is_valid());
290 generator.CompleteWithResponse(); // This should end up doing nothing.
291 }
292
293 // TODO(yzshen): add more tests.
294
295 } // namespace
296 } // namespace test
297 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/connector_unittest.cc ('k') | mojo/public/cpp/bindings/tests/router_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698