xref: /aosp_15_r20/external/libchrome/mojo/public/cpp/bindings/tests/pickle_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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,T actual)27 void DoExpectResult(int foo, int bar, const base::Closure& callback, T actual) {
28   EXPECT_EQ(foo, actual.foo());
29   EXPECT_EQ(bar, actual.bar());
30   callback.Run();
31 }
32 
33 template <typename T>
ExpectResult(const T & t,const base::Closure & callback)34 base::Callback<void(T)> ExpectResult(const T& t,
35                                      const base::Closure& callback) {
36   return base::Bind(&DoExpectResult<T>, t.foo(), t.bar(), callback);
37 }
38 
39 template <typename T>
DoFail(const std::string & reason,T)40 void DoFail(const std::string& reason, T) {
41   EXPECT_TRUE(false) << reason;
42 }
43 
44 template <typename T>
Fail(const std::string & reason)45 base::Callback<void(T)> Fail(const std::string& reason) {
46   return base::Bind(&DoFail<T>, reason);
47 }
48 
49 template <typename T>
DoExpectEnumResult(T expected,const base::Closure & callback,T actual)50 void DoExpectEnumResult(T expected, const base::Closure& callback, T actual) {
51   EXPECT_EQ(expected, actual);
52   callback.Run();
53 }
54 
55 template <typename T>
ExpectEnumResult(T t,const base::Closure & callback)56 base::Callback<void(T)> ExpectEnumResult(T t, const base::Closure& callback) {
57   return base::Bind(&DoExpectEnumResult<T>, t, callback);
58 }
59 
60 template <typename T>
DoEnumFail(const std::string & reason,T)61 void DoEnumFail(const std::string& reason, T) {
62   EXPECT_TRUE(false) << reason;
63 }
64 
65 template <typename T>
EnumFail(const std::string & reason)66 base::Callback<void(T)> EnumFail(const std::string& reason) {
67   return base::Bind(&DoEnumFail<T>, reason);
68 }
69 
70 template <typename T>
ExpectError(InterfacePtr<T> * proxy,const base::Closure & callback)71 void ExpectError(InterfacePtr<T>* proxy, const base::Closure& callback) {
72   proxy->set_connection_error_handler(callback);
73 }
74 
75 template <typename Func, typename Arg>
RunSimpleLambda(Func func,Arg arg)76 void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); }
77 
78 template <typename Arg, typename Func>
BindSimpleLambda(Func func)79 base::Callback<void(Arg)> BindSimpleLambda(Func func) {
80   return base::Bind(&RunSimpleLambda<Func, Arg>, func);
81 }
82 
83 // This implements the generated Chromium variant of PicklePasser.
84 class ChromiumPicklePasserImpl : public PicklePasser {
85  public:
ChromiumPicklePasserImpl()86   ChromiumPicklePasserImpl() {}
87 
88   // mojo::test::PicklePasser:
PassPickledStruct(PickledStructChromium pickle,const PassPickledStructCallback & callback)89   void PassPickledStruct(PickledStructChromium pickle,
90                          const PassPickledStructCallback& callback) override {
91     callback.Run(std::move(pickle));
92   }
93 
PassPickledEnum(PickledEnumChromium pickle,const PassPickledEnumCallback & callback)94   void PassPickledEnum(PickledEnumChromium pickle,
95                        const PassPickledEnumCallback& callback) override {
96     callback.Run(pickle);
97   }
98 
PassPickleContainer(PickleContainerPtr container,const PassPickleContainerCallback & callback)99   void PassPickleContainer(
100       PickleContainerPtr container,
101       const PassPickleContainerCallback& callback) override {
102     callback.Run(std::move(container));
103   }
104 
PassPickles(std::vector<PickledStructChromium> pickles,const PassPicklesCallback & callback)105   void PassPickles(std::vector<PickledStructChromium> pickles,
106                    const PassPicklesCallback& callback) override {
107     callback.Run(std::move(pickles));
108   }
109 
PassPickleArrays(std::vector<std::vector<PickledStructChromium>> pickle_arrays,const PassPickleArraysCallback & callback)110   void PassPickleArrays(
111       std::vector<std::vector<PickledStructChromium>> pickle_arrays,
112       const PassPickleArraysCallback& callback) override {
113     callback.Run(std::move(pickle_arrays));
114   }
115 };
116 
117 // This implements the generated Blink variant of PicklePasser.
118 class BlinkPicklePasserImpl : public blink::PicklePasser {
119  public:
BlinkPicklePasserImpl()120   BlinkPicklePasserImpl() {}
121 
122   // mojo::test::blink::PicklePasser:
PassPickledStruct(PickledStructBlink pickle,const PassPickledStructCallback & callback)123   void PassPickledStruct(PickledStructBlink pickle,
124                          const PassPickledStructCallback& callback) override {
125     callback.Run(std::move(pickle));
126   }
127 
PassPickledEnum(PickledEnumBlink pickle,const PassPickledEnumCallback & callback)128   void PassPickledEnum(PickledEnumBlink pickle,
129                        const PassPickledEnumCallback& callback) override {
130     callback.Run(pickle);
131   }
132 
PassPickleContainer(blink::PickleContainerPtr container,const PassPickleContainerCallback & callback)133   void PassPickleContainer(
134       blink::PickleContainerPtr container,
135       const PassPickleContainerCallback& callback) override {
136     callback.Run(std::move(container));
137   }
138 
PassPickles(WTF::Vector<PickledStructBlink> pickles,const PassPicklesCallback & callback)139   void PassPickles(WTF::Vector<PickledStructBlink> pickles,
140                    const PassPicklesCallback& callback) override {
141     callback.Run(std::move(pickles));
142   }
143 
PassPickleArrays(WTF::Vector<WTF::Vector<PickledStructBlink>> pickle_arrays,const PassPickleArraysCallback & callback)144   void PassPickleArrays(
145       WTF::Vector<WTF::Vector<PickledStructBlink>> pickle_arrays,
146       const PassPickleArraysCallback& callback) override {
147     callback.Run(std::move(pickle_arrays));
148   }
149 };
150 
151 // A test which runs both Chromium and Blink implementations of the
152 // PicklePasser service.
153 class PickleTest : public testing::Test {
154  public:
PickleTest()155   PickleTest() {}
156 
157   template <typename ProxyType = PicklePasser>
ConnectToChromiumService()158   InterfacePtr<ProxyType> ConnectToChromiumService() {
159     InterfacePtr<ProxyType> proxy;
160     chromium_bindings_.AddBinding(
161         &chromium_service_,
162         ConvertInterfaceRequest<PicklePasser>(mojo::MakeRequest(&proxy)));
163     return proxy;
164   }
165 
166   template <typename ProxyType = blink::PicklePasser>
ConnectToBlinkService()167   InterfacePtr<ProxyType> ConnectToBlinkService() {
168     InterfacePtr<ProxyType> proxy;
169     blink_bindings_.AddBinding(&blink_service_,
170                                ConvertInterfaceRequest<blink::PicklePasser>(
171                                    mojo::MakeRequest(&proxy)));
172     return proxy;
173   }
174 
175  protected:
ForceMessageSerialization(bool forced)176   static void ForceMessageSerialization(bool forced) {
177     // Force messages to be serialized in this test since it intentionally
178     // exercises StructTraits logic.
179     Connector::OverrideDefaultSerializationBehaviorForTesting(
180         forced ? Connector::OutgoingSerializationMode::kEager
181                : Connector::OutgoingSerializationMode::kLazy,
182         Connector::IncomingSerializationMode::kDispatchAsIs);
183   }
184 
185   class ScopedForceMessageSerialization {
186    public:
ScopedForceMessageSerialization()187     ScopedForceMessageSerialization() { ForceMessageSerialization(true); }
~ScopedForceMessageSerialization()188     ~ScopedForceMessageSerialization() { ForceMessageSerialization(false); }
189 
190    private:
191     DISALLOW_COPY_AND_ASSIGN(ScopedForceMessageSerialization);
192   };
193 
194  private:
195   base::MessageLoop loop_;
196   ChromiumPicklePasserImpl chromium_service_;
197   BindingSet<PicklePasser> chromium_bindings_;
198   BlinkPicklePasserImpl blink_service_;
199   BindingSet<blink::PicklePasser> blink_bindings_;
200 };
201 
202 }  // namespace
203 
TEST_F(PickleTest,ChromiumProxyToChromiumService)204 TEST_F(PickleTest, ChromiumProxyToChromiumService) {
205   auto chromium_proxy = ConnectToChromiumService();
206   {
207     base::RunLoop loop;
208     chromium_proxy->PassPickledStruct(
209         PickledStructChromium(1, 2),
210         ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure()));
211     loop.Run();
212   }
213   {
214     base::RunLoop loop;
215     chromium_proxy->PassPickledStruct(
216         PickledStructChromium(4, 5),
217         ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure()));
218     loop.Run();
219   }
220 
221   {
222     base::RunLoop loop;
223     chromium_proxy->PassPickledEnum(
224         PickledEnumChromium::VALUE_1,
225         ExpectEnumResult(PickledEnumChromium::VALUE_1, loop.QuitClosure()));
226     loop.Run();
227   }
228 }
229 
TEST_F(PickleTest,ChromiumProxyToBlinkService)230 TEST_F(PickleTest, ChromiumProxyToBlinkService) {
231   auto chromium_proxy = ConnectToBlinkService<PicklePasser>();
232   {
233     base::RunLoop loop;
234     chromium_proxy->PassPickledStruct(
235         PickledStructChromium(1, 2),
236         ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure()));
237     loop.Run();
238   }
239   {
240     base::RunLoop loop;
241     chromium_proxy->PassPickledStruct(
242         PickledStructChromium(4, 5),
243         ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure()));
244     loop.Run();
245   }
246   // The Blink service should drop our connection because the
247   // PickledStructBlink ParamTraits deserializer rejects negative values.
248   {
249     base::RunLoop loop;
250     chromium_proxy->PassPickledStruct(
251         PickledStructChromium(-1, -1),
252         Fail<PickledStructChromium>("Blink service should reject this."));
253     ExpectError(&chromium_proxy, loop.QuitClosure());
254     loop.Run();
255   }
256 
257   chromium_proxy = ConnectToBlinkService<PicklePasser>();
258   {
259     base::RunLoop loop;
260     chromium_proxy->PassPickledEnum(
261         PickledEnumChromium::VALUE_0,
262         ExpectEnumResult(PickledEnumChromium::VALUE_0, loop.QuitClosure()));
263     loop.Run();
264   }
265 
266   // The Blink service should drop our connection because the
267   // PickledEnumBlink ParamTraits deserializer rejects this value.
268   {
269     base::RunLoop loop;
270     chromium_proxy->PassPickledEnum(
271         PickledEnumChromium::VALUE_2,
272         EnumFail<PickledEnumChromium>("Blink service should reject this."));
273     ExpectError(&chromium_proxy, loop.QuitClosure());
274     loop.Run();
275   }
276 }
277 
TEST_F(PickleTest,BlinkProxyToBlinkService)278 TEST_F(PickleTest, BlinkProxyToBlinkService) {
279   auto blink_proxy = ConnectToBlinkService();
280   {
281     base::RunLoop loop;
282     blink_proxy->PassPickledStruct(
283         PickledStructBlink(1, 1),
284         ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure()));
285     loop.Run();
286   }
287 
288   {
289     base::RunLoop loop;
290     blink_proxy->PassPickledEnum(
291         PickledEnumBlink::VALUE_0,
292         ExpectEnumResult(PickledEnumBlink::VALUE_0, loop.QuitClosure()));
293     loop.Run();
294   }
295 }
296 
TEST_F(PickleTest,BlinkProxyToChromiumService)297 TEST_F(PickleTest, BlinkProxyToChromiumService) {
298   auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>();
299   {
300     base::RunLoop loop;
301     blink_proxy->PassPickledStruct(
302         PickledStructBlink(1, 1),
303         ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure()));
304     loop.Run();
305   }
306 
307   {
308     base::RunLoop loop;
309     blink_proxy->PassPickledEnum(
310         PickledEnumBlink::VALUE_1,
311         ExpectEnumResult(PickledEnumBlink::VALUE_1, loop.QuitClosure()));
312     loop.Run();
313   }
314 }
315 
TEST_F(PickleTest,PickleArray)316 TEST_F(PickleTest, PickleArray) {
317   ScopedForceMessageSerialization force_serialization;
318   auto proxy = ConnectToChromiumService();
319   auto pickles = std::vector<PickledStructChromium>(2);
320   pickles[0].set_foo(1);
321   pickles[0].set_bar(2);
322   pickles[0].set_baz(100);
323   pickles[1].set_foo(3);
324   pickles[1].set_bar(4);
325   pickles[1].set_baz(100);
326   {
327     base::RunLoop run_loop;
328     // Verify that the array of pickled structs can be serialized and
329     // deserialized intact. This ensures that the ParamTraits are actually used
330     // rather than doing a byte-for-byte copy of the element data, beacuse the
331     // |baz| field should never be serialized.
332     proxy->PassPickles(std::move(pickles),
333                        BindSimpleLambda<std::vector<PickledStructChromium>>(
334                            [&](std::vector<PickledStructChromium> passed) {
335                              ASSERT_EQ(2u, passed.size());
336                              EXPECT_EQ(1, passed[0].foo());
337                              EXPECT_EQ(2, passed[0].bar());
338                              EXPECT_EQ(0, passed[0].baz());
339                              EXPECT_EQ(3, passed[1].foo());
340                              EXPECT_EQ(4, passed[1].bar());
341                              EXPECT_EQ(0, passed[1].baz());
342                              run_loop.Quit();
343                            }));
344     run_loop.Run();
345   }
346 }
347 
TEST_F(PickleTest,PickleArrayArray)348 TEST_F(PickleTest, PickleArrayArray) {
349   ScopedForceMessageSerialization force_serialization;
350   auto proxy = ConnectToChromiumService();
351   auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2);
352   for (size_t i = 0; i < 2; ++i)
353     pickle_arrays[i] = std::vector<PickledStructChromium>(2);
354 
355   pickle_arrays[0][0].set_foo(1);
356   pickle_arrays[0][0].set_bar(2);
357   pickle_arrays[0][0].set_baz(100);
358   pickle_arrays[0][1].set_foo(3);
359   pickle_arrays[0][1].set_bar(4);
360   pickle_arrays[0][1].set_baz(100);
361   pickle_arrays[1][0].set_foo(5);
362   pickle_arrays[1][0].set_bar(6);
363   pickle_arrays[1][0].set_baz(100);
364   pickle_arrays[1][1].set_foo(7);
365   pickle_arrays[1][1].set_bar(8);
366   pickle_arrays[1][1].set_baz(100);
367   {
368     base::RunLoop run_loop;
369     // Verify that the array-of-arrays serializes and deserializes properly.
370     proxy->PassPickleArrays(
371         std::move(pickle_arrays),
372         BindSimpleLambda<std::vector<std::vector<PickledStructChromium>>>(
373             [&](std::vector<std::vector<PickledStructChromium>> passed) {
374               ASSERT_EQ(2u, passed.size());
375               ASSERT_EQ(2u, passed[0].size());
376               ASSERT_EQ(2u, passed[1].size());
377               EXPECT_EQ(1, passed[0][0].foo());
378               EXPECT_EQ(2, passed[0][0].bar());
379               EXPECT_EQ(0, passed[0][0].baz());
380               EXPECT_EQ(3, passed[0][1].foo());
381               EXPECT_EQ(4, passed[0][1].bar());
382               EXPECT_EQ(0, passed[0][1].baz());
383               EXPECT_EQ(5, passed[1][0].foo());
384               EXPECT_EQ(6, passed[1][0].bar());
385               EXPECT_EQ(0, passed[1][0].baz());
386               EXPECT_EQ(7, passed[1][1].foo());
387               EXPECT_EQ(8, passed[1][1].bar());
388               EXPECT_EQ(0, passed[1][1].baz());
389               run_loop.Quit();
390             }));
391     run_loop.Run();
392   }
393 }
394 
TEST_F(PickleTest,PickleContainer)395 TEST_F(PickleTest, PickleContainer) {
396   ScopedForceMessageSerialization force_serialization;
397   auto proxy = ConnectToChromiumService();
398   PickleContainerPtr pickle_container = PickleContainer::New();
399   pickle_container->f_struct.set_foo(42);
400   pickle_container->f_struct.set_bar(43);
401   pickle_container->f_struct.set_baz(44);
402   pickle_container->f_enum = PickledEnumChromium::VALUE_1;
403   EXPECT_TRUE(pickle_container.Equals(pickle_container));
404   EXPECT_FALSE(pickle_container.Equals(PickleContainer::New()));
405   {
406     base::RunLoop run_loop;
407     proxy->PassPickleContainer(std::move(pickle_container),
408                                BindSimpleLambda<PickleContainerPtr>(
409                                    [&](PickleContainerPtr passed) {
410                                      ASSERT_FALSE(passed.is_null());
411                                      EXPECT_EQ(42, passed->f_struct.foo());
412                                      EXPECT_EQ(43, passed->f_struct.bar());
413                                      EXPECT_EQ(0, passed->f_struct.baz());
414                                      EXPECT_EQ(PickledEnumChromium::VALUE_1,
415                                                passed->f_enum);
416                                      run_loop.Quit();
417                                    }));
418     run_loop.Run();
419   }
420 }
421 
422 }  // namespace test
423 }  // namespace mojo
424