OLD | NEW |
| (Empty) |
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/environment/environment.h" | |
10 #include "mojo/public/cpp/system/macros.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 struct TypeConverter<int32_t, sample::BarPtr> { | |
18 static int32_t Convert(const sample::BarPtr& bar) { | |
19 return static_cast<int32_t>(bar->alpha) << 16 | | |
20 static_cast<int32_t>(bar->beta) << 8 | | |
21 static_cast<int32_t>(bar->gamma); | |
22 } | |
23 }; | |
24 | |
25 } // namespace mojo | |
26 | |
27 namespace sample { | |
28 namespace { | |
29 | |
30 // Set this variable to true to print the message in hex. | |
31 bool g_dump_message_as_hex = false; | |
32 | |
33 // Set this variable to true to print the message in human readable form. | |
34 bool g_dump_message_as_text = false; | |
35 | |
36 // Make a sample |Foo|. | |
37 FooPtr MakeFoo() { | |
38 mojo::String name("foopy"); | |
39 | |
40 BarPtr bar(Bar::New()); | |
41 bar->alpha = 20; | |
42 bar->beta = 40; | |
43 bar->gamma = 60; | |
44 bar->type = Bar::TYPE_VERTICAL; | |
45 | |
46 mojo::Array<BarPtr> extra_bars(3); | |
47 for (size_t i = 0; i < extra_bars.size(); ++i) { | |
48 Bar::Type type = i % 2 == 0 ? Bar::TYPE_VERTICAL : Bar::TYPE_HORIZONTAL; | |
49 BarPtr bar(Bar::New()); | |
50 uint8_t base = static_cast<uint8_t>(i * 100); | |
51 bar->alpha = base; | |
52 bar->beta = base + 20; | |
53 bar->gamma = base + 40; | |
54 bar->type = type; | |
55 extra_bars[i] = bar.Pass(); | |
56 } | |
57 | |
58 mojo::Array<uint8_t> data(10); | |
59 for (size_t i = 0; i < data.size(); ++i) | |
60 data[i] = static_cast<uint8_t>(data.size() - i); | |
61 | |
62 mojo::Array<mojo::ScopedDataPipeConsumerHandle> input_streams(2); | |
63 mojo::Array<mojo::ScopedDataPipeProducerHandle> output_streams(2); | |
64 for (size_t i = 0; i < input_streams.size(); ++i) { | |
65 MojoCreateDataPipeOptions options; | |
66 options.struct_size = sizeof(MojoCreateDataPipeOptions); | |
67 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
68 options.element_num_bytes = 1; | |
69 options.capacity_num_bytes = 1024; | |
70 mojo::ScopedDataPipeProducerHandle producer; | |
71 mojo::ScopedDataPipeConsumerHandle consumer; | |
72 mojo::CreateDataPipe(&options, &producer, &consumer); | |
73 input_streams[i] = consumer.Pass(); | |
74 output_streams[i] = producer.Pass(); | |
75 } | |
76 | |
77 mojo::Array<mojo::Array<bool>> array_of_array_of_bools(2); | |
78 for (size_t i = 0; i < 2; ++i) { | |
79 mojo::Array<bool> array_of_bools(2); | |
80 for (size_t j = 0; j < 2; ++j) | |
81 array_of_bools[j] = j; | |
82 array_of_array_of_bools[i] = array_of_bools.Pass(); | |
83 } | |
84 | |
85 mojo::MessagePipe pipe; | |
86 FooPtr foo(Foo::New()); | |
87 foo->name = name; | |
88 foo->x = 1; | |
89 foo->y = 2; | |
90 foo->a = false; | |
91 foo->b = true; | |
92 foo->c = false; | |
93 foo->bar = bar.Pass(); | |
94 foo->extra_bars = extra_bars.Pass(); | |
95 foo->data = data.Pass(); | |
96 foo->source = pipe.handle1.Pass(); | |
97 foo->input_streams = input_streams.Pass(); | |
98 foo->output_streams = output_streams.Pass(); | |
99 foo->array_of_array_of_bools = array_of_array_of_bools.Pass(); | |
100 | |
101 return foo.Pass(); | |
102 } | |
103 | |
104 // Check that the given |Foo| is identical to the one made by |MakeFoo()|. | |
105 void CheckFoo(const Foo& foo) { | |
106 const std::string kName("foopy"); | |
107 ASSERT_FALSE(foo.name.is_null()); | |
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.get()); | |
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_FALSE(foo.input_streams.is_null()); | |
143 EXPECT_EQ(2u, foo.input_streams.size()); | |
144 | |
145 EXPECT_FALSE(foo.output_streams.is_null()); | |
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 mojo::String& str) { | |
186 PrintSpacer(depth); | |
187 std::cout << name << ": \"" << str.get() << "\"" << 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 mojo::Array<T>& array) { | |
205 PrintSpacer(depth); | |
206 std::cout << name << ":" << std::endl; | |
207 if (!array.is_null()) { | |
208 ++depth; | |
209 for (size_t i = 0; i < array.size(); ++i) { | |
210 std::stringstream buf; | |
211 buf << i; | |
212 Print(depth, buf.str().data(), array.at(i)); | |
213 } | |
214 --depth; | |
215 } | |
216 } | |
217 | |
218 void Print(int depth, const char* name, const FooPtr& foo) { | |
219 PrintSpacer(depth); | |
220 std::cout << name << ":" << std::endl; | |
221 if (!foo.is_null()) { | |
222 ++depth; | |
223 Print(depth, "name", foo->name); | |
224 Print(depth, "x", foo->x); | |
225 Print(depth, "y", foo->y); | |
226 Print(depth, "a", foo->a); | |
227 Print(depth, "b", foo->b); | |
228 Print(depth, "c", foo->c); | |
229 Print(depth, "bar", foo->bar); | |
230 Print(depth, "extra_bars", foo->extra_bars); | |
231 Print(depth, "data", foo->data); | |
232 Print(depth, "source", foo->source); | |
233 Print(depth, "input_streams", foo->input_streams); | |
234 Print(depth, "output_streams", foo->output_streams); | |
235 Print(depth, "array_of_array_of_bools", foo->array_of_array_of_bools); | |
236 --depth; | |
237 } | |
238 } | |
239 | |
240 void DumpHex(const uint8_t* bytes, uint32_t num_bytes) { | |
241 for (uint32_t i = 0; i < num_bytes; ++i) { | |
242 std::cout << std::setw(2) << std::setfill('0') << std::hex | |
243 << uint32_t(bytes[i]); | |
244 | |
245 if (i % 16 == 15) { | |
246 std::cout << std::endl; | |
247 continue; | |
248 } | |
249 | |
250 if (i % 2 == 1) | |
251 std::cout << " "; | |
252 if (i % 8 == 7) | |
253 std::cout << " "; | |
254 } | |
255 } | |
256 | |
257 class ServiceImpl : public Service { | |
258 public: | |
259 void Frobinate(FooPtr foo, BazOptions baz, PortPtr port) override { | |
260 // Users code goes here to handle the incoming Frobinate message. | |
261 | |
262 // We mainly check that we're given the expected arguments. | |
263 EXPECT_FALSE(foo.is_null()); | |
264 if (!foo.is_null()) | |
265 CheckFoo(*foo); | |
266 EXPECT_EQ(BAZ_OPTIONS_EXTRA, baz); | |
267 | |
268 if (g_dump_message_as_text) { | |
269 // Also dump the Foo structure and all of its members. | |
270 std::cout << "Frobinate:" << std::endl; | |
271 int depth = 1; | |
272 Print(depth, "foo", foo); | |
273 Print(depth, "baz", baz); | |
274 Print(depth, "port", port.get()); | |
275 } | |
276 } | |
277 | |
278 void GetPort(mojo::InterfaceRequest<Port> port_request) override {} | |
279 }; | |
280 | |
281 class ServiceProxyImpl : public ServiceProxy { | |
282 public: | |
283 explicit ServiceProxyImpl(mojo::MessageReceiverWithResponder* receiver) | |
284 : ServiceProxy(receiver) {} | |
285 }; | |
286 | |
287 class SimpleMessageReceiver : public mojo::MessageReceiverWithResponder { | |
288 public: | |
289 bool Accept(mojo::Message* message) override { | |
290 // Imagine some IPC happened here. | |
291 | |
292 if (g_dump_message_as_hex) { | |
293 DumpHex(reinterpret_cast<const uint8_t*>(message->data()), | |
294 message->data_num_bytes()); | |
295 } | |
296 | |
297 // In the receiving process, an implementation of ServiceStub is known to | |
298 // the system. It receives the incoming message. | |
299 ServiceImpl impl; | |
300 | |
301 ServiceStub stub; | |
302 stub.set_sink(&impl); | |
303 return stub.Accept(message); | |
304 } | |
305 | |
306 bool AcceptWithResponder(mojo::Message* message, | |
307 mojo::MessageReceiver* responder) override { | |
308 return false; | |
309 } | |
310 }; | |
311 | |
312 class BindingsSampleTest : public testing::Test { | |
313 public: | |
314 BindingsSampleTest() {} | |
315 ~BindingsSampleTest() override {} | |
316 | |
317 private: | |
318 mojo::Environment env_; | |
319 | |
320 MOJO_DISALLOW_COPY_AND_ASSIGN(BindingsSampleTest); | |
321 }; | |
322 | |
323 TEST_F(BindingsSampleTest, Basic) { | |
324 SimpleMessageReceiver receiver; | |
325 | |
326 // User has a proxy to a Service somehow. | |
327 Service* service = new ServiceProxyImpl(&receiver); | |
328 | |
329 // User constructs a message to send. | |
330 | |
331 // Notice that it doesn't matter in what order the structs / arrays are | |
332 // allocated. Here, the various members of Foo are allocated before Foo is | |
333 // allocated. | |
334 | |
335 FooPtr foo = MakeFoo(); | |
336 CheckFoo(*foo); | |
337 | |
338 PortPtr port; | |
339 service->Frobinate(foo.Pass(), Service::BAZ_OPTIONS_EXTRA, port.Pass()); | |
340 | |
341 delete service; | |
342 } | |
343 | |
344 TEST_F(BindingsSampleTest, DefaultValues) { | |
345 DefaultsTestPtr defaults(DefaultsTest::New()); | |
346 EXPECT_EQ(-12, defaults->a0); | |
347 EXPECT_EQ(kTwelve, defaults->a1); | |
348 EXPECT_EQ(1234, defaults->a2); | |
349 EXPECT_EQ(34567U, defaults->a3); | |
350 EXPECT_EQ(123456, defaults->a4); | |
351 EXPECT_EQ(3456789012U, defaults->a5); | |
352 EXPECT_EQ(-111111111111LL, defaults->a6); | |
353 EXPECT_EQ(9999999999999999999ULL, defaults->a7); | |
354 EXPECT_EQ(0x12345, defaults->a8); | |
355 EXPECT_EQ(-0x12345, defaults->a9); | |
356 EXPECT_EQ(1234, defaults->a10); | |
357 EXPECT_TRUE(defaults->a11); | |
358 EXPECT_FALSE(defaults->a12); | |
359 EXPECT_FLOAT_EQ(123.25f, defaults->a13); | |
360 EXPECT_DOUBLE_EQ(1234567890.123, defaults->a14); | |
361 EXPECT_DOUBLE_EQ(1E10, defaults->a15); | |
362 EXPECT_DOUBLE_EQ(-1.2E+20, defaults->a16); | |
363 EXPECT_DOUBLE_EQ(1.23E-20, defaults->a17); | |
364 EXPECT_TRUE(defaults->a18.is_null()); | |
365 EXPECT_TRUE(defaults->a19.is_null()); | |
366 EXPECT_EQ(Bar::TYPE_BOTH, defaults->a20); | |
367 EXPECT_TRUE(defaults->a21.is_null()); | |
368 ASSERT_FALSE(defaults->a22.is_null()); | |
369 EXPECT_EQ(imported::SHAPE_RECTANGLE, defaults->a22->shape); | |
370 EXPECT_EQ(imported::COLOR_BLACK, defaults->a22->color); | |
371 EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, defaults->a23); | |
372 EXPECT_EQ(0x123456789, defaults->a24); | |
373 EXPECT_EQ(-0x123456789, defaults->a25); | |
374 } | |
375 | |
376 } // namespace | |
377 } // namespace sample | |
OLD | NEW |