Home | History | Annotate | Download | only in tests
      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>
     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>
     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>
     44 void DoFail(const std::string& reason, const T&) {
     45   EXPECT_TRUE(false) << reason;
     46 }
     47 
     48 template <typename T>
     49 base::Callback<void(const T&)> Fail(const std::string& reason) {
     50   return base::Bind(&DoFail<T>, reason);
     51 }
     52 
     53 template <typename T>
     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:
     61   ChromiumRectServiceImpl() {}
     62 
     63   // mojo::test::RectService:
     64   void AddRect(const RectChromium& r) override {
     65     if (r.GetArea() > largest_rect_.GetArea())
     66       largest_rect_ = r;
     67   }
     68 
     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:
     80   BlinkRectServiceImpl() {}
     81 
     82   // mojo::test::blink::RectService:
     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 
     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:
    104   StructTraitsTest() {}
    105 
    106  protected:
    107   void BindToChromiumService(RectServiceRequest request) {
    108     chromium_bindings_.AddBinding(&chromium_service_, std::move(request));
    109   }
    110   void BindToChromiumService(blink::RectServiceRequest request) {
    111     chromium_bindings_.AddBinding(
    112         &chromium_service_,
    113         ConvertInterfaceRequest<RectService>(std::move(request)));
    114   }
    115 
    116   void BindToBlinkService(blink::RectServiceRequest request) {
    117     blink_bindings_.AddBinding(&blink_service_, std::move(request));
    118   }
    119   void BindToBlinkService(RectServiceRequest request) {
    120     blink_bindings_.AddBinding(
    121         &blink_service_,
    122         ConvertInterfaceRequest<blink::RectService>(std::move(request)));
    123   }
    124 
    125   TraitsTestServicePtr GetTraitsTestProxy() {
    126     return traits_test_bindings_.CreateInterfacePtrAndBind(this);
    127   }
    128 
    129  private:
    130   // TraitsTestService:
    131   void EchoStructWithTraits(
    132       const StructWithTraitsImpl& s,
    133       const EchoStructWithTraitsCallback& callback) override {
    134     callback.Run(s);
    135   }
    136 
    137   void EchoPassByValueStructWithTraits(
    138       PassByValueStructWithTraitsImpl s,
    139       const EchoPassByValueStructWithTraitsCallback& callback) override {
    140     callback.Run(std::move(s));
    141   }
    142 
    143   void EchoEnumWithTraits(EnumWithTraitsImpl e,
    144                           const EchoEnumWithTraitsCallback& callback) override {
    145     callback.Run(e);
    146   }
    147 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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