Home | History | Annotate | Download | only in synchronization
      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