Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / public / cpp / bindings / tests / sample_service_unittest.cc
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 <algorithm>
6 #include <ostream>
7 #include <string>
8
9 #include "mojo/public/cpp/bindings/allocation_scope.h"
10 #include "mojo/public/cpp/environment/environment.h"
11 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace mojo {
15
16 template <>
17 class TypeConverter<sample::Bar, int32_t> {
18  public:
19   static int32_t ConvertTo(const sample::Bar& 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   MOJO_ALLOW_IMPLICIT_TYPE_CONVERSION();
26 };
27
28 }  // namespace mojo
29
30 namespace sample {
31 namespace {
32
33 // Set this variable to true to print the message in hex.
34 bool g_dump_message_as_hex = false;
35
36 // Set this variable to true to print the message in human readable form.
37 bool g_dump_message_as_text = false;
38
39 // Make a sample |Foo|.
40 Foo MakeFoo() {
41   mojo::String name("foopy");
42
43   Bar::Builder bar;
44   bar.set_alpha(20);
45   bar.set_beta(40);
46   bar.set_gamma(60);
47   bar.set_type(Bar::TYPE_VERTICAL);
48
49   mojo::Array<Bar>::Builder extra_bars(3);
50   for (size_t i = 0; i < extra_bars.size(); ++i) {
51     Bar::Type type = i % 2 == 0 ? Bar::TYPE_VERTICAL : Bar::TYPE_HORIZONTAL;
52     Bar::Builder bar;
53     uint8_t base = static_cast<uint8_t>(i * 100);
54     bar.set_alpha(base);
55     bar.set_beta(base + 20);
56     bar.set_gamma(base + 40);
57     bar.set_type(type);
58     extra_bars[i] = bar.Finish();
59   }
60
61   mojo::Array<uint8_t>::Builder data(10);
62   for (size_t i = 0; i < data.size(); ++i)
63     data[i] = static_cast<uint8_t>(data.size() - i);
64
65   mojo::Array<mojo::DataPipeConsumerHandle>::Builder input_streams(2);
66   mojo::Array<mojo::DataPipeProducerHandle>::Builder output_streams(2);
67   for (size_t i = 0; i < input_streams.size(); ++i) {
68     MojoCreateDataPipeOptions options;
69     options.struct_size = sizeof(MojoCreateDataPipeOptions);
70     options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
71     options.element_num_bytes = 1;
72     options.capacity_num_bytes = 1024;
73     mojo::ScopedDataPipeProducerHandle producer;
74     mojo::ScopedDataPipeConsumerHandle consumer;
75     mojo::CreateDataPipe(&options, &producer, &consumer);
76     input_streams[i] = consumer.Pass();
77     output_streams[i] = producer.Pass();
78   }
79
80   mojo::Array<mojo::Array<bool> >::Builder array_of_array_of_bools(2);
81   for (size_t i = 0; i < 2; ++i) {
82     mojo::Array<bool>::Builder array_of_bools(2);
83     for (size_t j = 0; j < 2; ++j) {
84       array_of_bools[j] = j;
85     }
86     array_of_array_of_bools[i] = array_of_bools.Finish();
87   }
88
89   mojo::ScopedMessagePipeHandle pipe0, pipe1;
90   mojo::CreateMessagePipe(&pipe0, &pipe1);
91
92   Foo::Builder foo;
93   foo.set_name(name);
94   foo.set_x(1);
95   foo.set_y(2);
96   foo.set_a(false);
97   foo.set_b(true);
98   foo.set_c(false);
99   foo.set_bar(bar.Finish());
100   foo.set_extra_bars(extra_bars.Finish());
101   foo.set_data(data.Finish());
102   foo.set_source(pipe1.Pass());
103   foo.set_input_streams(input_streams.Finish());
104   foo.set_output_streams(output_streams.Finish());
105   foo.set_array_of_array_of_bools(array_of_array_of_bools.Finish());
106
107   return foo.Finish();
108 }
109
110 // Check that the given |Foo| is identical to the one made by |MakeFoo()|.
111 void CheckFoo(const Foo& foo) {
112   const std::string kName("foopy");
113   ASSERT_FALSE(foo.name().is_null());
114   EXPECT_EQ(kName.size(), foo.name().size());
115   for (size_t i = 0; i < std::min(kName.size(), foo.name().size()); i++) {
116     // Test both |operator[]| and |at|.
117     EXPECT_EQ(kName[i], foo.name().at(i)) << i;
118     EXPECT_EQ(kName[i], foo.name()[i]) << i;
119   }
120   EXPECT_EQ(kName, foo.name().To<std::string>());
121
122   EXPECT_EQ(1, foo.x());
123   EXPECT_EQ(2, foo.y());
124   EXPECT_FALSE(foo.a());
125   EXPECT_TRUE(foo.b());
126   EXPECT_FALSE(foo.c());
127
128   EXPECT_EQ(20, foo.bar().alpha());
129   EXPECT_EQ(40, foo.bar().beta());
130   EXPECT_EQ(60, foo.bar().gamma());
131   EXPECT_EQ(Bar::TYPE_VERTICAL, foo.bar().type());
132
133   EXPECT_EQ(3u, foo.extra_bars().size());
134   for (size_t i = 0; i < foo.extra_bars().size(); i++) {
135     uint8_t base = static_cast<uint8_t>(i * 100);
136     Bar::Type type = i % 2 == 0 ? Bar::TYPE_VERTICAL : Bar::TYPE_HORIZONTAL;
137     EXPECT_EQ(base, foo.extra_bars()[i].alpha()) << i;
138     EXPECT_EQ(base + 20, foo.extra_bars()[i].beta()) << i;
139     EXPECT_EQ(base + 40, foo.extra_bars()[i].gamma()) << i;
140     EXPECT_EQ(type, foo.extra_bars()[i].type()) << i;
141   }
142
143   EXPECT_EQ(10u, foo.data().size());
144   for (size_t i = 0; i < foo.data().size(); ++i) {
145     EXPECT_EQ(static_cast<uint8_t>(foo.data().size() - i), foo.data()[i]) << i;
146   }
147
148   EXPECT_FALSE(foo.input_streams().is_null());
149   EXPECT_EQ(2u, foo.input_streams().size());
150
151   EXPECT_FALSE(foo.output_streams().is_null());
152   EXPECT_EQ(2u, foo.output_streams().size());
153
154   EXPECT_EQ(2u, foo.array_of_array_of_bools().size());
155   for (size_t i = 0; i < foo.array_of_array_of_bools().size(); ++i) {
156     EXPECT_EQ(2u, foo.array_of_array_of_bools()[i].size());
157     for (size_t j = 0; j < foo.array_of_array_of_bools()[i].size(); ++j) {
158       EXPECT_EQ(bool(j), foo.array_of_array_of_bools()[i][j]);
159     }
160   }
161 }
162
163 void PrintSpacer(int depth) {
164   for (int i = 0; i < depth; ++i)
165     std::cout << "   ";
166 }
167
168 void Print(int depth, const char* name, bool value) {
169   PrintSpacer(depth);
170   std::cout << name << ": " << (value ? "true" : "false") << std::endl;
171 }
172
173 void Print(int depth, const char* name, int32_t value) {
174   PrintSpacer(depth);
175   std::cout << name << ": " << value << std::endl;
176 }
177
178 void Print(int depth, const char* name, uint8_t value) {
179   PrintSpacer(depth);
180   std::cout << name << ": " << uint32_t(value) << std::endl;
181 }
182
183 void Print(int depth, const char* name, mojo::Handle value) {
184   PrintSpacer(depth);
185   std::cout << name << ": 0x" << std::hex << value.value() << std::endl;
186 }
187
188 void Print(int depth, const char* name, const mojo::String& str) {
189   std::string s = str.To<std::string>();
190   PrintSpacer(depth);
191   std::cout << name << ": \"" << str.To<std::string>() << "\"" << std::endl;
192 }
193
194 void Print(int depth, const char* name, const Bar& bar) {
195   PrintSpacer(depth);
196   std::cout << name << ":" << std::endl;
197   if (!bar.is_null()) {
198     ++depth;
199     Print(depth, "alpha", bar.alpha());
200     Print(depth, "beta", bar.beta());
201     Print(depth, "gamma", bar.gamma());
202     Print(depth, "packed", bar.To<int32_t>());
203     --depth;
204   }
205 }
206
207 template <typename T>
208 void Print(int depth, const char* name,
209                   const mojo::Passable<T>& passable) {
210   Print(depth, name, passable.get());
211 }
212
213 template <typename T>
214 void Print(int depth, const char* name, const mojo::Array<T>& array) {
215   PrintSpacer(depth);
216   std::cout << name << ":" << std::endl;
217   if (!array.is_null()) {
218     ++depth;
219     for (size_t i = 0; i < array.size(); ++i) {
220       std::stringstream buf;
221       buf << i;
222       Print(depth, buf.str().data(), array.at(i));
223     }
224     --depth;
225   }
226 }
227
228 void Print(int depth, const char* name, const Foo& foo) {
229   PrintSpacer(depth);
230   std::cout << name << ":" << std::endl;
231   if (!foo.is_null()) {
232     ++depth;
233     Print(depth, "name", foo.name());
234     Print(depth, "x", foo.x());
235     Print(depth, "y", foo.y());
236     Print(depth, "a", foo.a());
237     Print(depth, "b", foo.b());
238     Print(depth, "c", foo.c());
239     Print(depth, "bar", foo.bar());
240     Print(depth, "extra_bars", foo.extra_bars());
241     Print(depth, "data", foo.data());
242     Print(depth, "source", foo.source().get());
243     Print(depth, "input_streams", foo.input_streams());
244     Print(depth, "output_streams", foo.output_streams());
245     Print(depth, "array_of_array_of_bools", foo.array_of_array_of_bools());
246     --depth;
247   }
248 }
249
250 void DumpHex(const uint8_t* bytes, uint32_t num_bytes) {
251   for (uint32_t i = 0; i < num_bytes; ++i) {
252     std::cout << std::setw(2) << std::setfill('0') << std::hex <<
253         uint32_t(bytes[i]);
254
255     if (i % 16 == 15) {
256       std::cout << std::endl;
257       continue;
258     }
259
260     if (i % 2 == 1)
261       std::cout << " ";
262     if (i % 8 == 7)
263       std::cout << " ";
264   }
265 }
266
267 class ServiceImpl : public Service {
268  public:
269   ServiceImpl() : client_(NULL) {
270   }
271
272   virtual void SetClient(ServiceClient* client) MOJO_OVERRIDE {
273     client_ = client;
274   }
275
276   virtual void Frobinate(const Foo& foo, BazOptions baz, PortPtr port)
277       MOJO_OVERRIDE {
278     // Users code goes here to handle the incoming Frobinate message.
279
280     // We mainly check that we're given the expected arguments.
281     CheckFoo(foo);
282     EXPECT_EQ(BAZ_EXTRA, baz);
283
284     if (g_dump_message_as_text) {
285       // Also dump the Foo structure and all of its members.
286       std::cout << "Frobinate:" << std::endl;
287       int depth = 1;
288       Print(depth, "foo", foo);
289       Print(depth, "baz", baz);
290       Print(depth, "port", port.get());
291     }
292   }
293
294  private:
295   ServiceClient* client_;
296 };
297
298 class ServiceProxyImpl : public ServiceProxy {
299  public:
300   explicit ServiceProxyImpl(mojo::MessageReceiver* receiver)
301       : ServiceProxy(receiver) {
302   }
303
304   virtual void SetClient(ServiceClient* client) MOJO_OVERRIDE {
305     assert(false);
306   }
307 };
308
309 class SimpleMessageReceiver : public mojo::MessageReceiver {
310  public:
311   virtual bool Accept(mojo::Message* message) MOJO_OVERRIDE {
312     // Imagine some IPC happened here.
313
314     if (g_dump_message_as_hex) {
315       DumpHex(reinterpret_cast<const uint8_t*>(message->data()),
316               message->data_num_bytes());
317     }
318
319     // In the receiving process, an implementation of ServiceStub is known to
320     // the system. It receives the incoming message.
321     ServiceImpl impl;
322
323     ServiceStub stub;
324     stub.set_sink(&impl);
325     return stub.Accept(message);
326   }
327
328   virtual bool AcceptWithResponder(mojo::Message* message,
329                                    mojo::MessageReceiver* responder)
330                                        MOJO_OVERRIDE {
331     return false;
332   }
333 };
334
335 TEST(BindingsSampleTest, Basic) {
336   mojo::Environment env;
337   SimpleMessageReceiver receiver;
338
339   // User has a proxy to a Service somehow.
340   Service* service = new ServiceProxyImpl(&receiver);
341
342   // User constructs a message to send.
343
344   // Notice that it doesn't matter in what order the structs / arrays are
345   // allocated. Here, the various members of Foo are allocated before Foo is
346   // allocated.
347
348   mojo::AllocationScope scope;
349
350   Foo foo = MakeFoo();
351   CheckFoo(foo);
352
353   PortPtr port;
354   service->Frobinate(foo, Service::BAZ_EXTRA, port.Pass());
355 }
356
357 TEST(BindingsSampleTest, DefaultValues) {
358   mojo::Environment env;
359   SimpleMessageReceiver receiver;
360   mojo::AllocationScope scope;
361
362   Bar bar = Bar::Builder().Finish();
363   EXPECT_EQ(255, bar.alpha());
364
365   Foo foo = Foo::Builder().Finish();
366   ASSERT_FALSE(foo.name().is_null());
367   EXPECT_EQ("Fooby", foo.name().To<std::string>());
368   EXPECT_TRUE(foo.a());
369   EXPECT_EQ(3u, foo.data().size());
370   EXPECT_EQ(1, foo.data()[0]);
371   EXPECT_EQ(2, foo.data()[1]);
372   EXPECT_EQ(3, foo.data()[2]);
373
374   DefaultsTestInner inner = DefaultsTestInner::Builder().Finish();
375   EXPECT_EQ(1u, inner.names().size());
376   EXPECT_EQ("Jim", inner.names()[0].To<std::string>());
377   EXPECT_EQ(6*12, inner.height());
378
379   DefaultsTest full = DefaultsTest::Builder().Finish();
380   EXPECT_EQ(1u, full.people().size());
381   EXPECT_EQ(32, full.people()[0].age());
382   EXPECT_EQ(2u, full.people()[0].names().size());
383   EXPECT_EQ("Bob", full.people()[0].names()[0].To<std::string>());
384   EXPECT_EQ("Bobby", full.people()[0].names()[1].To<std::string>());
385   EXPECT_EQ(6*12, full.people()[0].height());
386
387   EXPECT_EQ(7, full.point().x());
388   EXPECT_EQ(15, full.point().y());
389
390   EXPECT_EQ(1u, full.shape_masks().size());
391   EXPECT_EQ(1 << imported::SHAPE_RECTANGLE, full.shape_masks()[0]);
392
393   EXPECT_EQ(imported::SHAPE_CIRCLE, full.thing().shape());
394   EXPECT_EQ(imported::COLOR_BLACK, full.thing().color());
395 }
396
397 }  // namespace
398 }  // namespace sample