one_shot_event_unittest.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2013 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/one_shot_event.h"
  5. #include "base/bind.h"
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/run_loop.h"
  8. #include "base/task/single_thread_task_runner.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/test/test_simple_task_runner.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace base {
  13. void Increment(int* i) {
  14. ++*i;
  15. }
  16. // |*did_delete_instance| will be set to true upon its destruction.
  17. class RefCountedClass : public base::RefCounted<RefCountedClass> {
  18. public:
  19. explicit RefCountedClass(bool* did_delete_instance)
  20. : did_delete_instance_(did_delete_instance) {
  21. DCHECK(!*did_delete_instance_);
  22. }
  23. RefCountedClass(const RefCountedClass&) = delete;
  24. RefCountedClass& operator=(const RefCountedClass&) = delete;
  25. void PerformTask() { did_perform_task_ = true; }
  26. bool did_perform_task() const { return did_perform_task_; }
  27. private:
  28. friend class base::RefCounted<RefCountedClass>;
  29. ~RefCountedClass() { *did_delete_instance_ = true; }
  30. const raw_ptr<bool> did_delete_instance_; // Not owned.
  31. bool did_perform_task_ = false;
  32. };
  33. TEST(OneShotEventTest, RecordsSignal) {
  34. OneShotEvent event;
  35. EXPECT_FALSE(event.is_signaled());
  36. event.Signal();
  37. EXPECT_TRUE(event.is_signaled());
  38. }
  39. TEST(OneShotEventTest, CallsQueueAsDistinctTask) {
  40. OneShotEvent event;
  41. scoped_refptr<base::TestSimpleTaskRunner> runner(
  42. new base::TestSimpleTaskRunner);
  43. int i = 0;
  44. event.Post(FROM_HERE, base::BindOnce(&Increment, &i), runner);
  45. event.Post(FROM_HERE, base::BindOnce(&Increment, &i), runner);
  46. EXPECT_EQ(0U, runner->NumPendingTasks());
  47. event.Signal();
  48. auto pending_tasks = runner->TakePendingTasks();
  49. ASSERT_EQ(2U, pending_tasks.size());
  50. EXPECT_NE(pending_tasks[0].location.line_number(),
  51. pending_tasks[1].location.line_number())
  52. << "Make sure FROM_HERE is propagated.";
  53. }
  54. TEST(OneShotEventTest, CallsQueue) {
  55. OneShotEvent event;
  56. scoped_refptr<base::TestSimpleTaskRunner> runner(
  57. new base::TestSimpleTaskRunner);
  58. int i = 0;
  59. event.Post(FROM_HERE, base::BindOnce(&Increment, &i), runner);
  60. event.Post(FROM_HERE, base::BindOnce(&Increment, &i), runner);
  61. EXPECT_EQ(0U, runner->NumPendingTasks());
  62. event.Signal();
  63. ASSERT_EQ(2U, runner->NumPendingTasks());
  64. EXPECT_EQ(0, i);
  65. runner->RunPendingTasks();
  66. EXPECT_EQ(2, i);
  67. }
  68. TEST(OneShotEventTest, CallsAfterSignalDontRunInline) {
  69. OneShotEvent event;
  70. scoped_refptr<base::TestSimpleTaskRunner> runner(
  71. new base::TestSimpleTaskRunner);
  72. int i = 0;
  73. event.Signal();
  74. event.Post(FROM_HERE, base::BindOnce(&Increment, &i), runner);
  75. EXPECT_EQ(1U, runner->NumPendingTasks());
  76. EXPECT_EQ(0, i);
  77. runner->RunPendingTasks();
  78. EXPECT_EQ(1, i);
  79. }
  80. TEST(OneShotEventTest, PostDefaultsToCurrentMessageLoop) {
  81. OneShotEvent event;
  82. scoped_refptr<base::TestSimpleTaskRunner> runner(
  83. new base::TestSimpleTaskRunner);
  84. base::test::SingleThreadTaskEnvironment task_environment;
  85. int runner_i = 0;
  86. int loop_i = 0;
  87. event.Post(FROM_HERE, base::BindOnce(&Increment, &runner_i), runner);
  88. event.Post(FROM_HERE, base::BindOnce(&Increment, &loop_i));
  89. event.Signal();
  90. EXPECT_EQ(1U, runner->NumPendingTasks());
  91. EXPECT_EQ(0, runner_i);
  92. runner->RunPendingTasks();
  93. EXPECT_EQ(1, runner_i);
  94. EXPECT_EQ(0, loop_i);
  95. base::RunLoop().RunUntilIdle();
  96. EXPECT_EQ(1, loop_i);
  97. }
  98. void CheckSignaledAndPostIncrement(
  99. OneShotEvent* event,
  100. const scoped_refptr<base::SingleThreadTaskRunner>& runner,
  101. int* i) {
  102. EXPECT_TRUE(event->is_signaled());
  103. event->Post(FROM_HERE, base::BindOnce(&Increment, i), runner);
  104. }
  105. TEST(OneShotEventTest, IsSignaledAndPostsFromCallbackWork) {
  106. OneShotEvent event;
  107. scoped_refptr<base::TestSimpleTaskRunner> runner(
  108. new base::TestSimpleTaskRunner);
  109. int i = 0;
  110. event.Post(FROM_HERE,
  111. base::BindOnce(&CheckSignaledAndPostIncrement, &event, runner, &i),
  112. runner);
  113. EXPECT_EQ(0, i);
  114. event.Signal();
  115. // CheckSignaledAndPostIncrement is queued on |runner|.
  116. EXPECT_EQ(1U, runner->NumPendingTasks());
  117. EXPECT_EQ(0, i);
  118. runner->RunPendingTasks();
  119. // Increment is queued on |runner|.
  120. EXPECT_EQ(1U, runner->NumPendingTasks());
  121. EXPECT_EQ(0, i);
  122. runner->RunPendingTasks();
  123. // Increment has run.
  124. EXPECT_EQ(0U, runner->NumPendingTasks());
  125. EXPECT_EQ(1, i);
  126. }
  127. // Tests that OneShotEvent does not keep references to tasks once OneShotEvent
  128. // Signal()s.
  129. TEST(OneShotEventTest, DropsCallbackRefUponSignalled) {
  130. auto runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
  131. bool did_delete_instance = false;
  132. OneShotEvent event;
  133. {
  134. auto ref_counted_class =
  135. base::MakeRefCounted<RefCountedClass>(&did_delete_instance);
  136. event.Post(FROM_HERE,
  137. base::BindOnce(&RefCountedClass::PerformTask, ref_counted_class),
  138. runner);
  139. event.Signal();
  140. runner->RunPendingTasks();
  141. EXPECT_TRUE(ref_counted_class->did_perform_task());
  142. }
  143. // Once OneShotEvent doesn't have any queued events, it should have dropped
  144. // all the references to the callbacks it received through Post().
  145. EXPECT_TRUE(did_delete_instance);
  146. }
  147. } // namespace base