| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/public/cpp/bindings/allocation_scope.h" | |
| 6 #include "mojo/public/cpp/environment/environment.h" | 5 #include "mojo/public/cpp/environment/environment.h" |
| 7 #include "mojo/public/cpp/test_support/test_utils.h" | 6 #include "mojo/public/cpp/test_support/test_utils.h" |
| 8 #include "mojo/public/cpp/utility/run_loop.h" | 7 #include "mojo/public/cpp/utility/run_loop.h" |
| 9 #include "mojo/public/interfaces/bindings/tests/sample_factory.mojom.h" | 8 #include "mojo/public/interfaces/bindings/tests/sample_factory.mojom.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 10 |
| 12 namespace mojo { | 11 namespace mojo { |
| 13 namespace test { | 12 namespace test { |
| 14 namespace { | 13 namespace { |
| 15 | 14 |
| 16 const char kText1[] = "hello"; | 15 const char kText1[] = "hello"; |
| 17 const char kText2[] = "world"; | 16 const char kText2[] = "world"; |
| 18 | 17 |
| 19 class SampleFactoryImpl : public InterfaceImpl<sample::Factory> { | 18 class SampleFactoryImpl : public InterfaceImpl<sample::Factory> { |
| 20 public: | 19 public: |
| 21 virtual void OnConnectionError() MOJO_OVERRIDE { | 20 virtual void OnConnectionError() MOJO_OVERRIDE { |
| 22 delete this; | 21 delete this; |
| 23 } | 22 } |
| 24 | 23 |
| 25 virtual void DoStuff(const sample::Request& request, | 24 virtual void DoStuff(sample::RequestPtr request, |
| 26 ScopedMessagePipeHandle pipe) MOJO_OVERRIDE { | 25 ScopedMessagePipeHandle pipe) MOJO_OVERRIDE { |
| 27 std::string text1; | 26 std::string text1; |
| 28 if (pipe.is_valid()) | 27 if (pipe.is_valid()) |
| 29 EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1)); | 28 EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1)); |
| 30 | 29 |
| 31 std::string text2; | 30 std::string text2; |
| 32 if (request.pipe().is_valid()) { | 31 if (request->pipe.is_valid()) { |
| 33 EXPECT_TRUE(ReadTextMessage(request.pipe().get(), &text2)); | 32 EXPECT_TRUE(ReadTextMessage(request->pipe.get(), &text2)); |
| 34 | 33 |
| 35 // Ensure that simply accessing request.pipe() does not close it. | 34 // Ensure that simply accessing request->pipe does not close it. |
| 36 EXPECT_TRUE(request.pipe().is_valid()); | 35 EXPECT_TRUE(request->pipe.is_valid()); |
| 37 } | 36 } |
| 38 | 37 |
| 39 ScopedMessagePipeHandle pipe0; | 38 ScopedMessagePipeHandle pipe0; |
| 40 if (!text2.empty()) { | 39 if (!text2.empty()) { |
| 41 CreateMessagePipe(&pipe0, &pipe1_); | 40 CreateMessagePipe(&pipe0, &pipe1_); |
| 42 EXPECT_TRUE(WriteTextMessage(pipe1_.get(), text2)); | 41 EXPECT_TRUE(WriteTextMessage(pipe1_.get(), text2)); |
| 43 } | 42 } |
| 44 | 43 |
| 45 AllocationScope scope; | 44 sample::ResponsePtr response(sample::Response::New()); |
| 46 sample::Response::Builder response; | 45 response->x = 2; |
| 47 response.set_x(2); | 46 response->pipe = pipe0.Pass(); |
| 48 response.set_pipe(pipe0.Pass()); | 47 client()->DidStuff(response.Pass(), text1); |
| 49 client()->DidStuff(response.Finish(), text1); | |
| 50 } | 48 } |
| 51 | 49 |
| 52 virtual void DoStuff2(ScopedDataPipeConsumerHandle pipe) MOJO_OVERRIDE { | 50 virtual void DoStuff2(ScopedDataPipeConsumerHandle pipe) MOJO_OVERRIDE { |
| 53 // Read the data from the pipe, writing the response (as a string) to | 51 // Read the data from the pipe, writing the response (as a string) to |
| 54 // DidStuff2(). | 52 // DidStuff2(). |
| 55 ASSERT_TRUE(pipe.is_valid()); | 53 ASSERT_TRUE(pipe.is_valid()); |
| 56 uint32_t data_size = 0; | 54 uint32_t data_size = 0; |
| 57 ASSERT_EQ(MOJO_RESULT_OK, | 55 ASSERT_EQ(MOJO_RESULT_OK, |
| 58 ReadDataRaw(pipe.get(), NULL, &data_size, | 56 ReadDataRaw(pipe.get(), NULL, &data_size, |
| 59 MOJO_READ_DATA_FLAG_QUERY)); | 57 MOJO_READ_DATA_FLAG_QUERY)); |
| 60 ASSERT_NE(0, static_cast<int>(data_size)); | 58 ASSERT_NE(0, static_cast<int>(data_size)); |
| 61 char data[64]; | 59 char data[64]; |
| 62 ASSERT_LT(static_cast<int>(data_size), 64); | 60 ASSERT_LT(static_cast<int>(data_size), 64); |
| 63 ASSERT_EQ(MOJO_RESULT_OK, | 61 ASSERT_EQ(MOJO_RESULT_OK, |
| 64 ReadDataRaw(pipe.get(), data, &data_size, | 62 ReadDataRaw(pipe.get(), data, &data_size, |
| 65 MOJO_READ_DATA_FLAG_ALL_OR_NONE)); | 63 MOJO_READ_DATA_FLAG_ALL_OR_NONE)); |
| 66 | 64 |
| 67 AllocationScope scope; | 65 client()->DidStuff2(data); |
| 68 client()->DidStuff2(String(std::string(data))); | |
| 69 } | 66 } |
| 70 | 67 |
| 71 private: | 68 private: |
| 72 ScopedMessagePipeHandle pipe1_; | 69 ScopedMessagePipeHandle pipe1_; |
| 73 }; | 70 }; |
| 74 | 71 |
| 75 class SampleFactoryClientImpl : public sample::FactoryClient { | 72 class SampleFactoryClientImpl : public sample::FactoryClient { |
| 76 public: | 73 public: |
| 77 SampleFactoryClientImpl() : got_response_(false) { | 74 SampleFactoryClientImpl() : got_response_(false) { |
| 78 } | 75 } |
| 79 | 76 |
| 80 void set_expected_text_reply(const std::string& expected_text_reply) { | 77 void set_expected_text_reply(const std::string& expected_text_reply) { |
| 81 expected_text_reply_ = expected_text_reply; | 78 expected_text_reply_ = expected_text_reply; |
| 82 } | 79 } |
| 83 | 80 |
| 84 bool got_response() const { | 81 bool got_response() const { |
| 85 return got_response_; | 82 return got_response_; |
| 86 } | 83 } |
| 87 | 84 |
| 88 virtual void DidStuff(const sample::Response& response, | 85 virtual void DidStuff(sample::ResponsePtr response, |
| 89 const String& text_reply) MOJO_OVERRIDE { | 86 const String& text_reply) MOJO_OVERRIDE { |
| 90 EXPECT_EQ(expected_text_reply_, text_reply.To<std::string>()); | 87 EXPECT_EQ(expected_text_reply_, text_reply); |
| 91 | 88 |
| 92 if (response.pipe().is_valid()) { | 89 if (response->pipe.is_valid()) { |
| 93 std::string text2; | 90 std::string text2; |
| 94 EXPECT_TRUE(ReadTextMessage(response.pipe().get(), &text2)); | 91 EXPECT_TRUE(ReadTextMessage(response->pipe.get(), &text2)); |
| 95 | 92 |
| 96 // Ensure that simply accessing response.pipe() does not close it. | 93 // Ensure that simply accessing response.pipe does not close it. |
| 97 EXPECT_TRUE(response.pipe().is_valid()); | 94 EXPECT_TRUE(response->pipe.is_valid()); |
| 98 | 95 |
| 99 EXPECT_EQ(std::string(kText2), text2); | 96 EXPECT_EQ(std::string(kText2), text2); |
| 100 | 97 |
| 101 // Do some more tests of handle passing: | 98 // Do some more tests of handle passing: |
| 102 ScopedMessagePipeHandle p = response.pipe().Pass(); | 99 ScopedMessagePipeHandle p = response->pipe.Pass(); |
| 103 EXPECT_TRUE(p.is_valid()); | 100 EXPECT_TRUE(p.is_valid()); |
| 104 EXPECT_FALSE(response.pipe().is_valid()); | 101 EXPECT_FALSE(response->pipe.is_valid()); |
| 105 } | 102 } |
| 106 | 103 |
| 107 got_response_ = true; | 104 got_response_ = true; |
| 108 } | 105 } |
| 109 | 106 |
| 110 virtual void DidStuff2(const String& text_reply) MOJO_OVERRIDE { | 107 virtual void DidStuff2(const String& text_reply) MOJO_OVERRIDE { |
| 111 got_response_ = true; | 108 got_response_ = true; |
| 112 EXPECT_EQ(expected_text_reply_, text_reply.To<std::string>()); | 109 EXPECT_EQ(expected_text_reply_, text_reply); |
| 113 } | 110 } |
| 114 | 111 |
| 115 private: | 112 private: |
| 116 ScopedMessagePipeHandle pipe1_; | 113 ScopedMessagePipeHandle pipe1_; |
| 117 ScopedMessagePipeHandle pipe3_; | 114 ScopedMessagePipeHandle pipe3_; |
| 118 std::string expected_text_reply_; | 115 std::string expected_text_reply_; |
| 119 bool got_response_; | 116 bool got_response_; |
| 120 }; | 117 }; |
| 121 | 118 |
| 122 class HandlePassingTest : public testing::Test { | 119 class HandlePassingTest : public testing::Test { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 146 ScopedMessagePipeHandle pipe0, pipe1; | 143 ScopedMessagePipeHandle pipe0, pipe1; |
| 147 CreateMessagePipe(&pipe0, &pipe1); | 144 CreateMessagePipe(&pipe0, &pipe1); |
| 148 | 145 |
| 149 EXPECT_TRUE(WriteTextMessage(pipe1.get(), kText1)); | 146 EXPECT_TRUE(WriteTextMessage(pipe1.get(), kText1)); |
| 150 | 147 |
| 151 ScopedMessagePipeHandle pipe2, pipe3; | 148 ScopedMessagePipeHandle pipe2, pipe3; |
| 152 CreateMessagePipe(&pipe2, &pipe3); | 149 CreateMessagePipe(&pipe2, &pipe3); |
| 153 | 150 |
| 154 EXPECT_TRUE(WriteTextMessage(pipe3.get(), kText2)); | 151 EXPECT_TRUE(WriteTextMessage(pipe3.get(), kText2)); |
| 155 | 152 |
| 156 { | 153 sample::RequestPtr request(sample::Request::New()); |
| 157 AllocationScope scope; | 154 request->x = 1; |
| 158 sample::Request::Builder request; | 155 request->pipe = pipe2.Pass(); |
| 159 request.set_x(1); | 156 factory->DoStuff(request.Pass(), pipe0.Pass()); |
| 160 request.set_pipe(pipe2.Pass()); | |
| 161 factory->DoStuff(request.Finish(), pipe0.Pass()); | |
| 162 } | |
| 163 | 157 |
| 164 EXPECT_FALSE(factory_client.got_response()); | 158 EXPECT_FALSE(factory_client.got_response()); |
| 165 | 159 |
| 166 PumpMessages(); | 160 PumpMessages(); |
| 167 | 161 |
| 168 EXPECT_TRUE(factory_client.got_response()); | 162 EXPECT_TRUE(factory_client.got_response()); |
| 169 } | 163 } |
| 170 | 164 |
| 171 TEST_F(HandlePassingTest, PassInvalid) { | 165 TEST_F(HandlePassingTest, PassInvalid) { |
| 172 sample::FactoryPtr factory; | 166 sample::FactoryPtr factory; |
| 173 BindToProxy(new SampleFactoryImpl(), &factory); | 167 BindToProxy(new SampleFactoryImpl(), &factory); |
| 174 | 168 |
| 175 SampleFactoryClientImpl factory_client; | 169 SampleFactoryClientImpl factory_client; |
| 176 factory.set_client(&factory_client); | 170 factory.set_client(&factory_client); |
| 177 | 171 |
| 178 { | 172 sample::RequestPtr request(sample::Request::New()); |
| 179 AllocationScope scope; | 173 request->x = 1; |
| 180 sample::Request::Builder request; | 174 factory->DoStuff(request.Pass(), ScopedMessagePipeHandle().Pass()); |
| 181 request.set_x(1); | |
| 182 factory->DoStuff(request.Finish(), ScopedMessagePipeHandle().Pass()); | |
| 183 } | |
| 184 | 175 |
| 185 EXPECT_FALSE(factory_client.got_response()); | 176 EXPECT_FALSE(factory_client.got_response()); |
| 186 | 177 |
| 187 PumpMessages(); | 178 PumpMessages(); |
| 188 | 179 |
| 189 EXPECT_TRUE(factory_client.got_response()); | 180 EXPECT_TRUE(factory_client.got_response()); |
| 190 } | 181 } |
| 191 | 182 |
| 192 // Verifies DataPipeConsumer can be passed and read from. | 183 // Verifies DataPipeConsumer can be passed and read from. |
| 193 TEST_F(HandlePassingTest, DataPipe) { | 184 TEST_F(HandlePassingTest, DataPipe) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 209 ASSERT_EQ(MOJO_RESULT_OK, | 200 ASSERT_EQ(MOJO_RESULT_OK, |
| 210 CreateDataPipe(&options, &producer_handle, &consumer_handle)); | 201 CreateDataPipe(&options, &producer_handle, &consumer_handle)); |
| 211 std::string expected_text_reply = "got it"; | 202 std::string expected_text_reply = "got it"; |
| 212 factory_client.set_expected_text_reply(expected_text_reply); | 203 factory_client.set_expected_text_reply(expected_text_reply); |
| 213 // +1 for \0. | 204 // +1 for \0. |
| 214 uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1); | 205 uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1); |
| 215 ASSERT_EQ(MOJO_RESULT_OK, | 206 ASSERT_EQ(MOJO_RESULT_OK, |
| 216 WriteDataRaw(producer_handle.get(), expected_text_reply.c_str(), | 207 WriteDataRaw(producer_handle.get(), expected_text_reply.c_str(), |
| 217 &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); | 208 &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); |
| 218 | 209 |
| 219 { | 210 factory->DoStuff2(consumer_handle.Pass()); |
| 220 AllocationScope scope; | |
| 221 factory->DoStuff2(consumer_handle.Pass()); | |
| 222 } | |
| 223 | 211 |
| 224 EXPECT_FALSE(factory_client.got_response()); | 212 EXPECT_FALSE(factory_client.got_response()); |
| 225 | 213 |
| 226 PumpMessages(); | 214 PumpMessages(); |
| 227 | 215 |
| 228 EXPECT_TRUE(factory_client.got_response()); | 216 EXPECT_TRUE(factory_client.got_response()); |
| 229 } | 217 } |
| 230 | 218 |
| 231 TEST_F(HandlePassingTest, PipesAreClosed) { | 219 TEST_F(HandlePassingTest, PipesAreClosed) { |
| 232 sample::FactoryPtr factory; | 220 sample::FactoryPtr factory; |
| 233 BindToProxy(new SampleFactoryImpl(), &factory); | 221 BindToProxy(new SampleFactoryImpl(), &factory); |
| 234 | 222 |
| 235 SampleFactoryClientImpl factory_client; | 223 SampleFactoryClientImpl factory_client; |
| 236 factory.set_client(&factory_client); | 224 factory.set_client(&factory_client); |
| 237 | 225 |
| 238 MessagePipe extra_pipe; | 226 MessagePipe extra_pipe; |
| 239 | 227 |
| 240 MojoHandle handle0_value = extra_pipe.handle0.get().value(); | 228 MojoHandle handle0_value = extra_pipe.handle0.get().value(); |
| 241 MojoHandle handle1_value = extra_pipe.handle1.get().value(); | 229 MojoHandle handle1_value = extra_pipe.handle1.get().value(); |
| 242 | 230 |
| 243 { | 231 { |
| 244 AllocationScope scope; | 232 Array<ScopedMessagePipeHandle> pipes(2); |
| 245 | |
| 246 Array<MessagePipeHandle>::Builder pipes(2); | |
| 247 pipes[0] = extra_pipe.handle0.Pass(); | 233 pipes[0] = extra_pipe.handle0.Pass(); |
| 248 pipes[1] = extra_pipe.handle1.Pass(); | 234 pipes[1] = extra_pipe.handle1.Pass(); |
| 249 | 235 |
| 250 sample::Request::Builder request_builder; | 236 sample::RequestPtr request(sample::Request::New()); |
| 251 request_builder.set_more_pipes(pipes.Finish()); | 237 request->more_pipes = pipes.Pass(); |
| 252 | 238 |
| 253 sample::Request request = request_builder.Finish(); | 239 factory->DoStuff(request.Pass(), ScopedMessagePipeHandle()); |
| 254 | |
| 255 factory->DoStuff(request, ScopedMessagePipeHandle()); | |
| 256 | |
| 257 // The handles should have been transferred to the underlying Message. | |
| 258 EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[0].get().value()); | |
| 259 EXPECT_EQ(MOJO_HANDLE_INVALID, request.more_pipes()[1].get().value()); | |
| 260 } | 240 } |
| 261 | 241 |
| 262 // We expect the pipes to have been closed. | 242 // We expect the pipes to have been closed. |
| 263 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value)); | 243 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value)); |
| 264 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value)); | 244 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value)); |
| 265 } | 245 } |
| 266 | 246 |
| 247 TEST_F(HandlePassingTest, IsHandle) { |
| 248 // Validate that mojo::internal::IsHandle<> works as expected since this. |
| 249 // template is key to ensuring that we don't leak handles. |
| 250 EXPECT_TRUE(internal::IsHandle<Handle>::value); |
| 251 EXPECT_TRUE(internal::IsHandle<MessagePipeHandle>::value); |
| 252 EXPECT_TRUE(internal::IsHandle<DataPipeConsumerHandle>::value); |
| 253 EXPECT_TRUE(internal::IsHandle<DataPipeProducerHandle>::value); |
| 254 EXPECT_TRUE(internal::IsHandle<SharedBufferHandle>::value); |
| 255 |
| 256 // Basic sanity checks... |
| 257 EXPECT_FALSE(internal::IsHandle<int>::value); |
| 258 EXPECT_FALSE(internal::IsHandle<sample::FactoryPtr>::value); |
| 259 EXPECT_FALSE(internal::IsHandle<String>::value); |
| 260 } |
| 261 |
| 267 } // namespace | 262 } // namespace |
| 268 } // namespace test | 263 } // namespace test |
| 269 } // namespace mojo | 264 } // namespace mojo |
| OLD | NEW |