OLD | NEW |
| (Empty) |
1 // Copyright 2007-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 | |
17 #include <iostream> | |
18 #include "base/scoped_ptr.h" | |
19 #include "omaha/base/queue_timer.h" | |
20 #include "omaha/base/scoped_any.h" | |
21 #include "omaha/base/timer.h" | |
22 #include "omaha/testing/unit_test.h" | |
23 | |
24 namespace omaha { | |
25 | |
26 class QueueTimerTest : public testing::Test { | |
27 protected: | |
28 QueueTimerTest() | |
29 : timer_queue_(NULL), | |
30 cnt_(0), | |
31 max_cnt_(0) {} | |
32 | |
33 virtual void SetUp() { | |
34 cnt_ = 0; | |
35 timer_queue_ = ::CreateTimerQueue(); | |
36 ASSERT_TRUE(timer_queue_); | |
37 reset(ev_, ::CreateEvent(NULL, true, false, NULL)); | |
38 } | |
39 | |
40 virtual void TearDown() { | |
41 // First destroy the timer, otherwise the timer could fire and | |
42 // access invalid test case state. | |
43 queue_timer_.reset(); | |
44 reset(ev_); | |
45 ASSERT_TRUE(::DeleteTimerQueueEx(timer_queue_, INVALID_HANDLE_VALUE)); | |
46 cnt_ = 0; | |
47 max_cnt_ = 0; | |
48 } | |
49 | |
50 // Handles the alarm mode of the timer queue, where the timer fires once. | |
51 static void AlarmCallback(QueueTimer* queue_timer); | |
52 | |
53 // Handles the periodic timer. | |
54 static void TimerCallback(QueueTimer* queue_timer); | |
55 | |
56 HANDLE timer_queue_; | |
57 scoped_ptr<QueueTimer> queue_timer_; | |
58 scoped_event ev_; | |
59 volatile int cnt_; | |
60 volatile int max_cnt_; | |
61 }; | |
62 | |
63 void QueueTimerTest::AlarmCallback(QueueTimer* queue_timer) { | |
64 ASSERT_TRUE(queue_timer); | |
65 void* ctx = queue_timer->ctx(); | |
66 QueueTimerTest* test = static_cast<QueueTimerTest*>(ctx); | |
67 test->cnt_ = 1; | |
68 ASSERT_TRUE(::SetEvent(get(test->ev_))); | |
69 } | |
70 | |
71 void QueueTimerTest::TimerCallback(QueueTimer* queue_timer) { | |
72 ASSERT_TRUE(queue_timer); | |
73 void* ctx = queue_timer->ctx(); | |
74 QueueTimerTest* test = static_cast<QueueTimerTest*>(ctx); | |
75 | |
76 // Wait max_cnt_ ticks before signaling. | |
77 ++test->cnt_; | |
78 if (test->cnt_ == test->max_cnt_) { | |
79 ::SetEvent(get(test->ev_)); | |
80 } | |
81 } | |
82 | |
83 TEST_F(QueueTimerTest, QuickAlarm) { | |
84 queue_timer_.reset(new QueueTimer(timer_queue_, | |
85 &QueueTimerTest::AlarmCallback, | |
86 this)); | |
87 const int kWaitTimeMaxMs = 1000; | |
88 | |
89 // Set the timer to fire once right away. | |
90 LowResTimer timer(true); | |
91 ASSERT_HRESULT_SUCCEEDED( | |
92 queue_timer_->Start(0, 0, WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE)); | |
93 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(ev_), kWaitTimeMaxMs)); | |
94 EXPECT_EQ(1, cnt_); | |
95 | |
96 // Expect the alarm to fire quickly. | |
97 EXPECT_GE(50u, timer.GetMilliseconds()); | |
98 } | |
99 | |
100 // The test takes about 50 seconds to run. | |
101 TEST_F(QueueTimerTest, Alarm) { | |
102 if (!ShouldRunEnormousTest()) { | |
103 return; | |
104 } | |
105 | |
106 queue_timer_.reset(new QueueTimer(timer_queue_, | |
107 &QueueTimerTest::AlarmCallback, | |
108 this)); | |
109 const int kWaitTimeMaxMs = 60 * 1000; // 60 seconds. | |
110 | |
111 // Set the timer to fire once after 5 sec, 10 sec, 15 sec, 20 sec and wait. | |
112 LowResTimer timer(false); | |
113 for (int i = 1; i <= 4; ++i) { | |
114 const int time_interval_ms = 5 * 1000 * i; | |
115 SCOPED_TRACE(testing::Message() << "time_interval_ms=" << time_interval_ms); | |
116 | |
117 timer.Start(); | |
118 ASSERT_HRESULT_SUCCEEDED( | |
119 queue_timer_->Start(time_interval_ms, 0, WT_EXECUTEONLYONCE)); | |
120 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(ev_), kWaitTimeMaxMs)); | |
121 | |
122 int actual_time_ms = timer.GetMilliseconds(); | |
123 timer.Reset(); | |
124 | |
125 // Expect the alarm to fire anytime between a narrow interval. | |
126 EXPECT_EQ(1, cnt_); | |
127 EXPECT_LE(time_interval_ms - 50, actual_time_ms); | |
128 EXPECT_GE(time_interval_ms + 150, actual_time_ms); | |
129 | |
130 cnt_ = 0; | |
131 ::ResetEvent(get(ev_)); | |
132 } | |
133 | |
134 // Set the timer to fire once after 2000 ms but do not wait for it to fire. | |
135 ASSERT_HRESULT_SUCCEEDED( | |
136 queue_timer_->Start(2000, 0, WT_EXECUTEONLYONCE)); | |
137 EXPECT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(get(ev_), 100)); | |
138 EXPECT_EQ(0, cnt_); | |
139 } | |
140 | |
141 // The test takes about 35 seconds to run. | |
142 TEST_F(QueueTimerTest, Timer) { | |
143 if (!ShouldRunEnormousTest()) { | |
144 return; | |
145 } | |
146 | |
147 queue_timer_.reset(new QueueTimer(timer_queue_, | |
148 &QueueTimerTest::TimerCallback, | |
149 this)); | |
150 const int kWaitTimeMaxMs = 60 * 1000; // 60 seconds. | |
151 | |
152 max_cnt_ = 4; | |
153 | |
154 // Set the timer to fire at 10 seconds intervals with an initial delay of | |
155 // 5 seconds. | |
156 LowResTimer timer(true); | |
157 ASSERT_HRESULT_SUCCEEDED(queue_timer_->Start(5000, 10000, WT_EXECUTEDEFAULT)); | |
158 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(get(ev_), kWaitTimeMaxMs)); | |
159 | |
160 int actual_time_ms = timer.GetMilliseconds(); | |
161 | |
162 EXPECT_EQ(4, cnt_); | |
163 EXPECT_LE(35 * 1000 - 50, actual_time_ms); | |
164 EXPECT_GE(35 * 1000 + 350, actual_time_ms); | |
165 | |
166 // Tests it can't start periodic timers more than one time. | |
167 ASSERT_EQ(E_UNEXPECTED, queue_timer_->Start(25, 50, WT_EXECUTEDEFAULT)); | |
168 } | |
169 | |
170 } // namespace omaha | |
171 | |
OLD | NEW |