• 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 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
18 
19 namespace mojo {
20 namespace test {
21 namespace {
22 
23 const char kHelloWorld[] = "hello world";
24 
25 // Replace the "o"s in "hello world" with "o"s with acute.
26 const char kUTF8HelloWorld[] = "hell\xC3\xB3 w\xC3\xB3rld";
27 
28 class TestWTFImpl : public TestWTF {
29  public:
TestWTFImpl(TestWTFRequest request)30   explicit TestWTFImpl(TestWTFRequest request)
31       : binding_(this, std::move(request)) {}
32 
33   // mojo::test::TestWTF implementation:
EchoString(const base::Optional<std::string> & str,const EchoStringCallback & callback)34   void EchoString(const base::Optional<std::string>& str,
35                   const EchoStringCallback& callback) override {
36     callback.Run(str);
37   }
38 
EchoStringArray(const base::Optional<std::vector<base::Optional<std::string>>> & arr,const EchoStringArrayCallback & callback)39   void EchoStringArray(
40       const base::Optional<std::vector<base::Optional<std::string>>>& arr,
41       const EchoStringArrayCallback& callback) override {
42     callback.Run(std::move(arr));
43   }
44 
EchoStringMap(const base::Optional<base::flat_map<std::string,base::Optional<std::string>>> & str_map,const EchoStringMapCallback & callback)45   void EchoStringMap(
46       const base::Optional<
47           base::flat_map<std::string, base::Optional<std::string>>>& 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.insert("0", WTF::String());
79   str_map.insert("1", kHelloWorld);
80   str_map.insert("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(base::Optional<WTF::Vector<WTF::String>> * expected_arr,const base::Closure & closure,const base::Optional<WTF::Vector<WTF::String>> & arr)92 void ExpectStringArray(base::Optional<WTF::Vector<WTF::String>>* expected_arr,
93                        const base::Closure& closure,
94                        const base::Optional<WTF::Vector<WTF::String>>& arr) {
95   EXPECT_EQ(*expected_arr, arr);
96   closure.Run();
97 }
98 
ExpectStringMap(base::Optional<WTF::HashMap<WTF::String,WTF::String>> * expected_map,const base::Closure & closure,const base::Optional<WTF::HashMap<WTF::String,WTF::String>> & map)99 void ExpectStringMap(
100     base::Optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map,
101     const base::Closure& closure,
102     const base::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_WTFVectorToWTFVector)109 TEST_F(WTFTypesTest, Serialization_WTFVectorToWTFVector) {
110   using MojomType = ArrayDataView<StringDataView>;
111 
112   WTF::Vector<WTF::String> strs = ConstructStringArray();
113   auto cloned_strs = strs;
114 
115   mojo::Message message(0, 0, 0, 0, nullptr);
116   mojo::internal::SerializationContext context;
117   typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
118       writer;
119   mojo::internal::ContainerValidateParams validate_params(
120       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
121   mojo::internal::Serialize<MojomType>(cloned_strs, message.payload_buffer(),
122                                        &writer, &validate_params, &context);
123 
124   WTF::Vector<WTF::String> strs2;
125   mojo::internal::Deserialize<MojomType>(writer.data(), &strs2, &context);
126 
127   EXPECT_EQ(strs, strs2);
128 }
129 
TEST_F(WTFTypesTest,Serialization_WTFVectorInlineCapacity)130 TEST_F(WTFTypesTest, Serialization_WTFVectorInlineCapacity) {
131   using MojomType = ArrayDataView<StringDataView>;
132 
133   WTF::Vector<WTF::String, 1> strs(4);
134   // strs[0] is null.
135   // strs[1] is empty.
136   strs[1] = "";
137   strs[2] = kHelloWorld;
138   strs[3] = WTF::String::FromUTF8(kUTF8HelloWorld);
139   auto cloned_strs = strs;
140 
141   mojo::Message message(0, 0, 0, 0, nullptr);
142   mojo::internal::SerializationContext context;
143   typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
144       writer;
145   mojo::internal::ContainerValidateParams validate_params(
146       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
147   mojo::internal::Serialize<MojomType>(cloned_strs, message.payload_buffer(),
148                                        &writer, &validate_params, &context);
149 
150   WTF::Vector<WTF::String, 1> strs2;
151   mojo::internal::Deserialize<MojomType>(writer.data(), &strs2, &context);
152 
153   EXPECT_EQ(strs, strs2);
154 }
155 
TEST_F(WTFTypesTest,Serialization_WTFVectorToStlVector)156 TEST_F(WTFTypesTest, Serialization_WTFVectorToStlVector) {
157   using MojomType = ArrayDataView<StringDataView>;
158 
159   WTF::Vector<WTF::String> strs = ConstructStringArray();
160   auto cloned_strs = strs;
161 
162   mojo::Message message(0, 0, 0, 0, nullptr);
163   mojo::internal::SerializationContext context;
164   typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
165       writer;
166   mojo::internal::ContainerValidateParams validate_params(
167       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
168   mojo::internal::Serialize<MojomType>(cloned_strs, message.payload_buffer(),
169                                        &writer, &validate_params, &context);
170 
171   std::vector<base::Optional<std::string>> strs2;
172   mojo::internal::Deserialize<MojomType>(writer.data(), &strs2, &context);
173 
174   ASSERT_EQ(4u, strs2.size());
175   EXPECT_FALSE(strs2[0]);
176   EXPECT_EQ("", *strs2[1]);
177   EXPECT_EQ(kHelloWorld, *strs2[2]);
178   EXPECT_EQ(kUTF8HelloWorld, *strs2[3]);
179 }
180 
TEST_F(WTFTypesTest,Serialization_PublicAPI)181 TEST_F(WTFTypesTest, Serialization_PublicAPI) {
182   blink::TestWTFStructPtr input(blink::TestWTFStruct::New(kHelloWorld, 42));
183 
184   blink::TestWTFStructPtr cloned_input = input.Clone();
185 
186   auto data = blink::TestWTFStruct::Serialize(&input);
187 
188   blink::TestWTFStructPtr output;
189   ASSERT_TRUE(blink::TestWTFStruct::Deserialize(std::move(data), &output));
190   EXPECT_TRUE(cloned_input.Equals(output));
191 }
192 
TEST_F(WTFTypesTest,SendString)193 TEST_F(WTFTypesTest, SendString) {
194   blink::TestWTFPtr ptr;
195   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr)));
196 
197   WTF::Vector<WTF::String> strs = ConstructStringArray();
198 
199   for (size_t i = 0; i < strs.size(); ++i) {
200     base::RunLoop loop;
201     // Test that a WTF::String is unchanged after the following conversion:
202     //   - serialized;
203     //   - deserialized as base::Optional<std::string>;
204     //   - serialized;
205     //   - deserialized as WTF::String.
206     ptr->EchoString(strs[i],
207                     base::Bind(&ExpectString, strs[i], loop.QuitClosure()));
208     loop.Run();
209   }
210 }
211 
TEST_F(WTFTypesTest,SendStringArray)212 TEST_F(WTFTypesTest, SendStringArray) {
213   blink::TestWTFPtr ptr;
214   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr)));
215 
216   base::Optional<WTF::Vector<WTF::String>> arrs[3];
217   // arrs[0] is empty.
218   arrs[0].emplace();
219   // arrs[1] is null.
220   arrs[2] = ConstructStringArray();
221 
222   for (size_t i = 0; i < arraysize(arrs); ++i) {
223     base::RunLoop loop;
224     // Test that a base::Optional<WTF::Vector<WTF::String>> is unchanged after
225     // the following conversion:
226     //   - serialized;
227     //   - deserialized as
228     //     base::Optional<std::vector<base::Optional<std::string>>>;
229     //   - serialized;
230     //   - deserialized as base::Optional<WTF::Vector<WTF::String>>.
231     ptr->EchoStringArray(
232         arrs[i], base::Bind(&ExpectStringArray, base::Unretained(&arrs[i]),
233                             loop.QuitClosure()));
234     loop.Run();
235   }
236 }
237 
TEST_F(WTFTypesTest,SendStringMap)238 TEST_F(WTFTypesTest, SendStringMap) {
239   blink::TestWTFPtr ptr;
240   TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(MakeRequest(&ptr)));
241 
242   base::Optional<WTF::HashMap<WTF::String, WTF::String>> maps[3];
243   // maps[0] is empty.
244   maps[0].emplace();
245   // maps[1] is null.
246   maps[2] = ConstructStringMap();
247 
248   for (size_t i = 0; i < arraysize(maps); ++i) {
249     base::RunLoop loop;
250     // Test that a base::Optional<WTF::HashMap<WTF::String, WTF::String>> is
251     // unchanged after the following conversion:
252     //   - serialized;
253     //   - deserialized as base::Optional<
254     //         base::flat_map<std::string, base::Optional<std::string>>>;
255     //   - serialized;
256     //   - deserialized as base::Optional<WTF::HashMap<WTF::String,
257     //     WTF::String>>.
258     ptr->EchoStringMap(maps[i],
259                        base::Bind(&ExpectStringMap, base::Unretained(&maps[i]),
260                                   loop.QuitClosure()));
261     loop.Run();
262   }
263 }
264 
TEST_F(WTFTypesTest,NestedStruct_CloneAndEquals)265 TEST_F(WTFTypesTest, NestedStruct_CloneAndEquals) {
266   auto a = blink::TestWTFStructWrapper::New();
267   a->nested_struct = blink::TestWTFStruct::New("foo", 1);
268   a->array_struct.push_back(blink::TestWTFStruct::New("bar", 2));
269   a->array_struct.push_back(blink::TestWTFStruct::New("bar", 3));
270   a->map_struct.insert(blink::TestWTFStruct::New("baz", 4),
271                        blink::TestWTFStruct::New("baz", 5));
272   auto b = a.Clone();
273   EXPECT_EQ(a, b);
274   EXPECT_EQ(2u, b->array_struct.size());
275   EXPECT_EQ(1u, b->map_struct.size());
276   EXPECT_NE(blink::TestWTFStructWrapper::New(), a);
277   EXPECT_NE(blink::TestWTFStructWrapper::New(), b);
278 }
279 
280 }  // namespace test
281 }  // namespace mojo
282