waitable_event_watcher_unittest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
15ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
35ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// found in the LICENSE file.
45ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
55ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "base/message_loop.h"
65ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "base/synchronization/waitable_event.h"
75ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "base/synchronization/waitable_event_watcher.h"
85ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "base/threading/platform_thread.h"
95ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "testing/gtest/include/gtest/gtest.h"
105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsennamespace base {
125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsennamespace {
145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenclass QuitDelegate : public WaitableEventWatcher::Delegate {
165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen public:
175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  virtual void OnWaitableEventSignaled(WaitableEvent* event) {
185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    MessageLoop::current()->Quit();
195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  }
205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen};
215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenclass DecrementCountDelegate : public WaitableEventWatcher::Delegate {
235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen public:
245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  explicit DecrementCountDelegate(int* counter) : counter_(counter) {
255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  }
265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  virtual void OnWaitableEventSignaled(WaitableEvent* object) {
275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    --(*counter_);
285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  }
295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen private:
305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  int* counter_;
315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen};
325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  MessageLoop message_loop(message_loop_type);
355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // A manual-reset event that is not yet signaled.
375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  WaitableEvent event(true, false);
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
395abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  WaitableEventWatcher watcher;
405abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  EXPECT_TRUE(watcher.GetWatchedEvent() == NULL);
41e14391e94c850b8bd03680c23b38978db68687a8John Reck
425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  QuitDelegate delegate;
435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  watcher.StartWatching(&event, &delegate);
445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  EXPECT_EQ(&event, watcher.GetWatchedEvent());
455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  event.Signal();
475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4868513a70bcd92384395513322f1b801e7bf9c729Steve Block  MessageLoop::current()->Run();
495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  EXPECT_TRUE(watcher.GetWatchedEvent() == NULL);
515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
535abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickvoid RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  MessageLoop message_loop(message_loop_type);
555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // A manual-reset event that is not yet signaled.
572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block  WaitableEvent event(true, false);
585abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
595abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  WaitableEventWatcher watcher;
605abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
615abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  QuitDelegate delegate;
625abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  watcher.StartWatching(&event, &delegate);
635abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch  watcher.StopWatching();
655abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick}
665abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick
675abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrickvoid RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
685abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  MessageLoop message_loop(message_loop_type);
695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // A manual-reset event that is not yet signaled.
715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  WaitableEvent event(true, false);
725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  WaitableEventWatcher watcher;
745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  int counter = 1;
765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  DecrementCountDelegate delegate(&counter);
775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  watcher.StartWatching(&event, &delegate);
795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  event.Signal();
815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // Let the background thread do its business
8368513a70bcd92384395513322f1b801e7bf9c729Steve Block  base::PlatformThread::Sleep(30);
845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  watcher.StopWatching();
865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch  MessageLoop::current()->RunAllPending();
885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch  // Our delegate should not have fired.
905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  EXPECT_EQ(1, counter);
915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
92cad810f21b803229eb11403f9209855525a25d57Steve Block
935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // Simulate a MessageLoop that dies before an WaitableEventWatcher.  This
955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // ordinarily doesn't happen when people use the Thread class, but it can
965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  // happen when people use the Singleton pattern or atexit.
975abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick  WaitableEvent event(true, false);
985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  {
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