OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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_button/logout_button_tray.h" | |
6 | |
7 #include <queue> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "ash/system/status_area_widget.h" | |
12 #include "base/callback.h" | |
13 #include "base/logging.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/single_thread_task_runner.h" | |
16 #include "base/thread_task_runner_handle.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 #include "ui/events/event.h" | |
19 #include "ui/events/keycodes/keyboard_codes.h" | |
20 #include "ui/views/controls/button/label_button.h" | |
21 | |
22 namespace ash { | |
23 namespace internal { | |
24 | |
25 class LogoutConfirmationDialogTest; | |
26 | |
27 // A SingleThreadTaskRunner that mocks the current time and allows it to be | |
28 // fast-forwarded. | |
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 }; | |
stevenjb
2013/12/18 21:55:20
It looks like this was copied from session_length_
binjin
2013/12/19 16:30:39
Done.
| |
64 | |
65 class MockLogoutConfirmationDelegate | |
66 : public LogoutConfirmationDialogView::Delegate { | |
67 public: | |
68 MockLogoutConfirmationDelegate( | |
69 scoped_refptr<MockTimeSingleThreadTaskRunner> runner, | |
70 LogoutConfirmationDialogTest* tester); | |
71 | |
72 // LogoutConfirmationDialogView::Delegate: | |
73 virtual void LogoutCurrentUser() OVERRIDE; | |
74 virtual base::TimeTicks GetCurrentTime() OVERRIDE const; | |
75 | |
76 bool WasLogoutCalled() const; | |
stevenjb
2013/12/18 21:55:20
bool logout_called() const { return logout_called_
binjin
2013/12/19 16:30:39
Done.
| |
77 | |
78 private: | |
79 bool logout_called_; | |
80 | |
81 scoped_refptr<MockTimeSingleThreadTaskRunner> runner_; | |
82 LogoutConfirmationDialogTest* tester_; | |
83 | |
84 DISALLOW_COPY_AND_ASSIGN(MockLogoutConfirmationDelegate); | |
85 }; | |
86 | |
87 class LogoutConfirmationDialogTest : public testing::Test { | |
88 public: | |
89 LogoutConfirmationDialogTest(); | |
90 virtual ~LogoutConfirmationDialogTest(); | |
91 | |
92 // testing::Test: | |
93 virtual void SetUp() OVERRIDE; | |
94 | |
95 void ChangeDialogDuration(base::TimeDelta duration); | |
96 void PressButton(); | |
97 void PressDialogButtonYes(); | |
98 void CloseDialog(); | |
99 | |
100 protected: | |
101 scoped_ptr<LogoutButtonTray> logout_button_; | |
102 scoped_refptr<MockTimeSingleThreadTaskRunner> runner_; | |
103 base::ThreadTaskRunnerHandle runner_handle_; | |
104 MockLogoutConfirmationDelegate* delegate_; | |
stevenjb
2013/12/18 21:55:20
nit: DISALLOW...
binjin
2013/12/19 16:30:39
Done.
| |
105 }; | |
106 | |
107 MockTimeSingleThreadTaskRunner::MockTimeSingleThreadTaskRunner() { | |
108 } | |
109 | |
110 bool MockTimeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { | |
111 return true; | |
112 } | |
113 | |
114 bool MockTimeSingleThreadTaskRunner::PostDelayedTask( | |
115 const tracked_objects::Location& from_here, | |
116 const base::Closure& task, | |
117 base::TimeDelta delay) { | |
118 tasks_.push(std::pair<base::TimeTicks, base::Closure>(now_ + delay, task)); | |
119 return true; | |
120 } | |
121 | |
122 bool MockTimeSingleThreadTaskRunner::PostNonNestableDelayedTask( | |
123 const tracked_objects::Location& from_here, | |
124 const base::Closure& task, | |
125 base::TimeDelta delay) { | |
126 NOTREACHED(); | |
127 return false; | |
128 } | |
129 | |
130 const base::TimeTicks& MockTimeSingleThreadTaskRunner::GetCurrentTime() const { | |
131 return now_; | |
132 } | |
133 | |
134 void MockTimeSingleThreadTaskRunner::FastForwardBy(base::TimeDelta delta) { | |
135 const base::TimeTicks latest = now_ + delta; | |
136 while (!tasks_.empty() && tasks_.top().first <= latest) { | |
137 now_ = tasks_.top().first; | |
138 base::Closure task = tasks_.top().second; | |
139 tasks_.pop(); | |
140 task.Run(); | |
141 } | |
142 now_ = latest; | |
143 } | |
144 | |
145 void MockTimeSingleThreadTaskRunner::FastForwardUntilNoTasksRemain() { | |
146 while (!tasks_.empty()) { | |
147 now_ = tasks_.top().first; | |
148 base::Closure task = tasks_.top().second; | |
149 tasks_.pop(); | |
150 task.Run(); | |
151 } | |
152 } | |
153 | |
154 bool MockTimeSingleThreadTaskRunner::TemporalOrder::operator()( | |
155 const std::pair<base::TimeTicks, base::Closure>& first_task, | |
156 const std::pair<base::TimeTicks, base::Closure>& second_task) const { | |
157 return first_task.first > second_task.first; | |
158 } | |
159 | |
160 MockTimeSingleThreadTaskRunner::~MockTimeSingleThreadTaskRunner() { | |
161 } | |
162 | |
163 MockLogoutConfirmationDelegate::MockLogoutConfirmationDelegate( | |
164 scoped_refptr<MockTimeSingleThreadTaskRunner> runner, | |
165 LogoutConfirmationDialogTest* tester) : runner_(runner), | |
stevenjb
2013/12/18 21:55:20
: on new line
binjin
2013/12/19 16:30:39
Done.
| |
166 tester_(tester) { | |
167 logout_called_ = false; | |
stevenjb
2013/12/18 21:55:20
Set in initializer list
binjin
2013/12/19 16:30:39
Done.
| |
168 } | |
169 | |
170 void MockLogoutConfirmationDelegate::LogoutCurrentUser() { | |
171 logout_called_ = true; | |
172 tester_->CloseDialog(); | |
173 } | |
174 | |
175 base::TimeTicks MockLogoutConfirmationDelegate::GetCurrentTime() const { | |
176 return runner_->GetCurrentTime(); | |
177 } | |
178 | |
179 bool MockLogoutConfirmationDelegate::WasLogoutCalled() const { | |
180 return logout_called_; | |
181 } | |
182 | |
183 LogoutConfirmationDialogTest::LogoutConfirmationDialogTest() | |
184 : runner_(new MockTimeSingleThreadTaskRunner), | |
185 runner_handle_(runner_) { | |
186 } | |
187 | |
188 LogoutConfirmationDialogTest::~LogoutConfirmationDialogTest() { | |
189 } | |
190 | |
191 void LogoutConfirmationDialogTest::PressButton() { | |
192 const ui::TranslatedKeyEvent faked_event(false, | |
193 static_cast<ui::KeyboardCode>(0), 0); | |
stevenjb
2013/12/18 21:55:20
align second line with 'false' or put 'false' on s
binjin
2013/12/19 16:30:39
Done.
| |
194 logout_button_->ButtonPressed( | |
195 reinterpret_cast<views::Button*>(logout_button_->button_), faked_event); | |
196 } | |
197 | |
198 void LogoutConfirmationDialogTest::PressDialogButtonYes() { | |
199 logout_button_->confirmation_dialog_->Accept(); | |
200 // |confirmation_dialog_| might already be destroyed, if not, manually call | |
201 // OnClosed() to simulate real browser environment behavior. | |
202 if (logout_button_->confirmation_dialog_) | |
203 logout_button_->confirmation_dialog_->OnClosed(); | |
204 } | |
205 | |
206 void LogoutConfirmationDialogTest::CloseDialog() { | |
207 if (logout_button_->confirmation_dialog_) | |
208 logout_button_->confirmation_dialog_->OnClosed(); | |
209 } | |
210 | |
211 void LogoutConfirmationDialogTest::SetUp() { | |
212 logout_button_.reset(new LogoutButtonTray(NULL)); | |
213 delegate_ = new MockLogoutConfirmationDelegate(runner_, this); | |
214 logout_button_->SetDelegateForTest( | |
215 scoped_ptr<LogoutConfirmationDialogView::Delegate>(delegate_)); | |
216 ChangeDialogDuration(base::TimeDelta::FromSeconds(20)); | |
217 } | |
218 | |
219 void LogoutConfirmationDialogTest::ChangeDialogDuration( | |
220 base::TimeDelta duration) { | |
221 logout_button_->OnLogoutDialogDurationChanged(duration); | |
222 } | |
223 | |
224 TEST_F(LogoutConfirmationDialogTest, NoClickWithDefaultValue) { | |
225 PressButton(); | |
226 | |
227 // Verify that the dialog is showing immediately after the logout button was | |
228 // pressed. | |
229 runner_->FastForwardBy(base::TimeDelta::FromSeconds(0)); | |
230 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
231 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
232 | |
233 // Verify that the dialog is still showing after 19 seconds since the logout | |
234 // button was pressed. | |
235 runner_->FastForwardBy(base::TimeDelta::FromSeconds(19)); | |
236 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
237 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
238 | |
239 // Verify that the dialog is closed after 21 seconds since the logout button | |
240 // was pressed. | |
241 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | |
242 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
243 EXPECT_TRUE(delegate_->WasLogoutCalled()); | |
244 } | |
245 | |
246 TEST_F(LogoutConfirmationDialogTest, ZeroPreferenceValue) { | |
247 ChangeDialogDuration(base::TimeDelta::FromSeconds(0)); | |
248 | |
249 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
250 | |
251 PressButton(); | |
252 | |
253 // Verify that user was logged out immediately after the logout button was | |
254 // pressed. | |
255 runner_->FastForwardBy(base::TimeDelta::FromSeconds(0)); | |
256 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
257 EXPECT_TRUE(delegate_->WasLogoutCalled()); | |
258 | |
259 runner_->FastForwardUntilNoTasksRemain(); | |
260 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
261 } | |
262 | |
263 TEST_F(LogoutConfirmationDialogTest, OnTheFlyDialogDurationChange) { | |
264 ChangeDialogDuration(base::TimeDelta::FromSeconds(5)); | |
265 | |
266 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
267 | |
268 PressButton(); | |
269 | |
270 // Verify that the dialog is showing immediately after the logout button was | |
271 // pressed. | |
272 runner_->FastForwardBy(base::TimeDelta::FromSeconds(0)); | |
273 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
274 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
275 | |
276 // Verify that the dialog is still showing after 3 seconds since the logout | |
277 // button was pressed. | |
278 runner_->FastForwardBy(base::TimeDelta::FromSeconds(3)); | |
279 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
280 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
281 | |
282 // And at this point we change the dialog duration preference. | |
283 ChangeDialogDuration(base::TimeDelta::FromSeconds(10)); | |
284 | |
285 // Verify that the dialog is still showing after 9 seconds since the logout | |
286 // button was pressed, with dialog duration preference changed. | |
287 runner_->FastForwardBy(base::TimeDelta::FromSeconds(6)); | |
288 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
289 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
290 | |
291 // Verify that the dialog is closed after 11 seconds since the logout button | |
292 // was pressed. | |
293 runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); | |
294 EXPECT_FALSE(logout_button_->IsConfirmationDialogShowing()); | |
295 EXPECT_TRUE(delegate_->WasLogoutCalled()); | |
296 } | |
297 | |
298 TEST_F(LogoutConfirmationDialogTest, UserClickedButton) { | |
299 PressButton(); | |
300 | |
301 // Verify that the dialog is showing immediately after the logout button was | |
302 // pressed. | |
303 runner_->FastForwardBy(base::TimeDelta::FromSeconds(0)); | |
304 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
305 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
306 | |
307 // Verify that the dialog is still showing after 3 seconds since the logout | |
308 // button was pressed. | |
309 runner_->FastForwardBy(base::TimeDelta::FromSeconds(3)); | |
310 EXPECT_TRUE(logout_button_->IsConfirmationDialogShowing()); | |
311 EXPECT_FALSE(delegate_->WasLogoutCalled()); | |
312 | |
313 // And at this point we click the accept button. | |
314 PressDialogButtonYes(); | |
315 | |
316 // Verify that the user was logged out immediately after the accept button | |
317 // was clicked. | |
318 runner_->FastForwardBy(base::TimeDelta::FromSeconds(0)); | |
319 EXPECT_TRUE(delegate_->WasLogoutCalled()); | |
320 } | |
321 | |
322 } // namespace internal | |
323 } // namespace ash | |
OLD | NEW |