Upstream version 7.36.149.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   virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
46       MOJO_OVERRIDE {
47     return false;
48   }
49
50  private:
51   internal::MessageQueue* queue_;
52 };
53
54 class ResponseGenerator : public MessageReceiver {
55  public:
56   ResponseGenerator() {
57   }
58
59   virtual bool Accept(Message* message) MOJO_OVERRIDE {
60     return false;
61   }
62
63   virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
64       MOJO_OVERRIDE {
65     EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse));
66
67     return SendResponse(message->name(), message->request_id(), responder);
68   }
69
70   bool SendResponse(uint32_t name, uint64_t request_id,
71                     MessageReceiver* responder) {
72     Message response;
73     AllocResponseMessage(name, "world", request_id, &response);
74
75     bool result = responder->Accept(&response);
76     delete responder;
77     return result;
78   }
79 };
80
81 class LazyResponseGenerator : public ResponseGenerator {
82  public:
83   LazyResponseGenerator() : responder_(NULL), name_(0), request_id_(0) {
84   }
85
86   virtual ~LazyResponseGenerator() {
87     delete responder_;
88   }
89
90   virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
91       MOJO_OVERRIDE {
92     name_ = message->name();
93     request_id_ = message->request_id();
94     responder_ = responder;
95     return true;
96   }
97
98   bool has_responder() const { return !!responder_; }
99
100   void Complete() {
101     SendResponse(name_, request_id_, responder_);
102     responder_ = NULL;
103   }
104
105  private:
106   MessageReceiver* responder_;
107   uint32_t name_;
108   uint32_t request_id_;
109 };
110
111 class RouterTest : public testing::Test {
112  public:
113   RouterTest() {
114   }
115
116   virtual void SetUp() MOJO_OVERRIDE {
117     CreateMessagePipe(&handle0_, &handle1_);
118   }
119
120   virtual void TearDown() MOJO_OVERRIDE {
121   }
122
123   void PumpMessages() {
124     loop_.RunUntilIdle();
125   }
126
127  protected:
128   ScopedMessagePipeHandle handle0_;
129   ScopedMessagePipeHandle handle1_;
130
131  private:
132   Environment env_;
133   RunLoop loop_;
134 };
135
136 TEST_F(RouterTest, BasicRequestResponse) {
137   internal::Router router0(handle0_.Pass());
138   internal::Router router1(handle1_.Pass());
139
140   ResponseGenerator generator;
141   router1.set_incoming_receiver(&generator);
142
143   Message request;
144   AllocRequestMessage(1, "hello", &request);
145
146   internal::MessageQueue message_queue;
147   router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
148
149   PumpMessages();
150
151   EXPECT_FALSE(message_queue.IsEmpty());
152
153   Message response;
154   message_queue.Pop(&response);
155
156   EXPECT_EQ(std::string("world"),
157             std::string(reinterpret_cast<const char*>(response.payload())));
158 }
159
160 TEST_F(RouterTest, RequestWithNoReceiver) {
161   internal::Router router0(handle0_.Pass());
162   internal::Router router1(handle1_.Pass());
163
164   // Without an incoming receiver set on router1, we expect router0 to observe
165   // an error as a result of sending a message.
166
167   Message request;
168   AllocRequestMessage(1, "hello", &request);
169
170   internal::MessageQueue message_queue;
171   router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
172
173   PumpMessages();
174
175   EXPECT_TRUE(router0.encountered_error());
176   EXPECT_TRUE(router1.encountered_error());
177   EXPECT_TRUE(message_queue.IsEmpty());
178 }
179
180 TEST_F(RouterTest, LateResponse) {
181   // Test that things won't blow up if we try to send a message to a
182   // MessageReceiver, which was given to us via AcceptWithResponder,
183   // after the router has gone away.
184
185   LazyResponseGenerator generator;
186   {
187     internal::Router router0(handle0_.Pass());
188     internal::Router router1(handle1_.Pass());
189
190     router1.set_incoming_receiver(&generator);
191
192     Message request;
193     AllocRequestMessage(1, "hello", &request);
194
195     internal::MessageQueue message_queue;
196     router0.AcceptWithResponder(&request,
197                                 new MessageAccumulator(&message_queue));
198
199     PumpMessages();
200
201     EXPECT_TRUE(generator.has_responder());
202
203   }
204
205   generator.Complete();  // This should end up doing nothing.
206 }
207
208 }  // namespace
209 }  // namespace test
210 }  // namespace mojo