Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / base / scoped_generic_unittest.cc
1 // Copyright 2014 The Chromium Authors
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 "base/scoped_generic.h"
6
7 #include <memory>
8 #include <unordered_map>
9 #include <unordered_set>
10 #include <utility>
11 #include <vector>
12
13 #include "base/containers/contains.h"
14 #include "base/memory/raw_ptr.h"
15 #include "build/build_config.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 namespace {
21
22 struct IntTraits {
23   IntTraits(std::vector<int>* freed) : freed_ints(freed) {}
24
25   static int InvalidValue() {
26     return -1;
27   }
28   void Free(int value) {
29     freed_ints->push_back(value);
30   }
31
32   raw_ptr<std::vector<int>> freed_ints;
33 };
34
35 using ScopedInt = ScopedGeneric<int, IntTraits>;
36
37 }  // namespace
38
39 TEST(ScopedGenericTest, ScopedGeneric) {
40   std::vector<int> values_freed;
41   IntTraits traits(&values_freed);
42
43   // Invalid case, delete should not be called.
44   {
45     ScopedInt a(IntTraits::InvalidValue(), traits);
46   }
47   EXPECT_TRUE(values_freed.empty());
48
49   // Simple deleting case.
50   static const int kFirst = 0;
51   {
52     ScopedInt a(kFirst, traits);
53   }
54   ASSERT_EQ(1u, values_freed.size());
55   ASSERT_EQ(kFirst, values_freed[0]);
56   values_freed.clear();
57
58   // Release should return the right value and leave the object empty.
59   {
60     ScopedInt a(kFirst, traits);
61     EXPECT_EQ(kFirst, a.release());
62
63     ScopedInt b(IntTraits::InvalidValue(), traits);
64     EXPECT_EQ(IntTraits::InvalidValue(), b.release());
65   }
66   ASSERT_TRUE(values_freed.empty());
67
68   // Reset should free the old value, then the new one should go away when
69   // it goes out of scope.
70   static const int kSecond = 1;
71   {
72     ScopedInt b(kFirst, traits);
73     b.reset(kSecond);
74     ASSERT_EQ(1u, values_freed.size());
75     ASSERT_EQ(kFirst, values_freed[0]);
76   }
77   ASSERT_EQ(2u, values_freed.size());
78   ASSERT_EQ(kSecond, values_freed[1]);
79   values_freed.clear();
80
81   // Move constructor.
82   {
83     ScopedInt a(kFirst, traits);
84     ScopedInt b(std::move(a));
85     EXPECT_TRUE(values_freed.empty());  // Nothing should be freed.
86     ASSERT_EQ(IntTraits::InvalidValue(), a.get());
87     ASSERT_EQ(kFirst, b.get());
88   }
89
90   ASSERT_EQ(1u, values_freed.size());
91   ASSERT_EQ(kFirst, values_freed[0]);
92   values_freed.clear();
93
94   // Move assign.
95   {
96     ScopedInt a(kFirst, traits);
97     ScopedInt b(kSecond, traits);
98     b = std::move(a);
99     ASSERT_EQ(1u, values_freed.size());
100     EXPECT_EQ(kSecond, values_freed[0]);
101     ASSERT_EQ(IntTraits::InvalidValue(), a.get());
102     ASSERT_EQ(kFirst, b.get());
103   }
104
105   ASSERT_EQ(2u, values_freed.size());
106   EXPECT_EQ(kFirst, values_freed[1]);
107   values_freed.clear();
108 }
109
110 TEST(ScopedGenericTest, Operators) {
111   std::vector<int> values_freed;
112   IntTraits traits(&values_freed);
113
114   static const int kFirst = 0;
115   static const int kSecond = 1;
116   {
117     ScopedInt a(kFirst, traits);
118     EXPECT_TRUE(a == kFirst);
119     EXPECT_FALSE(a != kFirst);
120     EXPECT_FALSE(a == kSecond);
121     EXPECT_TRUE(a != kSecond);
122
123     EXPECT_TRUE(kFirst == a);
124     EXPECT_FALSE(kFirst != a);
125     EXPECT_FALSE(kSecond == a);
126     EXPECT_TRUE(kSecond != a);
127   }
128
129   // is_valid().
130   {
131     ScopedInt a(kFirst, traits);
132     EXPECT_TRUE(a.is_valid());
133     a.reset();
134     EXPECT_FALSE(a.is_valid());
135   }
136 }
137
138 TEST(ScopedGenericTest, Receive) {
139   std::vector<int> values_freed;
140   IntTraits traits(&values_freed);
141   auto a = std::make_unique<ScopedInt>(123, traits);
142
143   EXPECT_EQ(123, a->get());
144
145   {
146     ScopedInt::Receiver r(*a);
147     EXPECT_EQ(123, a->get());
148     *r.get() = 456;
149     EXPECT_EQ(123, a->get());
150   }
151
152   EXPECT_EQ(456, a->get());
153
154   {
155     ScopedInt::Receiver r(*a);
156     EXPECT_DEATH_IF_SUPPORTED(a.reset(), "");
157     EXPECT_DEATH_IF_SUPPORTED(ScopedInt::Receiver(*a).get(), "");
158   }
159 }
160
161 namespace {
162
163 struct TrackedIntTraits : public ScopedGenericOwnershipTracking {
164   using OwnerMap =
165       std::unordered_map<int, const ScopedGeneric<int, TrackedIntTraits>*>;
166   TrackedIntTraits(std::unordered_set<int>* freed, OwnerMap* owners)
167       : freed(freed), owners(owners) {}
168
169   static int InvalidValue() { return -1; }
170
171   void Free(int value) {
172     auto it = owners->find(value);
173     ASSERT_EQ(owners->end(), it);
174
175     ASSERT_EQ(0U, freed->count(value));
176     freed->insert(value);
177   }
178
179   void Acquire(const ScopedGeneric<int, TrackedIntTraits>& owner, int value) {
180     auto it = owners->find(value);
181     ASSERT_EQ(owners->end(), it);
182     (*owners)[value] = &owner;
183   }
184
185   void Release(const ScopedGeneric<int, TrackedIntTraits>& owner, int value) {
186     auto it = owners->find(value);
187     ASSERT_NE(owners->end(), it);
188     owners->erase(it);
189   }
190
191   raw_ptr<std::unordered_set<int>> freed;
192   raw_ptr<OwnerMap> owners;
193 };
194
195 using ScopedTrackedInt = ScopedGeneric<int, TrackedIntTraits>;
196
197 }  // namespace
198
199 TEST(ScopedGenericTest, OwnershipTracking) {
200   TrackedIntTraits::OwnerMap owners;
201   std::unordered_set<int> freed;
202   TrackedIntTraits traits(&freed, &owners);
203
204 #define ASSERT_OWNED(value, owner)            \
205   ASSERT_TRUE(base::Contains(owners, value)); \
206   ASSERT_EQ(&owner, owners[value]);           \
207   ASSERT_FALSE(base::Contains(freed, value))
208
209 #define ASSERT_UNOWNED(value)                  \
210   ASSERT_FALSE(base::Contains(owners, value)); \
211   ASSERT_FALSE(base::Contains(freed, value))
212
213 #define ASSERT_FREED(value)                    \
214   ASSERT_FALSE(base::Contains(owners, value)); \
215   ASSERT_TRUE(base::Contains(freed, value))
216
217   // Constructor.
218   {
219     {
220       ScopedTrackedInt a(0, traits);
221       ASSERT_OWNED(0, a);
222     }
223     ASSERT_FREED(0);
224   }
225
226   owners.clear();
227   freed.clear();
228
229   // Reset.
230   {
231     ScopedTrackedInt a(0, traits);
232     ASSERT_OWNED(0, a);
233     a.reset(1);
234     ASSERT_FREED(0);
235     ASSERT_OWNED(1, a);
236     a.reset();
237     ASSERT_FREED(0);
238     ASSERT_FREED(1);
239   }
240
241   owners.clear();
242   freed.clear();
243
244   // Release.
245   {
246     {
247       ScopedTrackedInt a(0, traits);
248       ASSERT_OWNED(0, a);
249       int released = a.release();
250       ASSERT_EQ(0, released);
251       ASSERT_UNOWNED(0);
252     }
253     ASSERT_UNOWNED(0);
254   }
255
256   owners.clear();
257   freed.clear();
258
259   // Move constructor.
260   {
261     ScopedTrackedInt a(0, traits);
262     ASSERT_OWNED(0, a);
263     {
264       ScopedTrackedInt b(std::move(a));
265       ASSERT_OWNED(0, b);
266     }
267     ASSERT_FREED(0);
268   }
269
270   owners.clear();
271   freed.clear();
272
273   // Move assignment.
274   {
275     {
276       ScopedTrackedInt a(0, traits);
277       ScopedTrackedInt b(1, traits);
278       ASSERT_OWNED(0, a);
279       ASSERT_OWNED(1, b);
280       a = std::move(b);
281       ASSERT_OWNED(1, a);
282       ASSERT_FREED(0);
283     }
284     ASSERT_FREED(1);
285   }
286
287   owners.clear();
288   freed.clear();
289
290 #undef ASSERT_OWNED
291 #undef ASSERT_UNOWNED
292 #undef ASSERT_FREED
293 }
294
295 // Cheesy manual "no compile" test for manually validating changes.
296 #if 0
297 TEST(ScopedGenericTest, NoCompile) {
298   // Assignment shouldn't work.
299   /*{
300     ScopedInt a(kFirst, traits);
301     ScopedInt b(a);
302   }*/
303
304   // Comparison shouldn't work.
305   /*{
306     ScopedInt a(kFirst, traits);
307     ScopedInt b(kFirst, traits);
308     if (a == b) {
309     }
310   }*/
311
312   // Implicit conversion to bool shouldn't work.
313   /*{
314     ScopedInt a(kFirst, traits);
315     bool result = a;
316   }*/
317 }
318 #endif
319
320 }  // namespace base