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 "gtest/gtest.h" | |
6 #include "mojo/public/cpp/bindings/array.h" | |
7 #include "mojo/public/cpp/bindings/lib/array_serialization.h" | |
8 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | |
9 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" | |
10 #include "mojo/public/cpp/bindings/lib/map_serialization.h" | |
11 #include "mojo/public/cpp/bindings/lib/validate_params.h" | |
12 #include "mojo/public/cpp/bindings/map.h" | |
13 #include "mojo/public/cpp/bindings/string.h" | |
14 #include "mojo/public/cpp/bindings/tests/container_test_util.h" | |
15 #include "mojo/public/interfaces/bindings/tests/rect.mojom.h" | |
16 | |
17 namespace mojo { | |
18 namespace test { | |
19 | |
20 namespace { | |
21 | |
22 using mojo::internal::Array_Data; | |
23 using mojo::internal::ArrayValidateParams; | |
24 using mojo::internal::FixedBufferForTesting; | |
25 using mojo::internal::Map_Data; | |
26 using mojo::internal::String_Data; | |
27 using mojo::internal::ValidationError; | |
28 | |
29 struct StringIntData { | |
30 const char* string_data; | |
31 int int_data; | |
32 } kStringIntData[] = { | |
33 {"one", 1}, | |
34 {"two", 2}, | |
35 {"three", 3}, | |
36 {"four", 4}, | |
37 }; | |
38 | |
39 const size_t kStringIntDataSize = 4; | |
40 | |
41 TEST(MapTest, Testability) { | |
42 Map<int32_t, int32_t> map; | |
43 EXPECT_FALSE(map); | |
44 EXPECT_TRUE(map.is_null()); | |
45 | |
46 map[123] = 456; | |
47 EXPECT_TRUE(map); | |
48 EXPECT_FALSE(map.is_null()); | |
49 } | |
50 | |
51 // Tests that basic Map operations work. | |
52 TEST(MapTest, InsertWorks) { | |
53 Map<String, int> map; | |
54 for (size_t i = 0; i < kStringIntDataSize; ++i) | |
55 map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); | |
56 | |
57 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
58 EXPECT_EQ(kStringIntData[i].int_data, | |
59 map.at(kStringIntData[i].string_data)); | |
60 } | |
61 } | |
62 | |
63 TEST(MapTest, TestIndexOperator) { | |
64 Map<String, int> map; | |
65 for (size_t i = 0; i < kStringIntDataSize; ++i) | |
66 map[kStringIntData[i].string_data] = kStringIntData[i].int_data; | |
67 | |
68 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
69 EXPECT_EQ(kStringIntData[i].int_data, | |
70 map.at(kStringIntData[i].string_data)); | |
71 } | |
72 } | |
73 | |
74 TEST(MapTest, TestIndexOperatorAsRValue) { | |
75 Map<String, int> map; | |
76 for (size_t i = 0; i < kStringIntDataSize; ++i) | |
77 map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); | |
78 | |
79 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
80 EXPECT_EQ(kStringIntData[i].int_data, map[kStringIntData[i].string_data]); | |
81 } | |
82 } | |
83 | |
84 TEST(MapTest, TestIndexOperatorMoveOnly) { | |
85 ASSERT_EQ(0u, MoveOnlyType::num_instances()); | |
86 mojo::Map<mojo::String, mojo::Array<int32_t>> map; | |
87 std::vector<MoveOnlyType*> value_ptrs; | |
88 | |
89 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
90 const char* key = kStringIntData[i].string_data; | |
91 auto array = Array<int32_t>::New(1); | |
92 array[0] = kStringIntData[i].int_data; | |
93 map[key] = array.Pass(); | |
94 EXPECT_TRUE(map); | |
95 } | |
96 | |
97 // We now read back that data, to test the behavior of operator[]. | |
98 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
99 auto it = map.find(kStringIntData[i].string_data); | |
100 ASSERT_TRUE(it != map.end()); | |
101 ASSERT_EQ(1u, it.GetValue().size()); | |
102 EXPECT_EQ(kStringIntData[i].int_data, it.GetValue()[0]); | |
103 } | |
104 } | |
105 | |
106 TEST(MapTest, ConstructedFromArray) { | |
107 auto keys = Array<String>::New(kStringIntDataSize); | |
108 auto values = Array<int>::New(kStringIntDataSize); | |
109 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
110 keys[i] = kStringIntData[i].string_data; | |
111 values[i] = kStringIntData[i].int_data; | |
112 } | |
113 | |
114 Map<String, int> map(keys.Pass(), values.Pass()); | |
115 | |
116 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
117 EXPECT_EQ(kStringIntData[i].int_data, | |
118 map.at(mojo::String(kStringIntData[i].string_data))); | |
119 } | |
120 } | |
121 | |
122 TEST(MapTest, Insert_Copyable) { | |
123 ASSERT_EQ(0u, CopyableType::num_instances()); | |
124 mojo::Map<mojo::String, CopyableType> map; | |
125 std::vector<CopyableType*> value_ptrs; | |
126 | |
127 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
128 const char* key = kStringIntData[i].string_data; | |
129 CopyableType value; | |
130 value_ptrs.push_back(value.ptr()); | |
131 map.insert(key, value); | |
132 ASSERT_EQ(i + 1, map.size()); | |
133 ASSERT_EQ(i + 1, value_ptrs.size()); | |
134 EXPECT_EQ(map.size() + 1, CopyableType::num_instances()); | |
135 EXPECT_TRUE(map.at(key).copied()); | |
136 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); | |
137 map.at(key).ResetCopied(); | |
138 EXPECT_TRUE(map); | |
139 } | |
140 | |
141 // std::map doesn't have a capacity() method like std::vector so this test is | |
142 // a lot more boring. | |
143 | |
144 map.reset(); | |
145 EXPECT_EQ(0u, CopyableType::num_instances()); | |
146 } | |
147 | |
148 TEST(MapTest, Insert_MoveOnly) { | |
149 ASSERT_EQ(0u, MoveOnlyType::num_instances()); | |
150 mojo::Map<mojo::String, MoveOnlyType> map; | |
151 std::vector<MoveOnlyType*> value_ptrs; | |
152 | |
153 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
154 const char* key = kStringIntData[i].string_data; | |
155 MoveOnlyType value; | |
156 value_ptrs.push_back(value.ptr()); | |
157 map.insert(key, value.Pass()); | |
158 ASSERT_EQ(i + 1, map.size()); | |
159 ASSERT_EQ(i + 1, value_ptrs.size()); | |
160 EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances()); | |
161 EXPECT_TRUE(map.at(key).moved()); | |
162 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); | |
163 map.at(key).ResetMoved(); | |
164 EXPECT_TRUE(map); | |
165 } | |
166 | |
167 // std::map doesn't have a capacity() method like std::vector so this test is | |
168 // a lot more boring. | |
169 | |
170 map.reset(); | |
171 EXPECT_EQ(0u, MoveOnlyType::num_instances()); | |
172 } | |
173 | |
174 TEST(MapTest, IndexOperator_MoveOnly) { | |
175 ASSERT_EQ(0u, MoveOnlyType::num_instances()); | |
176 mojo::Map<mojo::String, MoveOnlyType> map; | |
177 std::vector<MoveOnlyType*> value_ptrs; | |
178 | |
179 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
180 const char* key = kStringIntData[i].string_data; | |
181 MoveOnlyType value; | |
182 value_ptrs.push_back(value.ptr()); | |
183 map[key] = value.Pass(); | |
184 ASSERT_EQ(i + 1, map.size()); | |
185 ASSERT_EQ(i + 1, value_ptrs.size()); | |
186 EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances()); | |
187 EXPECT_TRUE(map.at(key).moved()); | |
188 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); | |
189 map.at(key).ResetMoved(); | |
190 EXPECT_TRUE(map); | |
191 } | |
192 | |
193 // std::map doesn't have a capacity() method like std::vector so this test is | |
194 // a lot more boring. | |
195 | |
196 map.reset(); | |
197 EXPECT_EQ(0u, MoveOnlyType::num_instances()); | |
198 } | |
199 | |
200 TEST(MapTest, STLToMojo) { | |
201 std::map<std::string, int> stl_data; | |
202 for (size_t i = 0; i < kStringIntDataSize; ++i) | |
203 stl_data[kStringIntData[i].string_data] = kStringIntData[i].int_data; | |
204 | |
205 Map<String, int32_t> mojo_data = Map<String, int32_t>::From(stl_data); | |
206 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
207 EXPECT_EQ(kStringIntData[i].int_data, | |
208 mojo_data.at(kStringIntData[i].string_data)); | |
209 } | |
210 } | |
211 | |
212 TEST(MapTest, MojoToSTL) { | |
213 Map<String, int32_t> mojo_map; | |
214 for (size_t i = 0; i < kStringIntDataSize; ++i) | |
215 mojo_map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); | |
216 | |
217 std::map<std::string, int> stl_map = | |
218 mojo_map.To<std::map<std::string, int>>(); | |
219 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
220 auto it = stl_map.find(kStringIntData[i].string_data); | |
221 ASSERT_TRUE(it != stl_map.end()); | |
222 EXPECT_EQ(kStringIntData[i].int_data, it->second); | |
223 } | |
224 } | |
225 | |
226 TEST(MapTest, MapArrayClone) { | |
227 Map<String, Array<String>> m; | |
228 for (size_t i = 0; i < kStringIntDataSize; ++i) { | |
229 Array<String> s; | |
230 s.push_back(kStringIntData[i].string_data); | |
231 m.insert(kStringIntData[i].string_data, s.Pass()); | |
232 } | |
233 | |
234 Map<String, Array<String>> m2 = m.Clone(); | |
235 | |
236 for (auto it = m2.begin(); it != m2.end(); ++it) { | |
237 ASSERT_EQ(1u, it.GetValue().size()); | |
238 EXPECT_EQ(it.GetKey(), it.GetValue().at(0)); | |
239 } | |
240 } | |
241 | |
242 TEST(MapTest, ArrayOfMap) { | |
243 { | |
244 auto array = Array<Map<int32_t, int8_t>>::New(1); | |
245 array[0].insert(1, 42); | |
246 | |
247 size_t size = GetSerializedSize_(array); | |
248 FixedBufferForTesting buf(size); | |
249 Array_Data<Map_Data<int32_t, int8_t>*>* data = nullptr; | |
250 ArrayValidateParams validate_params( | |
251 0, false, new ArrayValidateParams(0, false, nullptr)); | |
252 EXPECT_EQ(ValidationError::NONE, | |
253 SerializeArray_(&array, &buf, &data, &validate_params)); | |
254 | |
255 Array<Map<int32_t, int8_t>> deserialized_array; | |
256 Deserialize_(data, &deserialized_array); | |
257 | |
258 ASSERT_EQ(1u, deserialized_array.size()); | |
259 ASSERT_EQ(1u, deserialized_array[0].size()); | |
260 ASSERT_EQ(42, deserialized_array[0].at(1)); | |
261 } | |
262 | |
263 { | |
264 auto array = Array<Map<String, Array<bool>>>::New(1); | |
265 auto map_value = Array<bool>::New(2); | |
266 map_value[0] = false; | |
267 map_value[1] = true; | |
268 array[0].insert("hello world", map_value.Pass()); | |
269 | |
270 size_t size = GetSerializedSize_(array); | |
271 FixedBufferForTesting buf(size); | |
272 Array_Data<Map_Data<String_Data*, Array_Data<bool>*>*>* data = nullptr; | |
273 ArrayValidateParams validate_params( | |
274 0, false, new ArrayValidateParams( | |
275 0, false, new ArrayValidateParams(0, false, nullptr))); | |
276 EXPECT_EQ(ValidationError::NONE, | |
277 SerializeArray_(&array, &buf, &data, &validate_params)); | |
278 | |
279 Array<Map<String, Array<bool>>> deserialized_array; | |
280 Deserialize_(data, &deserialized_array); | |
281 | |
282 ASSERT_EQ(1u, deserialized_array.size()); | |
283 ASSERT_EQ(1u, deserialized_array[0].size()); | |
284 ASSERT_FALSE(deserialized_array[0].at("hello world")[0]); | |
285 ASSERT_TRUE(deserialized_array[0].at("hello world")[1]); | |
286 } | |
287 } | |
288 | |
289 TEST(MapTest, Serialization_MapWithScopedEnumKeys) { | |
290 enum class TestEnum : int32_t { | |
291 E0, | |
292 E1, | |
293 E2, | |
294 E3, | |
295 }; | |
296 static const TestEnum TEST_KEYS[] = { | |
297 TestEnum::E0, TestEnum::E2, TestEnum::E1, TestEnum::E3, | |
298 }; | |
299 static const uint32_t TEST_VALS[] = {17, 29, 5, 61}; | |
300 | |
301 ASSERT_EQ(MOJO_ARRAYSIZE(TEST_KEYS), MOJO_ARRAYSIZE(TEST_VALS)); | |
302 | |
303 Map<TestEnum, uint32_t> test_map; | |
304 for (size_t i = 0; i < MOJO_ARRAYSIZE(TEST_KEYS); ++i) { | |
305 test_map[TEST_KEYS[i]] = TEST_VALS[i]; | |
306 } | |
307 | |
308 size_t size = GetSerializedSize_(test_map); | |
309 FixedBufferForTesting buf(size); | |
310 Map_Data<int32_t, uint32_t>* data = nullptr; | |
311 ArrayValidateParams validate_params(0, false, nullptr); | |
312 | |
313 SerializeMap_(&test_map, &buf, &data, &validate_params); | |
314 | |
315 Map<TestEnum, uint32_t> test_map2; | |
316 Deserialize_(data, &test_map2); | |
317 | |
318 EXPECT_TRUE(test_map2.Equals(test_map)); | |
319 | |
320 for (auto iter = test_map.cbegin(); iter != test_map.cend(); ++iter) { | |
321 ASSERT_NE(test_map2.find(iter.GetKey()), test_map2.end()); | |
322 EXPECT_EQ(test_map.at(iter.GetKey()), test_map.at(iter.GetKey())); | |
323 } | |
324 | |
325 for (auto iter = test_map2.cbegin(); iter != test_map2.cend(); ++iter) { | |
326 ASSERT_NE(test_map.find(iter.GetKey()), test_map.end()); | |
327 EXPECT_EQ(test_map2.at(iter.GetKey()), test_map2.at(iter.GetKey())); | |
328 } | |
329 } | |
330 | |
331 TEST(MapTest, Serialization_MapWithScopedEnumVals) { | |
332 enum class TestEnum : int32_t { | |
333 E0, | |
334 E1, | |
335 E2, | |
336 E3, | |
337 }; | |
338 static const uint32_t TEST_KEYS[] = {17, 29, 5, 61}; | |
339 static const TestEnum TEST_VALS[] = { | |
340 TestEnum::E0, TestEnum::E2, TestEnum::E1, TestEnum::E3, | |
341 }; | |
342 | |
343 ASSERT_EQ(MOJO_ARRAYSIZE(TEST_KEYS), MOJO_ARRAYSIZE(TEST_VALS)); | |
344 | |
345 Map<uint32_t, TestEnum> test_map; | |
346 for (size_t i = 0; i < MOJO_ARRAYSIZE(TEST_KEYS); ++i) { | |
347 test_map[TEST_KEYS[i]] = TEST_VALS[i]; | |
348 } | |
349 | |
350 size_t size = GetSerializedSize_(test_map); | |
351 FixedBufferForTesting buf(size); | |
352 Map_Data<uint32_t, int32_t>* data = nullptr; | |
353 ArrayValidateParams validate_params(0, false, nullptr); | |
354 | |
355 SerializeMap_(&test_map, &buf, &data, &validate_params); | |
356 | |
357 Map<uint32_t, TestEnum> test_map2; | |
358 Deserialize_(data, &test_map2); | |
359 | |
360 EXPECT_TRUE(test_map2.Equals(test_map)); | |
361 | |
362 for (auto iter = test_map.cbegin(); iter != test_map.cend(); ++iter) { | |
363 ASSERT_NE(test_map2.find(iter.GetKey()), test_map2.end()); | |
364 EXPECT_EQ(test_map.at(iter.GetKey()), test_map.at(iter.GetKey())); | |
365 } | |
366 | |
367 for (auto iter = test_map2.cbegin(); iter != test_map2.cend(); ++iter) { | |
368 ASSERT_NE(test_map.find(iter.GetKey()), test_map.end()); | |
369 EXPECT_EQ(test_map2.at(iter.GetKey()), test_map2.at(iter.GetKey())); | |
370 } | |
371 } | |
372 | |
373 // Test serialization/deserialization of a map with null elements. | |
374 TEST(MapTest, Serialization_MapOfNullableStructs) { | |
375 ArrayValidateParams validate_nullable(2, true, nullptr); | |
376 ArrayValidateParams validate_non_nullable(2, false, nullptr); | |
377 | |
378 Map<uint32_t, RectPtr> map; | |
379 map[0] = RectPtr(); | |
380 map[1] = Rect::New(); | |
381 map[1]->x = 1; | |
382 map[1]->y = 2; | |
383 map[1]->width = 3; | |
384 map[1]->height = 4; | |
385 EXPECT_TRUE(map[0].is_null()); | |
386 EXPECT_TRUE(!map[1].is_null()); | |
387 | |
388 size_t size = GetSerializedSize_(map); | |
389 EXPECT_EQ(8u + // map header | |
390 (8u + 8u) + // pointers to keys and values array | |
391 (8u + 2 * 4u) + // keys array data | |
392 (8u + // values array data | |
393 (8u) + // 1 null value | |
394 (8u + 8U + 4 * 4U)), // 1 Rect value | |
395 size); | |
396 | |
397 // 1. Should not be able to serialize null elements. | |
398 { | |
399 FixedBufferForTesting buf(size); | |
400 Map_Data<int32_t, Rect::Data_*>* data = nullptr; | |
401 EXPECT_EQ(ValidationError::UNEXPECTED_NULL_POINTER, | |
402 SerializeMap_(&map, &buf, &data, &validate_non_nullable)); | |
403 } | |
404 | |
405 // 2. Successfully serialize null elements. | |
406 FixedBufferForTesting buf(size); | |
407 Map_Data<int32_t, Rect::Data_*>* data = nullptr; | |
408 EXPECT_EQ(ValidationError::NONE, | |
409 SerializeMap_(&map, &buf, &data, &validate_nullable)); | |
410 EXPECT_NE(nullptr, data); | |
411 | |
412 // 3. Deserialize deserialize null elements. | |
413 Map<uint32_t, RectPtr> map2; | |
414 EXPECT_EQ(0u, map2.size()); | |
415 EXPECT_TRUE(map2.is_null()); | |
416 Deserialize_(data, &map2); | |
417 EXPECT_EQ(2u, map2.size()); | |
418 EXPECT_FALSE(map2.is_null()); | |
419 EXPECT_TRUE(map2[0].is_null()); | |
420 EXPECT_FALSE(map2[1].is_null()); | |
421 EXPECT_EQ(1, map2[1]->x); | |
422 EXPECT_EQ(2, map2[1]->y); | |
423 EXPECT_EQ(3, map2[1]->width); | |
424 EXPECT_EQ(4, map2[1]->height); | |
425 } | |
426 | |
427 } // namespace | |
428 } // namespace test | |
429 } // namespace mojo | |
OLD | NEW |