• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <process.h>
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:
OnObjectSignaled(HANDLE object)23   void OnObjectSignaled(HANDLE object) override {
24     RunLoop::QuitCurrentWhenIdleDeprecated();
25   }
26 };
27 
28 class DecrementCountDelegate : public ObjectWatcher::Delegate {
29  public:
DecrementCountDelegate(int * counter)30   explicit DecrementCountDelegate(int* counter) : counter_(counter) {}
OnObjectSignaled(HANDLE object)31   void OnObjectSignaled(HANDLE object) override { --(*counter_); }
32 
33  private:
34   raw_ptr<int> counter_;
35 };
36 
RunTest_BasicSignal(test::TaskEnvironment::MainThreadType main_thread_type)37 void RunTest_BasicSignal(
38     test::TaskEnvironment::MainThreadType main_thread_type) {
39   test::TaskEnvironment task_environment(main_thread_type);
40 
41   ObjectWatcher watcher;
42   EXPECT_FALSE(watcher.IsWatching());
43 
44   // A manual-reset event that is not yet signaled.
45   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
46 
47   QuitDelegate delegate;
48   bool ok = watcher.StartWatchingOnce(event, &delegate);
49   EXPECT_TRUE(ok);
50   EXPECT_TRUE(watcher.IsWatching());
51   EXPECT_EQ(event, watcher.GetWatchedObject());
52 
53   SetEvent(event);
54 
55   RunLoop().Run();
56 
57   EXPECT_FALSE(watcher.IsWatching());
58   CloseHandle(event);
59 }
60 
RunTest_BasicCancel(test::TaskEnvironment::MainThreadType main_thread_type)61 void RunTest_BasicCancel(
62     test::TaskEnvironment::MainThreadType main_thread_type) {
63   test::TaskEnvironment task_environment(main_thread_type);
64 
65   ObjectWatcher watcher;
66 
67   // A manual-reset event that is not yet signaled.
68   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
69 
70   QuitDelegate delegate;
71   bool ok = watcher.StartWatchingOnce(event, &delegate);
72   EXPECT_TRUE(ok);
73 
74   watcher.StopWatching();
75 
76   CloseHandle(event);
77 }
78 
RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType main_thread_type)79 void RunTest_CancelAfterSet(
80     test::TaskEnvironment::MainThreadType main_thread_type) {
81   test::TaskEnvironment task_environment(main_thread_type);
82 
83   ObjectWatcher watcher;
84 
85   int counter = 1;
86   DecrementCountDelegate delegate(&counter);
87 
88   // A manual-reset event that is not yet signaled.
89   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);
90 
91   bool ok = watcher.StartWatchingOnce(event, &delegate);
92   EXPECT_TRUE(ok);
93 
94   SetEvent(event);
95 
96   // Let the background thread do its business
97   Sleep(30);
98 
99   watcher.StopWatching();
100 
101   RunLoop().RunUntilIdle();
102 
103   // Our delegate should not have fired.
104   EXPECT_EQ(1, counter);
105 
106   CloseHandle(event);
107 }
108 
RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType main_thread_type)109 void RunTest_SignalBeforeWatch(
110     test::TaskEnvironment::MainThreadType main_thread_type) {
111   test::TaskEnvironment task_environment(main_thread_type);
112 
113   ObjectWatcher watcher;
114 
115   // A manual-reset event that is signaled before we begin watching.
116   HANDLE event = CreateEvent(nullptr, TRUE, TRUE, nullptr);
117 
118   QuitDelegate delegate;
119   bool ok = watcher.StartWatchingOnce(event, &delegate);
120   EXPECT_TRUE(ok);
121 
122   RunLoop().Run();
123 
124   EXPECT_FALSE(watcher.IsWatching());
125   CloseHandle(event);
126 }
127 
RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType main_thread_type)128 void RunTest_OutlivesTaskEnvironment(
129     test::TaskEnvironment::MainThreadType main_thread_type) {
130   // Simulate a task environment that dies before an ObjectWatcher.  This
131   // ordinarily doesn't happen when people use the Thread class, but it can
132   // happen when people use the Singleton pattern or atexit.
133   HANDLE event = CreateEvent(nullptr, TRUE, FALSE, nullptr);  // not signaled
134   {
135     ObjectWatcher watcher;
136     {
137       test::TaskEnvironment task_environment(main_thread_type);
138 
139       QuitDelegate delegate;
140       watcher.StartWatchingOnce(event, &delegate);
141     }
142   }
143   CloseHandle(event);
144 }
145 
146 class QuitAfterMultipleDelegate : public ObjectWatcher::Delegate {
147  public:
QuitAfterMultipleDelegate(HANDLE event,int iterations)148   QuitAfterMultipleDelegate(HANDLE event, int iterations)
149       : event_(event), iterations_(iterations) {}
OnObjectSignaled(HANDLE object)150   void OnObjectSignaled(HANDLE object) override {
151     if (--iterations_) {
152       SetEvent(event_);
153     } else {
154       RunLoop::QuitCurrentWhenIdleDeprecated();
155     }
156   }
157 
158  private:
159   HANDLE event_;
160   int iterations_;
161 };
162 
RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType main_thread_type)163 void RunTest_ExecuteMultipleTimes(
164     test::TaskEnvironment::MainThreadType main_thread_type) {
165   test::TaskEnvironment task_environment(main_thread_type);
166 
167   ObjectWatcher watcher;
168   EXPECT_FALSE(watcher.IsWatching());
169 
170   // An auto-reset event that is not yet signaled.
171   HANDLE event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
172 
173   QuitAfterMultipleDelegate delegate(event, 2);
174   bool ok = watcher.StartWatchingMultipleTimes(event, &delegate);
175   EXPECT_TRUE(ok);
176   EXPECT_TRUE(watcher.IsWatching());
177   EXPECT_EQ(event, watcher.GetWatchedObject());
178 
179   SetEvent(event);
180 
181   RunLoop().Run();
182 
183   EXPECT_TRUE(watcher.IsWatching());
184   EXPECT_TRUE(watcher.StopWatching());
185   CloseHandle(event);
186 }
187 
188 }  // namespace
189 
190 //-----------------------------------------------------------------------------
191 
TEST(ObjectWatcherTest,BasicSignal)192 TEST(ObjectWatcherTest, BasicSignal) {
193   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::DEFAULT);
194   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::IO);
195   RunTest_BasicSignal(test::TaskEnvironment::MainThreadType::UI);
196 }
197 
TEST(ObjectWatcherTest,BasicCancel)198 TEST(ObjectWatcherTest, BasicCancel) {
199   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::DEFAULT);
200   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::IO);
201   RunTest_BasicCancel(test::TaskEnvironment::MainThreadType::UI);
202 }
203 
TEST(ObjectWatcherTest,CancelAfterSet)204 TEST(ObjectWatcherTest, CancelAfterSet) {
205   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::DEFAULT);
206   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::IO);
207   RunTest_CancelAfterSet(test::TaskEnvironment::MainThreadType::UI);
208 }
209 
TEST(ObjectWatcherTest,SignalBeforeWatch)210 TEST(ObjectWatcherTest, SignalBeforeWatch) {
211   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::DEFAULT);
212   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::IO);
213   RunTest_SignalBeforeWatch(test::TaskEnvironment::MainThreadType::UI);
214 }
215 
TEST(ObjectWatcherTest,OutlivesTaskEnvironment)216 TEST(ObjectWatcherTest, OutlivesTaskEnvironment) {
217   RunTest_OutlivesTaskEnvironment(
218       test::TaskEnvironment::MainThreadType::DEFAULT);
219   RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::IO);
220   RunTest_OutlivesTaskEnvironment(test::TaskEnvironment::MainThreadType::UI);
221 }
222 
TEST(ObjectWatcherTest,ExecuteMultipleTimes)223 TEST(ObjectWatcherTest, ExecuteMultipleTimes) {
224   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::DEFAULT);
225   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::IO);
226   RunTest_ExecuteMultipleTimes(test::TaskEnvironment::MainThreadType::UI);
227 }
228 
229 }  // namespace win
230 }  // namespace base
231