bind_post_task_unittest.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2020 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/task/bind_post_task.h"
  5. #include "base/bind.h"
  6. #include "base/callback.h"
  7. #include "base/sequence_checker_impl.h"
  8. #include "base/task/sequenced_task_runner.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/threading/sequenced_task_runner_handle.h"
  11. #include "base/threading/thread.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. namespace base {
  14. namespace {
  15. void SetBool(bool* variable, bool value) {
  16. *variable = value;
  17. }
  18. void SetInt(int* variable, int value) {
  19. *variable = value;
  20. }
  21. void SetIntFromUniquePtr(int* variable, std::unique_ptr<int> value) {
  22. *variable = *value;
  23. }
  24. int Multiply(int value) {
  25. return value * 5;
  26. }
  27. void ClearReference(OnceClosure callback) {}
  28. class SequenceRestrictionChecker {
  29. public:
  30. explicit SequenceRestrictionChecker(bool& set_on_destroy)
  31. : set_on_destroy_(set_on_destroy) {}
  32. ~SequenceRestrictionChecker() {
  33. EXPECT_TRUE(checker_.CalledOnValidSequence());
  34. set_on_destroy_ = true;
  35. }
  36. void Run() { EXPECT_TRUE(checker_.CalledOnValidSequence()); }
  37. private:
  38. SequenceCheckerImpl checker_;
  39. bool& set_on_destroy_;
  40. };
  41. } // namespace
  42. class BindPostTaskTest : public testing::Test {
  43. protected:
  44. test::SingleThreadTaskEnvironment task_environment_;
  45. scoped_refptr<SequencedTaskRunner> task_runner_ =
  46. SequencedTaskRunnerHandle::Get();
  47. };
  48. TEST_F(BindPostTaskTest, OnceClosure) {
  49. bool val = false;
  50. OnceClosure cb = BindOnce(&SetBool, &val, true);
  51. OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  52. std::move(post_cb).Run();
  53. EXPECT_FALSE(val);
  54. RunLoop().RunUntilIdle();
  55. EXPECT_TRUE(val);
  56. }
  57. TEST_F(BindPostTaskTest, OnceCallback) {
  58. OnceCallback<void(bool*, bool)> cb = BindOnce(&SetBool);
  59. OnceCallback<void(bool*, bool)> post_cb =
  60. BindPostTask(task_runner_, std::move(cb));
  61. bool val = false;
  62. std::move(post_cb).Run(&val, true);
  63. EXPECT_FALSE(val);
  64. RunLoop().RunUntilIdle();
  65. EXPECT_TRUE(val);
  66. }
  67. TEST_F(BindPostTaskTest, OnceWithBoundMoveOnlyArg) {
  68. int val = 0;
  69. OnceClosure cb =
  70. BindOnce(&SetIntFromUniquePtr, &val, std::make_unique<int>(10));
  71. OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  72. std::move(post_cb).Run();
  73. EXPECT_EQ(val, 0);
  74. RunLoop().RunUntilIdle();
  75. EXPECT_EQ(val, 10);
  76. }
  77. TEST_F(BindPostTaskTest, OnceWithUnboundMoveOnlyArg) {
  78. int val = 0;
  79. OnceCallback<void(std::unique_ptr<int>)> cb =
  80. BindOnce(&SetIntFromUniquePtr, &val);
  81. OnceCallback<void(std::unique_ptr<int>)> post_cb =
  82. BindPostTask(task_runner_, std::move(cb));
  83. std::move(post_cb).Run(std::make_unique<int>(10));
  84. EXPECT_EQ(val, 0);
  85. RunLoop().RunUntilIdle();
  86. EXPECT_EQ(val, 10);
  87. }
  88. TEST_F(BindPostTaskTest, OnceWithIgnoreResult) {
  89. OnceCallback<void(int)> post_cb =
  90. BindPostTask(task_runner_, BindOnce(IgnoreResult(&Multiply)));
  91. std::move(post_cb).Run(1);
  92. RunLoop().RunUntilIdle();
  93. }
  94. TEST_F(BindPostTaskTest, OnceThen) {
  95. int value = 0;
  96. // Multiply() returns an int and SetInt() takes an int as a parameter.
  97. OnceClosure then_cb =
  98. BindOnce(&Multiply, 5)
  99. .Then(BindPostTask(task_runner_, BindOnce(&SetInt, &value)));
  100. std::move(then_cb).Run();
  101. EXPECT_EQ(value, 0);
  102. RunLoop().RunUntilIdle();
  103. EXPECT_EQ(value, 25);
  104. }
  105. // Ensure that the input callback is run/destroyed on the correct thread even if
  106. // the callback returned from BindPostTask() is run on a different thread.
  107. TEST_F(BindPostTaskTest, OnceRunDestroyedOnBound) {
  108. Thread target_thread("testing");
  109. ASSERT_TRUE(target_thread.Start());
  110. // SequenceRestrictionChecker checks it's creation, Run() and deletion all
  111. // happen on the main thread.
  112. bool destroyed = false;
  113. auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
  114. // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is run
  115. // on a different thread which triggers a PostTask() back to the test main
  116. // thread to invoke `cb` which runs SequenceRestrictionChecker::Run(). After
  117. // `cb` has been invoked `checker` is destroyed along with the BindState.
  118. OnceClosure cb =
  119. BindOnce(&SequenceRestrictionChecker::Run, std::move(checker));
  120. OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  121. target_thread.task_runner()->PostTask(FROM_HERE, std::move(post_cb));
  122. target_thread.FlushForTesting();
  123. EXPECT_FALSE(destroyed);
  124. RunLoop().RunUntilIdle();
  125. EXPECT_TRUE(destroyed);
  126. }
  127. // Ensure that the input callback is destroyed on the correct thread even if the
  128. // callback returned from BindPostTask() is destroyed without being run on a
  129. // different thread.
  130. TEST_F(BindPostTaskTest, OnceNotRunDestroyedOnBound) {
  131. Thread target_thread("testing");
  132. ASSERT_TRUE(target_thread.Start());
  133. // SequenceRestrictionChecker checks it's creation and deletion all happen on
  134. // the test main thread.
  135. bool destroyed = false;
  136. auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
  137. // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is
  138. // deleted on a different thread which triggers a PostTask() back to the test
  139. // main thread to destroy `cb` and `checker`.
  140. OnceClosure cb =
  141. BindOnce(&SequenceRestrictionChecker::Run, std::move(checker));
  142. OnceClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  143. target_thread.task_runner()->PostTask(
  144. FROM_HERE, BindOnce(&ClearReference, std::move(post_cb)));
  145. target_thread.FlushForTesting();
  146. EXPECT_FALSE(destroyed);
  147. RunLoop().RunUntilIdle();
  148. EXPECT_TRUE(destroyed);
  149. }
  150. TEST_F(BindPostTaskTest, RepeatingClosure) {
  151. bool val = false;
  152. RepeatingClosure cb = BindRepeating(&SetBool, &val, true);
  153. RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  154. post_cb.Run();
  155. EXPECT_FALSE(val);
  156. RunLoop().RunUntilIdle();
  157. EXPECT_TRUE(val);
  158. val = false;
  159. post_cb.Run();
  160. EXPECT_FALSE(val);
  161. RunLoop().RunUntilIdle();
  162. EXPECT_TRUE(val);
  163. }
  164. TEST_F(BindPostTaskTest, RepeatingCallback) {
  165. RepeatingCallback<void(bool*, bool)> cb = BindRepeating(&SetBool);
  166. RepeatingCallback<void(bool*, bool)> post_cb =
  167. BindPostTask(task_runner_, std::move(cb));
  168. bool val = false;
  169. post_cb.Run(&val, true);
  170. EXPECT_FALSE(val);
  171. RunLoop().RunUntilIdle();
  172. EXPECT_TRUE(val);
  173. post_cb.Run(&val, false);
  174. EXPECT_TRUE(val);
  175. RunLoop().RunUntilIdle();
  176. EXPECT_FALSE(val);
  177. }
  178. TEST_F(BindPostTaskTest, RepeatingWithUnboundMoveOnlyArg) {
  179. int val = 0;
  180. RepeatingCallback<void(std::unique_ptr<int>)> cb =
  181. BindRepeating(&SetIntFromUniquePtr, &val);
  182. RepeatingCallback<void(std::unique_ptr<int>)> post_cb =
  183. BindPostTask(task_runner_, std::move(cb));
  184. post_cb.Run(std::make_unique<int>(10));
  185. EXPECT_EQ(val, 0);
  186. RunLoop().RunUntilIdle();
  187. EXPECT_EQ(val, 10);
  188. post_cb.Run(std::make_unique<int>(20));
  189. EXPECT_EQ(val, 10);
  190. RunLoop().RunUntilIdle();
  191. EXPECT_EQ(val, 20);
  192. }
  193. TEST_F(BindPostTaskTest, RepeatingWithIgnoreResult) {
  194. RepeatingCallback<void(int)> post_cb =
  195. BindPostTask(task_runner_, BindRepeating(IgnoreResult(&Multiply)));
  196. std::move(post_cb).Run(1);
  197. RunLoop().RunUntilIdle();
  198. }
  199. TEST_F(BindPostTaskTest, RepeatingThen) {
  200. int value = 0;
  201. // Multiply() returns an int and SetInt() takes an int as a parameter.
  202. RepeatingCallback<void(int)> then_cb = BindRepeating(&Multiply).Then(
  203. BindPostTask(task_runner_, BindRepeating(&SetInt, &value)));
  204. then_cb.Run(5);
  205. EXPECT_EQ(value, 0);
  206. RunLoop().RunUntilIdle();
  207. EXPECT_EQ(value, 25);
  208. then_cb.Run(10);
  209. EXPECT_EQ(value, 25);
  210. RunLoop().RunUntilIdle();
  211. EXPECT_EQ(value, 50);
  212. }
  213. // Ensure that the input callback is run/destroyed on the correct thread even if
  214. // the callback returned from BindPostTask() is run on a different thread.
  215. TEST_F(BindPostTaskTest, RepeatingRunDestroyedOnBound) {
  216. Thread target_thread("testing");
  217. ASSERT_TRUE(target_thread.Start());
  218. // SequenceRestrictionChecker checks it's creation, Run() and deletion all
  219. // happen on the main thread.
  220. bool destroyed = false;
  221. auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
  222. // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is run
  223. // on a different thread which triggers a PostTask() back to the test main
  224. // thread to invoke `cb` which runs SequenceRestrictionChecker::Run(). After
  225. // `cb` has been invoked `checker` is destroyed along with the BindState.
  226. RepeatingClosure cb =
  227. BindRepeating(&SequenceRestrictionChecker::Run, std::move(checker));
  228. RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  229. target_thread.task_runner()->PostTask(FROM_HERE, std::move(post_cb));
  230. target_thread.FlushForTesting();
  231. EXPECT_FALSE(destroyed);
  232. RunLoop().RunUntilIdle();
  233. EXPECT_TRUE(destroyed);
  234. }
  235. // Ensure that the input callback is destroyed on the correct thread even if the
  236. // callback returned from BindPostTask() is destroyed without being run on a
  237. // different thread.
  238. TEST_F(BindPostTaskTest, RepeatingNotRunDestroyedOnBound) {
  239. Thread target_thread("testing");
  240. ASSERT_TRUE(target_thread.Start());
  241. // SequenceRestrictionChecker checks it's creation and deletion all happen on
  242. // the test main thread.
  243. bool destroyed = false;
  244. auto checker = std::make_unique<SequenceRestrictionChecker>(destroyed);
  245. // `checker` is owned by `cb` which is wrapped in `post_cb`. `post_cb` is
  246. // deleted on a different thread which triggers a PostTask() back to the test
  247. // main thread to destroy `cb` and `checker`.
  248. RepeatingClosure cb =
  249. BindRepeating(&SequenceRestrictionChecker::Run, std::move(checker));
  250. RepeatingClosure post_cb = BindPostTask(task_runner_, std::move(cb));
  251. target_thread.task_runner()->PostTask(
  252. FROM_HERE, BindRepeating(&ClearReference, std::move(post_cb)));
  253. target_thread.FlushForTesting();
  254. EXPECT_FALSE(destroyed);
  255. RunLoop().RunUntilIdle();
  256. EXPECT_TRUE(destroyed);
  257. }
  258. } // namespace base