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 <string>
      6 #include <utility>
      7 
      8 #include "base/bind.h"
      9 #include "base/callback.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/run_loop.h"
     13 #include "mojo/public/cpp/bindings/binding_set.h"
     14 #include "mojo/public/cpp/bindings/interface_request.h"
     15 #include "mojo/public/cpp/bindings/tests/pickled_types_blink.h"
     16 #include "mojo/public/cpp/bindings/tests/pickled_types_chromium.h"
     17 #include "mojo/public/cpp/bindings/tests/variant_test_util.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(int foo,
     28                     int bar,
     29                     const base::Closure& callback,
     30                     const T& actual) {
     31   EXPECT_EQ(foo, actual.foo());
     32   EXPECT_EQ(bar, actual.bar());
     33   callback.Run();
     34 }
     35 
     36 template <typename T>
     37 base::Callback<void(const T&)> ExpectResult(const T& t,
     38                                             const base::Closure& callback) {
     39   return base::Bind(&DoExpectResult<T>, t.foo(), t.bar(), callback);
     40 }
     41 
     42 template <typename T>
     43 void DoFail(const std::string& reason, const T&) {
     44   EXPECT_TRUE(false) << reason;
     45 }
     46 
     47 template <typename T>
     48 base::Callback<void(const T&)> Fail(const std::string& reason) {
     49   return base::Bind(&DoFail<T>, reason);
     50 }
     51 
     52 template <typename T>
     53 void DoExpectEnumResult(T expected, const base::Closure& callback, T actual) {
     54   EXPECT_EQ(expected, actual);
     55   callback.Run();
     56 }
     57 
     58 template <typename T>
     59 base::Callback<void(T)> ExpectEnumResult(T t, const base::Closure& callback) {
     60   return base::Bind(&DoExpectEnumResult<T>, t, callback);
     61 }
     62 
     63 template <typename T>
     64 void DoEnumFail(const std::string& reason, T) {
     65   EXPECT_TRUE(false) << reason;
     66 }
     67 
     68 template <typename T>
     69 base::Callback<void(T)> EnumFail(const std::string& reason) {
     70   return base::Bind(&DoEnumFail<T>, reason);
     71 }
     72 
     73 template <typename T>
     74 void ExpectError(InterfacePtr<T>* proxy, const base::Closure& callback) {
     75   proxy->set_connection_error_handler(callback);
     76 }
     77 
     78 template <typename Func, typename Arg>
     79 void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); }
     80 
     81 template <typename Arg, typename Func>
     82 base::Callback<void(Arg)> BindSimpleLambda(Func func) {
     83   return base::Bind(&RunSimpleLambda<Func, Arg>, func);
     84 }
     85 
     86 // This implements the generated Chromium variant of PicklePasser.
     87 class ChromiumPicklePasserImpl : public PicklePasser {
     88  public:
     89   ChromiumPicklePasserImpl() {}
     90 
     91   // mojo::test::PicklePasser:
     92   void PassPickledStruct(const PickledStructChromium& pickle,
     93                          const PassPickledStructCallback& callback) override {
     94     callback.Run(pickle);
     95   }
     96 
     97   void PassPickledEnum(PickledEnumChromium pickle,
     98                        const PassPickledEnumCallback& callback) override {
     99     callback.Run(pickle);
    100   }
    101 
    102   void PassPickleContainer(
    103       PickleContainerPtr container,
    104       const PassPickleContainerCallback& callback) override {
    105     callback.Run(std::move(container));
    106   }
    107 
    108   void PassPickles(const std::vector<PickledStructChromium>& pickles,
    109                    const PassPicklesCallback& callback) override {
    110     callback.Run(pickles);
    111   }
    112 
    113   void PassPickleArrays(
    114       const std::vector<std::vector<PickledStructChromium>>& pickle_arrays,
    115       const PassPickleArraysCallback& callback) override {
    116     callback.Run(pickle_arrays);
    117   }
    118 };
    119 
    120 // This implements the generated Blink variant of PicklePasser.
    121 class BlinkPicklePasserImpl : public blink::PicklePasser {
    122  public:
    123   BlinkPicklePasserImpl() {}
    124 
    125   // mojo::test::blink::PicklePasser:
    126   void PassPickledStruct(const PickledStructBlink& pickle,
    127                          const PassPickledStructCallback& callback) override {
    128     callback.Run(pickle);
    129   }
    130 
    131   void PassPickledEnum(PickledEnumBlink pickle,
    132                        const PassPickledEnumCallback& callback) override {
    133     callback.Run(pickle);
    134   }
    135 
    136   void PassPickleContainer(
    137       blink::PickleContainerPtr container,
    138       const PassPickleContainerCallback& callback) override {
    139     callback.Run(std::move(container));
    140   }
    141 
    142   void PassPickles(const WTF::Vector<PickledStructBlink>& pickles,
    143                    const PassPicklesCallback& callback) override {
    144     callback.Run(pickles);
    145   }
    146 
    147   void PassPickleArrays(
    148       const WTF::Vector<WTF::Vector<PickledStructBlink>>& pickle_arrays,
    149       const PassPickleArraysCallback& callback) override {
    150     callback.Run(pickle_arrays);
    151   }
    152 };
    153 
    154 // A test which runs both Chromium and Blink implementations of the
    155 // PicklePasser service.
    156 class PickleTest : public testing::Test {
    157  public:
    158   PickleTest() {}
    159 
    160   template <typename ProxyType = PicklePasser>
    161   InterfacePtr<ProxyType> ConnectToChromiumService() {
    162     InterfacePtr<ProxyType> proxy;
    163     InterfaceRequest<ProxyType> request = GetProxy(&proxy);
    164     chromium_bindings_.AddBinding(
    165         &chromium_service_,
    166         ConvertInterfaceRequest<PicklePasser>(std::move(request)));
    167     return proxy;
    168   }
    169 
    170   template <typename ProxyType = blink::PicklePasser>
    171   InterfacePtr<ProxyType> ConnectToBlinkService() {
    172     InterfacePtr<ProxyType> proxy;
    173     InterfaceRequest<ProxyType> request = GetProxy(&proxy);
    174     blink_bindings_.AddBinding(
    175         &blink_service_,
    176         ConvertInterfaceRequest<blink::PicklePasser>(std::move(request)));
    177     return proxy;
    178   }
    179 
    180  private:
    181   base::MessageLoop loop_;
    182   ChromiumPicklePasserImpl chromium_service_;
    183   BindingSet<PicklePasser> chromium_bindings_;
    184   BlinkPicklePasserImpl blink_service_;
    185   BindingSet<blink::PicklePasser> blink_bindings_;
    186 };
    187 
    188 }  // namespace
    189 
    190 TEST_F(PickleTest, ChromiumProxyToChromiumService) {
    191   auto chromium_proxy = ConnectToChromiumService();
    192   {
    193     base::RunLoop loop;
    194     chromium_proxy->PassPickledStruct(
    195         PickledStructChromium(1, 2),
    196         ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure()));
    197     loop.Run();
    198   }
    199   {
    200     base::RunLoop loop;
    201     chromium_proxy->PassPickledStruct(
    202         PickledStructChromium(4, 5),
    203         ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure()));
    204     loop.Run();
    205   }
    206 
    207   {
    208     base::RunLoop loop;
    209     chromium_proxy->PassPickledEnum(
    210         PickledEnumChromium::VALUE_1,
    211         ExpectEnumResult(PickledEnumChromium::VALUE_1, loop.QuitClosure()));
    212     loop.Run();
    213   }
    214 }
    215 
    216 TEST_F(PickleTest, ChromiumProxyToBlinkService) {
    217   auto chromium_proxy = ConnectToBlinkService<PicklePasser>();
    218   {
    219     base::RunLoop loop;
    220     chromium_proxy->PassPickledStruct(
    221         PickledStructChromium(1, 2),
    222         ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure()));
    223     loop.Run();
    224   }
    225   {
    226     base::RunLoop loop;
    227     chromium_proxy->PassPickledStruct(
    228         PickledStructChromium(4, 5),
    229         ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure()));
    230     loop.Run();
    231   }
    232   // The Blink service should drop our connection because the
    233   // PickledStructBlink ParamTraits deserializer rejects negative values.
    234   {
    235     base::RunLoop loop;
    236     chromium_proxy->PassPickledStruct(
    237         PickledStructChromium(-1, -1),
    238         Fail<PickledStructChromium>("Blink service should reject this."));
    239     ExpectError(&chromium_proxy, loop.QuitClosure());
    240     loop.Run();
    241   }
    242 
    243   chromium_proxy = ConnectToBlinkService<PicklePasser>();
    244   {
    245     base::RunLoop loop;
    246     chromium_proxy->PassPickledEnum(
    247         PickledEnumChromium::VALUE_0,
    248         ExpectEnumResult(PickledEnumChromium::VALUE_0, loop.QuitClosure()));
    249     loop.Run();
    250   }
    251 
    252   // The Blink service should drop our connection because the
    253   // PickledEnumBlink ParamTraits deserializer rejects this value.
    254   {
    255     base::RunLoop loop;
    256     chromium_proxy->PassPickledEnum(
    257         PickledEnumChromium::VALUE_2,
    258         EnumFail<PickledEnumChromium>("Blink service should reject this."));
    259     ExpectError(&chromium_proxy, loop.QuitClosure());
    260     loop.Run();
    261   }
    262 }
    263 
    264 TEST_F(PickleTest, BlinkProxyToBlinkService) {
    265   auto blink_proxy = ConnectToBlinkService();
    266   {
    267     base::RunLoop loop;
    268     blink_proxy->PassPickledStruct(
    269         PickledStructBlink(1, 1),
    270         ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure()));
    271     loop.Run();
    272   }
    273 
    274   {
    275     base::RunLoop loop;
    276     blink_proxy->PassPickledEnum(
    277         PickledEnumBlink::VALUE_0,
    278         ExpectEnumResult(PickledEnumBlink::VALUE_0, loop.QuitClosure()));
    279     loop.Run();
    280   }
    281 }
    282 
    283 TEST_F(PickleTest, BlinkProxyToChromiumService) {
    284   auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>();
    285   {
    286     base::RunLoop loop;
    287     blink_proxy->PassPickledStruct(
    288         PickledStructBlink(1, 1),
    289         ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure()));
    290     loop.Run();
    291   }
    292 
    293   {
    294     base::RunLoop loop;
    295     blink_proxy->PassPickledEnum(
    296         PickledEnumBlink::VALUE_1,
    297         ExpectEnumResult(PickledEnumBlink::VALUE_1, loop.QuitClosure()));
    298     loop.Run();
    299   }
    300 }
    301 
    302 TEST_F(PickleTest, PickleArray) {
    303   auto proxy = ConnectToChromiumService();
    304   auto pickles = Array<PickledStructChromium>::New(2);
    305   pickles[0].set_foo(1);
    306   pickles[0].set_bar(2);
    307   pickles[0].set_baz(100);
    308   pickles[1].set_foo(3);
    309   pickles[1].set_bar(4);
    310   pickles[1].set_baz(100);
    311   {
    312     base::RunLoop run_loop;
    313     // Verify that the array of pickled structs can be serialized and
    314     // deserialized intact. This ensures that the ParamTraits are actually used
    315     // rather than doing a byte-for-byte copy of the element data, beacuse the
    316     // |baz| field should never be serialized.
    317     proxy->PassPickles(
    318         std::move(pickles),
    319         BindSimpleLambda<const std::vector<PickledStructChromium>&>(
    320             [&](const std::vector<PickledStructChromium>& passed) {
    321               ASSERT_EQ(2u, passed.size());
    322               EXPECT_EQ(1, passed[0].foo());
    323               EXPECT_EQ(2, passed[0].bar());
    324               EXPECT_EQ(0, passed[0].baz());
    325               EXPECT_EQ(3, passed[1].foo());
    326               EXPECT_EQ(4, passed[1].bar());
    327               EXPECT_EQ(0, passed[1].baz());
    328               run_loop.Quit();
    329             }));
    330     run_loop.Run();
    331   }
    332 }
    333 
    334 TEST_F(PickleTest, PickleArrayArray) {
    335   auto proxy = ConnectToChromiumService();
    336   auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2);
    337   for (size_t i = 0; i < 2; ++i)
    338     pickle_arrays[i] = std::vector<PickledStructChromium>(2);
    339 
    340   pickle_arrays[0][0].set_foo(1);
    341   pickle_arrays[0][0].set_bar(2);
    342   pickle_arrays[0][0].set_baz(100);
    343   pickle_arrays[0][1].set_foo(3);
    344   pickle_arrays[0][1].set_bar(4);
    345   pickle_arrays[0][1].set_baz(100);
    346   pickle_arrays[1][0].set_foo(5);
    347   pickle_arrays[1][0].set_bar(6);
    348   pickle_arrays[1][0].set_baz(100);
    349   pickle_arrays[1][1].set_foo(7);
    350   pickle_arrays[1][1].set_bar(8);
    351   pickle_arrays[1][1].set_baz(100);
    352   {
    353     base::RunLoop run_loop;
    354     // Verify that the array-of-arrays serializes and deserializes properly.
    355     proxy->PassPickleArrays(
    356         pickle_arrays,
    357         BindSimpleLambda<
    358             const std::vector<std::vector<PickledStructChromium>>&>(
    359             [&](const std::vector<std::vector<PickledStructChromium>>& passed) {
    360               ASSERT_EQ(2u, passed.size());
    361               ASSERT_EQ(2u, passed[0].size());
    362               ASSERT_EQ(2u, passed[1].size());
    363               EXPECT_EQ(1, passed[0][0].foo());
    364               EXPECT_EQ(2, passed[0][0].bar());
    365               EXPECT_EQ(0, passed[0][0].baz());
    366               EXPECT_EQ(3, passed[0][1].foo());
    367               EXPECT_EQ(4, passed[0][1].bar());
    368               EXPECT_EQ(0, passed[0][1].baz());
    369               EXPECT_EQ(5, passed[1][0].foo());
    370               EXPECT_EQ(6, passed[1][0].bar());
    371               EXPECT_EQ(0, passed[1][0].baz());
    372               EXPECT_EQ(7, passed[1][1].foo());
    373               EXPECT_EQ(8, passed[1][1].bar());
    374               EXPECT_EQ(0, passed[1][1].baz());
    375               run_loop.Quit();
    376             }));
    377     run_loop.Run();
    378   }
    379 }
    380 
    381 TEST_F(PickleTest, PickleContainer) {
    382   auto proxy = ConnectToChromiumService();
    383   PickleContainerPtr pickle_container = PickleContainer::New();
    384   pickle_container->f_struct.set_foo(42);
    385   pickle_container->f_struct.set_bar(43);
    386   pickle_container->f_struct.set_baz(44);
    387   pickle_container->f_enum = PickledEnumChromium::VALUE_1;
    388   EXPECT_TRUE(pickle_container.Equals(pickle_container));
    389   EXPECT_FALSE(pickle_container.Equals(PickleContainer::New()));
    390   {
    391     base::RunLoop run_loop;
    392     proxy->PassPickleContainer(std::move(pickle_container),
    393                                BindSimpleLambda<PickleContainerPtr>(
    394                                    [&](PickleContainerPtr passed) {
    395                                      ASSERT_FALSE(passed.is_null());
    396                                      EXPECT_EQ(42, passed->f_struct.foo());
    397                                      EXPECT_EQ(43, passed->f_struct.bar());
    398                                      EXPECT_EQ(0, passed->f_struct.baz());
    399                                      EXPECT_EQ(PickledEnumChromium::VALUE_1,
    400                                                passed->f_enum);
    401                                      run_loop.Quit();
    402                                    }));
    403     run_loop.Run();
    404   }
    405 }
    406 
    407 }  // namespace test
    408 }  // namespace mojo
    409