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 "base/compiler_specific.h"
8#include "base/threading/platform_thread.h"
9#include "base/time/time.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace base {
13
14TEST(WaitableEventTest, ManualBasics) {
15  WaitableEvent event(true, false);
16
17  EXPECT_FALSE(event.IsSignaled());
18
19  event.Signal();
20  EXPECT_TRUE(event.IsSignaled());
21  EXPECT_TRUE(event.IsSignaled());
22
23  event.Reset();
24  EXPECT_FALSE(event.IsSignaled());
25  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
26
27  event.Signal();
28  event.Wait();
29  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
30}
31
32TEST(WaitableEventTest, AutoBasics) {
33  WaitableEvent event(false, false);
34
35  EXPECT_FALSE(event.IsSignaled());
36
37  event.Signal();
38  EXPECT_TRUE(event.IsSignaled());
39  EXPECT_FALSE(event.IsSignaled());
40
41  event.Reset();
42  EXPECT_FALSE(event.IsSignaled());
43  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
44
45  event.Signal();
46  event.Wait();
47  EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
48
49  event.Signal();
50  EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
51}
52
53TEST(WaitableEventTest, WaitManyShortcut) {
54  WaitableEvent* ev[5];
55  for (unsigned i = 0; i < 5; ++i)
56    ev[i] = new WaitableEvent(false, false);
57
58  ev[3]->Signal();
59  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
60
61  ev[3]->Signal();
62  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
63
64  ev[4]->Signal();
65  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
66
67  ev[0]->Signal();
68  EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
69
70  for (unsigned i = 0; i < 5; ++i)
71    delete ev[i];
72}
73
74class WaitableEventSignaler : public PlatformThread::Delegate {
75 public:
76  WaitableEventSignaler(double seconds, WaitableEvent* ev)
77      : seconds_(seconds),
78        ev_(ev) {
79  }
80
81  virtual void ThreadMain() OVERRIDE {
82    PlatformThread::Sleep(TimeDelta::FromSecondsD(seconds_));
83    ev_->Signal();
84  }
85
86 private:
87  const double seconds_;
88  WaitableEvent *const ev_;
89};
90
91TEST(WaitableEventTest, WaitAndDelete) {
92  // This test tests that if a WaitableEvent can be safely deleted
93  // when |Wait| is done without additional synchrnization.
94  // If this test crashes, it is a bug.
95
96  WaitableEvent* ev = new WaitableEvent(false, false);
97
98  WaitableEventSignaler signaler(0.01, ev);
99  PlatformThreadHandle thread;
100  PlatformThread::Create(0, &signaler, &thread);
101
102  ev->Wait();
103  delete ev;
104
105  PlatformThread::Join(thread);
106}
107
108TEST(WaitableEventTest, WaitMany) {
109  // This test tests that if a WaitableEvent can be safely deleted
110  // when |WaitMany| is done without additional synchrnization.
111  // If this test crashes, it is a bug.
112
113  WaitableEvent* ev[5];
114  for (unsigned i = 0; i < 5; ++i)
115    ev[i] = new WaitableEvent(false, false);
116
117  WaitableEventSignaler signaler(0.01, ev[2]);
118  PlatformThreadHandle thread;
119  PlatformThread::Create(0, &signaler, &thread);
120
121  size_t index = WaitableEvent::WaitMany(ev, 5);
122
123  for (unsigned i = 0; i < 5; ++i)
124    delete ev[i];
125
126  PlatformThread::Join(thread);
127  EXPECT_EQ(2u, index);
128}
129
130}  // namespace base
131