Home | History | Annotate | Download | only in tests
      1 // Copyright 2014 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 <stddef.h>
      6 #include <stdint.h>
      7 #include <algorithm>
      8 #include <ostream>
      9 #include <string>
     10 #include <utility>
     11 
     12 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace mojo {
     16 
     17 template <>
     18 struct TypeConverter<int32_t, sample::BarPtr> {
     19   static int32_t Convert(const sample::BarPtr& bar) {
     20     return static_cast<int32_t>(bar->alpha) << 16 |
     21            static_cast<int32_t>(bar->beta) << 8 |
     22            static_cast<int32_t>(bar->gamma);
     23   }
     24 };
     25 
     26 }  // namespace mojo
     27 
     28 namespace sample {
     29 namespace {
     30 
     31 // Set this variable to true to print the message in hex.
     32 bool g_dump_message_as_hex = false;
     33 
     34 // Set this variable to true to print the message in human readable form.
     35 bool g_dump_message_as_text = false;
     36 
     37 // Make a sample |Foo|.
     38 FooPtr MakeFoo() {
     39   std::string name("foopy");
     40 
     41   BarPtr bar(Bar::New());
     42   bar->alpha = 20;
     43   bar->beta = 40;
     44   bar->gamma = 60;
     45   bar->type = Bar::Type::VERTICAL;
     46 
     47   std::vector<BarPtr> extra_bars(3);
     48   for (size_t i = 0; i < extra_bars.size(); ++i) {
     49     Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL;
     50     BarPtr bar(Bar::New());
     51     uint8_t base = static_cast<uint8_t>(i * 100);
     52     bar->alpha = base;
     53     bar->beta = base + 20;
     54     bar->gamma = base + 40;
     55     bar->type = type;
     56     extra_bars[i] = std::move(bar);
     57   }
     58 
     59   std::vector<uint8_t> data(10);
     60   for (size_t i = 0; i < data.size(); ++i)
     61     data[i] = static_cast<uint8_t>(data.size() - i);
     62 
     63   std::vector<mojo::ScopedDataPipeConsumerHandle> input_streams(2);
     64   std::vector<mojo::ScopedDataPipeProducerHandle> output_streams(2);
     65   for (size_t i = 0; i < input_streams.size(); ++i) {
     66     MojoCreateDataPipeOptions options;
     67     options.struct_size = sizeof(MojoCreateDataPipeOptions);
     68     options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
     69     options.element_num_bytes = 1;
     70     options.capacity_num_bytes = 1024;
     71     mojo::ScopedDataPipeProducerHandle producer;
     72     mojo::ScopedDataPipeConsumerHandle consumer;
     73     mojo::CreateDataPipe(&options, &producer, &consumer);
     74     input_streams[i] = std::move(consumer);
     75     output_streams[i] = std::move(producer);
     76   }
     77 
     78   std::vector<std::vector<bool>> array_of_array_of_bools(2);
     79   for (size_t i = 0; i < 2; ++i) {
     80     std::vector<bool> array_of_bools(2);
     81     for (size_t j = 0; j < 2; ++j)
     82       array_of_bools[j] = j;
     83     array_of_array_of_bools[i] = std::move(array_of_bools);
     84   }
     85 
     86   mojo::MessagePipe pipe;
     87   FooPtr foo(Foo::New());
     88   foo->name = name;
     89   foo->x = 1;
     90   foo->y = 2;
     91   foo->a = false;
     92   foo->b = true;
     93   foo->c = false;
     94   foo->bar = std::move(bar);
     95   foo->extra_bars = std::move(extra_bars);
     96   foo->data = std::move(data);
     97   foo->source = std::move(pipe.handle1);
     98   foo->input_streams = std::move(input_streams);
     99   foo->output_streams = std::move(output_streams);
    100   foo->array_of_array_of_bools = std::move(array_of_array_of_bools);
    101 
    102   return foo;
    103 }
    104 
    105 // Check that the given |Foo| is identical to the one made by |MakeFoo()|.
    106 void CheckFoo(const Foo& foo) {
    107   const std::string kName("foopy");
    108   EXPECT_EQ(kName.size(), foo.name.size());
    109   for (size_t i = 0; i < std::min(kName.size(), foo.name.size()); i++) {
    110     // Test both |operator[]| and |at|.
    111     EXPECT_EQ(kName[i], foo.name.at(i)) << i;
    112     EXPECT_EQ(kName[i], foo.name[i]) << i;
    113   }
    114   EXPECT_EQ(kName, foo.name);
    115 
    116   EXPECT_EQ(1, foo.x);
    117   EXPECT_EQ(2, foo.y);
    118   EXPECT_FALSE(foo.a);
    119   EXPECT_TRUE(foo.b);
    120   EXPECT_FALSE(foo.c);
    121 
    122   EXPECT_EQ(20, foo.bar->alpha);
    123   EXPECT_EQ(40, foo.bar->beta);
    124   EXPECT_EQ(60, foo.bar->gamma);
    125   EXPECT_EQ(Bar::Type::VERTICAL, foo.bar->type);
    126 
    127   EXPECT_EQ(3u, foo.extra_bars->size());
    128   for (size_t i = 0; i < foo.extra_bars->size(); i++) {
    129     uint8_t base = static_cast<uint8_t>(i * 100);
    130     Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL;
    131     EXPECT_EQ(base, (*foo.extra_bars)[i]->alpha) << i;
    132     EXPECT_EQ(base + 20, (*foo.extra_bars)[i]->beta) << i;
    133     EXPECT_EQ(base + 40, (*foo.extra_bars)[i]->gamma) << i;
    134     EXPECT_EQ(type, (*foo.extra_bars)[i]->type) << i;
    135   }
    136 
    137   EXPECT_EQ(10u, foo.data->size());
    138   for (size_t i = 0; i < foo.data->size(); ++i) {
    139     EXPECT_EQ(static_cast<uint8_t>(foo.data->size() - i), (*foo.data)[i]) << i;
    140   }
    141 
    142   EXPECT_TRUE(foo.input_streams);
    143   EXPECT_EQ(2u, foo.input_streams->size());
    144 
    145   EXPECT_TRUE(foo.output_streams);
    146   EXPECT_EQ(2u, foo.output_streams->size());
    147 
    148   EXPECT_EQ(2u, foo.array_of_array_of_bools->size());
    149   for (size_t i = 0; i < foo.array_of_array_of_bools->size(); ++i) {
    150     EXPECT_EQ(2u, (*foo.array_of_array_of_bools)[i].size());
    151     for (size_t j = 0; j < (*foo.array_of_array_of_bools)[i].size(); ++j) {
    152       EXPECT_EQ(bool(j), (*foo.array_of_array_of_bools)[i][j]);
    153     }
    154   }
    155 }
    156 
    157 void PrintSpacer(int depth) {
    158   for (int i = 0; i < depth; ++i)
    159     std::cout << "   ";
    160 }
    161 
    162 void Print(int depth, const char* name, bool value) {
    163   PrintSpacer(depth);
    164   std::cout << name << ": " << (value ? "true" : "false") << std::endl;
    165 }
    166 
    167 void Print(int depth, const char* name, int32_t value) {
    168   PrintSpacer(depth);
    169   std::cout << name << ": " << value << std::endl;
    170 }
    171 
    172 void Print(int depth, const char* name, uint8_t value) {
    173   PrintSpacer(depth);
    174   std::cout << name << ": " << uint32_t(value) << std::endl;
    175 }
    176 
    177 template <typename H>
    178 void Print(int depth,
    179            const char* name,
    180            const mojo::ScopedHandleBase<H>& value) {
    181   PrintSpacer(depth);
    182   std::cout << name << ": 0x" << std::hex << value.get().value() << std::endl;
    183 }
    184 
    185 void Print(int depth, const char* name, const std::string& str) {
    186   PrintSpacer(depth);
    187   std::cout << name << ": \"" << str << "\"" << std::endl;
    188 }
    189 
    190 void Print(int depth, const char* name, const BarPtr& bar) {
    191   PrintSpacer(depth);
    192   std::cout << name << ":" << std::endl;
    193   if (!bar.is_null()) {
    194     ++depth;
    195     Print(depth, "alpha", bar->alpha);
    196     Print(depth, "beta", bar->beta);
    197     Print(depth, "gamma", bar->gamma);
    198     Print(depth, "packed", bar.To<int32_t>());
    199     --depth;
    200   }
    201 }
    202 
    203 template <typename T>
    204 void Print(int depth, const char* name, const std::vector<T>& array) {
    205   PrintSpacer(depth);
    206   std::cout << name << ":" << std::endl;
    207   ++depth;
    208   for (size_t i = 0; i < array.size(); ++i) {
    209     std::stringstream buf;
    210     buf << i;
    211     Print(depth, buf.str().data(), array.at(i));
    212   }
    213   --depth;
    214 }
    215 
    216 template <typename T>
    217 void Print(int depth,
    218            const char* name,
    219            const base::Optional<std::vector<T>>& array) {
    220   if (array)
    221     Print(depth, name, *array);
    222   else
    223     Print(depth, name, std::vector<T>());
    224 }
    225 
    226 void Print(int depth, const char* name, const FooPtr& foo) {
    227   PrintSpacer(depth);
    228   std::cout << name << ":" << std::endl;
    229   if (!foo.is_null()) {
    230     ++depth;
    231     Print(depth, "name", foo->name);
    232     Print(depth, "x", foo->x);
    233     Print(depth, "y", foo->y);
    234     Print(depth, "a", foo->a);
    235     Print(depth, "b", foo->b);
    236     Print(depth, "c", foo->c);
    237     Print(depth, "bar", foo->bar);
    238     Print(depth, "extra_bars", foo->extra_bars);
    239     Print(depth, "data", foo->data);
    240     Print(depth, "source", foo->source);
    241     Print(depth, "input_streams", foo->input_streams);
    242     Print(depth, "output_streams", foo->output_streams);
    243     Print(depth, "array_of_array_of_bools", foo->array_of_array_of_bools);
    244     --depth;
    245   }
    246 }
    247 
    248 void DumpHex(const uint8_t* bytes, uint32_t num_bytes) {
    249   for (uint32_t i = 0; i < num_bytes; ++i) {
    250     std::cout << std::setw(2) << std::setfill('0') << std::hex
    251               << uint32_t(bytes[i]);
    252 
    253     if (i % 16 == 15) {
    254       std::cout << std::endl;
    255       continue;
    256     }
    257 
    258     if (i % 2 == 1)
    259       std::cout << " ";
    260     if (i % 8 == 7)
    261       std::cout << " ";
    262   }
    263 }
    264 
    265 class ServiceImpl : public Service {
    266  public:
    267   void Frobinate(FooPtr foo,
    268                  BazOptions baz,
    269                  PortPtr port,
    270                  const Service::FrobinateCallback& callback) override {
    271     // Users code goes here to handle the incoming Frobinate message.
    272 
    273     // We mainly check that we're given the expected arguments.
    274     EXPECT_FALSE(foo.is_null());
    275     if (!foo.is_null())
    276       CheckFoo(*foo);
    277     EXPECT_EQ(BazOptions::EXTRA, baz);
    278 
    279     if (g_dump_message_as_text) {
    280       // Also dump the Foo structure and all of its members.
    281       std::cout << "Frobinate:" << std::endl;
    282       int depth = 1;
    283       Print(depth, "foo", foo);
    284       Print(depth, "baz", static_cast<int32_t>(baz));
    285       Print(depth, "port", port.get());
    286     }
    287     callback.Run(5);
    288   }
    289 
    290   void GetPort(mojo::InterfaceRequest<Port> port_request) override {}
    291 };
    292 
    293 class ServiceProxyImpl : public ServiceProxy {
    294  public:
    295   explicit ServiceProxyImpl(mojo::MessageReceiverWithResponder* receiver)
    296       : ServiceProxy(receiver) {}
    297 };
    298 
    299 class SimpleMessageReceiver : public mojo::MessageReceiverWithResponder {
    300  public:
    301   bool Accept(mojo::Message* message) override {
    302     // Imagine some IPC happened here.
    303 
    304     if (g_dump_message_as_hex) {
    305       DumpHex(reinterpret_cast<const uint8_t*>(message->data()),
    306               message->data_num_bytes());
    307     }
    308 
    309     // In the receiving process, an implementation of ServiceStub is known to
    310     // the system. It receives the incoming message.
    311     ServiceImpl impl;
    312 
    313     ServiceStub stub;
    314     stub.set_sink(&impl);
    315     return stub.Accept(message);
    316   }
    317 
    318   bool AcceptWithResponder(mojo::Message* message,
    319                            mojo::MessageReceiver* responder) override {
    320     return false;
    321   }
    322 };
    323 
    324 using BindingsSampleTest = testing::Test;
    325 
    326 TEST_F(BindingsSampleTest, Basic) {
    327   SimpleMessageReceiver receiver;
    328 
    329   // User has a proxy to a Service somehow.
    330   Service* service = new ServiceProxyImpl(&receiver);
    331 
    332   // User constructs a message to send.
    333 
    334   // Notice that it doesn't matter in what order the structs / arrays are
    335   // allocated. Here, the various members of Foo are allocated before Foo is
    336   // allocated.
    337 
    338   FooPtr foo = MakeFoo();
    339   CheckFoo(*foo);
    340 
    341   PortPtr port;
    342   service->Frobinate(std::move(foo), Service::BazOptions::EXTRA,
    343                      std::move(port), Service::FrobinateCallback());
    344 
    345   delete service;
    346 }
    347 
    348 TEST_F(BindingsSampleTest, DefaultValues) {
    349   DefaultsTestPtr defaults(DefaultsTest::New());
    350   EXPECT_EQ(-12, defaults->a0);
    351   EXPECT_EQ(kTwelve, defaults->a1);
    352   EXPECT_EQ(1234, defaults->a2);
    353   EXPECT_EQ(34567U, defaults->a3);
    354   EXPECT_EQ(123456, defaults->a4);
    355   EXPECT_EQ(3456789012U, defaults->a5);
    356   EXPECT_EQ(-111111111111LL, defaults->a6);
    357   EXPECT_EQ(9999999999999999999ULL, defaults->a7);
    358   EXPECT_EQ(0x12345, defaults->a8);
    359   EXPECT_EQ(-0x12345, defaults->a9);
    360   EXPECT_EQ(1234, defaults->a10);
    361   EXPECT_TRUE(defaults->a11);
    362   EXPECT_FALSE(defaults->a12);
    363   EXPECT_FLOAT_EQ(123.25f, defaults->a13);
    364   EXPECT_DOUBLE_EQ(1234567890.123, defaults->a14);
    365   EXPECT_DOUBLE_EQ(1E10, defaults->a15);
    366   EXPECT_DOUBLE_EQ(-1.2E+20, defaults->a16);
    367   EXPECT_DOUBLE_EQ(1.23E-20, defaults->a17);
    368   EXPECT_TRUE(defaults->a18.empty());
    369   EXPECT_TRUE(defaults->a19.empty());
    370   EXPECT_EQ(Bar::Type::BOTH, defaults->a20);
    371   EXPECT_TRUE(defaults->a21.is_null());
    372   ASSERT_FALSE(defaults->a22.is_null());
    373   EXPECT_EQ(imported::Shape::RECTANGLE, defaults->a22->shape);
    374   EXPECT_EQ(imported::Color::BLACK, defaults->a22->color);
    375   EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, defaults->a23);
    376   EXPECT_EQ(0x123456789, defaults->a24);
    377   EXPECT_EQ(-0x123456789, defaults->a25);
    378 }
    379 
    380 }  // namespace
    381 }  // namespace sample
    382