1 // Copyright 2013 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.
5 #include "mojo/public/cpp/bindings/allocation_scope.h"
6 #include "mojo/public/cpp/environment/environment.h"
7 #include "mojo/public/cpp/test_support/test_utils.h"
8 #include "mojo/public/cpp/utility/run_loop.h"
9 #include "mojo/public/interfaces/bindings/tests/sample_factory.mojom.h"
10 #include "testing/gtest/include/gtest/gtest.h"
16 const char kText1[] = "hello";
17 const char kText2[] = "world";
19 class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
21 virtual void OnConnectionError() MOJO_OVERRIDE {
25 virtual void SetClient(sample::FactoryClient* client) MOJO_OVERRIDE {
29 virtual void DoStuff(const sample::Request& request,
30 ScopedMessagePipeHandle pipe) MOJO_OVERRIDE {
33 EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1));
36 if (request.pipe().is_valid()) {
37 EXPECT_TRUE(ReadTextMessage(request.pipe().get(), &text2));
39 // Ensure that simply accessing request.pipe() does not close it.
40 EXPECT_TRUE(request.pipe().is_valid());
43 ScopedMessagePipeHandle pipe0;
45 CreateMessagePipe(&pipe0, &pipe1_);
46 EXPECT_TRUE(WriteTextMessage(pipe1_.get(), text2));
49 AllocationScope scope;
50 sample::Response::Builder response;
52 response.set_pipe(pipe0.Pass());
53 client_->DidStuff(response.Finish(), text1);
56 virtual void DoStuff2(ScopedDataPipeConsumerHandle pipe) MOJO_OVERRIDE {
57 // Read the data from the pipe, writing the response (as a string) to
59 ASSERT_TRUE(pipe.is_valid());
60 uint32_t data_size = 0;
61 ASSERT_EQ(MOJO_RESULT_OK,
62 ReadDataRaw(pipe.get(), NULL, &data_size,
63 MOJO_READ_DATA_FLAG_QUERY));
64 ASSERT_NE(0, static_cast<int>(data_size));
66 ASSERT_LT(static_cast<int>(data_size), 64);
67 ASSERT_EQ(MOJO_RESULT_OK,
68 ReadDataRaw(pipe.get(), data, &data_size,
69 MOJO_READ_DATA_FLAG_ALL_OR_NONE));
71 AllocationScope scope;
72 client_->DidStuff2(String(std::string(data)));
76 sample::FactoryClient* client_;
77 ScopedMessagePipeHandle pipe1_;
80 class SampleFactoryClientImpl : public sample::FactoryClient {
82 SampleFactoryClientImpl() : got_response_(false) {
85 void set_expected_text_reply(const std::string& expected_text_reply) {
86 expected_text_reply_ = expected_text_reply;
89 bool got_response() const {
93 virtual void DidStuff(const sample::Response& response,
94 const String& text_reply) MOJO_OVERRIDE {
95 EXPECT_EQ(expected_text_reply_, text_reply.To<std::string>());
97 if (response.pipe().is_valid()) {
99 EXPECT_TRUE(ReadTextMessage(response.pipe().get(), &text2));
101 // Ensure that simply accessing response.pipe() does not close it.
102 EXPECT_TRUE(response.pipe().is_valid());
104 EXPECT_EQ(std::string(kText2), text2);
106 // Do some more tests of handle passing:
107 ScopedMessagePipeHandle p = response.pipe().Pass();
108 EXPECT_TRUE(p.is_valid());
109 EXPECT_FALSE(response.pipe().is_valid());
112 got_response_ = true;
115 virtual void DidStuff2(const String& text_reply) MOJO_OVERRIDE {
116 got_response_ = true;
117 EXPECT_EQ(expected_text_reply_, text_reply.To<std::string>());
121 ScopedMessagePipeHandle pipe1_;
122 ScopedMessagePipeHandle pipe3_;
123 std::string expected_text_reply_;
127 class HandlePassingTest : public testing::Test {
129 virtual void TearDown() {
133 void PumpMessages() {
134 loop_.RunUntilIdle();
142 TEST_F(HandlePassingTest, Basic) {
143 sample::FactoryPtr factory;
144 BindToProxy(new SampleFactoryImpl(), &factory);
146 SampleFactoryClientImpl factory_client;
147 factory_client.set_expected_text_reply(kText1);
149 factory->SetClient(&factory_client);
151 ScopedMessagePipeHandle pipe0, pipe1;
152 CreateMessagePipe(&pipe0, &pipe1);
154 EXPECT_TRUE(WriteTextMessage(pipe1.get(), kText1));
156 ScopedMessagePipeHandle pipe2, pipe3;
157 CreateMessagePipe(&pipe2, &pipe3);
159 EXPECT_TRUE(WriteTextMessage(pipe3.get(), kText2));
162 AllocationScope scope;
163 sample::Request::Builder request;
165 request.set_pipe(pipe2.Pass());
166 factory->DoStuff(request.Finish(), pipe0.Pass());
169 EXPECT_FALSE(factory_client.got_response());
173 EXPECT_TRUE(factory_client.got_response());
176 TEST_F(HandlePassingTest, PassInvalid) {
177 sample::FactoryPtr factory;
178 BindToProxy(new SampleFactoryImpl(), &factory);
180 SampleFactoryClientImpl factory_client;
181 factory->SetClient(&factory_client);
184 AllocationScope scope;
185 sample::Request::Builder request;
187 factory->DoStuff(request.Finish(), ScopedMessagePipeHandle().Pass());
190 EXPECT_FALSE(factory_client.got_response());
194 EXPECT_TRUE(factory_client.got_response());
197 // Verifies DataPipeConsumer can be passed and read from.
198 TEST_F(HandlePassingTest, DataPipe) {
199 sample::FactoryPtr factory;
200 BindToProxy(new SampleFactoryImpl(), &factory);
202 SampleFactoryClientImpl factory_client;
203 factory->SetClient(&factory_client);
205 // Writes a string to a data pipe and passes the data pipe (consumer) to the
207 ScopedDataPipeProducerHandle producer_handle;
208 ScopedDataPipeConsumerHandle consumer_handle;
209 MojoCreateDataPipeOptions options = {
210 sizeof(MojoCreateDataPipeOptions),
211 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
214 ASSERT_EQ(MOJO_RESULT_OK,
215 CreateDataPipe(&options, &producer_handle, &consumer_handle));
216 std::string expected_text_reply = "got it";
217 factory_client.set_expected_text_reply(expected_text_reply);
219 uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1);
220 ASSERT_EQ(MOJO_RESULT_OK,
221 WriteDataRaw(producer_handle.get(), expected_text_reply.c_str(),
222 &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
225 AllocationScope scope;
226 factory->DoStuff2(consumer_handle.Pass());
229 EXPECT_FALSE(factory_client.got_response());
233 EXPECT_TRUE(factory_client.got_response());
236 TEST_F(HandlePassingTest, PipesAreClosed) {
237 sample::FactoryPtr factory;
238 BindToProxy(new SampleFactoryImpl(), &factory);
240 SampleFactoryClientImpl factory_client;
241 factory->SetClient(&factory_client);
243 MessagePipe extra_pipe;
245 MojoHandle handle0_value = extra_pipe.handle0.get().value();
246 MojoHandle handle1_value = extra_pipe.handle1.get().value();
249 AllocationScope scope;
251 Array<MessagePipeHandle>::Builder pipes(2);
252 pipes[0] = extra_pipe.handle0.Pass();
253 pipes[1] = extra_pipe.handle1.Pass();
255 sample::Request::Builder request_builder;
256 request_builder.set_more_pipes(pipes.Finish());
258 sample::Request request = request_builder.Finish();
260 factory->DoStuff(request, ScopedMessagePipeHandle());
262 // The handles should have been transferred to the underlying Message.
263 EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[0].get().value());
264 EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[1].get().value());
267 // We expect the pipes to have been closed.
268 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value));
269 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value));