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