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.
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"
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);
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);
35 class MessageAccumulator : public MessageReceiver {
37 explicit MessageAccumulator(internal::MessageQueue* queue) : queue_(queue) {
40 virtual bool Accept(Message* message) MOJO_OVERRIDE {
41 queue_->Push(message);
46 internal::MessageQueue* queue_;
49 class ResponseGenerator : public MessageReceiverWithResponder {
54 virtual bool Accept(Message* message) MOJO_OVERRIDE {
58 virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
60 EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse));
62 return SendResponse(message->name(), message->request_id(), responder);
65 bool SendResponse(uint32_t name, uint64_t request_id,
66 MessageReceiver* responder) {
68 AllocResponseMessage(name, "world", request_id, &response);
70 bool result = responder->Accept(&response);
76 class LazyResponseGenerator : public ResponseGenerator {
78 LazyResponseGenerator() : responder_(NULL), name_(0), request_id_(0) {
81 virtual ~LazyResponseGenerator() {
85 virtual bool AcceptWithResponder(Message* message, MessageReceiver* responder)
87 name_ = message->name();
88 request_id_ = message->request_id();
89 responder_ = responder;
93 bool has_responder() const { return !!responder_; }
96 SendResponse(name_, request_id_, responder_);
101 MessageReceiver* responder_;
103 uint32_t request_id_;
106 class RouterTest : public testing::Test {
111 virtual void SetUp() MOJO_OVERRIDE {
112 CreateMessagePipe(NULL, &handle0_, &handle1_);
115 virtual void TearDown() MOJO_OVERRIDE {
118 void PumpMessages() {
119 loop_.RunUntilIdle();
123 ScopedMessagePipeHandle handle0_;
124 ScopedMessagePipeHandle handle1_;
131 TEST_F(RouterTest, BasicRequestResponse) {
132 internal::Router router0(handle0_.Pass(), internal::FilterChain());
133 internal::Router router1(handle1_.Pass(), internal::FilterChain());
135 ResponseGenerator generator;
136 router1.set_incoming_receiver(&generator);
139 AllocRequestMessage(1, "hello", &request);
141 internal::MessageQueue message_queue;
142 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
146 EXPECT_FALSE(message_queue.IsEmpty());
149 message_queue.Pop(&response);
151 EXPECT_EQ(std::string("world"),
152 std::string(reinterpret_cast<const char*>(response.payload())));
155 TEST_F(RouterTest, BasicRequestResponse_Synchronous) {
156 internal::Router router0(handle0_.Pass(), internal::FilterChain());
157 internal::Router router1(handle1_.Pass(), internal::FilterChain());
159 ResponseGenerator generator;
160 router1.set_incoming_receiver(&generator);
163 AllocRequestMessage(1, "hello", &request);
165 internal::MessageQueue message_queue;
166 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
168 router1.WaitForIncomingMessage();
169 router0.WaitForIncomingMessage();
171 EXPECT_FALSE(message_queue.IsEmpty());
174 message_queue.Pop(&response);
176 EXPECT_EQ(std::string("world"),
177 std::string(reinterpret_cast<const char*>(response.payload())));
180 TEST_F(RouterTest, RequestWithNoReceiver) {
181 internal::Router router0(handle0_.Pass(), internal::FilterChain());
182 internal::Router router1(handle1_.Pass(), internal::FilterChain());
184 // Without an incoming receiver set on router1, we expect router0 to observe
185 // an error as a result of sending a message.
188 AllocRequestMessage(1, "hello", &request);
190 internal::MessageQueue message_queue;
191 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue));
195 EXPECT_TRUE(router0.encountered_error());
196 EXPECT_TRUE(router1.encountered_error());
197 EXPECT_TRUE(message_queue.IsEmpty());
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.
205 LazyResponseGenerator generator;
207 internal::Router router0(handle0_.Pass(), internal::FilterChain());
208 internal::Router router1(handle1_.Pass(), internal::FilterChain());
210 router1.set_incoming_receiver(&generator);
213 AllocRequestMessage(1, "hello", &request);
215 internal::MessageQueue message_queue;
216 router0.AcceptWithResponder(&request,
217 new MessageAccumulator(&message_queue));
221 EXPECT_TRUE(generator.has_responder());
225 generator.Complete(); // This should end up doing nothing.