singleton_unittest.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. // Copyright (c) 2012 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 <stdint.h>
  5. #include "base/at_exit.h"
  6. #include "base/memory/aligned_memory.h"
  7. #include "base/memory/singleton.h"
  8. #include "testing/gtest/include/gtest/gtest.h"
  9. namespace base {
  10. namespace {
  11. static_assert(DefaultSingletonTraits<int>::kRegisterAtExit == true,
  12. "object must be deleted on process exit");
  13. typedef void (*CallbackFunc)();
  14. template <size_t alignment>
  15. class AlignedData {
  16. public:
  17. AlignedData() = default;
  18. ~AlignedData() = default;
  19. alignas(alignment) char data_[alignment];
  20. };
  21. class IntSingleton {
  22. public:
  23. static IntSingleton* GetInstance() {
  24. return Singleton<IntSingleton>::get();
  25. }
  26. int value_;
  27. };
  28. class Init5Singleton {
  29. public:
  30. struct Trait;
  31. static Init5Singleton* GetInstance() {
  32. return Singleton<Init5Singleton, Trait>::get();
  33. }
  34. int value_;
  35. };
  36. struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
  37. static Init5Singleton* New() {
  38. Init5Singleton* instance = new Init5Singleton();
  39. instance->value_ = 5;
  40. return instance;
  41. }
  42. };
  43. int* SingletonInt() {
  44. return &IntSingleton::GetInstance()->value_;
  45. }
  46. int* SingletonInt5() {
  47. return &Init5Singleton::GetInstance()->value_;
  48. }
  49. template <typename Type>
  50. struct CallbackTrait : public DefaultSingletonTraits<Type> {
  51. static void Delete(Type* instance) {
  52. if (instance->callback_)
  53. (instance->callback_)();
  54. DefaultSingletonTraits<Type>::Delete(instance);
  55. }
  56. };
  57. class CallbackSingleton {
  58. public:
  59. CallbackSingleton() : callback_(nullptr) {}
  60. CallbackFunc callback_;
  61. };
  62. class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
  63. public:
  64. struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
  65. CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
  66. static CallbackSingletonWithNoLeakTrait* GetInstance() {
  67. return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
  68. }
  69. };
  70. class CallbackSingletonWithLeakTrait : public CallbackSingleton {
  71. public:
  72. struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
  73. static const bool kRegisterAtExit = false;
  74. };
  75. CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
  76. static CallbackSingletonWithLeakTrait* GetInstance() {
  77. return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
  78. }
  79. };
  80. class CallbackSingletonWithStaticTrait : public CallbackSingleton {
  81. public:
  82. struct Trait;
  83. CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
  84. static CallbackSingletonWithStaticTrait* GetInstance() {
  85. return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
  86. }
  87. };
  88. struct CallbackSingletonWithStaticTrait::Trait
  89. : public StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait> {
  90. static void Delete(CallbackSingletonWithStaticTrait* instance) {
  91. if (instance->callback_)
  92. (instance->callback_)();
  93. StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait>::Delete(
  94. instance);
  95. }
  96. };
  97. template <class Type>
  98. class AlignedTestSingleton {
  99. public:
  100. AlignedTestSingleton() = default;
  101. ~AlignedTestSingleton() = default;
  102. static AlignedTestSingleton* GetInstance() {
  103. return Singleton<AlignedTestSingleton,
  104. StaticMemorySingletonTraits<AlignedTestSingleton>>::get();
  105. }
  106. Type type_;
  107. };
  108. void SingletonNoLeak(CallbackFunc CallOnQuit) {
  109. CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
  110. }
  111. void SingletonLeak(CallbackFunc CallOnQuit) {
  112. CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
  113. }
  114. CallbackFunc* GetLeakySingleton() {
  115. return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
  116. }
  117. void DeleteLeakySingleton() {
  118. DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
  119. CallbackSingletonWithLeakTrait::GetInstance());
  120. }
  121. void SingletonStatic(CallbackFunc CallOnQuit) {
  122. CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
  123. }
  124. CallbackFunc* GetStaticSingleton() {
  125. CallbackSingletonWithStaticTrait* instance =
  126. CallbackSingletonWithStaticTrait::GetInstance();
  127. if (instance == nullptr) {
  128. return nullptr;
  129. } else {
  130. return &instance->callback_;
  131. }
  132. }
  133. class SingletonTest : public testing::Test {
  134. public:
  135. SingletonTest() = default;
  136. void SetUp() override {
  137. non_leak_called_ = false;
  138. leaky_called_ = false;
  139. static_called_ = false;
  140. }
  141. protected:
  142. void VerifiesCallbacks() {
  143. EXPECT_TRUE(non_leak_called_);
  144. EXPECT_FALSE(leaky_called_);
  145. EXPECT_TRUE(static_called_);
  146. non_leak_called_ = false;
  147. leaky_called_ = false;
  148. static_called_ = false;
  149. }
  150. void VerifiesCallbacksNotCalled() {
  151. EXPECT_FALSE(non_leak_called_);
  152. EXPECT_FALSE(leaky_called_);
  153. EXPECT_FALSE(static_called_);
  154. non_leak_called_ = false;
  155. leaky_called_ = false;
  156. static_called_ = false;
  157. }
  158. static void CallbackNoLeak() {
  159. non_leak_called_ = true;
  160. }
  161. static void CallbackLeak() {
  162. leaky_called_ = true;
  163. }
  164. static void CallbackStatic() {
  165. static_called_ = true;
  166. }
  167. private:
  168. static bool non_leak_called_;
  169. static bool leaky_called_;
  170. static bool static_called_;
  171. };
  172. bool SingletonTest::non_leak_called_ = false;
  173. bool SingletonTest::leaky_called_ = false;
  174. bool SingletonTest::static_called_ = false;
  175. TEST_F(SingletonTest, Basic) {
  176. int* singleton_int;
  177. int* singleton_int_5;
  178. CallbackFunc* leaky_singleton;
  179. CallbackFunc* static_singleton;
  180. {
  181. ShadowingAtExitManager sem;
  182. {
  183. singleton_int = SingletonInt();
  184. }
  185. // Ensure POD type initialization.
  186. EXPECT_EQ(*singleton_int, 0);
  187. *singleton_int = 1;
  188. EXPECT_EQ(singleton_int, SingletonInt());
  189. EXPECT_EQ(*singleton_int, 1);
  190. {
  191. singleton_int_5 = SingletonInt5();
  192. }
  193. // Is default initialized to 5.
  194. EXPECT_EQ(*singleton_int_5, 5);
  195. SingletonNoLeak(&CallbackNoLeak);
  196. SingletonLeak(&CallbackLeak);
  197. SingletonStatic(&CallbackStatic);
  198. static_singleton = GetStaticSingleton();
  199. leaky_singleton = GetLeakySingleton();
  200. EXPECT_TRUE(leaky_singleton);
  201. }
  202. // Verify that only the expected callback has been called.
  203. VerifiesCallbacks();
  204. // Delete the leaky singleton.
  205. DeleteLeakySingleton();
  206. // The static singleton can't be acquired post-atexit.
  207. EXPECT_EQ(nullptr, GetStaticSingleton());
  208. {
  209. ShadowingAtExitManager sem;
  210. // Verifiy that the variables were reset.
  211. {
  212. singleton_int = SingletonInt();
  213. EXPECT_EQ(*singleton_int, 0);
  214. }
  215. {
  216. singleton_int_5 = SingletonInt5();
  217. EXPECT_EQ(*singleton_int_5, 5);
  218. }
  219. {
  220. // Resurrect the static singleton, and assert that it
  221. // still points to the same (static) memory.
  222. CallbackSingletonWithStaticTrait::Trait::ResurrectForTesting();
  223. EXPECT_EQ(GetStaticSingleton(), static_singleton);
  224. }
  225. }
  226. // The leaky singleton shouldn't leak since SingletonLeak has not been called.
  227. VerifiesCallbacksNotCalled();
  228. }
  229. TEST_F(SingletonTest, Alignment) {
  230. // Create some static singletons with increasing sizes and alignment
  231. // requirements. By ordering this way, the linker will need to do some work to
  232. // ensure proper alignment of the static data.
  233. AlignedTestSingleton<int32_t>* align4 =
  234. AlignedTestSingleton<int32_t>::GetInstance();
  235. AlignedTestSingleton<AlignedData<32>>* align32 =
  236. AlignedTestSingleton<AlignedData<32>>::GetInstance();
  237. AlignedTestSingleton<AlignedData<128>>* align128 =
  238. AlignedTestSingleton<AlignedData<128>>::GetInstance();
  239. AlignedTestSingleton<AlignedData<4096>>* align4096 =
  240. AlignedTestSingleton<AlignedData<4096>>::GetInstance();
  241. EXPECT_TRUE(IsAligned(align4, 4));
  242. EXPECT_TRUE(IsAligned(align32, 32));
  243. EXPECT_TRUE(IsAligned(align128, 128));
  244. EXPECT_TRUE(IsAligned(align4096, 4096));
  245. }
  246. } // namespace
  247. } // namespace base