Chromium Code Reviews| Index: ash/system/logout_confirmation/logout_confirmation_controller_unittest.cc |
| diff --git a/ash/system/logout_confirmation/logout_confirmation_controller_unittest.cc b/ash/system/logout_confirmation/logout_confirmation_controller_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..85d744796951cfed8c40e5915299d547e5d25094 |
| --- /dev/null |
| +++ b/ash/system/logout_confirmation/logout_confirmation_controller_unittest.cc |
| @@ -0,0 +1,249 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "ash/system/logout_confirmation/logout_confirmation_controller.h" |
| + |
| +#include <queue> |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/compiler_specific.h" |
| +#include "base/location.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/single_thread_task_runner.h" |
| +#include "base/thread_task_runner_handle.h" |
| +#include "base/time/tick_clock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace ash { |
| +namespace internal { |
| + |
| +namespace { |
| + |
| +// A SingleThreadTaskRunner that mocks the current time and allows it to be |
| +// fast-forwarded. TODO(bartfab): Copies of this class exist in several tests. |
| +// Consolidate them (crbug.com/329911). |
|
stevenjb
2014/02/27 17:58:44
Would be nice to get this done sooner than later.
bartfab (slow)
2014/02/28 12:13:49
The problem is that it requires buy-in from base o
|
| +class MockTimeSingleThreadTaskRunner : public base::SingleThreadTaskRunner { |
| + public: |
| + MockTimeSingleThreadTaskRunner(); |
| + |
| + // base::SingleThreadTaskRunner: |
| + virtual bool RunsTasksOnCurrentThread() const OVERRIDE; |
| + virtual bool PostDelayedTask(const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) OVERRIDE; |
| + virtual bool PostNonNestableDelayedTask( |
| + const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) OVERRIDE; |
| + |
| + const base::TimeTicks& GetCurrentTime() const; |
| + |
| + void FastForwardBy(base::TimeDelta delta); |
| + void FastForwardUntilNoTasksRemain(); |
| + |
| + private: |
| + // Strict weak temporal ordering of tasks. |
| + class TemporalOrder { |
| + public: |
| + bool operator()( |
| + const std::pair<base::TimeTicks, base::Closure>& first_task, |
| + const std::pair<base::TimeTicks, base::Closure>& second_task) const; |
| + }; |
| + |
| + virtual ~MockTimeSingleThreadTaskRunner(); |
| + |
| + base::TimeTicks now_; |
| + std::priority_queue<std::pair<base::TimeTicks, base::Closure>, |
| + std::vector<std::pair<base::TimeTicks, base::Closure> >, |
| + TemporalOrder> tasks_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockTimeSingleThreadTaskRunner); |
| +}; |
| + |
| +// A base::TickClock that uses a MockTimeSingleThreadTaskRunner as the source of |
| +// the current time. |
| +class MockClock : public base::TickClock { |
| + public: |
| + explicit MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner); |
| + virtual ~MockClock(); |
| + |
| + // base::TickClock: |
| + virtual base::TimeTicks NowTicks() OVERRIDE; |
| + |
| + private: |
| + scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockClock); |
| +}; |
| + |
| + |
| +MockTimeSingleThreadTaskRunner::MockTimeSingleThreadTaskRunner() { |
| +} |
| + |
| +bool MockTimeSingleThreadTaskRunner::RunsTasksOnCurrentThread() const { |
| + return true; |
| +} |
| + |
| +bool MockTimeSingleThreadTaskRunner::PostDelayedTask( |
| + const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) { |
| + tasks_.push(std::pair<base::TimeTicks, base::Closure>(now_ + delay, task)); |
|
stevenjb
2014/02/27 17:58:44
nit: std::make_pair(now_ + delay, task)
bartfab (slow)
2014/02/28 12:13:49
Done.
|
| + return true; |
| +} |
| + |
| +bool MockTimeSingleThreadTaskRunner::PostNonNestableDelayedTask( |
| + const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) { |
| + NOTREACHED(); |
| + return false; |
| +} |
| + |
| +const base::TimeTicks& MockTimeSingleThreadTaskRunner::GetCurrentTime() const { |
| + return now_; |
| +} |
| + |
| +void MockTimeSingleThreadTaskRunner::FastForwardBy(base::TimeDelta delta) { |
| + const base::TimeTicks latest = now_ + delta; |
| + while (!tasks_.empty() && tasks_.top().first <= latest) { |
| + now_ = tasks_.top().first; |
| + base::Closure task = tasks_.top().second; |
| + tasks_.pop(); |
| + task.Run(); |
| + } |
| + now_ = latest; |
| +} |
| + |
| +void MockTimeSingleThreadTaskRunner::FastForwardUntilNoTasksRemain() { |
| + while (!tasks_.empty()) { |
| + now_ = tasks_.top().first; |
| + base::Closure task = tasks_.top().second; |
| + tasks_.pop(); |
| + task.Run(); |
| + } |
| +} |
| + |
| +bool MockTimeSingleThreadTaskRunner::TemporalOrder::operator()( |
| + const std::pair<base::TimeTicks, base::Closure>& first_task, |
| + const std::pair<base::TimeTicks, base::Closure>& second_task) const { |
| + return first_task.first > second_task.first; |
| +} |
| + |
| +MockTimeSingleThreadTaskRunner::~MockTimeSingleThreadTaskRunner() { |
| +} |
| + |
| +MockClock::MockClock(scoped_refptr<MockTimeSingleThreadTaskRunner> task_runner) |
| + : task_runner_(task_runner) { |
| +} |
| + |
| +MockClock::~MockClock() { |
| +} |
| + |
| +base::TimeTicks MockClock::NowTicks() { |
| + return task_runner_->GetCurrentTime(); |
| +} |
| + |
| +} // namespace |
| + |
| +class LogoutConfirmationControllerTest : public testing::Test { |
| + protected: |
| + LogoutConfirmationControllerTest(); |
| + virtual ~LogoutConfirmationControllerTest(); |
| + |
| + void LogOut(); |
| + |
| + bool log_out_called_; |
| + |
| + scoped_refptr<MockTimeSingleThreadTaskRunner> runner_; |
| + base::ThreadTaskRunnerHandle runner_handle_; |
| + |
| + LogoutConfirmationController controller_; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(LogoutConfirmationControllerTest); |
| +}; |
| + |
| +LogoutConfirmationControllerTest::LogoutConfirmationControllerTest() |
| + : log_out_called_(false), |
| + runner_(new MockTimeSingleThreadTaskRunner), |
| + runner_handle_(runner_), |
| + controller_(scoped_ptr<base::TickClock>(new MockClock(runner_)), |
| + base::Bind(&LogoutConfirmationControllerTest::LogOut, |
| + base::Unretained(this))) { |
| +} |
| + |
| +LogoutConfirmationControllerTest::~LogoutConfirmationControllerTest() { |
| +} |
| + |
| +void LogoutConfirmationControllerTest::LogOut() { |
| + log_out_called_ = true; |
| +} |
| + |
| +// Verifies that |
| +TEST_F(LogoutConfirmationControllerTest, ZeroDuration) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout(runner_->GetCurrentTime()); |
| + runner_->FastForwardBy(base::TimeDelta()); |
| + EXPECT_TRUE(log_out_called_); |
| +} |
| + |
| +TEST_F(LogoutConfirmationControllerTest, DurationExpired) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
| + EXPECT_FALSE(log_out_called_); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
| + EXPECT_TRUE(log_out_called_); |
| +} |
| + |
| +TEST_F(LogoutConfirmationControllerTest, DurationShortened) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(30)); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
| + EXPECT_FALSE(log_out_called_); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
| + EXPECT_TRUE(log_out_called_); |
| +} |
| + |
| +TEST_F(LogoutConfirmationControllerTest, DurationExtended) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(9)); |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + runner_->FastForwardBy(base::TimeDelta::FromSeconds(2)); |
| + EXPECT_TRUE(log_out_called_); |
| +} |
| + |
| +TEST_F(LogoutConfirmationControllerTest, UserAccepted) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + controller_.OnLogoutConfirmed(); |
| + EXPECT_TRUE(log_out_called_); |
| +} |
| + |
| +TEST_F(LogoutConfirmationControllerTest, UserDeclineed) { |
| + EXPECT_FALSE(log_out_called_); |
| + controller_.ConfirmLogout( |
| + runner_->GetCurrentTime() + base::TimeDelta::FromSeconds(10)); |
| + controller_.OnDialogClosed(); |
| + runner_->FastForwardUntilNoTasksRemain(); |
| + EXPECT_FALSE(log_out_called_); |
| +} |
| + |
| +} // namespace internal |
| +} // namespace ash |