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>
DoExpectResult(int foo,int bar,const base::Closure & callback,const T & actual)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>
ExpectResult(const T & t,const base::Closure & callback)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>
DoFail(const std::string & reason,const T &)43 void DoFail(const std::string& reason, const T&) {
44 EXPECT_TRUE(false) << reason;
45 }
46
47 template <typename T>
Fail(const std::string & reason)48 base::Callback<void(const T&)> Fail(const std::string& reason) {
49 return base::Bind(&DoFail<T>, reason);
50 }
51
52 template <typename T>
DoExpectEnumResult(T expected,const base::Closure & callback,T actual)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>
ExpectEnumResult(T t,const base::Closure & callback)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>
DoEnumFail(const std::string & reason,T)64 void DoEnumFail(const std::string& reason, T) {
65 EXPECT_TRUE(false) << reason;
66 }
67
68 template <typename T>
EnumFail(const std::string & reason)69 base::Callback<void(T)> EnumFail(const std::string& reason) {
70 return base::Bind(&DoEnumFail<T>, reason);
71 }
72
73 template <typename T>
ExpectError(InterfacePtr<T> * proxy,const base::Closure & callback)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>
RunSimpleLambda(Func func,Arg arg)79 void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); }
80
81 template <typename Arg, typename Func>
BindSimpleLambda(Func 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:
ChromiumPicklePasserImpl()89 ChromiumPicklePasserImpl() {}
90
91 // mojo::test::PicklePasser:
PassPickledStruct(const PickledStructChromium & pickle,const PassPickledStructCallback & callback)92 void PassPickledStruct(const PickledStructChromium& pickle,
93 const PassPickledStructCallback& callback) override {
94 callback.Run(pickle);
95 }
96
PassPickledEnum(PickledEnumChromium pickle,const PassPickledEnumCallback & callback)97 void PassPickledEnum(PickledEnumChromium pickle,
98 const PassPickledEnumCallback& callback) override {
99 callback.Run(pickle);
100 }
101
PassPickleContainer(PickleContainerPtr container,const PassPickleContainerCallback & callback)102 void PassPickleContainer(
103 PickleContainerPtr container,
104 const PassPickleContainerCallback& callback) override {
105 callback.Run(std::move(container));
106 }
107
PassPickles(const std::vector<PickledStructChromium> & pickles,const PassPicklesCallback & callback)108 void PassPickles(const std::vector<PickledStructChromium>& pickles,
109 const PassPicklesCallback& callback) override {
110 callback.Run(pickles);
111 }
112
PassPickleArrays(const std::vector<std::vector<PickledStructChromium>> & pickle_arrays,const PassPickleArraysCallback & callback)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:
BlinkPicklePasserImpl()123 BlinkPicklePasserImpl() {}
124
125 // mojo::test::blink::PicklePasser:
PassPickledStruct(const PickledStructBlink & pickle,const PassPickledStructCallback & callback)126 void PassPickledStruct(const PickledStructBlink& pickle,
127 const PassPickledStructCallback& callback) override {
128 callback.Run(pickle);
129 }
130
PassPickledEnum(PickledEnumBlink pickle,const PassPickledEnumCallback & callback)131 void PassPickledEnum(PickledEnumBlink pickle,
132 const PassPickledEnumCallback& callback) override {
133 callback.Run(pickle);
134 }
135
PassPickleContainer(blink::PickleContainerPtr container,const PassPickleContainerCallback & callback)136 void PassPickleContainer(
137 blink::PickleContainerPtr container,
138 const PassPickleContainerCallback& callback) override {
139 callback.Run(std::move(container));
140 }
141
PassPickles(const WTF::Vector<PickledStructBlink> & pickles,const PassPicklesCallback & callback)142 void PassPickles(const WTF::Vector<PickledStructBlink>& pickles,
143 const PassPicklesCallback& callback) override {
144 callback.Run(pickles);
145 }
146
PassPickleArrays(const WTF::Vector<WTF::Vector<PickledStructBlink>> & pickle_arrays,const PassPickleArraysCallback & callback)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:
PickleTest()158 PickleTest() {}
159
160 template <typename ProxyType = PicklePasser>
ConnectToChromiumService()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>
ConnectToBlinkService()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
TEST_F(PickleTest,ChromiumProxyToChromiumService)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
TEST_F(PickleTest,ChromiumProxyToBlinkService)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
TEST_F(PickleTest,BlinkProxyToBlinkService)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
TEST_F(PickleTest,BlinkProxyToChromiumService)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
TEST_F(PickleTest,PickleArray)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
TEST_F(PickleTest,PickleArrayArray)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
TEST_F(PickleTest,PickleContainer)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