OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 "ash/system/logout_confirmation/logout_confirmation_controller.h" | |
6 | |
7 #include <queue> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/bind_helpers.h" | |
13 #include "base/compiler_specific.h" | |
14 #include "base/location.h" | |
15 #include "base/memory/ref_counted.h" | |
16 #include "base/single_thread_task_runner.h" | |
17 #include "base/thread_task_runner_handle.h" | |
18 #include "base/time/tick_clock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace ash { | |
22 namespace internal { | |
23 | |
24 namespace { | |
25 | |
26 // A SingleThreadTaskRunner that mocks the current time and allows it to be | |
27 // fast-forwarded. TODO(bartfab): Copies of this class exist in several tests. | |
28 // Consolidate them (crbug.com/329911). | |
stevenjb
2014/02/27 17:58:44
Would be nice to get this done sooner than later.
bartfab (slow)
2014/02/28 12:13:49
The problem is that it requires buy-in from base o
| |
29 class MockTimeSingleThreadTaskRunner : public base::SingleThreadTaskRunner { | |
30 public: | |
31 MockTimeSingleThreadTaskRunner(); | |
32 | |
33 // base::SingleThreadTaskRunner: | |
34 virtual bool RunsTasksOnCurrentThread() const OVERRIDE; | |
35 virtual bool PostDelayedTask(const tracked_objects::Location& from_here, | |
36 const base::Closure& task, | |
37 base::TimeDelta delay) OVERRIDE; | |
38 virtual bool PostNonNestableDelayedTask( | |
39 const tracked_objects::Location& from_here, | |
40 const base::Closure& task, | |
41 base::TimeDelta delay) OVERRIDE; | |
42 | |
43 const base::TimeTicks& GetCurrentTime() const; | |
44 | |
45 void FastForwardBy(base::TimeDelta delta); | |
46 void FastForwardUntilNoTasksRemain(); | |
47 | |
48 private: | |
49 // Strict weak temporal ordering of tasks. | |
50 class TemporalOrder { | |
51 public: | |
52 bool operator()( | |
53 const std::pair<base::TimeTicks, base::Closure>& first_task, | |
54 const std::pair<base::TimeTicks, base::Closure>& second_task) const; | |
55 }; | |
56 | |
57 virtual ~MockTimeSingleThreadTaskRunner(); | |
58 | |
59 base::TimeTicks now_; | |
60 std::priority_queue<std::pair<base::TimeTicks, base::Closure>, | |
61 std::vector<std::pair<base::TimeTicks, base::Closure> >, | |
62 TemporalOrder> tasks_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(MockTimeSingleThreadTaskRunner); | |
65 }; | |
66 | |
67 // A base::TickClock that uses a MockTimeSingleThreadTaskRunner as the source of | |
68 // the current time. | |
69 class MockClock : public base::TickClock { | |
70 public: | |
71 explicit MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner); | |
72 virtual ~MockClock(); | |
73 | |
74 // base::TickClock: | |
75 virtual base::TimeTicks NowTicks() OVERRIDE; | |
76 | |
77 private: | |
78 scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner_; | |
79 | |
80 DISALLOW_COPY_AND_ASSIGN(MockClock); | |
81 }; | |
82 | |
83 | |
84 MockTimeSingleThreadTaskRunner::MockTimeSingleThreadTaskRunner() { | |
85 } | |
86 | |
87 bool MockTimeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { | |
88 return true; | |
89 } | |
90 | |
91 bool MockTimeSingleThreadTaskRunner::PostDelayedTask( | |
92 const tracked_objects::Location& from_here, | |
93 const base::Closure& task, | |
94 base::TimeDelta delay) { | |
95 tasks_.push(std::pair<base::TimeTicks, base::Closure>(now_ + delay, task)); | |
stevenjb
2014/02/27 17:58:44
nit: std::make_pair(now_ + delay, task)
bartfab (slow)
2014/02/28 12:13:49
Done.
| |
96 return true; | |
97 } | |
98 | |
99 bool MockTimeSingleThreadTaskRunner::PostNonNestableDelayedTask( | |
100 const tracked_objects::Location& from_here, | |
101 const base::Closure& task, | |
102 base::TimeDelta delay) { | |
103 NOTREACHED(); | |
104 return false; | |
105 } | |
106 | |
107 const base::TimeTicks& MockTimeSingleThreadTaskRunner::GetCurrentTime() const { | |
108 return now_; | |
109 } | |
110 | |
111 void MockTimeSingleThreadTaskRunner::FastForwardBy(base::TimeDelta delta) { | |
112 const base::TimeTicks latest = now_ + delta; | |
113 while (!tasks_.empty() && tasks_.top().first <= latest) { | |
114 now_ = tasks_.top().first; | |
115 base::Closure task = tasks_.top().second; | |
116 tasks_.pop(); | |
117 task.Run(); | |
118 } | |
119 now_ = latest; | |
120 } | |
121 | |
122 void MockTimeSingleThreadTaskRunner::FastForwardUntilNoTasksRemain() { | |
123 while (!tasks_.empty()) { | |
124 now_ = tasks_.top().first; | |
125 base::Closure task = tasks_.top().second; | |
126 tasks_.pop(); | |
127 task.Run(); | |
128 } | |
129 } | |
130 | |
131 bool MockTimeSingleThreadTaskRunner::TemporalOrder::operator()( | |
132 const std::pair<base::TimeTicks, base::Closure>& first_task, | |
133 const std::pair<base::TimeTicks, base::Closure>& second_task) const { | |
134 return first_task.first > second_task.first; | |
135 } | |
136 | |
137 MockTimeSingleThreadTaskRunner::~MockTimeSingleThreadTaskRunner() { | |
138 } | |
139 | |
140 MockClock::MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner) | |
141 : task_runner_(task_runner) { | |
142 } | |
143 | |
144 MockClock::~MockClock() { | |
145 } | |
146 | |
147 base::TimeTicks MockClock::NowTicks() { | |
148 return task_runner_->GetCurrentTime(); | |
149 } | |
150 | |
151 } // namespace | |
152 | |
153 class LogoutConfirmationControllerTest : public testing::Test { | |
154 protected: | |
155 LogoutConfirmationControllerTest(); | |
156 virtual ~LogoutConfirmationControllerTest(); | |
157 | |
158 void LogOut(); | |
159 | |
160 bool log_out_called_; | |
161 | |
162 scoped_refptr<MockTimeSingleThreadTaskRunner> runner_; | |
163 base::ThreadTaskRunnerHandle runner_handle_; | |
164 | |
165 LogoutConfirmationController controller_; | |
166 | |
167 private: | |
168 DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest); | |
169 }; | |
170 | |
171 LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() | |
172 : log_out_called_(false), | |
173 runner_(new MockTimeSingleThreadTaskRunner), | |
174 runner_handle_(runner_), | |
175 controller_(scoped_ptr<base::TickClock>(new MockClock(runner_)), | |
176 base::Bind(&LogoutConfirmationControllerTest::LogOut, | |
177 base::Unretained(this))) { | |
178 } | |
179 | |
180 LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() { | |
181 } | |
182 | |
183 void LogoutConfirmationControllerTest::LogOut() { | |
184 log_out_called_ = true; | |
185 } | |
186 | |
187 // Verifies that | |
188 TEST_F(LogoutConfirmationControllerTest, ZeroDuration) { | |
189 EXPECT_FALSE(log_out_called_); | |
190 controller_.ConfirmLogout(runner_->GetCurrentTime()); | |
191 runner_->FastForwardBy(base::TimeDelta()); | |
192 EXPECT_TRUE(log_out_called_); | |
193 } | |
194 | |
195 TEST_F(LogoutConfirmationControllerTest, DurationExpired) { | |
196 EXPECT_FALSE(log_out_called_); | |
197 controller_.ConfirmLogout( | |
198 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
199 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | |
200 EXPECT_FALSE(log_out_called_); | |
201 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | |
202 EXPECT_TRUE(log_out_called_); | |
203 } | |
204 | |
205 TEST_F(LogoutConfirmationControllerTest, DurationShortened) { | |
206 EXPECT_FALSE(log_out_called_); | |
207 controller_.ConfirmLogout( | |
208 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(30)); | |
209 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | |
210 EXPECT_FALSE(log_out_called_); | |
211 controller_.ConfirmLogout( | |
212 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
213 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | |
214 EXPECT_FALSE(log_out_called_); | |
215 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | |
216 EXPECT_TRUE(log_out_called_); | |
217 } | |
218 | |
219 TEST_F(LogoutConfirmationControllerTest, DurationExtended) { | |
220 EXPECT_FALSE(log_out_called_); | |
221 controller_.ConfirmLogout( | |
222 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
223 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | |
224 EXPECT_FALSE(log_out_called_); | |
225 controller_.ConfirmLogout( | |
226 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
227 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | |
228 EXPECT_TRUE(log_out_called_); | |
229 } | |
230 | |
231 TEST_F(LogoutConfirmationControllerTest, UserAccepted) { | |
232 EXPECT_FALSE(log_out_called_); | |
233 controller_.ConfirmLogout( | |
234 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
235 controller_.OnLogoutConfirmed(); | |
236 EXPECT_TRUE(log_out_called_); | |
237 } | |
238 | |
239 TEST_F(LogoutConfirmationControllerTest, UserDeclineed) { | |
240 EXPECT_FALSE(log_out_called_); | |
241 controller_.ConfirmLogout( | |
242 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | |
243 controller_.OnDialogClosed(); | |
244 runner_->FastForwardUntilNoTasksRemain(); | |
245 EXPECT_FALSE(log_out_called_); | |
246 } | |
247 | |
248 } // namespace internal | |
249 } // namespace ash | |
OLD | NEW |