scoped_generic_unittest.cc 6.9 KB

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