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
11 namespace base {
12
13 namespace {
14
15 class QuitDelegate : public WaitableEventWatcher::Delegate {
16 public:
OnWaitableEventSignaled(WaitableEvent * event)17 virtual void OnWaitableEventSignaled(WaitableEvent* event) {
18 MessageLoop::current()->Quit();
19 }
20 };
21
22 class DecrementCountDelegate : public WaitableEventWatcher::Delegate {
23 public:
DecrementCountDelegate(int * counter)24 explicit DecrementCountDelegate(int* counter) : counter_(counter) {
25 }
OnWaitableEventSignaled(WaitableEvent * object)26 virtual void OnWaitableEventSignaled(WaitableEvent* object) {
27 --(*counter_);
28 }
29 private:
30 int* counter_;
31 };
32
RunTest_BasicSignal(MessageLoop::Type message_loop_type)33 void 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
RunTest_BasicCancel(MessageLoop::Type message_loop_type)53 void 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
RunTest_CancelAfterSet(MessageLoop::Type message_loop_type)67 void 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
RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type)93 void 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
RunTest_DeleteUnder(MessageLoop::Type message_loop_type)109 void 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
TEST(WaitableEventWatcherTest,BasicSignal)129 TEST(WaitableEventWatcherTest, BasicSignal) {
130 RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
131 RunTest_BasicSignal(MessageLoop::TYPE_IO);
132 RunTest_BasicSignal(MessageLoop::TYPE_UI);
133 }
134
TEST(WaitableEventWatcherTest,BasicCancel)135 TEST(WaitableEventWatcherTest, BasicCancel) {
136 RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
137 RunTest_BasicCancel(MessageLoop::TYPE_IO);
138 RunTest_BasicCancel(MessageLoop::TYPE_UI);
139 }
140
TEST(WaitableEventWatcherTest,CancelAfterSet)141 TEST(WaitableEventWatcherTest, CancelAfterSet) {
142 RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
143 RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
144 RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
145 }
146
TEST(WaitableEventWatcherTest,OutlivesMessageLoop)147 TEST(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
TEST(WaitableEventWatcherTest,MAYBE_DeleteUnder)159 TEST(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