• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "mojo/public/cpp/environment/environment.h"
6 #include "mojo/public/cpp/test_support/test_utils.h"
7 #include "mojo/public/cpp/utility/run_loop.h"
8 #include "mojo/public/interfaces/bindings/tests/sample_factory.mojom.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 namespace mojo {
12 namespace test {
13 namespace {
14 
15 const char kText1[] = "hello";
16 const char kText2[] = "world";
17 
18 class StringRecorder {
19  public:
StringRecorder(std::string * buf)20   explicit StringRecorder(std::string* buf) : buf_(buf) {
21   }
Run(const String & a) const22   void Run(const String& a) const {
23     *buf_ = a.To<std::string>();
24   }
25  private:
26   std::string* buf_;
27 };
28 
29 class SampleObjectImpl : public InterfaceImpl<sample::Object> {
30  public:
OnConnectionError()31   virtual void OnConnectionError() MOJO_OVERRIDE {
32     delete this;
33   }
34 
SetName(const mojo::String & name)35   virtual void SetName(const mojo::String& name) MOJO_OVERRIDE {
36     name_ = name;
37   }
38 
GetName(const mojo::Callback<void (mojo::String)> & callback)39   virtual void GetName(const mojo::Callback<void(mojo::String)>& callback)
40       MOJO_OVERRIDE {
41     callback.Run(name_);
42   }
43 
44  private:
45   std::string name_;
46 };
47 
48 class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
49  public:
OnConnectionError()50   virtual void OnConnectionError() MOJO_OVERRIDE {
51     delete this;
52   }
53 
DoStuff(sample::RequestPtr request,ScopedMessagePipeHandle pipe)54   virtual void DoStuff(sample::RequestPtr request,
55                        ScopedMessagePipeHandle pipe) MOJO_OVERRIDE {
56     std::string text1;
57     if (pipe.is_valid())
58       EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1));
59 
60     std::string text2;
61     if (request->pipe.is_valid()) {
62       EXPECT_TRUE(ReadTextMessage(request->pipe.get(), &text2));
63 
64       // Ensure that simply accessing request->pipe does not close it.
65       EXPECT_TRUE(request->pipe.is_valid());
66     }
67 
68     ScopedMessagePipeHandle pipe0;
69     if (!text2.empty()) {
70       CreateMessagePipe(NULL, &pipe0, &pipe1_);
71       EXPECT_TRUE(WriteTextMessage(pipe1_.get(), text2));
72     }
73 
74     sample::ResponsePtr response(sample::Response::New());
75     response->x = 2;
76     response->pipe = pipe0.Pass();
77     client()->DidStuff(response.Pass(), text1);
78   }
79 
DoStuff2(ScopedDataPipeConsumerHandle pipe)80   virtual void DoStuff2(ScopedDataPipeConsumerHandle pipe) MOJO_OVERRIDE {
81     // Read the data from the pipe, writing the response (as a string) to
82     // DidStuff2().
83     ASSERT_TRUE(pipe.is_valid());
84     uint32_t data_size = 0;
85     ASSERT_EQ(MOJO_RESULT_OK,
86               ReadDataRaw(pipe.get(), NULL, &data_size,
87                           MOJO_READ_DATA_FLAG_QUERY));
88     ASSERT_NE(0, static_cast<int>(data_size));
89     char data[64];
90     ASSERT_LT(static_cast<int>(data_size), 64);
91     ASSERT_EQ(MOJO_RESULT_OK,
92               ReadDataRaw(pipe.get(), data, &data_size,
93                           MOJO_READ_DATA_FLAG_ALL_OR_NONE));
94 
95     client()->DidStuff2(data);
96   }
97 
CreateObject(InterfaceRequest<sample::Object> object_request)98   virtual void CreateObject(InterfaceRequest<sample::Object> object_request)
99       MOJO_OVERRIDE {
100     EXPECT_TRUE(object_request.is_pending());
101     BindToRequest(new SampleObjectImpl(), &object_request);
102   }
103 
104   // These aren't called or implemented, but exist here to test that the
105   // methods are generated with the correct argument types for imported
106   // interfaces.
RequestImportedInterface(InterfaceRequest<imported::ImportedInterface> imported,const mojo::Callback<void (InterfaceRequest<imported::ImportedInterface>)> & callback)107   virtual void RequestImportedInterface(
108       InterfaceRequest<imported::ImportedInterface> imported,
109       const mojo::Callback<void(InterfaceRequest<imported::ImportedInterface>)>&
110           callback) MOJO_OVERRIDE {}
TakeImportedInterface(imported::ImportedInterfacePtr imported,const mojo::Callback<void (imported::ImportedInterfacePtr)> & callback)111   virtual void TakeImportedInterface(
112       imported::ImportedInterfacePtr imported,
113       const mojo::Callback<void(imported::ImportedInterfacePtr)>& callback)
114       MOJO_OVERRIDE {}
115 
116  private:
117   ScopedMessagePipeHandle pipe1_;
118 };
119 
120 class SampleFactoryClientImpl : public sample::FactoryClient {
121  public:
SampleFactoryClientImpl()122   SampleFactoryClientImpl() : got_response_(false) {
123   }
124 
set_expected_text_reply(const std::string & expected_text_reply)125   void set_expected_text_reply(const std::string& expected_text_reply) {
126     expected_text_reply_ = expected_text_reply;
127   }
128 
got_response() const129   bool got_response() const {
130     return got_response_;
131   }
132 
DidStuff(sample::ResponsePtr response,const String & text_reply)133   virtual void DidStuff(sample::ResponsePtr response,
134                         const String& text_reply) MOJO_OVERRIDE {
135     EXPECT_EQ(expected_text_reply_, text_reply);
136 
137     if (response->pipe.is_valid()) {
138       std::string text2;
139       EXPECT_TRUE(ReadTextMessage(response->pipe.get(), &text2));
140 
141       // Ensure that simply accessing response.pipe does not close it.
142       EXPECT_TRUE(response->pipe.is_valid());
143 
144       EXPECT_EQ(std::string(kText2), text2);
145 
146       // Do some more tests of handle passing:
147       ScopedMessagePipeHandle p = response->pipe.Pass();
148       EXPECT_TRUE(p.is_valid());
149       EXPECT_FALSE(response->pipe.is_valid());
150     }
151 
152     got_response_ = true;
153   }
154 
DidStuff2(const String & text_reply)155   virtual void DidStuff2(const String& text_reply) MOJO_OVERRIDE {
156     got_response_ = true;
157     EXPECT_EQ(expected_text_reply_, text_reply);
158   }
159 
160  private:
161   ScopedMessagePipeHandle pipe1_;
162   ScopedMessagePipeHandle pipe3_;
163   std::string expected_text_reply_;
164   bool got_response_;
165 };
166 
167 class HandlePassingTest : public testing::Test {
168  public:
TearDown()169   virtual void TearDown() {
170     PumpMessages();
171   }
172 
PumpMessages()173   void PumpMessages() {
174     loop_.RunUntilIdle();
175   }
176 
177  private:
178   Environment env_;
179   RunLoop loop_;
180 };
181 
TEST_F(HandlePassingTest,Basic)182 TEST_F(HandlePassingTest, Basic) {
183   sample::FactoryPtr factory;
184   BindToProxy(new SampleFactoryImpl(), &factory);
185 
186   SampleFactoryClientImpl factory_client;
187   factory_client.set_expected_text_reply(kText1);
188 
189   factory.set_client(&factory_client);
190 
191   MessagePipe pipe0;
192   EXPECT_TRUE(WriteTextMessage(pipe0.handle1.get(), kText1));
193 
194   MessagePipe pipe1;
195   EXPECT_TRUE(WriteTextMessage(pipe1.handle1.get(), kText2));
196 
197   sample::RequestPtr request(sample::Request::New());
198   request->x = 1;
199   request->pipe = pipe1.handle0.Pass();
200   factory->DoStuff(request.Pass(), pipe0.handle0.Pass());
201 
202   EXPECT_FALSE(factory_client.got_response());
203 
204   PumpMessages();
205 
206   EXPECT_TRUE(factory_client.got_response());
207 }
208 
TEST_F(HandlePassingTest,PassInvalid)209 TEST_F(HandlePassingTest, PassInvalid) {
210   sample::FactoryPtr factory;
211   BindToProxy(new SampleFactoryImpl(), &factory);
212 
213   SampleFactoryClientImpl factory_client;
214   factory.set_client(&factory_client);
215 
216   sample::RequestPtr request(sample::Request::New());
217   request->x = 1;
218   factory->DoStuff(request.Pass(), ScopedMessagePipeHandle().Pass());
219 
220   EXPECT_FALSE(factory_client.got_response());
221 
222   PumpMessages();
223 
224   EXPECT_TRUE(factory_client.got_response());
225 }
226 
227 // Verifies DataPipeConsumer can be passed and read from.
TEST_F(HandlePassingTest,DataPipe)228 TEST_F(HandlePassingTest, DataPipe) {
229   sample::FactoryPtr factory;
230   BindToProxy(new SampleFactoryImpl(), &factory);
231 
232   SampleFactoryClientImpl factory_client;
233   factory.set_client(&factory_client);
234 
235   // Writes a string to a data pipe and passes the data pipe (consumer) to the
236   // factory.
237   ScopedDataPipeProducerHandle producer_handle;
238   ScopedDataPipeConsumerHandle consumer_handle;
239   MojoCreateDataPipeOptions options = {
240       sizeof(MojoCreateDataPipeOptions),
241       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
242       1,
243       1024};
244   ASSERT_EQ(MOJO_RESULT_OK,
245             CreateDataPipe(&options, &producer_handle, &consumer_handle));
246   std::string expected_text_reply = "got it";
247   factory_client.set_expected_text_reply(expected_text_reply);
248   // +1 for \0.
249   uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1);
250   ASSERT_EQ(MOJO_RESULT_OK,
251             WriteDataRaw(producer_handle.get(), expected_text_reply.c_str(),
252                          &data_size, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
253 
254   factory->DoStuff2(consumer_handle.Pass());
255 
256   EXPECT_FALSE(factory_client.got_response());
257 
258   PumpMessages();
259 
260   EXPECT_TRUE(factory_client.got_response());
261 }
262 
TEST_F(HandlePassingTest,PipesAreClosed)263 TEST_F(HandlePassingTest, PipesAreClosed) {
264   sample::FactoryPtr factory;
265   BindToProxy(new SampleFactoryImpl(), &factory);
266 
267   SampleFactoryClientImpl factory_client;
268   factory.set_client(&factory_client);
269 
270   MessagePipe extra_pipe;
271 
272   MojoHandle handle0_value = extra_pipe.handle0.get().value();
273   MojoHandle handle1_value = extra_pipe.handle1.get().value();
274 
275   {
276     Array<ScopedMessagePipeHandle> pipes(2);
277     pipes[0] = extra_pipe.handle0.Pass();
278     pipes[1] = extra_pipe.handle1.Pass();
279 
280     sample::RequestPtr request(sample::Request::New());
281     request->more_pipes = pipes.Pass();
282 
283     factory->DoStuff(request.Pass(), ScopedMessagePipeHandle());
284   }
285 
286   // We expect the pipes to have been closed.
287   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle0_value));
288   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handle1_value));
289 }
290 
TEST_F(HandlePassingTest,IsHandle)291 TEST_F(HandlePassingTest, IsHandle) {
292   // Validate that mojo::internal::IsHandle<> works as expected since this.
293   // template is key to ensuring that we don't leak handles.
294   EXPECT_TRUE(internal::IsHandle<Handle>::value);
295   EXPECT_TRUE(internal::IsHandle<MessagePipeHandle>::value);
296   EXPECT_TRUE(internal::IsHandle<DataPipeConsumerHandle>::value);
297   EXPECT_TRUE(internal::IsHandle<DataPipeProducerHandle>::value);
298   EXPECT_TRUE(internal::IsHandle<SharedBufferHandle>::value);
299 
300   // Basic sanity checks...
301   EXPECT_FALSE(internal::IsHandle<int>::value);
302   EXPECT_FALSE(internal::IsHandle<sample::FactoryPtr>::value);
303   EXPECT_FALSE(internal::IsHandle<String>::value);
304 }
305 
TEST_F(HandlePassingTest,CreateObject)306 TEST_F(HandlePassingTest, CreateObject) {
307   sample::FactoryPtr factory;
308   BindToProxy(new SampleFactoryImpl(), &factory);
309 
310   sample::ObjectPtr object1;
311   EXPECT_FALSE(object1.get());
312 
313   InterfaceRequest<sample::Object> object1_request = Get(&object1);
314   EXPECT_TRUE(object1_request.is_pending());
315   factory->CreateObject(object1_request.Pass());
316   EXPECT_FALSE(object1_request.is_pending());  // We've passed the request.
317 
318   ASSERT_TRUE(object1.get());
319   object1->SetName("object1");
320 
321   sample::ObjectPtr object2;
322   factory->CreateObject(Get(&object2));
323   object2->SetName("object2");
324 
325   std::string name1;
326   object1->GetName(StringRecorder(&name1));
327 
328   std::string name2;
329   object2->GetName(StringRecorder(&name2));
330 
331   PumpMessages();  // Yield for results.
332 
333   EXPECT_EQ(std::string("object1"), name1);
334   EXPECT_EQ(std::string("object2"), name2);
335 }
336 
337 }  // namespace
338 }  // namespace test
339 }  // namespace mojo
340