| 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 |