xref: /aosp_15_r20/external/cronet/base/win/object_watcher_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/win/object_watcher.h"
6 
7 #include <windows.h>
8 
9 #include <utility>
10 
11 #include "base/memory/raw_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/test/task_environment.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace base {
17 namespace win {
18 
19 namespace {
20 
21 class QuitDelegate : public ObjectWatcher::Delegate {
22  public:
QuitDelegate(base::OnceClosure quit_closure)23   explicit QuitDelegate(base::OnceClosure quit_closure)
24       : quit_closure_(std::move(quit_closure)) {}
25 
OnObjectSignaled(HANDLE object)26   void OnObjectSignaled(HANDLE object) override {
27     std::move(quit_closure_).Run();
28   }
29 
30  private:
31   base::OnceClosure quit_closure_;
32 };
33 
34 class DecrementCountDelegate : public ObjectWatcher::Delegate {
35  public:
DecrementCountDelegate(int * counter)36   explicit DecrementCountDelegate(int* counter) : counter_(counter) {}
OnObjectSignaled(HANDLE object)37   void OnObjectSignaled(HANDLE object) override { --(*counter_); }
38 
39  private:
40   raw_ptr<int> counter_;
41 };
42 
RunTest_BasicSignal(test::TaskEnvironment::MainThreadType main_thread_type)43 void RunTest_BasicSignal(
44     test::TaskEnvironment::MainThreadType main_thread_type) {
45   test::TaskEnvironment task_environment(main_thread_type);
46 
47   ObjectWatcher watcher;
48   EXPECT_FALSE(watcher.IsWatching());
49 
50   // A manual-reset event that is not yet signaled.
51   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
52 
53   base::RunLoop loop;
54   QuitDelegate delegate(loop.QuitWhenIdleClosure());
55   bool ok = watcher.StartWatchingOnce(event, &delegate);
56   EXPECT_TRUE(ok);
57   EXPECT_TRUE(watcher.IsWatching());
58   EXPECT_EQ(event, watcher.GetWatchedObject());
59 
60   SetEvent(event);
61 
62   loop.Run();
63 
64   EXPECT_FALSE(watcher.IsWatching());
65   CloseHandle(event);
66 }
67 
RunTest_BasicCancel(test::TaskEnvironment::MainThreadType main_thread_type)68 void RunTest_BasicCancel(
69     test::TaskEnvironment::MainThreadType main_thread_type) {
70   test::TaskEnvironment task_environment(main_thread_type);
71 
72   ObjectWatcher watcher;
73 
74   // A manual-reset event that is not yet signaled.
75   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
76 
77   base::RunLoop loop;
78   QuitDelegate delegate(loop.QuitWhenIdleClosure());
79   bool ok = watcher.StartWatchingOnce(event, &delegate);
80   EXPECT_TRUE(ok);
81 
82   watcher.StopWatching();
83 
84   CloseHandle(event);
85 }
86 
RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType main_thread_type)87 void RunTest_CancelAfterSet(
88     test::TaskEnvironment::MainThreadType main_thread_type) {
89   test::TaskEnvironment task_environment(main_thread_type);
90 
91   ObjectWatcher watcher;
92 
93   int counter = 1;
94   DecrementCountDelegate delegate(&counter);
95   base::RunLoop loop;
96   // A manual-reset event that is not yet signaled.
97   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
98 
99   bool ok = watcher.StartWatchingOnce(event, &delegate);
100   EXPECT_TRUE(ok);
101 
102   SetEvent(event);
103 
104   // Let the background thread do its business
105   Sleep(30);
106 
107   watcher.StopWatching();
108 
109   loop.RunUntilIdle();
110 
111   // Our delegate should not have fired.
112   EXPECT_EQ(1, counter);
113 
114   CloseHandle(event);
115 }
116 
RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType main_thread_type)117 void RunTest_SignalBeforeWatch(
118     test::TaskEnvironment::MainThreadType main_thread_type) {
119   test::TaskEnvironment task_environment(main_thread_type);
120 
121   ObjectWatcher watcher;
122 
123   // A manual-reset event that is signaled before we begin watching.
124   HANDLE event = CreateEvent(nullptr, TRUE, TRUE, nullptr);
125 
126   base::RunLoop loop;
127   QuitDelegate delegate(loop.QuitWhenIdleClosure());
128   bool ok = watcher.StartWatchingOnce(event, &delegate);
129   EXPECT_TRUE(ok);
130 
131   loop.Run();
132 
133   EXPECT_FALSE(watcher.IsWatching());
134   CloseHandle(event);
135 }
136 
RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType main_thread_type)137 void RunTest_OutlivesTaskEnvironment(
138     test::TaskEnvironment::MainThreadType main_thread_type) {
139   // Simulate a task environment that dies before an ObjectWatcher.  This
140   // ordinarily doesn't happen when people use the Thread class, but it can
141   // happen when people use the Singleton pattern or atexit.
142   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);  // not signaled
143   {
144     ObjectWatcher watcher;
145     {
146       test::TaskEnvironment task_environment(main_thread_type);
147 
148       base::RunLoop loop;
149       QuitDelegate delegate(loop.QuitWhenIdleClosure());
150       watcher.StartWatchingOnce(event, &delegate);
151     }
152   }
153   CloseHandle(event);
154 }
155 
156 class QuitAfterMultipleDelegate : public ObjectWatcher::Delegate {
157  public:
QuitAfterMultipleDelegate(HANDLE event,int iterations,base::OnceClosure quit_closure)158   QuitAfterMultipleDelegate(HANDLE event,
159                             int iterations,
160                             base::OnceClosure quit_closure)
161       : event_(event),
162         iterations_(iterations),
163         quit_closure_(std::move(quit_closure)) {}
OnObjectSignaled(HANDLE object)164   void OnObjectSignaled(HANDLE object) override {
165     if (--iterations_) {
166       SetEvent(event_);
167     } else {
168       std::move(quit_closure_).Run();
169     }
170   }
171 
172  private:
173   HANDLE event_;
174   int iterations_;
175   base::OnceClosure quit_closure_;
176 };
177 
RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType main_thread_type)178 void RunTest_ExecuteMultipleTimes(
179     test::TaskEnvironment::MainThreadType main_thread_type) {
180   test::TaskEnvironment task_environment(main_thread_type);
181 
182   ObjectWatcher watcher;
183   EXPECT_FALSE(watcher.IsWatching());
184 
185   // An auto-reset event that is not yet signaled.
186   HANDLE event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
187 
188   base::RunLoop loop;
189   QuitAfterMultipleDelegate delegate(event, 2, loop.QuitWhenIdleClosure());
190   bool ok = watcher.StartWatchingMultipleTimes(event, &delegate);
191   EXPECT_TRUE(ok);
192   EXPECT_TRUE(watcher.IsWatching());
193   EXPECT_EQ(event, watcher.GetWatchedObject());
194 
195   SetEvent(event);
196 
197   loop.Run();
198 
199   EXPECT_TRUE(watcher.IsWatching());
200   EXPECT_TRUE(watcher.StopWatching());
201   CloseHandle(event);
202 }
203 
204 }  // namespace
205 
206 //-----------------------------------------------------------------------------
207 
TEST(ObjectWatcherTest,BasicSignal)208 TEST(ObjectWatcherTest, BasicSignal) {
209   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::DEFAULT);
210   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::IO);
211   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::UI);
212 }
213 
TEST(ObjectWatcherTest,BasicCancel)214 TEST(ObjectWatcherTest, BasicCancel) {
215   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::DEFAULT);
216   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::IO);
217   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::UI);
218 }
219 
TEST(ObjectWatcherTest,CancelAfterSet)220 TEST(ObjectWatcherTest, CancelAfterSet) {
221   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::DEFAULT);
222   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::IO);
223   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::UI);
224 }
225 
TEST(ObjectWatcherTest,SignalBeforeWatch)226 TEST(ObjectWatcherTest, SignalBeforeWatch) {
227   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::DEFAULT);
228   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::IO);
229   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::UI);
230 }
231 
TEST(ObjectWatcherTest,OutlivesTaskEnvironment)232 TEST(ObjectWatcherTest, OutlivesTaskEnvironment) {
233   RunTest_OutlivesTaskEnvironment(
234       test::TaskEnvironment::MainThreadType::DEFAULT);
235   RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::IO);
236   RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::UI);
237 }
238 
TEST(ObjectWatcherTest,ExecuteMultipleTimes)239 TEST(ObjectWatcherTest, ExecuteMultipleTimes) {
240   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::DEFAULT);
241   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::IO);
242   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::UI);
243 }
244 
245 }  // namespace win
246 }  // namespace base
247