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: 23 RouterTest() {} 24 25 void SetUp() override { 26 CreateMessagePipe(nullptr, &handle0_, &handle1_); 27 } 28 29 void TearDown() override {} 30 31 void PumpMessages() { base::RunLoop().RunUntilIdle(); } 32 33 protected: 34 ScopedMessagePipeHandle handle0_; 35 ScopedMessagePipeHandle handle1_; 36 37 private: 38 base::MessageLoop loop_; 39 }; 40 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 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 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. 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 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. 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 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