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
17 namespace mojo {
18 namespace test {
19
20 namespace {
21
22 using MapTest = testing::Test;
23
MAP_COMMON_TEST(Map,NullAndEmpty)24 MAP_COMMON_TEST(Map, NullAndEmpty)
25 MAP_COMMON_TEST(Map, InsertWorks)
26 MAP_COMMON_TEST(Map, TestIndexOperator)
27 MAP_COMMON_TEST(Map, TestIndexOperatorAsRValue)
28 MAP_COMMON_TEST(Map, TestIndexOperatorMoveOnly)
29 MAP_COMMON_TEST(Map, MapArrayClone)
30 MAP_COMMON_TEST(Map, ArrayOfMap)
31
32 TEST_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
TEST_F(MapTest,DecomposeMapTo)48 TEST_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
TEST_F(MapTest,Insert_Copyable)86 TEST_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
TEST_F(MapTest,Insert_MoveOnly)112 TEST_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
TEST_F(MapTest,IndexOperator_MoveOnly)138 TEST_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
TEST_F(MapTest,STLToMojo)164 TEST_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
TEST_F(MapTest,MojoToSTL)176 TEST_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
TEST_F(MapTest,MoveFromAndToSTLMap_Copyable)190 TEST_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
TEST_F(MapTest,MoveFromAndToSTLMap_MoveOnly)209 TEST_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