| 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 |