OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/system/chromeos/session/logout_confirmation_controller.h" | 5 #include "ash/system/chromeos/session/logout_confirmation_controller.h" |
6 | 6 |
7 #include <queue> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | 7 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
13 #include "base/compiler_specific.h" | |
14 #include "base/location.h" | |
15 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
16 #include "base/single_thread_task_runner.h" | 10 #include "base/test/test_mock_time_task_runner.h" |
17 #include "base/thread_task_runner_handle.h" | 11 #include "base/thread_task_runner_handle.h" |
18 #include "base/time/tick_clock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
20 | 13 |
21 namespace ash { | 14 namespace ash { |
22 namespace { | |
23 | |
24 // A SingleThreadTaskRunner that mocks the current time and allows it to be | |
25 // fast-forwarded. TODO(bartfab): Copies of this class exist in several tests. | |
26 // Consolidate them (crbug.com/329911). | |
27 class MockTimeSingleThreadTaskRunner : public base::SingleThreadTaskRunner { | |
28 public: | |
29 MockTimeSingleThreadTaskRunner(); | |
30 | |
31 // base::SingleThreadTaskRunner: | |
32 virtual bool RunsTasksOnCurrentThread() const override; | |
33 virtual bool PostDelayedTask(const tracked_objects::Location& from_here, | |
34 const base::Closure& task, | |
35 base::TimeDelta delay) override; | |
36 virtual bool PostNonNestableDelayedTask( | |
37 const tracked_objects::Location& from_here, | |
38 const base::Closure& task, | |
39 base::TimeDelta delay) override; | |
40 | |
41 const base::TimeTicks& GetCurrentTime() const; | |
42 | |
43 void FastForwardBy(base::TimeDelta delta); | |
44 void FastForwardUntilNoTasksRemain(); | |
45 | |
46 private: | |
47 // Strict weak temporal ordering of tasks. | |
48 class TemporalOrder { | |
49 public: | |
50 bool operator()( | |
51 const std::pair<base::TimeTicks, base::Closure>& first_task, | |
52 const std::pair<base::TimeTicks, base::Closure>& second_task) const; | |
53 }; | |
54 | |
55 virtual ~MockTimeSingleThreadTaskRunner(); | |
56 | |
57 base::TimeTicks now_; | |
58 std::priority_queue<std::pair<base::TimeTicks, base::Closure>, | |
59 std::vector<std::pair<base::TimeTicks, base::Closure> >, | |
60 TemporalOrder> tasks_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(MockTimeSingleThreadTaskRunner); | |
63 }; | |
64 | |
65 // A base::TickClock that uses a MockTimeSingleThreadTaskRunner as the source of | |
66 // the current time. | |
67 class MockClock : public base::TickClock { | |
68 public: | |
69 explicit MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner); | |
70 virtual ~MockClock(); | |
71 | |
72 // base::TickClock: | |
73 virtual base::TimeTicks NowTicks() override; | |
74 | |
75 private: | |
76 scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner_; | |
77 | |
78 DISALLOW_COPY_AND_ASSIGN(MockClock); | |
79 }; | |
80 | |
81 | |
82 MockTimeSingleThreadTaskRunner::MockTimeSingleThreadTaskRunner() { | |
83 } | |
84 | |
85 bool MockTimeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { | |
86 return true; | |
87 } | |
88 | |
89 bool MockTimeSingleThreadTaskRunner::PostDelayedTask( | |
90 const tracked_objects::Location& from_here, | |
91 const base::Closure& task, | |
92 base::TimeDelta delay) { | |
93 tasks_.push(std::make_pair(now_ + delay, task)); | |
94 return true; | |
95 } | |
96 | |
97 bool MockTimeSingleThreadTaskRunner::PostNonNestableDelayedTask( | |
98 const tracked_objects::Location& from_here, | |
99 const base::Closure& task, | |
100 base::TimeDelta delay) { | |
101 NOTREACHED(); | |
102 return false; | |
103 } | |
104 | |
105 const base::TimeTicks& MockTimeSingleThreadTaskRunner::GetCurrentTime() const { | |
106 return now_; | |
107 } | |
108 | |
109 void MockTimeSingleThreadTaskRunner::FastForwardBy(base::TimeDelta delta) { | |
110 const base::TimeTicks latest = now_ + delta; | |
111 while (!tasks_.empty() && tasks_.top().first <= latest) { | |
112 now_ = tasks_.top().first; | |
113 base::Closure task = tasks_.top().second; | |
114 tasks_.pop(); | |
115 task.Run(); | |
116 } | |
117 now_ = latest; | |
118 } | |
119 | |
120 void MockTimeSingleThreadTaskRunner::FastForwardUntilNoTasksRemain() { | |
121 while (!tasks_.empty()) { | |
122 now_ = tasks_.top().first; | |
123 base::Closure task = tasks_.top().second; | |
124 tasks_.pop(); | |
125 task.Run(); | |
126 } | |
127 } | |
128 | |
129 bool MockTimeSingleThreadTaskRunner::TemporalOrder::operator()( | |
130 const std::pair<base::TimeTicks, base::Closure>& first_task, | |
131 const std::pair<base::TimeTicks, base::Closure>& second_task) const { | |
132 return first_task.first > second_task.first; | |
133 } | |
134 | |
135 MockTimeSingleThreadTaskRunner::~MockTimeSingleThreadTaskRunner() { | |
136 } | |
137 | |
138 MockClock::MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner) | |
139 : task_runner_(task_runner) { | |
140 } | |
141 | |
142 MockClock::~MockClock() { | |
143 } | |
144 | |
145 base::TimeTicks MockClock::NowTicks() { | |
146 return task_runner_->GetCurrentTime(); | |
147 } | |
148 | |
149 } // namespace | |
150 | 15 |
151 class LogoutConfirmationControllerTest : public testing::Test { | 16 class LogoutConfirmationControllerTest : public testing::Test { |
152 protected: | 17 protected: |
153 LogoutConfirmationControllerTest(); | 18 LogoutConfirmationControllerTest(); |
154 virtual ~LogoutConfirmationControllerTest(); | 19 virtual ~LogoutConfirmationControllerTest(); |
155 | 20 |
156 void LogOut(); | 21 void LogOut(); |
157 | 22 |
158 bool log_out_called_; | 23 bool log_out_called_; |
159 | 24 |
160 scoped_refptr<MockTimeSingleThreadTaskRunner> runner_; | 25 scoped_refptr<base::TestMockTimeTaskRunner> runner_; |
161 base::ThreadTaskRunnerHandle runner_handle_; | 26 base::ThreadTaskRunnerHandle runner_handle_; |
162 | 27 |
163 LogoutConfirmationController controller_; | 28 LogoutConfirmationController controller_; |
164 | 29 |
165 private: | 30 private: |
166 DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest); | 31 DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest); |
167 }; | 32 }; |
168 | 33 |
169 LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() | 34 LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() |
170 : log_out_called_(false), | 35 : log_out_called_(false), |
171 runner_(new MockTimeSingleThreadTaskRunner), | 36 runner_(new base::TestMockTimeTaskRunner), |
172 runner_handle_(runner_), | 37 runner_handle_(runner_), |
173 controller_(base::Bind(&LogoutConfirmationControllerTest::LogOut, | 38 controller_(base::Bind(&LogoutConfirmationControllerTest::LogOut, |
174 base::Unretained(this))) { | 39 base::Unretained(this))) { |
175 controller_.SetClockForTesting( | 40 controller_.SetClockForTesting(runner_->GetMockTickClock()); |
176 scoped_ptr<base::TickClock>(new MockClock(runner_))); | |
177 } | 41 } |
178 | 42 |
179 LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() { | 43 LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() { |
180 } | 44 } |
181 | 45 |
182 void LogoutConfirmationControllerTest::LogOut() { | 46 void LogoutConfirmationControllerTest::LogOut() { |
183 log_out_called_ = true; | 47 log_out_called_ = true; |
184 } | 48 } |
185 | 49 |
186 // Verifies that the user is logged out immediately if logout confirmation with | 50 // Verifies that the user is logged out immediately if logout confirmation with |
187 // a zero-length countdown is requested. | 51 // a zero-length countdown is requested. |
188 TEST_F(LogoutConfirmationControllerTest, ZeroDuration) { | 52 TEST_F(LogoutConfirmationControllerTest, ZeroDuration) { |
189 controller_.ConfirmLogout(runner_->GetCurrentTime()); | 53 controller_.ConfirmLogout(runner_->GetCurrentMockTime()); |
190 EXPECT_FALSE(log_out_called_); | 54 EXPECT_FALSE(log_out_called_); |
191 runner_->FastForwardBy(base::TimeDelta()); | 55 runner_->FastForwardBy(base::TimeDelta()); |
192 EXPECT_TRUE(log_out_called_); | 56 EXPECT_TRUE(log_out_called_); |
193 } | 57 } |
194 | 58 |
195 // Verifies that the user is logged out when the countdown expires. | 59 // Verifies that the user is logged out when the countdown expires. |
196 TEST_F(LogoutConfirmationControllerTest, DurationExpired) { | 60 TEST_F(LogoutConfirmationControllerTest, DurationExpired) { |
197 controller_.ConfirmLogout( | 61 controller_.ConfirmLogout( |
198 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 62 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
199 EXPECT_FALSE(log_out_called_); | 63 EXPECT_FALSE(log_out_called_); |
200 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | 64 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
201 EXPECT_FALSE(log_out_called_); | 65 EXPECT_FALSE(log_out_called_); |
202 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | 66 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
203 EXPECT_TRUE(log_out_called_); | 67 EXPECT_TRUE(log_out_called_); |
204 } | 68 } |
205 | 69 |
206 // Verifies that when a second request to confirm logout is made and the second | 70 // Verifies that when a second request to confirm logout is made and the second |
207 // request's countdown ends before the original request's, the user is logged | 71 // request's countdown ends before the original request's, the user is logged |
208 // out when the new countdown expires. | 72 // out when the new countdown expires. |
209 TEST_F(LogoutConfirmationControllerTest, DurationShortened) { | 73 TEST_F(LogoutConfirmationControllerTest, DurationShortened) { |
210 controller_.ConfirmLogout( | 74 controller_.ConfirmLogout( |
211 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(30)); | 75 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(30)); |
212 EXPECT_FALSE(log_out_called_); | 76 EXPECT_FALSE(log_out_called_); |
213 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | 77 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
214 EXPECT_FALSE(log_out_called_); | 78 EXPECT_FALSE(log_out_called_); |
215 controller_.ConfirmLogout( | 79 controller_.ConfirmLogout( |
216 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 80 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
217 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | 81 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
218 EXPECT_FALSE(log_out_called_); | 82 EXPECT_FALSE(log_out_called_); |
219 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | 83 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
220 EXPECT_TRUE(log_out_called_); | 84 EXPECT_TRUE(log_out_called_); |
221 } | 85 } |
222 | 86 |
223 // Verifies that when a second request to confirm logout is made and the second | 87 // Verifies that when a second request to confirm logout is made and the second |
224 // request's countdown ends after the original request's, the user is logged | 88 // request's countdown ends after the original request's, the user is logged |
225 // out when the original countdown expires. | 89 // out when the original countdown expires. |
226 TEST_F(LogoutConfirmationControllerTest, DurationExtended) { | 90 TEST_F(LogoutConfirmationControllerTest, DurationExtended) { |
227 controller_.ConfirmLogout( | 91 controller_.ConfirmLogout( |
228 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 92 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
229 EXPECT_FALSE(log_out_called_); | 93 EXPECT_FALSE(log_out_called_); |
230 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | 94 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
231 EXPECT_FALSE(log_out_called_); | 95 EXPECT_FALSE(log_out_called_); |
232 controller_.ConfirmLogout( | 96 controller_.ConfirmLogout( |
233 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 97 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
234 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | 98 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
235 EXPECT_TRUE(log_out_called_); | 99 EXPECT_TRUE(log_out_called_); |
236 } | 100 } |
237 | 101 |
238 // Verifies that when the screen is locked while the countdown is running, the | 102 // Verifies that when the screen is locked while the countdown is running, the |
239 // user is not logged out, even when the original countdown expires. | 103 // user is not logged out, even when the original countdown expires. |
240 TEST_F(LogoutConfirmationControllerTest, Lock) { | 104 TEST_F(LogoutConfirmationControllerTest, Lock) { |
241 controller_.ConfirmLogout( | 105 controller_.ConfirmLogout( |
242 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 106 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
243 EXPECT_FALSE(log_out_called_); | 107 EXPECT_FALSE(log_out_called_); |
244 controller_.OnLockStateChanged(true); | 108 controller_.OnLockStateChanged(true); |
245 runner_->FastForwardUntilNoTasksRemain(); | 109 runner_->FastForwardUntilNoTasksRemain(); |
246 EXPECT_FALSE(log_out_called_); | 110 EXPECT_FALSE(log_out_called_); |
247 } | 111 } |
248 | 112 |
249 // Verifies that when the user confirms the logout request, the user is logged | 113 // Verifies that when the user confirms the logout request, the user is logged |
250 // out immediately. | 114 // out immediately. |
251 TEST_F(LogoutConfirmationControllerTest, UserAccepted) { | 115 TEST_F(LogoutConfirmationControllerTest, UserAccepted) { |
252 controller_.ConfirmLogout( | 116 controller_.ConfirmLogout( |
253 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 117 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
254 EXPECT_FALSE(log_out_called_); | 118 EXPECT_FALSE(log_out_called_); |
255 controller_.OnLogoutConfirmed(); | 119 controller_.OnLogoutConfirmed(); |
256 EXPECT_TRUE(log_out_called_); | 120 EXPECT_TRUE(log_out_called_); |
257 } | 121 } |
258 | 122 |
259 // Verifies that when the user denies the logout request, the user is not logged | 123 // Verifies that when the user denies the logout request, the user is not logged |
260 // out, even when the original countdown expires. | 124 // out, even when the original countdown expires. |
261 TEST_F(LogoutConfirmationControllerTest, UserDenied) { | 125 TEST_F(LogoutConfirmationControllerTest, UserDenied) { |
262 controller_.ConfirmLogout( | 126 controller_.ConfirmLogout( |
263 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 127 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
264 EXPECT_FALSE(log_out_called_); | 128 EXPECT_FALSE(log_out_called_); |
265 controller_.OnDialogClosed(); | 129 controller_.OnDialogClosed(); |
266 runner_->FastForwardUntilNoTasksRemain(); | 130 runner_->FastForwardUntilNoTasksRemain(); |
267 EXPECT_FALSE(log_out_called_); | 131 EXPECT_FALSE(log_out_called_); |
268 } | 132 } |
269 | 133 |
270 // Verifies that after the user has denied a logout request, a subsequent logout | 134 // Verifies that after the user has denied a logout request, a subsequent logout |
271 // request is handled correctly and the user is logged out when the countdown | 135 // request is handled correctly and the user is logged out when the countdown |
272 // expires. | 136 // expires. |
273 TEST_F(LogoutConfirmationControllerTest, DurationExpiredAfterDeniedRequest) { | 137 TEST_F(LogoutConfirmationControllerTest, DurationExpiredAfterDeniedRequest) { |
274 controller_.ConfirmLogout( | 138 controller_.ConfirmLogout( |
275 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 139 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
276 EXPECT_FALSE(log_out_called_); | 140 EXPECT_FALSE(log_out_called_); |
277 controller_.OnDialogClosed(); | 141 controller_.OnDialogClosed(); |
278 runner_->FastForwardUntilNoTasksRemain(); | 142 runner_->FastForwardUntilNoTasksRemain(); |
279 EXPECT_FALSE(log_out_called_); | 143 EXPECT_FALSE(log_out_called_); |
280 | 144 |
281 controller_.ConfirmLogout( | 145 controller_.ConfirmLogout( |
282 runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); | 146 runner_->GetCurrentMockTime() + base::TimeDelta::FromSeconds(10)); |
283 EXPECT_FALSE(log_out_called_); | 147 EXPECT_FALSE(log_out_called_); |
284 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); | 148 runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
285 EXPECT_FALSE(log_out_called_); | 149 EXPECT_FALSE(log_out_called_); |
286 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | 150 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
287 EXPECT_TRUE(log_out_called_); | 151 EXPECT_TRUE(log_out_called_); |
288 } | 152 } |
289 | 153 |
290 } // namespace ash | 154 } // namespace ash |
OLD | NEW |