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 <process.h>
6
7#include "base/message_loop.h"
8#include "base/win/object_watcher.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace base {
12namespace win {
13
14namespace {
15
16class QuitDelegate : public ObjectWatcher::Delegate {
17 public:
18  virtual void OnObjectSignaled(HANDLE object) {
19    MessageLoop::current()->Quit();
20  }
21};
22
23class DecrementCountDelegate : public ObjectWatcher::Delegate {
24 public:
25  explicit DecrementCountDelegate(int* counter) : counter_(counter) {
26  }
27  virtual void OnObjectSignaled(HANDLE object) {
28    --(*counter_);
29  }
30 private:
31  int* counter_;
32};
33
34void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
35  MessageLoop message_loop(message_loop_type);
36
37  ObjectWatcher watcher;
38  EXPECT_EQ(NULL, watcher.GetWatchedObject());
39
40  // A manual-reset event that is not yet signaled.
41  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
42
43  QuitDelegate delegate;
44  bool ok = watcher.StartWatching(event, &delegate);
45  EXPECT_TRUE(ok);
46  EXPECT_EQ(event, watcher.GetWatchedObject());
47
48  SetEvent(event);
49
50  MessageLoop::current()->Run();
51
52  EXPECT_EQ(NULL, watcher.GetWatchedObject());
53  CloseHandle(event);
54}
55
56void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
57  MessageLoop message_loop(message_loop_type);
58
59  ObjectWatcher watcher;
60
61  // A manual-reset event that is not yet signaled.
62  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
63
64  QuitDelegate delegate;
65  bool ok = watcher.StartWatching(event, &delegate);
66  EXPECT_TRUE(ok);
67
68  watcher.StopWatching();
69
70  CloseHandle(event);
71}
72
73
74void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
75  MessageLoop message_loop(message_loop_type);
76
77  ObjectWatcher watcher;
78
79  int counter = 1;
80  DecrementCountDelegate delegate(&counter);
81
82    // A manual-reset event that is not yet signaled.
83  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
84
85  bool ok = watcher.StartWatching(event, &delegate);
86  EXPECT_TRUE(ok);
87
88  SetEvent(event);
89
90  // Let the background thread do its business
91  Sleep(30);
92
93  watcher.StopWatching();
94
95  MessageLoop::current()->RunAllPending();
96
97  // Our delegate should not have fired.
98  EXPECT_EQ(1, counter);
99
100  CloseHandle(event);
101}
102
103void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
104  // Simulate a MessageLoop that dies before an ObjectWatcher.  This ordinarily
105  // doesn't happen when people use the Thread class, but it can happen when
106  // people use the Singleton pattern or atexit.
107  HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);  // not signaled
108  {
109    ObjectWatcher watcher;
110    {
111      MessageLoop message_loop(message_loop_type);
112
113      QuitDelegate delegate;
114      watcher.StartWatching(event, &delegate);
115    }
116  }
117  CloseHandle(event);
118}
119
120}  // namespace
121
122//-----------------------------------------------------------------------------
123
124TEST(ObjectWatcherTest, BasicSignal) {
125  RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
126  RunTest_BasicSignal(MessageLoop::TYPE_IO);
127  RunTest_BasicSignal(MessageLoop::TYPE_UI);
128}
129
130TEST(ObjectWatcherTest, BasicCancel) {
131  RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
132  RunTest_BasicCancel(MessageLoop::TYPE_IO);
133  RunTest_BasicCancel(MessageLoop::TYPE_UI);
134}
135
136TEST(ObjectWatcherTest, CancelAfterSet) {
137  RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
138  RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
139  RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
140}
141
142TEST(ObjectWatcherTest, OutlivesMessageLoop) {
143  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);
144  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);
145  RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
146}
147
148}  // namespace win
149}  // namespace base
150