object_watcher_unittest.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright (c) 2011 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/win/object_watcher.h"
  5. #include <windows.h>
  6. #include <process.h>
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/task_environment.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace base {
  12. namespace win {
  13. namespace {
  14. class QuitDelegate : public ObjectWatcher::Delegate {
  15. public:
  16. void OnObjectSignaled(HANDLE object) override {
  17. RunLoop::QuitCurrentWhenIdleDeprecated();
  18. }
  19. };
  20. class DecrementCountDelegate : public ObjectWatcher::Delegate {
  21. public:
  22. explicit DecrementCountDelegate(int* counter) : counter_(counter) {}
  23. void OnObjectSignaled(HANDLE object) override { --(*counter_); }
  24. private:
  25. raw_ptr<int> counter_;
  26. };
  27. void RunTest_BasicSignal(
  28. test::TaskEnvironment::MainThreadType main_thread_type) {
  29. test::TaskEnvironment task_environment(main_thread_type);
  30. ObjectWatcher watcher;
  31. EXPECT_FALSE(watcher.IsWatching());
  32. // A manual-reset event that is not yet signaled.
  33. HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  34. QuitDelegate delegate;
  35. bool ok = watcher.StartWatchingOnce(event, &delegate);
  36. EXPECT_TRUE(ok);
  37. EXPECT_TRUE(watcher.IsWatching());
  38. EXPECT_EQ(event, watcher.GetWatchedObject());
  39. SetEvent(event);
  40. RunLoop().Run();
  41. EXPECT_FALSE(watcher.IsWatching());
  42. CloseHandle(event);
  43. }
  44. void RunTest_BasicCancel(
  45. test::TaskEnvironment::MainThreadType main_thread_type) {
  46. test::TaskEnvironment task_environment(main_thread_type);
  47. ObjectWatcher watcher;
  48. // A manual-reset event that is not yet signaled.
  49. HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  50. QuitDelegate delegate;
  51. bool ok = watcher.StartWatchingOnce(event, &delegate);
  52. EXPECT_TRUE(ok);
  53. watcher.StopWatching();
  54. CloseHandle(event);
  55. }
  56. void RunTest_CancelAfterSet(
  57. test::TaskEnvironment::MainThreadType main_thread_type) {
  58. test::TaskEnvironment task_environment(main_thread_type);
  59. ObjectWatcher watcher;
  60. int counter = 1;
  61. DecrementCountDelegate delegate(&counter);
  62. // A manual-reset event that is not yet signaled.
  63. HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  64. bool ok = watcher.StartWatchingOnce(event, &delegate);
  65. EXPECT_TRUE(ok);
  66. SetEvent(event);
  67. // Let the background thread do its business
  68. Sleep(30);
  69. watcher.StopWatching();
  70. RunLoop().RunUntilIdle();
  71. // Our delegate should not have fired.
  72. EXPECT_EQ(1, counter);
  73. CloseHandle(event);
  74. }
  75. void RunTest_SignalBeforeWatch(
  76. test::TaskEnvironment::MainThreadType main_thread_type) {
  77. test::TaskEnvironment task_environment(main_thread_type);
  78. ObjectWatcher watcher;
  79. // A manual-reset event that is signaled before we begin watching.
  80. HANDLE event = CreateEvent(nullptr, TRUE, TRUE, nullptr);
  81. QuitDelegate delegate;
  82. bool ok = watcher.StartWatchingOnce(event, &delegate);
  83. EXPECT_TRUE(ok);
  84. RunLoop().Run();
  85. EXPECT_FALSE(watcher.IsWatching());
  86. CloseHandle(event);
  87. }
  88. void RunTest_OutlivesTaskEnvironment(
  89. test::TaskEnvironment::MainThreadType main_thread_type) {
  90. // Simulate a task environment that dies before an ObjectWatcher. This
  91. // ordinarily doesn't happen when people use the Thread class, but it can
  92. // happen when people use the Singleton pattern or atexit.
  93. HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr); // not signaled
  94. {
  95. ObjectWatcher watcher;
  96. {
  97. test::TaskEnvironment task_environment(main_thread_type);
  98. QuitDelegate delegate;
  99. watcher.StartWatchingOnce(event, &delegate);
  100. }
  101. }
  102. CloseHandle(event);
  103. }
  104. class QuitAfterMultipleDelegate : public ObjectWatcher::Delegate {
  105. public:
  106. QuitAfterMultipleDelegate(HANDLE event, int iterations)
  107. : event_(event), iterations_(iterations) {}
  108. void OnObjectSignaled(HANDLE object) override {
  109. if (--iterations_) {
  110. SetEvent(event_);
  111. } else {
  112. RunLoop::QuitCurrentWhenIdleDeprecated();
  113. }
  114. }
  115. private:
  116. HANDLE event_;
  117. int iterations_;
  118. };
  119. void RunTest_ExecuteMultipleTimes(
  120. test::TaskEnvironment::MainThreadType main_thread_type) {
  121. test::TaskEnvironment task_environment(main_thread_type);
  122. ObjectWatcher watcher;
  123. EXPECT_FALSE(watcher.IsWatching());
  124. // An auto-reset event that is not yet signaled.
  125. HANDLE event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  126. QuitAfterMultipleDelegate delegate(event, 2);
  127. bool ok = watcher.StartWatchingMultipleTimes(event, &delegate);
  128. EXPECT_TRUE(ok);
  129. EXPECT_TRUE(watcher.IsWatching());
  130. EXPECT_EQ(event, watcher.GetWatchedObject());
  131. SetEvent(event);
  132. RunLoop().Run();
  133. EXPECT_TRUE(watcher.IsWatching());
  134. EXPECT_TRUE(watcher.StopWatching());
  135. CloseHandle(event);
  136. }
  137. } // namespace
  138. //-----------------------------------------------------------------------------
  139. TEST(ObjectWatcherTest, BasicSignal) {
  140. RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::DEFAULT);
  141. RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::IO);
  142. RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::UI);
  143. }
  144. TEST(ObjectWatcherTest, BasicCancel) {
  145. RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::DEFAULT);
  146. RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::IO);
  147. RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::UI);
  148. }
  149. TEST(ObjectWatcherTest, CancelAfterSet) {
  150. RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::DEFAULT);
  151. RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::IO);
  152. RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::UI);
  153. }
  154. TEST(ObjectWatcherTest, SignalBeforeWatch) {
  155. RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::DEFAULT);
  156. RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::IO);
  157. RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::UI);
  158. }
  159. TEST(ObjectWatcherTest, OutlivesTaskEnvironment) {
  160. RunTest_OutlivesTaskEnvironment(
  161. test::TaskEnvironment::MainThreadType::DEFAULT);
  162. RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::IO);
  163. RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::UI);
  164. }
  165. TEST(ObjectWatcherTest, ExecuteMultipleTimes) {
  166. RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::DEFAULT);
  167. RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::IO);
  168. RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::UI);
  169. }
  170. } // namespace win
  171. } // namespace base