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 <stdlib.h> 6 #include <string.h> 7 8 #include "mojo/public/cpp/bindings/lib/message_builder.h" 9 #include "mojo/public/cpp/bindings/lib/message_queue.h" 10 #include "mojo/public/cpp/bindings/lib/router.h" 11 #include "mojo/public/cpp/environment/environment.h" 12 #include "mojo/public/cpp/system/macros.h" 13 #include "mojo/public/cpp/utility/run_loop.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace mojo { 17 namespace test { 18 namespace { 19 20 void AllocRequestMessage(uint32_t name, const char* text, Message* message) { 21 size_t payload_size = strlen(text) + 1; // Plus null terminator. 22 internal::RequestMessageBuilder builder(name, payload_size); 23 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); 24 builder.Finish(message); 25 } 26 27 void AllocResponseMessage(uint32_t name, const char* text, 28 uint64_t request_id, Message* message) { 29 size_t payload_size = strlen(text) + 1; // Plus null terminator. 30 internal::ResponseMessageBuilder builder(name, payload_size, request_id); 31 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); 32 builder.Finish(message); 33 } 34 35 class MessageAccumulator : public MessageReceiver { 36 public: 37 explicit MessageAccumulator(internal::MessageQueue* queue) : queue_(queue) { 38 } 39 40 virtual bool Accept(Message* message) MOJO_OVERRIDE { 41 queue_->Push(message); 42 return true; 43 } 44 45 private: 46 internal::MessageQueue* queue_; 47 }; 48 49 class ResponseGenerator : public MessageReceiverWithResponder { 50 public: 51 ResponseGenerator() { 52 } 53 54 virtual bool Accept(Message* message) MOJO_OVERRIDE { 55 return false; 56 } 57 58 virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder) 59 MOJO_OVERRIDE { 60 EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse)); 61 62 return SendResponse(message->name(), message->request_id(), responder); 63 } 64 65 bool SendResponse(uint32_t name, uint64_t request_id, 66 MessageReceiver* responder) { 67 Message response; 68 AllocResponseMessage(name, "world", request_id, &response); 69 70 bool result = responder->Accept(&response); 71 delete responder; 72 return result; 73 } 74 }; 75 76 class LazyResponseGenerator : public ResponseGenerator { 77 public: 78 LazyResponseGenerator() : responder_(NULL), name_(0), request_id_(0) { 79 } 80 81 virtual ~LazyResponseGenerator() { 82 delete responder_; 83 } 84 85 virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder) 86 MOJO_OVERRIDE { 87 name_ = message->name(); 88 request_id_ = message->request_id(); 89 responder_ = responder; 90 return true; 91 } 92 93 bool has_responder() const { return !!responder_; } 94 95 void Complete() { 96 SendResponse(name_, request_id_, responder_); 97 responder_ = NULL; 98 } 99 100 private: 101 MessageReceiver* responder_; 102 uint32_t name_; 103 uint32_t request_id_; 104 }; 105 106 class RouterTest : public testing::Test { 107 public: 108 RouterTest() { 109 } 110 111 virtual void SetUp() MOJO_OVERRIDE { 112 CreateMessagePipe(NULL, &handle0_, &handle1_); 113 } 114 115 virtual void TearDown() MOJO_OVERRIDE { 116 } 117 118 void PumpMessages() { 119 loop_.RunUntilIdle(); 120 } 121 122 protected: 123 ScopedMessagePipeHandle handle0_; 124 ScopedMessagePipeHandle handle1_; 125 126 private: 127 Environment env_; 128 RunLoop loop_; 129 }; 130 131 TEST_F(RouterTest, BasicRequestResponse) { 132 internal::Router router0(handle0_.Pass(), internal::FilterChain()); 133 internal::Router router1(handle1_.Pass(), internal::FilterChain()); 134 135 ResponseGenerator generator; 136 router1.set_incoming_receiver(&generator); 137 138 Message request; 139 AllocRequestMessage(1, "hello", &request); 140 141 internal::MessageQueue message_queue; 142 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); 143 144 PumpMessages(); 145 146 EXPECT_FALSE(message_queue.IsEmpty()); 147 148 Message response; 149 message_queue.Pop(&response); 150 151 EXPECT_EQ(std::string("world"), 152 std::string(reinterpret_cast<const char*>(response.payload()))); 153 } 154 155 TEST_F(RouterTest, BasicRequestResponse_Synchronous) { 156 internal::Router router0(handle0_.Pass(), internal::FilterChain()); 157 internal::Router router1(handle1_.Pass(), internal::FilterChain()); 158 159 ResponseGenerator generator; 160 router1.set_incoming_receiver(&generator); 161 162 Message request; 163 AllocRequestMessage(1, "hello", &request); 164 165 internal::MessageQueue message_queue; 166 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); 167 168 router1.WaitForIncomingMessage(); 169 router0.WaitForIncomingMessage(); 170 171 EXPECT_FALSE(message_queue.IsEmpty()); 172 173 Message response; 174 message_queue.Pop(&response); 175 176 EXPECT_EQ(std::string("world"), 177 std::string(reinterpret_cast<const char*>(response.payload()))); 178 } 179 180 TEST_F(RouterTest, RequestWithNoReceiver) { 181 internal::Router router0(handle0_.Pass(), internal::FilterChain()); 182 internal::Router router1(handle1_.Pass(), internal::FilterChain()); 183 184 // Without an incoming receiver set on router1, we expect router0 to observe 185 // an error as a result of sending a message. 186 187 Message request; 188 AllocRequestMessage(1, "hello", &request); 189 190 internal::MessageQueue message_queue; 191 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); 192 193 PumpMessages(); 194 195 EXPECT_TRUE(router0.encountered_error()); 196 EXPECT_TRUE(router1.encountered_error()); 197 EXPECT_TRUE(message_queue.IsEmpty()); 198 } 199 200 TEST_F(RouterTest, LateResponse) { 201 // Test that things won't blow up if we try to send a message to a 202 // MessageReceiver, which was given to us via AcceptWithResponder, 203 // after the router has gone away. 204 205 LazyResponseGenerator generator; 206 { 207 internal::Router router0(handle0_.Pass(), internal::FilterChain()); 208 internal::Router router1(handle1_.Pass(), internal::FilterChain()); 209 210 router1.set_incoming_receiver(&generator); 211 212 Message request; 213 AllocRequestMessage(1, "hello", &request); 214 215 internal::MessageQueue message_queue; 216 router0.AcceptWithResponder(&request, 217 new MessageAccumulator(&message_queue)); 218 219 PumpMessages(); 220 221 EXPECT_TRUE(generator.has_responder()); 222 223 } 224 225 generator.Complete(); // This should end up doing nothing. 226 } 227 228 } // namespace 229 } // namespace test 230 } // namespace mojo 231