• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 "base/bind.h"
6 #include "base/macros.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "mojo/public/cpp/bindings/binding.h"
10 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
11 #include "mojo/public/cpp/bindings/lib/serialization.h"
12 #include "mojo/public/cpp/bindings/lib/wtf_serialization.h"
13 #include "mojo/public/cpp/bindings/tests/variant_test_util.h"
14 #include "mojo/public/interfaces/bindings/tests/test_wtf_types.mojom-blink.h"
15 #include "mojo/public/interfaces/bindings/tests/test_wtf_types.mojom.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace mojo {
19 namespace test {
20 namespace {
21 
22 const char kHelloWorld[] = "hello world";
23 
24 // Replace the "o"s in "hello world" with "o"s with acute.
25 const char kUTF8HelloWorld[] = "hell\xC3\xB3 w\xC3\xB3rld";
26 
27 class TestWTFImpl : public TestWTF {
28  public:
TestWTFImpl(TestWTFRequest request)29   explicit TestWTFImpl(TestWTFRequest request)
30       : binding_(this, std::move(request)) {}
31 
32   // mojo::test::TestWTF implementation:
EchoString(const base::Optional<std::string> & str,const EchoStringCallback & callback)33   void EchoString(const base::Optional<std::string>& str,
34                   const EchoStringCallback& callback) override {
35     callback.Run(str);
36   }
37 
EchoStringArray(const base::Optional<std::vector<base::Optional<std::string>>> & arr,const EchoStringArrayCallback & callback)38   void EchoStringArray(
39       const base::Optional<std::vector<base::Optional<std::string>>>& arr,
40       const EchoStringArrayCallback& callback) override {
41     callback.Run(std::move(arr));
42   }
43 
EchoStringMap(const base::Optional<std::unordered_map<std::string,base::Optional<std::string>>> & str_map,const EchoStringMapCallback & callback)44   void EchoStringMap(
45       const base::Optional<
46           std::unordered_map<std::string, base::Optional<std::string>>>&
47           str_map,
48       const EchoStringMapCallback& callback) override {
49     callback.Run(std::move(str_map));
50   }
51 
52  private:
53   Binding<TestWTF> binding_;
54 };
55 
56 class WTFTypesTest : public testing::Test {
57  public:
WTFTypesTest()58   WTFTypesTest() {}
59 
60  private:
61   base::MessageLoop loop_;
62 };
63 
ConstructStringArray()64 WTF::Vector<WTF::String> ConstructStringArray() {
65   WTF::Vector<WTF::String> strs(4);
66   // strs[0] is null.
67   // strs[1] is empty.
68   strs[1] = "";
69   strs[2] = kHelloWorld;
70   strs[3] = WTF::String::fromUTF8(kUTF8HelloWorld);
71 
72   return strs;
73 }
74 
ConstructStringMap()75 WTF::HashMap<WTF::String, WTF::String> ConstructStringMap() {
76   WTF::HashMap<WTF::String, WTF::String> str_map;
77   // A null string as value.
78   str_map.add("0", WTF::String());
79   str_map.add("1", kHelloWorld);
80   str_map.add("2", WTF::String::fromUTF8(kUTF8HelloWorld));
81 
82   return str_map;
83 }
84 
ExpectString(const WTF::String & expected_string,const base::Closure & closure,const WTF::String & string)85 void ExpectString(const WTF::String& expected_string,
86                   const base::Closure& closure,
87                   const WTF::String& string) {
88   EXPECT_EQ(expected_string, string);
89   closure.Run();
90 }
91 
ExpectStringArray(WTF::Optional<WTF::Vector<WTF::String>> * expected_arr,const base::Closure & closure,const WTF::Optional<WTF::Vector<WTF::String>> & arr)92 void ExpectStringArray(WTF::Optional<WTF::Vector<WTF::String>>* expected_arr,
93                        const base::Closure& closure,
94                        const WTF::Optional<WTF::Vector<WTF::String>>& arr) {
95   EXPECT_EQ(*expected_arr, arr);
96   closure.Run();
97 }
98 
ExpectStringMap(WTF::Optional<WTF::HashMap<WTF::String,WTF::String>> * expected_map,const base::Closure & closure,const WTF::Optional<WTF::HashMap<WTF::String,WTF::String>> & map)99 void ExpectStringMap(
100     WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map,
101     const base::Closure& closure,
102     const WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>& map) {
103   EXPECT_EQ(*expected_map, map);
104   closure.Run();
105 }
106 
107 }  // namespace
108 
TEST_F(WTFTypesTest,Serialization_WTFArrayToWTFArray)109 TEST_F(WTFTypesTest, Serialization_WTFArrayToWTFArray) {
110   WTFArray<WTF::String> strs = ConstructStringArray();
111   auto cloned_strs = strs.Clone();
112 
113   mojo::internal::SerializationContext context;
114   size_t size = mojo::internal::PrepareToSerialize<Array<mojo::String>>(
115       cloned_strs, &context);
116 
117   mojo::internal::FixedBufferForTesting buf(size);
118   typename mojo::internal::MojomTypeTraits<Array<mojo::String>>::Data* data;
119   mojo::internal::ContainerValidateParams validate_params(
120       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
121   mojo::internal::Serialize<Array<mojo::String>>(cloned_strs, &buf, &data,
122                                                  &validate_params, &context);
123 
124   WTFArray<WTF::String> strs2;
125   mojo::internal::Deserialize<Array<mojo::String>>(data, &strs2, &context);
126 
127   EXPECT_TRUE(strs.Equals(strs2));
128 }
129 
TEST_F(WTFTypesTest,Serialization_WTFVectorToWTFVector)130 TEST_F(WTFTypesTest, Serialization_WTFVectorToWTFVector) {
131   WTF::Vector<WTF::String> strs = ConstructStringArray();
132   auto cloned_strs = strs;
133 
134   mojo::internal::SerializationContext context;
135   size_t size = mojo::internal::PrepareToSerialize<Array<mojo::String>>(
136       cloned_strs, &context);
137 
138   mojo::internal::FixedBufferForTesting buf(size);
139   typename mojo::internal::MojomTypeTraits<Array<mojo::String>>::Data* data;
140   mojo::internal::ContainerValidateParams validate_params(
141       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
142   mojo::internal::Serialize<Array<mojo::String>>(cloned_strs, &buf, &data,
143                                                  &validate_params, &context);
144 
145   WTF::Vector<WTF::String> strs2;
146   mojo::internal::Deserialize<Array<mojo::String>>(data, &strs2, &context);
147 
148   EXPECT_EQ(strs, strs2);
149 }
150 
TEST_F(WTFTypesTest,Serialization_WTFArrayToMojoArray)151 TEST_F(WTFTypesTest, Serialization_WTFArrayToMojoArray) {
152   WTFArray<WTF::String> strs = ConstructStringArray();
153 
154   mojo::internal::SerializationContext context;
155   size_t size =
156       mojo::internal::PrepareToSerialize<Array<mojo::String>>(strs, &context);
157 
158   mojo::internal::FixedBufferForTesting buf(size);
159   typename mojo::internal::MojomTypeTraits<Array<mojo::String>>::Data* data;
160   mojo::internal::ContainerValidateParams validate_params(
161       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
162   mojo::internal::Serialize<Array<mojo::String>>(strs, &buf, &data,
163                                                  &validate_params, &context);
164 
165   Array<mojo::String> strs2;
166   mojo::internal::Deserialize<Array<mojo::String>>(data, &strs2, &context);
167 
168   ASSERT_EQ(4u, strs2.size());
169   EXPECT_TRUE(strs2[0].is_null());
170   EXPECT_TRUE("" == strs2[1]);
171   EXPECT_TRUE(kHelloWorld == strs2[2]);
172   EXPECT_TRUE(kUTF8HelloWorld == strs2[3]);
173 }
174 
TEST_F(WTFTypesTest,Serialization_WTFMapToWTFMap)175 TEST_F(WTFTypesTest, Serialization_WTFMapToWTFMap) {
176   using WTFType = WTFMap<WTF::String, WTF::String>;
177   using MojomType = Map<mojo::String, mojo::String>;
178 
179   WTFType str_map = ConstructStringMap();
180   WTFType cloned_str_map = str_map.Clone();
181 
182   mojo::internal::SerializationContext context;
183   size_t size =
184       mojo::internal::PrepareToSerialize<MojomType>(cloned_str_map, &context);
185 
186   mojo::internal::FixedBufferForTesting buf(size);
187   typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
188   mojo::internal::ContainerValidateParams validate_params(
189       new mojo::internal::ContainerValidateParams(
190           0, false,
191           new mojo::internal::ContainerValidateParams(0, false, nullptr)),
192       new mojo::internal::ContainerValidateParams(
193           0, true,
194           new mojo::internal::ContainerValidateParams(0, false, nullptr)));
195   mojo::internal::Serialize<MojomType>(cloned_str_map, &buf, &data,
196                                        &validate_params, &context);
197 
198   WTFType str_map2;
199   mojo::internal::Deserialize<MojomType>(data, &str_map2, &context);
200 
201   EXPECT_TRUE(str_map.Equals(str_map2));
202 }
203 
TEST_F(WTFTypesTest,Serialization_WTFMapToMojoMap)204 TEST_F(WTFTypesTest, Serialization_WTFMapToMojoMap) {
205   using WTFType = WTFMap<WTF::String, WTF::String>;
206   using MojomType = Map<mojo::String, mojo::String>;
207 
208   WTFType str_map = ConstructStringMap();
209 
210   mojo::internal::SerializationContext context;
211   size_t size =
212       mojo::internal::PrepareToSerialize<MojomType>(str_map, &context);
213 
214   mojo::internal::FixedBufferForTesting buf(size);
215   typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
216   mojo::internal::ContainerValidateParams validate_params(
217       new mojo::internal::ContainerValidateParams(
218           0, false,
219           new mojo::internal::ContainerValidateParams(0, false, nullptr)),
220       new mojo::internal::ContainerValidateParams(
221           0, true,
222           new mojo::internal::ContainerValidateParams(0, false, nullptr)));
223   mojo::internal::Serialize<MojomType>(str_map, &buf, &data, &validate_params,
224                                        &context);
225 
226   MojomType str_map2;
227   mojo::internal::Deserialize<MojomType>(data, &str_map2, &context);
228 
229   ASSERT_EQ(3u, str_map2.size());
230   EXPECT_TRUE(str_map2["0"].is_null());
231   EXPECT_TRUE(kHelloWorld == str_map2["1"]);
232   EXPECT_TRUE(kUTF8HelloWorld == str_map2["2"]);
233 }
234 
TEST_F(WTFTypesTest,Serialization_PublicAPI)235 TEST_F(WTFTypesTest, Serialization_PublicAPI) {
236   blink::TestWTFStructPtr input(blink::TestWTFStruct::New());
237   input->str = kHelloWorld;
238   input->integer = 42;
239 
240   blink::TestWTFStructPtr cloned_input = input.Clone();
241 
242   WTFArray<uint8_t> data = blink::TestWTFStruct::Serialize(&input);
243 
244   blink::TestWTFStructPtr output;
245   ASSERT_TRUE(blink::TestWTFStruct::Deserialize(std::move(data), &output));
246   EXPECT_TRUE(cloned_input.Equals(output));
247 }
248 
TEST_F(WTFTypesTest,SendString)249 TEST_F(WTFTypesTest, SendString) {
250   blink::TestWTFPtr ptr;
251   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr)));
252 
253   WTF::Vector<WTF::String> strs = ConstructStringArray();
254 
255   for (size_t i = 0; i < strs.size(); ++i) {
256     base::RunLoop loop;
257     // Test that a WTF::String is unchanged after the following conversion:
258     //   - serialized;
259     //   - deserialized as base::Optional<std::string>;
260     //   - serialized;
261     //   - deserialized as WTF::String.
262     ptr->EchoString(strs[i],
263                     base::Bind(&ExpectString, strs[i], loop.QuitClosure()));
264     loop.Run();
265   }
266 }
267 
TEST_F(WTFTypesTest,SendStringArray)268 TEST_F(WTFTypesTest, SendStringArray) {
269   blink::TestWTFPtr ptr;
270   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr)));
271 
272   WTF::Optional<WTF::Vector<WTF::String>> arrs[3];
273   // arrs[0] is empty.
274   arrs[0].emplace();
275   // arrs[1] is null.
276   arrs[2] = ConstructStringArray();
277 
278   for (size_t i = 0; i < arraysize(arrs); ++i) {
279     base::RunLoop loop;
280     // Test that a WTF::Optional<WTF::Vector<WTF::String>> is unchanged after
281     // the following conversion:
282     //   - serialized;
283     //   - deserialized as
284     //     base::Optional<std::vector<base::Optional<std::string>>>;
285     //   - serialized;
286     //   - deserialized as WTF::Optional<WTF::Vector<WTF::String>>.
287     ptr->EchoStringArray(
288         arrs[i], base::Bind(&ExpectStringArray, base::Unretained(&arrs[i]),
289                             loop.QuitClosure()));
290     loop.Run();
291   }
292 }
293 
TEST_F(WTFTypesTest,SendStringMap)294 TEST_F(WTFTypesTest, SendStringMap) {
295   blink::TestWTFPtr ptr;
296   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr)));
297 
298   WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> maps[3];
299   // maps[0] is empty.
300   maps[0].emplace();
301   // maps[1] is null.
302   maps[2] = ConstructStringMap();
303 
304   for (size_t i = 0; i < arraysize(maps); ++i) {
305     base::RunLoop loop;
306     // Test that a WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> is
307     // unchanged after the following conversion:
308     //   - serialized;
309     //   - deserialized as base::Optional<
310     //     std::unordered_map<std::string, base::Optional<std::string>>>;
311     //   - serialized;
312     //   - deserialized as WTF::Optional<WTF::HashMap<WTF::String,
313     //     WTF::String>>.
314     ptr->EchoStringMap(maps[i],
315                        base::Bind(&ExpectStringMap, base::Unretained(&maps[i]),
316                                   loop.QuitClosure()));
317     loop.Run();
318   }
319 }
320 
321 }  // namespace test
322 }  // namespace mojo
323