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: 17 virtual void OnWaitableEventSignaled(WaitableEvent* event) { 18 MessageLoop::current()->Quit(); 19 } 20 }; 21 22 class 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 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 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 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 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 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 129 TEST(WaitableEventWatcherTest, BasicSignal) { 130 RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT); 131 RunTest_BasicSignal(MessageLoop::TYPE_IO); 132 RunTest_BasicSignal(MessageLoop::TYPE_UI); 133 } 134 135 TEST(WaitableEventWatcherTest, BasicCancel) { 136 RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT); 137 RunTest_BasicCancel(MessageLoop::TYPE_IO); 138 RunTest_BasicCancel(MessageLoop::TYPE_UI); 139 } 140 141 TEST(WaitableEventWatcherTest, CancelAfterSet) { 142 RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT); 143 RunTest_CancelAfterSet(MessageLoop::TYPE_IO); 144 RunTest_CancelAfterSet(MessageLoop::TYPE_UI); 145 } 146 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 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