1// Copyright (c) 2012 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
5#include "base/synchronization/waitable_event.h"
6
7#include <stddef.h>
8
9#include "base/compiler_specific.h"
10#include "base/threading/platform_thread.h"
11#include "base/time/time.h"
12#include "build/build_config.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace base {
16
17TEST(WaitableEventTest, ManualBasics) {
18  WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
19                      WaitableEvent::InitialState::NOT_SIGNALED);
20
21  EXPECT_FALSE(event.IsSignaled());
22
23  event.Signal();
24  EXPECT_TRUE(event.IsSignaled());
25  EXPECT_TRUE(event.IsSignaled());
26
27  event.Reset();
28  EXPECT_FALSE(event.IsSignaled());
29  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
30
31  event.Signal();
32  event.Wait();
33  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
34}
35
36TEST(WaitableEventTest, AutoBasics) {
37  WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
38                      WaitableEvent::InitialState::NOT_SIGNALED);
39
40  EXPECT_FALSE(event.IsSignaled());
41
42  event.Signal();
43  EXPECT_TRUE(event.IsSignaled());
44  EXPECT_FALSE(event.IsSignaled());
45
46  event.Reset();
47  EXPECT_FALSE(event.IsSignaled());
48  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
49
50  event.Signal();
51  event.Wait();
52  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
53
54  event.Signal();
55  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
56}
57
58TEST(WaitableEventTest, WaitManyShortcut) {
59  WaitableEvent* ev[5];
60  for (unsigned i = 0; i < 5; ++i) {
61    ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
62                              WaitableEvent::InitialState::NOT_SIGNALED);
63  }
64
65  ev[3]->Signal();
66  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
67
68  ev[3]->Signal();
69  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
70
71  ev[4]->Signal();
72  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
73
74  ev[0]->Signal();
75  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
76
77  for (unsigned i = 0; i < 5; ++i)
78    delete ev[i];
79}
80
81class WaitableEventSignaler : public PlatformThread::Delegate {
82 public:
83  WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
84      : delay_(delay),
85        event_(event) {
86  }
87
88  void ThreadMain() override {
89    PlatformThread::Sleep(delay_);
90    event_->Signal();
91  }
92
93 private:
94  const TimeDelta delay_;
95  WaitableEvent* event_;
96};
97
98// Tests that a WaitableEvent can be safely deleted when |Wait| is done without
99// additional synchronization.
100TEST(WaitableEventTest, WaitAndDelete) {
101  WaitableEvent* ev =
102      new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
103                        WaitableEvent::InitialState::NOT_SIGNALED);
104
105  WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
106  PlatformThreadHandle thread;
107  PlatformThread::Create(0, &signaler, &thread);
108
109  ev->Wait();
110  delete ev;
111
112  PlatformThread::Join(thread);
113}
114
115// Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
116// without additional synchronization.
117TEST(WaitableEventTest, WaitMany) {
118  WaitableEvent* ev[5];
119  for (unsigned i = 0; i < 5; ++i) {
120    ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
121                              WaitableEvent::InitialState::NOT_SIGNALED);
122  }
123
124  WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
125  PlatformThreadHandle thread;
126  PlatformThread::Create(0, &signaler, &thread);
127
128  size_t index = WaitableEvent::WaitMany(ev, 5);
129
130  for (unsigned i = 0; i < 5; ++i)
131    delete ev[i];
132
133  PlatformThread::Join(thread);
134  EXPECT_EQ(2u, index);
135}
136
137// Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
138// a timeout of 0. (crbug.com/465948)
139#if defined(OS_POSIX)
140// crbug.com/465948 not fixed yet.
141#define MAYBE_TimedWait DISABLED_TimedWait
142#else
143#define MAYBE_TimedWait TimedWait
144#endif
145TEST(WaitableEventTest, MAYBE_TimedWait) {
146  WaitableEvent* ev =
147      new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
148                        WaitableEvent::InitialState::NOT_SIGNALED);
149
150  TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
151  WaitableEventSignaler signaler(thread_delay, ev);
152  PlatformThreadHandle thread;
153  TimeTicks start = TimeTicks::Now();
154  PlatformThread::Create(0, &signaler, &thread);
155
156  ev->TimedWait(TimeDelta::Max());
157  EXPECT_GE(TimeTicks::Now() - start, thread_delay);
158  delete ev;
159
160  PlatformThread::Join(thread);
161}
162
163}  // namespace base
164