Make possible HashSet<std::unique_ptr<>>
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / HashSet.cpp
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "Counters.h"
29 #include "MoveOnly.h"
30 #include <wtf/HashSet.h>
31 #include <wtf/OwnPtr.h>
32 #include <wtf/PassOwnPtr.h>
33
34 namespace TestWebKitAPI {
35
36 template<int initialCapacity>
37     struct InitialCapacityTestHashTraits : public WTF::UnsignedWithZeroKeyHashTraits<int> {
38     static const int minimumTableSize = initialCapacity;
39 };
40
41 template<unsigned size>
42 void testInitialCapacity()
43 {
44     const unsigned initialCapacity = WTF::HashTableCapacityForSize<size>::value;
45     HashSet<int, DefaultHash<int>::Hash, InitialCapacityTestHashTraits<initialCapacity> > testSet;
46
47     // Initial capacity is null.
48     ASSERT_EQ(0, testSet.capacity());
49
50     // Adding items up to size should never change the capacity.
51     for (size_t i = 0; i < size; ++i) {
52         testSet.add(i);
53         ASSERT_EQ(initialCapacity, static_cast<unsigned>(testSet.capacity()));
54     }
55
56     // Adding items up to less than half the capacity should not change the capacity.
57     unsigned capacityLimit = initialCapacity / 2 - 1;
58     for (size_t i = size; i < capacityLimit; ++i) {
59         testSet.add(i);
60         ASSERT_EQ(initialCapacity, static_cast<unsigned>(testSet.capacity()));
61     }
62
63     // Adding one more item increase the capacity.
64     testSet.add(initialCapacity);
65     EXPECT_GT(static_cast<unsigned>(testSet.capacity()), initialCapacity);
66 }
67
68 template<unsigned size> void generateTestCapacityUpToSize();
69 template<> void generateTestCapacityUpToSize<0>()
70 {
71 }
72 template<unsigned size> void generateTestCapacityUpToSize()
73 {
74     generateTestCapacityUpToSize<size - 1>();
75     testInitialCapacity<size>();
76 }
77
78 TEST(WTF_HashSet, InitialCapacity)
79 {
80     generateTestCapacityUpToSize<128>();
81 }
82
83 TEST(WTF_HashSet, MoveOnly)
84 {
85     HashSet<MoveOnly> hashSet;
86
87     for (size_t i = 0; i < 100; ++i) {
88         MoveOnly moveOnly(i + 1);
89         hashSet.add(WTF::move(moveOnly));
90     }
91
92     for (size_t i = 0; i < 100; ++i)
93         EXPECT_TRUE(hashSet.contains(MoveOnly(i + 1)));
94
95     for (size_t i = 0; i < 100; ++i)
96         EXPECT_TRUE(hashSet.remove(MoveOnly(i + 1)));
97
98     EXPECT_TRUE(hashSet.isEmpty());
99
100     for (size_t i = 0; i < 100; ++i)
101         hashSet.add(MoveOnly(i + 1));
102
103     for (size_t i = 0; i < 100; ++i)
104         EXPECT_TRUE(hashSet.take(MoveOnly(i + 1)) == MoveOnly(i + 1));
105
106     EXPECT_TRUE(hashSet.isEmpty());
107
108     for (size_t i = 0; i < 100; ++i)
109         hashSet.add(MoveOnly(i + 1));
110
111     HashSet<MoveOnly> secondSet;
112
113     for (size_t i = 0; i < 100; ++i)
114         secondSet.add(hashSet.takeAny());
115
116     EXPECT_TRUE(hashSet.isEmpty());
117
118     for (size_t i = 0; i < 100; ++i)
119         EXPECT_TRUE(secondSet.contains(MoveOnly(i + 1)));
120 }
121
122 TEST(WTF_HashSet, OwnPtrKey)
123 {
124     ConstructorDestructorCounter::TestingScope scope;
125
126     HashSet<OwnPtr<ConstructorDestructorCounter>> set;
127
128     OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
129     set.add(WTF::move(ownPtr));
130
131     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
132     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
133
134     set.clear();
135     
136     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
137     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
138 }
139
140 TEST(WTF_HashSet, OwnPtrKey_FindUsingRawPointer)
141 {
142     HashSet<OwnPtr<int>> set;
143
144     OwnPtr<int> ownPtr = adoptPtr(new int(5));
145     int* ptr = ownPtr.get();
146     set.add(WTF::move(ownPtr));
147
148     auto it = set.find(ptr);
149     ASSERT_TRUE(it != set.end());
150     EXPECT_EQ(ptr, it->get());
151     EXPECT_EQ(5, *it->get());
152 }
153
154 TEST(WTF_HashSet, OwnPtrKey_ContainsUsingRawPointer)
155 {
156     HashSet<OwnPtr<int>> set;
157
158     OwnPtr<int> ownPtr = adoptPtr(new int(5));
159     int* ptr = ownPtr.get();
160     set.add(WTF::move(ownPtr));
161
162     EXPECT_EQ(true, set.contains(ptr));
163 }
164
165 TEST(WTF_HashSet, OwnPtrKey_RemoveUsingRawPointer)
166 {
167     ConstructorDestructorCounter::TestingScope scope;
168
169     HashSet<OwnPtr<ConstructorDestructorCounter>> set;
170
171     OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
172     ConstructorDestructorCounter* ptr = ownPtr.get();
173     set.add(WTF::move(ownPtr));
174
175     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
176     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
177
178     bool result = set.remove(ptr);
179     EXPECT_EQ(true, result);
180
181     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
182     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
183 }
184
185 TEST(WTF_HashSet, OwnPtrKey_TakeUsingRawPointer)
186 {
187     ConstructorDestructorCounter::TestingScope scope;
188
189     HashSet<OwnPtr<ConstructorDestructorCounter>> set;
190
191     OwnPtr<ConstructorDestructorCounter> ownPtr = adoptPtr(new ConstructorDestructorCounter);
192     ConstructorDestructorCounter* ptr = ownPtr.get();
193     set.add(WTF::move(ownPtr));
194
195     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
196     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
197
198     auto result = set.take(ptr);
199     EXPECT_EQ(ptr, result.get());
200
201     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
202     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
203
204     result = nullptr;
205
206     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
207     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
208 }
209
210 TEST(WTF_HashSet, UniquePtrKey)
211 {
212     ConstructorDestructorCounter::TestingScope scope;
213
214     HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
215
216     auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
217     set.add(WTF::move(uniquePtr));
218
219     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
220     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
221
222     set.clear();
223
224     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
225     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
226 }
227
228 TEST(WTF_HashSet, UniquePtrKey_FindUsingRawPointer)
229 {
230     HashSet<std::unique_ptr<int>> set;
231
232     auto uniquePtr = std::make_unique<int>(5);
233     int* ptr = uniquePtr.get();
234     set.add(WTF::move(uniquePtr));
235
236     auto it = set.find(ptr);
237     ASSERT_TRUE(it != set.end());
238     EXPECT_EQ(ptr, it->get());
239     EXPECT_EQ(5, *it->get());
240 }
241
242 TEST(WTF_HashSet, UniquePtrKey_ContainsUsingRawPointer)
243 {
244     HashSet<std::unique_ptr<int>> set;
245
246     auto uniquePtr = std::make_unique<int>(5);
247     int* ptr = uniquePtr.get();
248     set.add(WTF::move(uniquePtr));
249
250     EXPECT_EQ(true, set.contains(ptr));
251 }
252
253 TEST(WTF_HashSet, UniquePtrKey_RemoveUsingRawPointer)
254 {
255     ConstructorDestructorCounter::TestingScope scope;
256
257     HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
258
259     auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
260     ConstructorDestructorCounter* ptr = uniquePtr.get();
261     set.add(WTF::move(uniquePtr));
262
263     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
264     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
265
266     bool result = set.remove(ptr);
267     EXPECT_EQ(true, result);
268
269     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
270     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
271 }
272
273 TEST(WTF_HashSet, UniquePtrKey_TakeUsingRawPointer)
274 {
275     ConstructorDestructorCounter::TestingScope scope;
276
277     HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
278
279     auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
280     ConstructorDestructorCounter* ptr = uniquePtr.get();
281     set.add(WTF::move(uniquePtr));
282
283     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
284     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
285
286     auto result = set.take(ptr);
287     EXPECT_EQ(ptr, result.get());
288
289     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
290     EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
291     
292     result = nullptr;
293
294     EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
295     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
296 }
297
298 } // namespace TestWebKitAPI