OLD | NEW |
(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 |
OLD | NEW |