1// Copyright (c) 2011 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/message_loop.h"
6#include "base/synchronization/waitable_event.h"
7#include "base/synchronization/waitable_event_watcher.h"
8#include "base/threading/platform_thread.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace base {
12
13namespace {
14
15class QuitDelegate : public WaitableEventWatcher::Delegate {
16 public:
17  virtual void OnWaitableEventSignaled(WaitableEvent* event) {
18    MessageLoop::current()->Quit();
19  }
20};
21
22class DecrementCountDelegate : public WaitableEventWatcher::Delegate {
23 public:
24  explicit DecrementCountDelegate(int* counter) : counter_(counter) {
25  }
26  virtual void OnWaitableEventSignaled(WaitableEvent* object) {
27    --(*counter_);
28  }
29 private:
30  int* counter_;
31};
32
33void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
34  MessageLoop message_loop(message_loop_type);
35
36  // A manual-reset event that is not yet signaled.
37  WaitableEvent event(true, false);
38
39  WaitableEventWatcher watcher;
40  EXPECT_TRUE(watcher.GetWatchedEvent() == NULL);
41
42  QuitDelegate delegate;
43  watcher.StartWatching(&event, &delegate);
44  EXPECT_EQ(&event, watcher.GetWatchedEvent());
45
46  event.Signal();
47
48  MessageLoop::current()->Run();
49
50  EXPECT_TRUE(watcher.GetWatchedEvent() == NULL);
51}
52
53void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
54  MessageLoop message_loop(message_loop_type);
55
56  // A manual-reset event that is not yet signaled.
57  WaitableEvent event(true, false);
58
59  WaitableEventWatcher watcher;
60
61  QuitDelegate delegate;
62  watcher.StartWatching(&event, &delegate);
63
64  watcher.StopWatching();
65}
66
67void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
68  MessageLoop message_loop(message_loop_type);
69
70  // A manual-reset event that is not yet signaled.
71  WaitableEvent event(true, false);
72
73  WaitableEventWatcher watcher;
74
75  int counter = 1;
76  DecrementCountDelegate delegate(&counter);
77
78  watcher.StartWatching(&event, &delegate);
79
80  event.Signal();
81
82  // Let the background thread do its business
83  base::PlatformThread::Sleep(30);
84
85  watcher.StopWatching();
86
87  MessageLoop::current()->RunAllPending();
88
89  // Our delegate should not have fired.
90  EXPECT_EQ(1, counter);
91}
92
93void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
94  // Simulate a MessageLoop that dies before an WaitableEventWatcher.  This
95  // ordinarily doesn't happen when people use the Thread class, but it can
96  // happen when people use the Singleton pattern or atexit.
97  WaitableEvent event(true, false);
98  {
99    WaitableEventWatcher watcher;
100    {
101      MessageLoop message_loop(message_loop_type);
102
103      QuitDelegate delegate;
104      watcher.StartWatching(&event, &delegate);
105    }
106  }
107}
108
109void RunTest_DeleteUnder(MessageLoop::Type message_loop_type) {
110  // Delete the WaitableEvent out from under the Watcher. This is explictly
111  // allowed by the interface.
112
113  MessageLoop message_loop(message_loop_type);
114
115  {
116    WaitableEventWatcher watcher;
117
118    WaitableEvent* event = new WaitableEvent(false, false);
119    QuitDelegate delegate;
120    watcher.StartWatching(event, &delegate);
121    delete event;
122  }
123}
124
125}  // namespace
126
127//-----------------------------------------------------------------------------
128
129TEST(WaitableEventWatcherTest, BasicSignal) {
130  RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
131  RunTest_BasicSignal(MessageLoop::TYPE_IO);
132  RunTest_BasicSignal(MessageLoop::TYPE_UI);
133}
134
135TEST(WaitableEventWatcherTest, BasicCancel) {
136  RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
137  RunTest_BasicCancel(MessageLoop::TYPE_IO);
138  RunTest_BasicCancel(MessageLoop::TYPE_UI);
139}
140
141TEST(WaitableEventWatcherTest, CancelAfterSet) {
142  RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
143  RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
144  RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
145}
146
147TEST(WaitableEventWatcherTest, OutlivesMessageLoop) {
148  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);
149  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);
150  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
151}
152
153#if defined(OS_WIN)
154// Crashes sometimes on vista.  http://crbug.com/62119
155#define MAYBE_DeleteUnder DISABLED_DeleteUnder
156#else
157#define MAYBE_DeleteUnder DeleteUnder
158#endif
159TEST(WaitableEventWatcherTest, MAYBE_DeleteUnder) {
160  RunTest_DeleteUnder(MessageLoop::TYPE_DEFAULT);
161  RunTest_DeleteUnder(MessageLoop::TYPE_IO);
162  RunTest_DeleteUnder(MessageLoop::TYPE_UI);
163}
164
165}  // namespace base
166