• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AllocRequestMessage(uint32_t name,const char * text,Message * message)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 
AllocResponseMessage(uint32_t name,const char * text,uint64_t request_id,Message * message)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:
MessageAccumulator(internal::MessageQueue * queue)37   explicit MessageAccumulator(internal::MessageQueue* queue) : queue_(queue) {
38   }
39 
Accept(Message * message)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:
ResponseGenerator()51   ResponseGenerator() {
52   }
53 
Accept(Message * message)54   virtual bool Accept(Message* message) MOJO_OVERRIDE {
55     return false;
56   }
57 
AcceptWithResponder(Message * message,MessageReceiver * responder)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 
SendResponse(uint32_t name,uint64_t request_id,MessageReceiver * responder)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:
LazyResponseGenerator()78   LazyResponseGenerator() : responder_(NULL), name_(0), request_id_(0) {
79   }
80 
~LazyResponseGenerator()81   virtual ~LazyResponseGenerator() {
82     delete responder_;
83   }
84 
AcceptWithResponder(Message * message,MessageReceiver * responder)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 
has_responder() const93   bool has_responder() const { return !!responder_; }
94 
Complete()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:
RouterTest()108   RouterTest() {
109   }
110 
SetUp()111   virtual void SetUp() MOJO_OVERRIDE {
112     CreateMessagePipe(NULL, &handle0_, &handle1_);
113   }
114 
TearDown()115   virtual void TearDown() MOJO_OVERRIDE {
116   }
117 
PumpMessages()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 
TEST_F(RouterTest,BasicRequestResponse)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 
TEST_F(RouterTest,BasicRequestResponse_Synchronous)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 
TEST_F(RouterTest,RequestWithNoReceiver)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 
TEST_F(RouterTest,LateResponse)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