Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / public / cpp / bindings / tests / router_unittest.cc
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