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