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