xref: /aosp_15_r20/external/cronet/base/synchronization/waitable_event_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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/synchronization/waitable_event.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <algorithm>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
15*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
16*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace base {
19*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,ManualBasics)20*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, ManualBasics) {
21*6777b538SAndroid Build Coastguard Worker   WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
22*6777b538SAndroid Build Coastguard Worker                       WaitableEvent::InitialState::NOT_SIGNALED);
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker   event.Signal();
27*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
28*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker   event.Reset();
31*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
32*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.TimedWait(Milliseconds(10)));
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker   event.Signal();
35*6777b538SAndroid Build Coastguard Worker   event.Wait();
36*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.TimedWait(Milliseconds(10)));
37*6777b538SAndroid Build Coastguard Worker }
38*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,ManualInitiallySignaled)39*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, ManualInitiallySignaled) {
40*6777b538SAndroid Build Coastguard Worker   WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
41*6777b538SAndroid Build Coastguard Worker                       WaitableEvent::InitialState::SIGNALED);
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
44*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker   event.Reset();
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
49*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   event.Signal();
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   event.Wait();
54*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
55*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,AutoBasics)58*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, AutoBasics) {
59*6777b538SAndroid Build Coastguard Worker   WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
60*6777b538SAndroid Build Coastguard Worker                       WaitableEvent::InitialState::NOT_SIGNALED);
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   event.Signal();
65*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
66*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   event.Reset();
69*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
70*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.TimedWait(Milliseconds(10)));
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   event.Signal();
73*6777b538SAndroid Build Coastguard Worker   event.Wait();
74*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.TimedWait(Milliseconds(10)));
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker   event.Signal();
77*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.TimedWait(Milliseconds(10)));
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,AutoInitiallySignaled)80*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, AutoInitiallySignaled) {
81*6777b538SAndroid Build Coastguard Worker   WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
82*6777b538SAndroid Build Coastguard Worker                       WaitableEvent::InitialState::SIGNALED);
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
85*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker   event.Signal();
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(event.IsSignaled());
90*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(event.IsSignaled());
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,WaitManyShortcut)93*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, WaitManyShortcut) {
94*6777b538SAndroid Build Coastguard Worker   WaitableEvent* ev[5];
95*6777b538SAndroid Build Coastguard Worker   for (auto*& i : ev) {
96*6777b538SAndroid Build Coastguard Worker     i = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
97*6777b538SAndroid Build Coastguard Worker                           WaitableEvent::InitialState::NOT_SIGNALED);
98*6777b538SAndroid Build Coastguard Worker   }
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   ev[3]->Signal();
101*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   ev[3]->Signal();
104*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   ev[4]->Signal();
107*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   ev[0]->Signal();
110*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   for (auto* i : ev)
113*6777b538SAndroid Build Coastguard Worker     delete i;
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker 
TEST(WaitableEventTest,WaitManyLeftToRight)116*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, WaitManyLeftToRight) {
117*6777b538SAndroid Build Coastguard Worker   WaitableEvent* ev[5];
118*6777b538SAndroid Build Coastguard Worker   for (auto*& i : ev) {
119*6777b538SAndroid Build Coastguard Worker     i = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
120*6777b538SAndroid Build Coastguard Worker                           WaitableEvent::InitialState::NOT_SIGNALED);
121*6777b538SAndroid Build Coastguard Worker   }
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker   // Test for consistent left-to-right return behavior across all permutations
124*6777b538SAndroid Build Coastguard Worker   // of the input array. This is to verify that only the indices -- and not
125*6777b538SAndroid Build Coastguard Worker   // the WaitableEvents' addresses -- are relevant in determining who wins when
126*6777b538SAndroid Build Coastguard Worker   // multiple events are signaled.
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker   std::sort(ev, ev + 5);
129*6777b538SAndroid Build Coastguard Worker   do {
130*6777b538SAndroid Build Coastguard Worker     ev[0]->Signal();
131*6777b538SAndroid Build Coastguard Worker     ev[1]->Signal();
132*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker     ev[2]->Signal();
135*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(1u, WaitableEvent::WaitMany(ev, 5));
136*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker     ev[3]->Signal();
139*6777b538SAndroid Build Coastguard Worker     ev[4]->Signal();
140*6777b538SAndroid Build Coastguard Worker     ev[0]->Signal();
141*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
142*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(3u, WaitableEvent::WaitMany(ev, 5));
143*6777b538SAndroid Build Coastguard Worker     ev[2]->Signal();
144*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
145*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(4u, WaitableEvent::WaitMany(ev, 5));
146*6777b538SAndroid Build Coastguard Worker   } while (std::next_permutation(ev, ev + 5));
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker   for (auto* i : ev)
149*6777b538SAndroid Build Coastguard Worker     delete i;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker class WaitableEventSignaler : public PlatformThread::Delegate {
153*6777b538SAndroid Build Coastguard Worker  public:
WaitableEventSignaler(TimeDelta delay,WaitableEvent * event)154*6777b538SAndroid Build Coastguard Worker   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
155*6777b538SAndroid Build Coastguard Worker       : delay_(delay),
156*6777b538SAndroid Build Coastguard Worker         event_(event) {
157*6777b538SAndroid Build Coastguard Worker   }
158*6777b538SAndroid Build Coastguard Worker 
ThreadMain()159*6777b538SAndroid Build Coastguard Worker   void ThreadMain() override {
160*6777b538SAndroid Build Coastguard Worker     PlatformThread::Sleep(delay_);
161*6777b538SAndroid Build Coastguard Worker     event_->Signal();
162*6777b538SAndroid Build Coastguard Worker   }
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker  private:
165*6777b538SAndroid Build Coastguard Worker   const TimeDelta delay_;
166*6777b538SAndroid Build Coastguard Worker   raw_ptr<WaitableEvent> event_;
167*6777b538SAndroid Build Coastguard Worker };
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
170*6777b538SAndroid Build Coastguard Worker // additional synchronization.
TEST(WaitableEventTest,WaitAndDelete)171*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, WaitAndDelete) {
172*6777b538SAndroid Build Coastguard Worker   WaitableEvent* ev =
173*6777b538SAndroid Build Coastguard Worker       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
174*6777b538SAndroid Build Coastguard Worker                         WaitableEvent::InitialState::NOT_SIGNALED);
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker   PlatformThreadHandle thread;
177*6777b538SAndroid Build Coastguard Worker   {
178*6777b538SAndroid Build Coastguard Worker     // Signaler can't outlive event.
179*6777b538SAndroid Build Coastguard Worker     WaitableEventSignaler signaler(Milliseconds(10), ev);
180*6777b538SAndroid Build Coastguard Worker     PlatformThread::Create(0, &signaler, &thread);
181*6777b538SAndroid Build Coastguard Worker     ev->Wait();
182*6777b538SAndroid Build Coastguard Worker   }
183*6777b538SAndroid Build Coastguard Worker   delete ev;
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   PlatformThread::Join(thread);
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
189*6777b538SAndroid Build Coastguard Worker // without additional synchronization.
TEST(WaitableEventTest,WaitMany)190*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, WaitMany) {
191*6777b538SAndroid Build Coastguard Worker   WaitableEvent* ev[5];
192*6777b538SAndroid Build Coastguard Worker   for (auto*& i : ev) {
193*6777b538SAndroid Build Coastguard Worker     i = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
194*6777b538SAndroid Build Coastguard Worker                           WaitableEvent::InitialState::NOT_SIGNALED);
195*6777b538SAndroid Build Coastguard Worker   }
196*6777b538SAndroid Build Coastguard Worker 
197*6777b538SAndroid Build Coastguard Worker   PlatformThreadHandle thread;
198*6777b538SAndroid Build Coastguard Worker   {
199*6777b538SAndroid Build Coastguard Worker     // Signaler can't outlive event.
200*6777b538SAndroid Build Coastguard Worker     WaitableEventSignaler signaler(Milliseconds(10), ev[2]);
201*6777b538SAndroid Build Coastguard Worker     PlatformThread::Create(0, &signaler, &thread);
202*6777b538SAndroid Build Coastguard Worker     size_t index = WaitableEvent::WaitMany(ev, 5);
203*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(2u, index);
204*6777b538SAndroid Build Coastguard Worker   }
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker   for (auto* i : ev)
207*6777b538SAndroid Build Coastguard Worker     delete i;
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker   PlatformThread::Join(thread);
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
213*6777b538SAndroid Build Coastguard Worker // a timeout of 0. (crbug.com/465948)
TEST(WaitableEventTest,TimedWait)214*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, TimedWait) {
215*6777b538SAndroid Build Coastguard Worker   WaitableEvent* ev =
216*6777b538SAndroid Build Coastguard Worker       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
217*6777b538SAndroid Build Coastguard Worker                         WaitableEvent::InitialState::NOT_SIGNALED);
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   PlatformThreadHandle thread;
220*6777b538SAndroid Build Coastguard Worker   TimeDelta thread_delay = Milliseconds(10);
221*6777b538SAndroid Build Coastguard Worker   {
222*6777b538SAndroid Build Coastguard Worker     // Signaler can't outlive event.
223*6777b538SAndroid Build Coastguard Worker     WaitableEventSignaler signaler(thread_delay, ev);
224*6777b538SAndroid Build Coastguard Worker     TimeTicks start = TimeTicks::Now();
225*6777b538SAndroid Build Coastguard Worker     PlatformThread::Create(0, &signaler, &thread);
226*6777b538SAndroid Build Coastguard Worker     EXPECT_TRUE(ev->TimedWait(TimeDelta::Max()));
227*6777b538SAndroid Build Coastguard Worker     EXPECT_GE(TimeTicks::Now() - start, thread_delay);
228*6777b538SAndroid Build Coastguard Worker   }
229*6777b538SAndroid Build Coastguard Worker   delete ev;
230*6777b538SAndroid Build Coastguard Worker 
231*6777b538SAndroid Build Coastguard Worker   PlatformThread::Join(thread);
232*6777b538SAndroid Build Coastguard Worker }
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker // Tests that a sub-ms TimedWait doesn't time out promptly.
TEST(WaitableEventTest,SubMsTimedWait)235*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, SubMsTimedWait) {
236*6777b538SAndroid Build Coastguard Worker   WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
237*6777b538SAndroid Build Coastguard Worker                    WaitableEvent::InitialState::NOT_SIGNALED);
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker   TimeDelta delay = Microseconds(900);
240*6777b538SAndroid Build Coastguard Worker   TimeTicks start_time = TimeTicks::Now();
241*6777b538SAndroid Build Coastguard Worker   ev.TimedWait(delay);
242*6777b538SAndroid Build Coastguard Worker   EXPECT_GE(TimeTicks::Now() - start_time, delay);
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker // Tests that timeouts of zero return immediately (true if already signaled,
246*6777b538SAndroid Build Coastguard Worker // false otherwise).
TEST(WaitableEventTest,ZeroTimeout)247*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, ZeroTimeout) {
248*6777b538SAndroid Build Coastguard Worker   WaitableEvent ev;
249*6777b538SAndroid Build Coastguard Worker   TimeTicks start_time = TimeTicks::Now();
250*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(ev.TimedWait(TimeDelta()));
251*6777b538SAndroid Build Coastguard Worker   EXPECT_LT(TimeTicks::Now() - start_time, Milliseconds(1));
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker   ev.Signal();
254*6777b538SAndroid Build Coastguard Worker   start_time = TimeTicks::Now();
255*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(ev.TimedWait(TimeDelta()));
256*6777b538SAndroid Build Coastguard Worker   EXPECT_LT(TimeTicks::Now() - start_time, Milliseconds(1));
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker 
259*6777b538SAndroid Build Coastguard Worker // Same as ZeroTimeout for negative timeouts.
TEST(WaitableEventTest,NegativeTimeout)260*6777b538SAndroid Build Coastguard Worker TEST(WaitableEventTest, NegativeTimeout) {
261*6777b538SAndroid Build Coastguard Worker   WaitableEvent ev;
262*6777b538SAndroid Build Coastguard Worker   TimeTicks start_time = TimeTicks::Now();
263*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(ev.TimedWait(Milliseconds(-10)));
264*6777b538SAndroid Build Coastguard Worker   EXPECT_LT(TimeTicks::Now() - start_time, Milliseconds(1));
265*6777b538SAndroid Build Coastguard Worker 
266*6777b538SAndroid Build Coastguard Worker   ev.Signal();
267*6777b538SAndroid Build Coastguard Worker   start_time = TimeTicks::Now();
268*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(ev.TimedWait(Milliseconds(-10)));
269*6777b538SAndroid Build Coastguard Worker   EXPECT_LT(TimeTicks::Now() - start_time, Milliseconds(1));
270*6777b538SAndroid Build Coastguard Worker }
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker }  // namespace base
273