weak_handle_unittest.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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 "components/sync/base/weak_handle.h"
  5. #include "base/bind.h"
  6. #include "base/run_loop.h"
  7. #include "base/test/task_environment.h"
  8. #include "base/threading/thread.h"
  9. #include "testing/gmock/include/gmock/gmock.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace syncer {
  12. using ::testing::_;
  13. using ::testing::SaveArg;
  14. using ::testing::StrictMock;
  15. class Base {
  16. public:
  17. Base() = default;
  18. WeakHandle<Base> AsWeakHandle() {
  19. return MakeWeakHandle(weak_ptr_factory_.GetWeakPtr());
  20. }
  21. void Kill() { weak_ptr_factory_.InvalidateWeakPtrs(); }
  22. MOCK_METHOD(void, Test, (), ());
  23. MOCK_METHOD(void, Test1, (const int&), ());
  24. MOCK_METHOD(void, Test2, (const int&, Base*), ());
  25. MOCK_METHOD(void, Test3, (const int&, Base*, float), ());
  26. MOCK_METHOD(void, Test4, (const int&, Base*, float, const char*), ());
  27. MOCK_METHOD(void, TestWithSelf, (const WeakHandle<Base>&), ());
  28. private:
  29. base::WeakPtrFactory<Base> weak_ptr_factory_{this};
  30. };
  31. class Derived : public Base, public base::SupportsWeakPtr<Derived> {};
  32. class WeakHandleTest : public ::testing::Test {
  33. protected:
  34. void TearDown() override {
  35. // Process any last-minute posted tasks.
  36. PumpLoop();
  37. }
  38. void PumpLoop() { base::RunLoop().RunUntilIdle(); }
  39. static void CallTestFromOtherThread(base::Location from_here,
  40. const WeakHandle<Base>& h) {
  41. base::Thread t("Test thread");
  42. ASSERT_TRUE(t.Start());
  43. t.task_runner()->PostTask(
  44. from_here, base::BindOnce(&WeakHandleTest::CallTest, from_here, h));
  45. }
  46. private:
  47. static void CallTest(base::Location from_here, const WeakHandle<Base>& h) {
  48. h.Call(from_here, &Base::Test);
  49. }
  50. base::test::SingleThreadTaskEnvironment task_environment_;
  51. };
  52. TEST_F(WeakHandleTest, Uninitialized) {
  53. // Default.
  54. WeakHandle<int> h;
  55. EXPECT_FALSE(h.IsInitialized());
  56. // Copy.
  57. {
  58. WeakHandle<int> h2(h);
  59. EXPECT_FALSE(h2.IsInitialized());
  60. }
  61. // Assign.
  62. {
  63. WeakHandle<int> h2;
  64. h2 = h;
  65. EXPECT_FALSE(h.IsInitialized());
  66. }
  67. }
  68. TEST_F(WeakHandleTest, InitializedAfterDestroy) {
  69. WeakHandle<Base> h;
  70. {
  71. StrictMock<Base> b;
  72. h = b.AsWeakHandle();
  73. }
  74. EXPECT_TRUE(h.IsInitialized());
  75. EXPECT_FALSE(h.Get());
  76. }
  77. TEST_F(WeakHandleTest, InitializedAfterInvalidate) {
  78. StrictMock<Base> b;
  79. WeakHandle<Base> h = b.AsWeakHandle();
  80. b.Kill();
  81. EXPECT_TRUE(h.IsInitialized());
  82. EXPECT_FALSE(h.Get());
  83. }
  84. TEST_F(WeakHandleTest, Call) {
  85. StrictMock<Base> b;
  86. const char test_str[] = "test";
  87. EXPECT_CALL(b, Test());
  88. EXPECT_CALL(b, Test1(5));
  89. EXPECT_CALL(b, Test2(5, &b));
  90. EXPECT_CALL(b, Test3(5, &b, 5));
  91. EXPECT_CALL(b, Test4(5, &b, 5, test_str));
  92. WeakHandle<Base> h = b.AsWeakHandle();
  93. EXPECT_TRUE(h.IsInitialized());
  94. // Should run.
  95. h.Call(FROM_HERE, &Base::Test);
  96. h.Call(FROM_HERE, &Base::Test1, 5);
  97. h.Call(FROM_HERE, &Base::Test2, 5, &b);
  98. h.Call(FROM_HERE, &Base::Test3, 5, &b, 5);
  99. h.Call(FROM_HERE, &Base::Test4, 5, &b, 5, test_str);
  100. PumpLoop();
  101. }
  102. TEST_F(WeakHandleTest, CallAfterDestroy) {
  103. {
  104. StrictMock<Base> b;
  105. EXPECT_CALL(b, Test()).Times(0);
  106. WeakHandle<Base> h = b.AsWeakHandle();
  107. EXPECT_TRUE(h.IsInitialized());
  108. // Should not run.
  109. h.Call(FROM_HERE, &Base::Test);
  110. }
  111. PumpLoop();
  112. }
  113. TEST_F(WeakHandleTest, CallAfterInvalidate) {
  114. StrictMock<Base> b;
  115. EXPECT_CALL(b, Test()).Times(0);
  116. WeakHandle<Base> h = b.AsWeakHandle();
  117. EXPECT_TRUE(h.IsInitialized());
  118. // Should not run.
  119. h.Call(FROM_HERE, &Base::Test);
  120. b.Kill();
  121. PumpLoop();
  122. }
  123. TEST_F(WeakHandleTest, CallThreaded) {
  124. StrictMock<Base> b;
  125. EXPECT_CALL(b, Test());
  126. WeakHandle<Base> h = b.AsWeakHandle();
  127. // Should run.
  128. CallTestFromOtherThread(FROM_HERE, h);
  129. PumpLoop();
  130. }
  131. TEST_F(WeakHandleTest, CallAfterDestroyThreaded) {
  132. WeakHandle<Base> h;
  133. {
  134. StrictMock<Base> b;
  135. EXPECT_CALL(b, Test()).Times(0);
  136. h = b.AsWeakHandle();
  137. }
  138. // Should not run.
  139. CallTestFromOtherThread(FROM_HERE, h);
  140. PumpLoop();
  141. }
  142. TEST_F(WeakHandleTest, CallAfterInvalidateThreaded) {
  143. StrictMock<Base> b;
  144. EXPECT_CALL(b, Test()).Times(0);
  145. WeakHandle<Base> h = b.AsWeakHandle();
  146. b.Kill();
  147. // Should not run.
  148. CallTestFromOtherThread(FROM_HERE, h);
  149. PumpLoop();
  150. }
  151. TEST_F(WeakHandleTest, DeleteOnOtherThread) {
  152. StrictMock<Base> b;
  153. EXPECT_CALL(b, Test()).Times(0);
  154. WeakHandle<Base>* h = new WeakHandle<Base>(b.AsWeakHandle());
  155. {
  156. base::Thread t("Test thread");
  157. ASSERT_TRUE(t.Start());
  158. t.task_runner()->DeleteSoon(FROM_HERE, h);
  159. }
  160. PumpLoop();
  161. }
  162. void CallTestWithSelf(const WeakHandle<Base>& b1) {
  163. StrictMock<Base> b2;
  164. b1.Call(FROM_HERE, &Base::TestWithSelf, b2.AsWeakHandle());
  165. }
  166. TEST_F(WeakHandleTest, WithDestroyedThread) {
  167. StrictMock<Base> b1;
  168. WeakHandle<Base> b2;
  169. EXPECT_CALL(b1, TestWithSelf).WillOnce(SaveArg<0>(&b2));
  170. {
  171. base::Thread t("Test thread");
  172. ASSERT_TRUE(t.Start());
  173. t.task_runner()->PostTask(
  174. FROM_HERE, base::BindOnce(&CallTestWithSelf, b1.AsWeakHandle()));
  175. }
  176. // Calls b1.TestWithSelf().
  177. PumpLoop();
  178. // Shouldn't do anything, since the thread is gone.
  179. b2.Call(FROM_HERE, &Base::Test);
  180. // |b2| shouldn't leak when it's destroyed, even if the original
  181. // thread is gone.
  182. }
  183. TEST_F(WeakHandleTest, InitializedAcrossCopyAssign) {
  184. StrictMock<Base> b;
  185. EXPECT_CALL(b, Test()).Times(3);
  186. EXPECT_TRUE(b.AsWeakHandle().IsInitialized());
  187. b.AsWeakHandle().Call(FROM_HERE, &Base::Test);
  188. {
  189. WeakHandle<Base> h(b.AsWeakHandle());
  190. EXPECT_TRUE(h.IsInitialized());
  191. h.Call(FROM_HERE, &Base::Test);
  192. h.Reset();
  193. EXPECT_FALSE(h.IsInitialized());
  194. }
  195. {
  196. WeakHandle<Base> h;
  197. h = b.AsWeakHandle();
  198. EXPECT_TRUE(h.IsInitialized());
  199. h.Call(FROM_HERE, &Base::Test);
  200. h.Reset();
  201. EXPECT_FALSE(h.IsInitialized());
  202. }
  203. PumpLoop();
  204. }
  205. TEST_F(WeakHandleTest, TypeConversionConstructor) {
  206. StrictMock<Derived> d;
  207. EXPECT_CALL(d, Test()).Times(2);
  208. const WeakHandle<Derived> weak_handle = MakeWeakHandle(d.AsWeakPtr());
  209. // Should trigger type conversion constructor.
  210. const WeakHandle<Base> base_weak_handle(weak_handle);
  211. // Should trigger regular copy constructor.
  212. const WeakHandle<Derived> derived_weak_handle(weak_handle);
  213. EXPECT_TRUE(base_weak_handle.IsInitialized());
  214. base_weak_handle.Call(FROM_HERE, &Base::Test);
  215. EXPECT_TRUE(derived_weak_handle.IsInitialized());
  216. // Copy constructor shouldn't construct a new |core_|.
  217. EXPECT_EQ(weak_handle.core_.get(), derived_weak_handle.core_.get());
  218. derived_weak_handle.Call(FROM_HERE, &Base::Test);
  219. PumpLoop();
  220. }
  221. TEST_F(WeakHandleTest, TypeConversionConstructorMakeWeakHandle) {
  222. const base::WeakPtr<Derived> weak_ptr;
  223. // Should trigger type conversion constructor after MakeWeakHandle.
  224. WeakHandle<Base> base_weak_handle(MakeWeakHandle(weak_ptr));
  225. // Should trigger regular copy constructor after MakeWeakHandle.
  226. const WeakHandle<Derived> derived_weak_handle(MakeWeakHandle(weak_ptr));
  227. EXPECT_TRUE(base_weak_handle.IsInitialized());
  228. EXPECT_TRUE(derived_weak_handle.IsInitialized());
  229. }
  230. TEST_F(WeakHandleTest, TypeConversionConstructorAssignment) {
  231. const WeakHandle<Derived> weak_handle = MakeWeakHandle(Derived().AsWeakPtr());
  232. // Should trigger type conversion constructor before the assignment.
  233. WeakHandle<Base> base_weak_handle;
  234. base_weak_handle = weak_handle;
  235. // Should trigger regular copy constructor before the assignment.
  236. WeakHandle<Derived> derived_weak_handle;
  237. derived_weak_handle = weak_handle;
  238. EXPECT_TRUE(base_weak_handle.IsInitialized());
  239. EXPECT_TRUE(derived_weak_handle.IsInitialized());
  240. // Copy constructor shouldn't construct a new |core_|.
  241. EXPECT_EQ(weak_handle.core_.get(), derived_weak_handle.core_.get());
  242. }
  243. TEST_F(WeakHandleTest, TypeConversionConstructorUninitialized) {
  244. const WeakHandle<Base> base_weak_handle = WeakHandle<Derived>();
  245. EXPECT_FALSE(base_weak_handle.IsInitialized());
  246. }
  247. TEST_F(WeakHandleTest, TypeConversionConstructorUninitializedAssignment) {
  248. WeakHandle<Base> base_weak_handle;
  249. base_weak_handle = WeakHandle<Derived>();
  250. EXPECT_FALSE(base_weak_handle.IsInitialized());
  251. }
  252. } // namespace syncer