• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 "base/bind.h"
6 #include "base/callback.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "mojo/public/cpp/bindings/binding_set.h"
11 #include "mojo/public/cpp/bindings/interface_request.h"
12 #include "mojo/public/cpp/bindings/tests/rect_blink.h"
13 #include "mojo/public/cpp/bindings/tests/rect_chromium.h"
14 #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl.h"
15 #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h"
16 #include "mojo/public/cpp/bindings/tests/variant_test_util.h"
17 #include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h"
18 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h"
19 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace mojo {
23 namespace test {
24 namespace {
25 
26 template <typename T>
DoExpectResult(const T & expected,const base::Closure & callback,const T & actual)27 void DoExpectResult(const T& expected,
28                     const base::Closure& callback,
29                     const T& actual) {
30   EXPECT_EQ(expected.x(), actual.x());
31   EXPECT_EQ(expected.y(), actual.y());
32   EXPECT_EQ(expected.width(), actual.width());
33   EXPECT_EQ(expected.height(), actual.height());
34   callback.Run();
35 }
36 
37 template <typename T>
ExpectResult(const T & r,const base::Closure & callback)38 base::Callback<void(const T&)> ExpectResult(const T& r,
39                                             const base::Closure& callback) {
40   return base::Bind(&DoExpectResult<T>, r, callback);
41 }
42 
43 template <typename T>
DoFail(const std::string & reason,const T &)44 void DoFail(const std::string& reason, const T&) {
45   EXPECT_TRUE(false) << reason;
46 }
47 
48 template <typename T>
Fail(const std::string & reason)49 base::Callback<void(const T&)> Fail(const std::string& reason) {
50   return base::Bind(&DoFail<T>, reason);
51 }
52 
53 template <typename T>
ExpectError(InterfacePtr<T> * proxy,const base::Closure & callback)54 void ExpectError(InterfacePtr<T> *proxy, const base::Closure& callback) {
55   proxy->set_connection_error_handler(callback);
56 }
57 
58 // This implements the generated Chromium variant of RectService.
59 class ChromiumRectServiceImpl : public RectService {
60  public:
ChromiumRectServiceImpl()61   ChromiumRectServiceImpl() {}
62 
63   // mojo::test::RectService:
AddRect(const RectChromium & r)64   void AddRect(const RectChromium& r) override {
65     if (r.GetArea() > largest_rect_.GetArea())
66       largest_rect_ = r;
67   }
68 
GetLargestRect(const GetLargestRectCallback & callback)69   void GetLargestRect(const GetLargestRectCallback& callback) override {
70     callback.Run(largest_rect_);
71   }
72 
73  private:
74   RectChromium largest_rect_;
75 };
76 
77 // This implements the generated Blink variant of RectService.
78 class BlinkRectServiceImpl : public blink::RectService {
79  public:
BlinkRectServiceImpl()80   BlinkRectServiceImpl() {}
81 
82   // mojo::test::blink::RectService:
AddRect(const RectBlink & r)83   void AddRect(const RectBlink& r) override {
84     if (r.computeArea() > largest_rect_.computeArea()) {
85       largest_rect_.setX(r.x());
86       largest_rect_.setY(r.y());
87       largest_rect_.setWidth(r.width());
88       largest_rect_.setHeight(r.height());
89     }
90   }
91 
GetLargestRect(const GetLargestRectCallback & callback)92   void GetLargestRect(const GetLargestRectCallback& callback) override {
93     callback.Run(largest_rect_);
94   }
95 
96  private:
97   RectBlink largest_rect_;
98 };
99 
100 // A test which runs both Chromium and Blink implementations of a RectService.
101 class StructTraitsTest : public testing::Test,
102                          public TraitsTestService {
103  public:
StructTraitsTest()104   StructTraitsTest() {}
105 
106  protected:
BindToChromiumService(RectServiceRequest request)107   void BindToChromiumService(RectServiceRequest request) {
108     chromium_bindings_.AddBinding(&chromium_service_, std::move(request));
109   }
BindToChromiumService(blink::RectServiceRequest request)110   void BindToChromiumService(blink::RectServiceRequest request) {
111     chromium_bindings_.AddBinding(
112         &chromium_service_,
113         ConvertInterfaceRequest<RectService>(std::move(request)));
114   }
115 
BindToBlinkService(blink::RectServiceRequest request)116   void BindToBlinkService(blink::RectServiceRequest request) {
117     blink_bindings_.AddBinding(&blink_service_, std::move(request));
118   }
BindToBlinkService(RectServiceRequest request)119   void BindToBlinkService(RectServiceRequest request) {
120     blink_bindings_.AddBinding(
121         &blink_service_,
122         ConvertInterfaceRequest<blink::RectService>(std::move(request)));
123   }
124 
GetTraitsTestProxy()125   TraitsTestServicePtr GetTraitsTestProxy() {
126     return traits_test_bindings_.CreateInterfacePtrAndBind(this);
127   }
128 
129  private:
130   // TraitsTestService:
EchoStructWithTraits(const StructWithTraitsImpl & s,const EchoStructWithTraitsCallback & callback)131   void EchoStructWithTraits(
132       const StructWithTraitsImpl& s,
133       const EchoStructWithTraitsCallback& callback) override {
134     callback.Run(s);
135   }
136 
EchoPassByValueStructWithTraits(PassByValueStructWithTraitsImpl s,const EchoPassByValueStructWithTraitsCallback & callback)137   void EchoPassByValueStructWithTraits(
138       PassByValueStructWithTraitsImpl s,
139       const EchoPassByValueStructWithTraitsCallback& callback) override {
140     callback.Run(std::move(s));
141   }
142 
EchoEnumWithTraits(EnumWithTraitsImpl e,const EchoEnumWithTraitsCallback & callback)143   void EchoEnumWithTraits(EnumWithTraitsImpl e,
144                           const EchoEnumWithTraitsCallback& callback) override {
145     callback.Run(e);
146   }
147 
EchoStructWithTraitsForUniquePtrTest(std::unique_ptr<int> e,const EchoStructWithTraitsForUniquePtrTestCallback & callback)148   void EchoStructWithTraitsForUniquePtrTest(
149       std::unique_ptr<int> e,
150       const EchoStructWithTraitsForUniquePtrTestCallback& callback) override {
151     callback.Run(std::move(e));
152   }
153 
154   base::MessageLoop loop_;
155 
156   ChromiumRectServiceImpl chromium_service_;
157   BindingSet<RectService> chromium_bindings_;
158 
159   BlinkRectServiceImpl blink_service_;
160   BindingSet<blink::RectService> blink_bindings_;
161 
162   BindingSet<TraitsTestService> traits_test_bindings_;
163 };
164 
165 }  // namespace
166 
TEST_F(StructTraitsTest,ChromiumProxyToChromiumService)167 TEST_F(StructTraitsTest, ChromiumProxyToChromiumService) {
168   RectServicePtr chromium_proxy;
169   BindToChromiumService(GetProxy(&chromium_proxy));
170   {
171     base::RunLoop loop;
172     chromium_proxy->AddRect(RectChromium(1, 1, 4, 5));
173     chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2));
174     chromium_proxy->GetLargestRect(
175         ExpectResult(RectChromium(1, 1, 4, 5), loop.QuitClosure()));
176     loop.Run();
177   }
178 }
179 
TEST_F(StructTraitsTest,ChromiumToBlinkService)180 TEST_F(StructTraitsTest, ChromiumToBlinkService) {
181   RectServicePtr chromium_proxy;
182   BindToBlinkService(GetProxy(&chromium_proxy));
183   {
184     base::RunLoop loop;
185     chromium_proxy->AddRect(RectChromium(1, 1, 4, 5));
186     chromium_proxy->AddRect(RectChromium(2, 2, 5, 5));
187     chromium_proxy->GetLargestRect(
188         ExpectResult(RectChromium(2, 2, 5, 5), loop.QuitClosure()));
189     loop.Run();
190   }
191   // The Blink service should drop our connection because RectBlink's
192   // deserializer rejects negative origins.
193   {
194     base::RunLoop loop;
195     ExpectError(&chromium_proxy, loop.QuitClosure());
196     chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2));
197     chromium_proxy->GetLargestRect(
198         Fail<RectChromium>("The pipe should have been closed."));
199     loop.Run();
200   }
201 }
202 
TEST_F(StructTraitsTest,BlinkProxyToBlinkService)203 TEST_F(StructTraitsTest, BlinkProxyToBlinkService) {
204   blink::RectServicePtr blink_proxy;
205   BindToBlinkService(GetProxy(&blink_proxy));
206   {
207     base::RunLoop loop;
208     blink_proxy->AddRect(RectBlink(1, 1, 4, 5));
209     blink_proxy->AddRect(RectBlink(10, 10, 20, 20));
210     blink_proxy->GetLargestRect(
211         ExpectResult(RectBlink(10, 10, 20, 20), loop.QuitClosure()));
212     loop.Run();
213   }
214 }
215 
TEST_F(StructTraitsTest,BlinkProxyToChromiumService)216 TEST_F(StructTraitsTest, BlinkProxyToChromiumService) {
217   blink::RectServicePtr blink_proxy;
218   BindToChromiumService(GetProxy(&blink_proxy));
219   {
220     base::RunLoop loop;
221     blink_proxy->AddRect(RectBlink(1, 1, 4, 5));
222     blink_proxy->AddRect(RectBlink(10, 10, 2, 2));
223     blink_proxy->GetLargestRect(
224         ExpectResult(RectBlink(1, 1, 4, 5), loop.QuitClosure()));
225     loop.Run();
226   }
227 }
228 
ExpectStructWithTraits(const StructWithTraitsImpl & expected,const base::Closure & closure,const StructWithTraitsImpl & passed)229 void ExpectStructWithTraits(const StructWithTraitsImpl& expected,
230                             const base::Closure& closure,
231                             const StructWithTraitsImpl& passed) {
232   EXPECT_EQ(expected.get_enum(), passed.get_enum());
233   EXPECT_EQ(expected.get_bool(), passed.get_bool());
234   EXPECT_EQ(expected.get_uint32(), passed.get_uint32());
235   EXPECT_EQ(expected.get_uint64(), passed.get_uint64());
236   EXPECT_EQ(expected.get_string(), passed.get_string());
237   EXPECT_EQ(expected.get_string_array(), passed.get_string_array());
238   EXPECT_EQ(expected.get_struct(), passed.get_struct());
239   EXPECT_EQ(expected.get_struct_array(), passed.get_struct_array());
240   EXPECT_EQ(expected.get_struct_map(), passed.get_struct_map());
241   closure.Run();
242 }
243 
TEST_F(StructTraitsTest,EchoStructWithTraits)244 TEST_F(StructTraitsTest, EchoStructWithTraits) {
245   StructWithTraitsImpl input;
246   input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1);
247   input.set_bool(true);
248   input.set_uint32(7);
249   input.set_uint64(42);
250   input.set_string("hello world!");
251   input.get_mutable_string_array().assign({"hello", "world!"});
252   input.get_mutable_struct().value = 42;
253   input.get_mutable_struct_array().resize(2);
254   input.get_mutable_struct_array()[0].value = 1;
255   input.get_mutable_struct_array()[1].value = 2;
256   input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024);
257   input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048);
258 
259   base::RunLoop loop;
260   TraitsTestServicePtr proxy = GetTraitsTestProxy();
261 
262   proxy->EchoStructWithTraits(
263       input,
264       base::Bind(&ExpectStructWithTraits, input, loop.QuitClosure()));
265   loop.Run();
266 }
267 
TEST_F(StructTraitsTest,CloneStructWithTraitsContainer)268 TEST_F(StructTraitsTest, CloneStructWithTraitsContainer) {
269   StructWithTraitsContainerPtr container = StructWithTraitsContainer::New();
270   container->f_struct.set_uint32(7);
271   container->f_struct.set_uint64(42);
272   StructWithTraitsContainerPtr cloned_container = container.Clone();
273   EXPECT_EQ(7u, cloned_container->f_struct.get_uint32());
274   EXPECT_EQ(42u, cloned_container->f_struct.get_uint64());
275 }
276 
CaptureMessagePipe(ScopedMessagePipeHandle * storage,const base::Closure & closure,PassByValueStructWithTraitsImpl passed)277 void CaptureMessagePipe(ScopedMessagePipeHandle* storage,
278                         const base::Closure& closure,
279                         PassByValueStructWithTraitsImpl passed) {
280   storage->reset(MessagePipeHandle(
281       passed.get_mutable_handle().release().value()));
282   closure.Run();
283 }
284 
TEST_F(StructTraitsTest,EchoPassByValueStructWithTraits)285 TEST_F(StructTraitsTest, EchoPassByValueStructWithTraits) {
286   MessagePipe mp;
287   PassByValueStructWithTraitsImpl input;
288   input.get_mutable_handle().reset(mp.handle0.release());
289 
290   base::RunLoop loop;
291   TraitsTestServicePtr proxy = GetTraitsTestProxy();
292 
293   ScopedMessagePipeHandle received;
294   proxy->EchoPassByValueStructWithTraits(
295       std::move(input),
296       base::Bind(&CaptureMessagePipe, &received, loop.QuitClosure()));
297   loop.Run();
298 
299   ASSERT_TRUE(received.is_valid());
300 
301   // Verify that the message pipe handle is correctly passed.
302   const char kHello[] = "hello";
303   const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
304   EXPECT_EQ(MOJO_RESULT_OK,
305             WriteMessageRaw(mp.handle1.get(), kHello, kHelloSize, nullptr, 0,
306                             MOJO_WRITE_MESSAGE_FLAG_NONE));
307 
308   EXPECT_EQ(MOJO_RESULT_OK, Wait(received.get(), MOJO_HANDLE_SIGNAL_READABLE,
309                                  MOJO_DEADLINE_INDEFINITE, nullptr));
310 
311   char buffer[10] = {0};
312   uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
313   EXPECT_EQ(MOJO_RESULT_OK,
314             ReadMessageRaw(received.get(), buffer, &buffer_size, nullptr,
315                            nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
316   EXPECT_EQ(kHelloSize, buffer_size);
317   EXPECT_STREQ(kHello, buffer);
318 }
319 
ExpectEnumWithTraits(EnumWithTraitsImpl expected_value,const base::Closure & closure,EnumWithTraitsImpl value)320 void ExpectEnumWithTraits(EnumWithTraitsImpl expected_value,
321                           const base::Closure& closure,
322                           EnumWithTraitsImpl value) {
323   EXPECT_EQ(expected_value, value);
324   closure.Run();
325 }
326 
TEST_F(StructTraitsTest,EchoEnumWithTraits)327 TEST_F(StructTraitsTest, EchoEnumWithTraits) {
328   base::RunLoop loop;
329   TraitsTestServicePtr proxy = GetTraitsTestProxy();
330 
331   proxy->EchoEnumWithTraits(
332       EnumWithTraitsImpl::CUSTOM_VALUE_1,
333       base::Bind(&ExpectEnumWithTraits, EnumWithTraitsImpl::CUSTOM_VALUE_1,
334                  loop.QuitClosure()));
335   loop.Run();
336 }
337 
TEST_F(StructTraitsTest,SerializeStructWithTraits)338 TEST_F(StructTraitsTest, SerializeStructWithTraits) {
339   StructWithTraitsImpl input;
340   input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1);
341   input.set_bool(true);
342   input.set_uint32(7);
343   input.set_uint64(42);
344   input.set_string("hello world!");
345   input.get_mutable_string_array().assign({"hello", "world!"});
346   input.get_mutable_struct().value = 42;
347   input.get_mutable_struct_array().resize(2);
348   input.get_mutable_struct_array()[0].value = 1;
349   input.get_mutable_struct_array()[1].value = 2;
350   input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024);
351   input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048);
352 
353   mojo::Array<uint8_t> data = StructWithTraits::Serialize(&input);
354   StructWithTraitsImpl output;
355   ASSERT_TRUE(StructWithTraits::Deserialize(std::move(data), &output));
356 
357   EXPECT_EQ(input.get_enum(), output.get_enum());
358   EXPECT_EQ(input.get_bool(), output.get_bool());
359   EXPECT_EQ(input.get_uint32(), output.get_uint32());
360   EXPECT_EQ(input.get_uint64(), output.get_uint64());
361   EXPECT_EQ(input.get_string(), output.get_string());
362   EXPECT_EQ(input.get_string_array(), output.get_string_array());
363   EXPECT_EQ(input.get_struct(), output.get_struct());
364   EXPECT_EQ(input.get_struct_array(), output.get_struct_array());
365   EXPECT_EQ(input.get_struct_map(), output.get_struct_map());
366 }
367 
ExpectUniquePtr(int expected,const base::Closure & closure,std::unique_ptr<int> value)368 void ExpectUniquePtr(int expected,
369                      const base::Closure& closure,
370                      std::unique_ptr<int> value) {
371   EXPECT_EQ(expected, *value);
372   closure.Run();
373 }
374 
TEST_F(StructTraitsTest,TypemapUniquePtr)375 TEST_F(StructTraitsTest, TypemapUniquePtr) {
376   base::RunLoop loop;
377   TraitsTestServicePtr proxy = GetTraitsTestProxy();
378 
379   proxy->EchoStructWithTraitsForUniquePtrTest(
380       base::MakeUnique<int>(12345),
381       base::Bind(&ExpectUniquePtr, 12345, loop.QuitClosure()));
382   loop.Run();
383 }
384 
385 }  // namespace test
386 }  // namespace mojo
387