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 "mojo/public/cpp/bindings/array.h" 6 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" 7 #include "mojo/public/cpp/bindings/lib/serialization.h" 8 #include "mojo/public/cpp/bindings/lib/validate_params.h" 9 #include "mojo/public/cpp/bindings/map.h" 10 #include "mojo/public/cpp/bindings/string.h" 11 #include "mojo/public/cpp/bindings/tests/container_test_util.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace WTF { 15 class String; 16 } 17 18 namespace mojo { 19 20 template <typename T> 21 class WTFArray; 22 23 template <typename K, typename V> 24 class WTFMap; 25 26 namespace test { 27 namespace { 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 } // namespace 42 43 template <template <typename...> class MapType> 44 struct TypeTraits; 45 46 template <> 47 struct TypeTraits<Map> { 48 using StringType = mojo::String; 49 template <typename T> 50 using ArrayType = Array<T>; 51 }; 52 53 template <> 54 struct TypeTraits<WTFMap> { 55 using StringType = WTF::String; 56 template <typename T> 57 using ArrayType = WTFArray<T>; 58 }; 59 60 // Common tests for both mojo::Map and mojo::WTFMap. 61 template <template <typename...> class MapType> 62 class MapCommonTest { 63 public: 64 using StringType = typename TypeTraits<MapType>::StringType; 65 template <typename T> 66 using ArrayType = typename TypeTraits<MapType>::template ArrayType<T>; 67 68 // Tests null and empty maps. 69 static void NullAndEmpty() { 70 MapType<char, char> map0; 71 EXPECT_TRUE(map0.empty()); 72 EXPECT_FALSE(map0.is_null()); 73 map0 = nullptr; 74 EXPECT_TRUE(map0.is_null()); 75 EXPECT_FALSE(map0.empty()); 76 77 MapType<char, char> map1(nullptr); 78 EXPECT_TRUE(map1.is_null()); 79 EXPECT_FALSE(map1.empty()); 80 map1.SetToEmpty(); 81 EXPECT_TRUE(map1.empty()); 82 EXPECT_FALSE(map1.is_null()); 83 } 84 85 // Tests that basic Map operations work. 86 static void InsertWorks() { 87 MapType<StringType, int> map; 88 for (size_t i = 0; i < kStringIntDataSize; ++i) 89 map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); 90 91 for (size_t i = 0; i < kStringIntDataSize; ++i) { 92 EXPECT_EQ(kStringIntData[i].int_data, 93 map.at(kStringIntData[i].string_data)); 94 } 95 } 96 97 static void TestIndexOperator() { 98 MapType<StringType, int> map; 99 for (size_t i = 0; i < kStringIntDataSize; ++i) 100 map[kStringIntData[i].string_data] = kStringIntData[i].int_data; 101 102 for (size_t i = 0; i < kStringIntDataSize; ++i) { 103 EXPECT_EQ(kStringIntData[i].int_data, 104 map.at(kStringIntData[i].string_data)); 105 } 106 } 107 108 static void TestIndexOperatorAsRValue() { 109 MapType<StringType, int> map; 110 for (size_t i = 0; i < kStringIntDataSize; ++i) 111 map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); 112 113 for (size_t i = 0; i < kStringIntDataSize; ++i) { 114 EXPECT_EQ(kStringIntData[i].int_data, map[kStringIntData[i].string_data]); 115 } 116 } 117 118 static void TestIndexOperatorMoveOnly() { 119 ASSERT_EQ(0u, MoveOnlyType::num_instances()); 120 MapType<StringType, ArrayType<int32_t>> map; 121 122 for (size_t i = 0; i < kStringIntDataSize; ++i) { 123 const char* key = kStringIntData[i].string_data; 124 ArrayType<int32_t> array(1); 125 array[0] = kStringIntData[i].int_data; 126 map[key] = std::move(array); 127 EXPECT_TRUE(map); 128 } 129 130 // We now read back that data, to test the behavior of operator[]. 131 for (size_t i = 0; i < kStringIntDataSize; ++i) { 132 auto& value = map[kStringIntData[i].string_data]; 133 ASSERT_EQ(1u, value.size()); 134 EXPECT_EQ(kStringIntData[i].int_data, value[0]); 135 } 136 } 137 138 static void MapArrayClone() { 139 MapType<StringType, ArrayType<StringType>> m; 140 for (size_t i = 0; i < kStringIntDataSize; ++i) { 141 ArrayType<StringType> s(1); 142 s[0] = StringType(kStringIntData[i].string_data); 143 m.insert(kStringIntData[i].string_data, std::move(s)); 144 } 145 146 MapType<StringType, ArrayType<StringType>> m2 = m.Clone(); 147 148 for (size_t i = 0; i < kStringIntDataSize; ++i) { 149 ASSERT_NE(m2.end(), m2.find(kStringIntData[i].string_data)); 150 ASSERT_EQ(1u, m2[kStringIntData[i].string_data].size()); 151 EXPECT_EQ(StringType(kStringIntData[i].string_data), 152 m2[kStringIntData[i].string_data][0]); 153 } 154 } 155 156 static void ArrayOfMap() { 157 { 158 using MojomType = Array<Map<int32_t, int8_t>>; 159 using UserType = ArrayType<MapType<int32_t, int8_t>>; 160 161 UserType array(1); 162 array[0].insert(1, 42); 163 164 mojo::internal::SerializationContext context; 165 size_t size = 166 mojo::internal::PrepareToSerialize<MojomType>(array, &context); 167 mojo::internal::FixedBufferForTesting buf(size); 168 typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; 169 mojo::internal::ContainerValidateParams validate_params( 170 0, false, 171 new mojo::internal::ContainerValidateParams( 172 new mojo::internal::ContainerValidateParams(0, false, nullptr), 173 new mojo::internal::ContainerValidateParams(0, false, nullptr))); 174 175 mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params, 176 &context); 177 178 UserType deserialized_array; 179 mojo::internal::Deserialize<MojomType>(data, &deserialized_array, 180 &context); 181 182 ASSERT_EQ(1u, deserialized_array.size()); 183 ASSERT_EQ(1u, deserialized_array[0].size()); 184 ASSERT_EQ(42, deserialized_array[0].at(1)); 185 } 186 187 { 188 using MojomType = Array<Map<String, Array<bool>>>; 189 using UserType = ArrayType<MapType<StringType, ArrayType<bool>>>; 190 191 UserType array(1); 192 ArrayType<bool> map_value(2); 193 map_value[0] = false; 194 map_value[1] = true; 195 array[0].insert("hello world", std::move(map_value)); 196 197 mojo::internal::SerializationContext context; 198 size_t size = 199 mojo::internal::PrepareToSerialize<MojomType>(array, &context); 200 mojo::internal::FixedBufferForTesting buf(size); 201 typename mojo::internal::MojomTypeTraits<MojomType>::Data* data; 202 mojo::internal::ContainerValidateParams validate_params( 203 0, false, 204 new mojo::internal::ContainerValidateParams( 205 new mojo::internal::ContainerValidateParams( 206 0, false, new mojo::internal::ContainerValidateParams( 207 0, false, nullptr)), 208 new mojo::internal::ContainerValidateParams( 209 0, false, new mojo::internal::ContainerValidateParams( 210 0, false, nullptr)))); 211 mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params, 212 &context); 213 214 UserType deserialized_array; 215 mojo::internal::Deserialize<MojomType>(data, &deserialized_array, 216 &context); 217 218 ASSERT_EQ(1u, deserialized_array.size()); 219 ASSERT_EQ(1u, deserialized_array[0].size()); 220 ASSERT_FALSE(deserialized_array[0].at("hello world")[0]); 221 ASSERT_TRUE(deserialized_array[0].at("hello world")[1]); 222 } 223 } 224 }; 225 226 #define MAP_COMMON_TEST(MapType, test_name) \ 227 TEST_F(MapType##Test, test_name) { MapCommonTest<MapType>::test_name(); } 228 229 } // namespace test 230 } // namespace mojo 231