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 "mojo/public/cpp/bindings/map.h" 6 7#include <stddef.h> 8#include <stdint.h> 9#include <utility> 10 11#include "mojo/public/cpp/bindings/array.h" 12#include "mojo/public/cpp/bindings/string.h" 13#include "mojo/public/cpp/bindings/tests/container_test_util.h" 14#include "mojo/public/cpp/bindings/tests/map_common_test.h" 15#include "testing/gtest/include/gtest/gtest.h" 16 17namespace mojo { 18namespace test { 19 20namespace { 21 22using MapTest = testing::Test; 23 24MAP_COMMON_TEST(Map, NullAndEmpty) 25MAP_COMMON_TEST(Map, InsertWorks) 26MAP_COMMON_TEST(Map, TestIndexOperator) 27MAP_COMMON_TEST(Map, TestIndexOperatorAsRValue) 28MAP_COMMON_TEST(Map, TestIndexOperatorMoveOnly) 29MAP_COMMON_TEST(Map, MapArrayClone) 30MAP_COMMON_TEST(Map, ArrayOfMap) 31 32TEST_F(MapTest, ConstructedFromArray) { 33 Array<String> keys(kStringIntDataSize); 34 Array<int> values(kStringIntDataSize); 35 for (size_t i = 0; i < kStringIntDataSize; ++i) { 36 keys[i] = kStringIntData[i].string_data; 37 values[i] = kStringIntData[i].int_data; 38 } 39 40 Map<String, int> map(std::move(keys), std::move(values)); 41 42 for (size_t i = 0; i < kStringIntDataSize; ++i) { 43 EXPECT_EQ(kStringIntData[i].int_data, 44 map.at(mojo::String(kStringIntData[i].string_data))); 45 } 46} 47 48TEST_F(MapTest, DecomposeMapTo) { 49 Array<String> keys(kStringIntDataSize); 50 Array<int> values(kStringIntDataSize); 51 for (size_t i = 0; i < kStringIntDataSize; ++i) { 52 keys[i] = kStringIntData[i].string_data; 53 values[i] = kStringIntData[i].int_data; 54 } 55 56 Map<String, int> map(std::move(keys), std::move(values)); 57 EXPECT_EQ(kStringIntDataSize, map.size()); 58 59 Array<String> keys2; 60 Array<int> values2; 61 map.DecomposeMapTo(&keys2, &values2); 62 EXPECT_EQ(0u, map.size()); 63 64 EXPECT_EQ(kStringIntDataSize, keys2.size()); 65 EXPECT_EQ(kStringIntDataSize, values2.size()); 66 67 for (size_t i = 0; i < kStringIntDataSize; ++i) { 68 // We are not guaranteed that the copies have the same sorting as the 69 // originals. 70 String key = kStringIntData[i].string_data; 71 int value = kStringIntData[i].int_data; 72 73 bool found = false; 74 for (size_t j = 0; j < keys2.size(); ++j) { 75 if (keys2[j] == key) { 76 EXPECT_EQ(value, values2[j]); 77 found = true; 78 break; 79 } 80 } 81 82 EXPECT_TRUE(found); 83 } 84} 85 86TEST_F(MapTest, Insert_Copyable) { 87 ASSERT_EQ(0u, CopyableType::num_instances()); 88 mojo::Map<mojo::String, CopyableType> map; 89 std::vector<CopyableType*> value_ptrs; 90 91 for (size_t i = 0; i < kStringIntDataSize; ++i) { 92 const char* key = kStringIntData[i].string_data; 93 CopyableType value; 94 value_ptrs.push_back(value.ptr()); 95 map.insert(key, value); 96 ASSERT_EQ(i + 1, map.size()); 97 ASSERT_EQ(i + 1, value_ptrs.size()); 98 EXPECT_EQ(map.size() + 1, CopyableType::num_instances()); 99 EXPECT_TRUE(map.at(key).copied()); 100 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); 101 map.at(key).ResetCopied(); 102 EXPECT_TRUE(map); 103 } 104 105 // std::map doesn't have a capacity() method like std::vector so this test is 106 // a lot more boring. 107 108 map = nullptr; 109 EXPECT_EQ(0u, CopyableType::num_instances()); 110} 111 112TEST_F(MapTest, Insert_MoveOnly) { 113 ASSERT_EQ(0u, MoveOnlyType::num_instances()); 114 mojo::Map<mojo::String, MoveOnlyType> map; 115 std::vector<MoveOnlyType*> value_ptrs; 116 117 for (size_t i = 0; i < kStringIntDataSize; ++i) { 118 const char* key = kStringIntData[i].string_data; 119 MoveOnlyType value; 120 value_ptrs.push_back(value.ptr()); 121 map.insert(key, std::move(value)); 122 ASSERT_EQ(i + 1, map.size()); 123 ASSERT_EQ(i + 1, value_ptrs.size()); 124 EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances()); 125 EXPECT_TRUE(map.at(key).moved()); 126 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); 127 map.at(key).ResetMoved(); 128 EXPECT_TRUE(map); 129 } 130 131 // std::map doesn't have a capacity() method like std::vector so this test is 132 // a lot more boring. 133 134 map = nullptr; 135 EXPECT_EQ(0u, MoveOnlyType::num_instances()); 136} 137 138TEST_F(MapTest, IndexOperator_MoveOnly) { 139 ASSERT_EQ(0u, MoveOnlyType::num_instances()); 140 mojo::Map<mojo::String, MoveOnlyType> map; 141 std::vector<MoveOnlyType*> value_ptrs; 142 143 for (size_t i = 0; i < kStringIntDataSize; ++i) { 144 const char* key = kStringIntData[i].string_data; 145 MoveOnlyType value; 146 value_ptrs.push_back(value.ptr()); 147 map[key] = std::move(value); 148 ASSERT_EQ(i + 1, map.size()); 149 ASSERT_EQ(i + 1, value_ptrs.size()); 150 EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances()); 151 EXPECT_TRUE(map.at(key).moved()); 152 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); 153 map.at(key).ResetMoved(); 154 EXPECT_TRUE(map); 155 } 156 157 // std::map doesn't have a capacity() method like std::vector so this test is 158 // a lot more boring. 159 160 map = nullptr; 161 EXPECT_EQ(0u, MoveOnlyType::num_instances()); 162} 163 164TEST_F(MapTest, STLToMojo) { 165 std::map<std::string, int> stl_data; 166 for (size_t i = 0; i < kStringIntDataSize; ++i) 167 stl_data[kStringIntData[i].string_data] = kStringIntData[i].int_data; 168 169 Map<String, int32_t> mojo_data = Map<String, int32_t>::From(stl_data); 170 for (size_t i = 0; i < kStringIntDataSize; ++i) { 171 EXPECT_EQ(kStringIntData[i].int_data, 172 mojo_data.at(kStringIntData[i].string_data)); 173 } 174} 175 176TEST_F(MapTest, MojoToSTL) { 177 Map<String, int32_t> mojo_map; 178 for (size_t i = 0; i < kStringIntDataSize; ++i) 179 mojo_map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); 180 181 std::map<std::string, int> stl_map = 182 mojo_map.To<std::map<std::string, int>>(); 183 for (size_t i = 0; i < kStringIntDataSize; ++i) { 184 auto it = stl_map.find(kStringIntData[i].string_data); 185 ASSERT_TRUE(it != stl_map.end()); 186 EXPECT_EQ(kStringIntData[i].int_data, it->second); 187 } 188} 189 190TEST_F(MapTest, MoveFromAndToSTLMap_Copyable) { 191 std::map<int32_t, CopyableType> map1; 192 map1.insert(std::make_pair(123, CopyableType())); 193 map1[123].ResetCopied(); 194 195 Map<int32_t, CopyableType> mojo_map(std::move(map1)); 196 ASSERT_EQ(1u, mojo_map.size()); 197 ASSERT_NE(mojo_map.end(), mojo_map.find(123)); 198 ASSERT_FALSE(mojo_map[123].copied()); 199 200 std::map<int32_t, CopyableType> map2(mojo_map.PassStorage()); 201 ASSERT_EQ(1u, map2.size()); 202 ASSERT_NE(map2.end(), map2.find(123)); 203 ASSERT_FALSE(map2[123].copied()); 204 205 ASSERT_EQ(0u, mojo_map.size()); 206 ASSERT_TRUE(mojo_map.is_null()); 207} 208 209TEST_F(MapTest, MoveFromAndToSTLMap_MoveOnly) { 210 std::map<int32_t, MoveOnlyType> map1; 211 map1.insert(std::make_pair(123, MoveOnlyType())); 212 213 Map<int32_t, MoveOnlyType> mojo_map(std::move(map1)); 214 ASSERT_EQ(1u, mojo_map.size()); 215 ASSERT_NE(mojo_map.end(), mojo_map.find(123)); 216 217 std::map<int32_t, MoveOnlyType> map2(mojo_map.PassStorage()); 218 ASSERT_EQ(1u, map2.size()); 219 ASSERT_NE(map2.end(), map2.find(123)); 220 221 ASSERT_EQ(0u, mojo_map.size()); 222 ASSERT_TRUE(mojo_map.is_null()); 223} 224 225} // namespace 226} // namespace test 227} // namespace mojo 228