Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / system / chromeos / session / logout_confirmation_controller_unittest.cc
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/chromeos/session/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 {
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
151 class LogoutConfirmationControllerTest : public testing::Test {
152  protected:
153   LogoutConfirmationControllerTest();
154   virtual ~LogoutConfirmationControllerTest();
155
156   void LogOut();
157
158   bool log_out_called_;
159
160   scoped_refptr<MockTimeSingleThreadTaskRunner> runner_;
161   base::ThreadTaskRunnerHandle runner_handle_;
162
163   LogoutConfirmationController controller_;
164
165  private:
166   DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest);
167 };
168
169 LogoutConfirmationControllerTest::LogoutConfirmationControllerTest()
170     : log_out_called_(false),
171       runner_(new MockTimeSingleThreadTaskRunner),
172       runner_handle_(runner_),
173       controller_(base::Bind(&LogoutConfirmationControllerTest::LogOut,
174                              base::Unretained(this))) {
175   controller_.SetClockForTesting(
176       scoped_ptr<base::TickClock>(new MockClock(runner_)));
177 }
178
179 LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() {
180 }
181
182 void LogoutConfirmationControllerTest::LogOut() {
183   log_out_called_ = true;
184 }
185
186 // Verifies that the user is logged out immediately if logout confirmation with
187 // a zero-length countdown is requested.
188 TEST_F(LogoutConfirmationControllerTest, ZeroDuration) {
189   controller_.ConfirmLogout(runner_->GetCurrentTime());
190   EXPECT_FALSE(log_out_called_);
191   runner_->FastForwardBy(base::TimeDelta());
192   EXPECT_TRUE(log_out_called_);
193 }
194
195 // Verifies that the user is logged out when the countdown expires.
196 TEST_F(LogoutConfirmationControllerTest, DurationExpired) {
197   controller_.ConfirmLogout(
198       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
199   EXPECT_FALSE(log_out_called_);
200   runner_->FastForwardBy(base::TimeDelta::FromSeconds(9));
201   EXPECT_FALSE(log_out_called_);
202   runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
203   EXPECT_TRUE(log_out_called_);
204 }
205
206 // 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
208 // out when the new countdown expires.
209 TEST_F(LogoutConfirmationControllerTest, DurationShortened) {
210   controller_.ConfirmLogout(
211       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(30));
212   EXPECT_FALSE(log_out_called_);
213   runner_->FastForwardBy(base::TimeDelta::FromSeconds(9));
214   EXPECT_FALSE(log_out_called_);
215   controller_.ConfirmLogout(
216       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
217   runner_->FastForwardBy(base::TimeDelta::FromSeconds(9));
218   EXPECT_FALSE(log_out_called_);
219   runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
220   EXPECT_TRUE(log_out_called_);
221 }
222
223 // 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
225 // out when the original countdown expires.
226 TEST_F(LogoutConfirmationControllerTest, DurationExtended) {
227   controller_.ConfirmLogout(
228       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
229   EXPECT_FALSE(log_out_called_);
230   runner_->FastForwardBy(base::TimeDelta::FromSeconds(9));
231   EXPECT_FALSE(log_out_called_);
232   controller_.ConfirmLogout(
233       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
234   runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
235   EXPECT_TRUE(log_out_called_);
236 }
237
238 // 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.
240 TEST_F(LogoutConfirmationControllerTest, Lock) {
241   controller_.ConfirmLogout(
242       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
243   EXPECT_FALSE(log_out_called_);
244   controller_.OnLockStateChanged(true);
245   runner_->FastForwardUntilNoTasksRemain();
246   EXPECT_FALSE(log_out_called_);
247 }
248
249 // Verifies that when the user confirms the logout request, the user is logged
250 // out immediately.
251 TEST_F(LogoutConfirmationControllerTest, UserAccepted) {
252   controller_.ConfirmLogout(
253       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
254   EXPECT_FALSE(log_out_called_);
255   controller_.OnLogoutConfirmed();
256   EXPECT_TRUE(log_out_called_);
257 }
258
259 // Verifies that when the user denies the logout request, the user is not logged
260 // out, even when the original countdown expires.
261 TEST_F(LogoutConfirmationControllerTest, UserDenied) {
262   controller_.ConfirmLogout(
263       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
264   EXPECT_FALSE(log_out_called_);
265   controller_.OnDialogClosed();
266   runner_->FastForwardUntilNoTasksRemain();
267   EXPECT_FALSE(log_out_called_);
268 }
269
270 // 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
272 // expires.
273 TEST_F(LogoutConfirmationControllerTest, DurationExpiredAfterDeniedRequest) {
274   controller_.ConfirmLogout(
275       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
276   EXPECT_FALSE(log_out_called_);
277   controller_.OnDialogClosed();
278   runner_->FastForwardUntilNoTasksRemain();
279   EXPECT_FALSE(log_out_called_);
280
281   controller_.ConfirmLogout(
282       runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10));
283   EXPECT_FALSE(log_out_called_);
284   runner_->FastForwardBy(base::TimeDelta::FromSeconds(9));
285   EXPECT_FALSE(log_out_called_);
286   runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
287   EXPECT_TRUE(log_out_called_);
288 }
289
290 }  // namespace ash