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