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