Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Unified Diff: chrome/browser/chromeos/session_length_limiter_unittest.cc

Issue 11499012: Add policy for limiting the session length (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Not sure why the patch is not applying - bot source out of sync with ToT? Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/session_length_limiter_unittest.cc
diff --git a/chrome/browser/chromeos/session_length_limiter_unittest.cc b/chrome/browser/chromeos/session_length_limiter_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..20a28b643c2151e78654a7c07a4709f7eb0d1547
--- /dev/null
+++ b/chrome/browser/chromeos/session_length_limiter_unittest.cc
@@ -0,0 +1,503 @@
+// Copyright (c) 2012 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 "chrome/browser/chromeos/session_length_limiter.h"
+
+#include <deque>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/string_number_conversions.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time.h"
+#include "chrome/browser/chromeos/login/mock_user_manager.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/session_length_limiter_factory.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::Pointee;
+using ::testing::Return;
+
+namespace chromeos {
+
+namespace {
+
+// The interval at which the SessionLengthLimiter fires periodic callbacks.
+const base::TimeDelta kSessionLengthLimitTimerInterval(
+ base::TimeDelta::FromSeconds(1));
+
+const base::TimeDelta kZeroTimeDelta;
+const base::TimeDelta kTenSeconds(base::TimeDelta::FromSeconds(10));
+
+class MockSessionLengthLimiterObserver : public SessionLengthLimiter::Observer {
+ public:
+ MOCK_METHOD1(SessionTimeRemainingChanged, void(const base::TimeDelta*));
+};
+
+class MockSessionLengthLimiterDelegate : public SessionLengthLimiter::Delegate {
+ public:
+ MOCK_CONST_METHOD0(GetCurrentTime, const base::Time(void));
+ MOCK_METHOD0(Logout, void(void));
+};
+
+// A SingleThreadTaskRunner that allows the task queue to be inspected and
+// delayed tasks to be run without waiting for the actual delays to expire.
+class ImmediateSingleThreadTaskRunner : public base::SingleThreadTaskRunner {
+ public:
+ virtual bool RunsTasksOnCurrentThread() const {
+ return true;
+ }
+
+ virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) OVERRIDE {
+ tasks_.push_back(std::pair<base::TimeDelta, base::Closure>(delay, task));
+ return true;
+ }
+
+ virtual bool PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) OVERRIDE {
+ NOTREACHED();
+ return false;
+ }
+
+ void RunTasks() {
+ std::deque<std::pair<base::TimeDelta, base::Closure> > tasks;
+ tasks.swap(tasks_);
+ for (std::deque<std::pair<base::TimeDelta, base::Closure> >::iterator
+ it = tasks.begin(); it != tasks.end(); ++it) {
+ it->second.Run();
+ }
+ }
+
+ const std::deque<std::pair<base::TimeDelta, base::Closure> >& tasks() const {
+ return tasks_;
+ }
+
+ private:
+ std::deque<std::pair<base::TimeDelta, base::Closure> > tasks_;
+
+ virtual ~ImmediateSingleThreadTaskRunner() {}
+};
+
+} // namespace
+
+class SessionLengthLimiterTest : public testing::Test {
+ protected:
+ SessionLengthLimiterTest() : delegate_(NULL) {
+ }
+
+ virtual void SetUp() {
+ old_user_manager_ = UserManager::Set(&mock_user_manager_);
+ runner_ = new ImmediateSingleThreadTaskRunner;
+
+ // Initialize the mock clock to a fixed value, ensuring that timezone
+ // differences or DST changes do not affect the test.
+ now_ = base::Time::UnixEpoch() + base::TimeDelta::FromDays(40 * 365);
+ session_start_time_ = now_;
+
+ SessionLengthLimiterFactory::GetInstance()->RegisterUserPrefs(&prefs_);
+ }
+
+ virtual void TearDown() {
+ session_length_limiter_->Shutdown();
+ UserManager::Set(old_user_manager_);
+ }
+
+ void CreateSessionLengthLimiter() {
+ delegate_ = new NiceMock<MockSessionLengthLimiterDelegate>;
+ ON_CALL(*delegate_, GetCurrentTime())
+ .WillByDefault(Invoke(this, &SessionLengthLimiterTest::GetCurrentTime));
+ EXPECT_CALL(*delegate_, Logout()).Times(0);
+
+ session_length_limiter_.reset(new SessionLengthLimiter(delegate_, &prefs_));
+ }
+
+ void SetHasBrowserRestarted(bool has_browser_restarted) {
+ EXPECT_CALL(mock_user_manager_, HasBrowserRestarted())
+ .WillRepeatedly((Return(has_browser_restarted)));
+ }
+
+ void SetSessionStartTimePref(int64 session_start_time) {
+ prefs_.SetUserPref(prefs::kSessionStartTime,
+ base::Value::CreateStringValue(
+ base::Int64ToString(session_start_time)));
+ }
+
+ void VerifySessionStartTimePref() {
+ base::Time session_start_time(base::Time::FromInternalValue(
+ prefs_.GetInt64(prefs::kSessionStartTime)));
+ EXPECT_EQ(session_start_time_, session_start_time);
+ }
+
+ void SetSessionLengthLimitPref(int64 session_length_limit) {
+ prefs_.SetUserPref(prefs::kSessionLengthLimit,
+ base::Value::CreateIntegerValue(session_length_limit));
+ }
+
+ void UpdateRemainingTime(int64 session_length_limit) {
+ if (!session_length_limit) {
+ remaining_.reset();
+ return;
+ }
+ base::TimeDelta remaining(
+ base::TimeDelta::FromMilliseconds(session_length_limit) -
+ (now_ - session_start_time_));
+ if (remaining < kZeroTimeDelta)
+ remaining = kZeroTimeDelta;
+ remaining_.reset(new base::TimeDelta(remaining));
+ }
+
+ void ExpectSessionTimeRemainingChangedCallback() {
+ EXPECT_CALL(observer_, SessionTimeRemainingChanged(_)).Times(0);
+ if (remaining_) {
+ EXPECT_CALL(observer_, SessionTimeRemainingChanged(
+ Pointee(Eq(*remaining_)))).Times(1);
+ } else {
+ EXPECT_CALL(observer_, SessionTimeRemainingChanged(NULL)).Times(1);
+ }
+ }
+
+ void ExpectLogout() {
+ Mock::VerifyAndClearExpectations(delegate_);
+ EXPECT_CALL(*delegate_, Logout()).Times(1);
+ }
+
+ void VerifyTimerTickIsEnqueued() {
+ ASSERT_EQ(1U, runner_->tasks().size());
+ EXPECT_EQ(kSessionLengthLimitTimerInterval,
+ runner_->tasks().front().first);
+ }
+
+ void VerifyTimerTick() {
+ ExpectSessionTimeRemainingChangedCallback();
+ runner_->RunTasks();
+ Mock::VerifyAndClearExpectations(&observer_);
+ VerifyTimerTickIsEnqueued();
+
+ now_ += kSessionLengthLimitTimerInterval;
+ *remaining_ -= kSessionLengthLimitTimerInterval;
+ if (*remaining_ < kZeroTimeDelta)
+ remaining_.reset(new base::TimeDelta(kZeroTimeDelta));
+ }
+
+ base::Time GetCurrentTime() const {
+ return now_;
+ }
+
+ UserManager* old_user_manager_;
+ MockUserManager mock_user_manager_;
+ scoped_refptr<ImmediateSingleThreadTaskRunner> runner_;
+ TestingPrefService prefs_;
+
+ MockSessionLengthLimiterObserver observer_;
+ MockSessionLengthLimiterDelegate* delegate_; // Owned by
+ // session_length_limiter_.
+
+ base::Time now_;
+ base::Time session_start_time_;
+
+ scoped_ptr<SessionLengthLimiter> session_length_limiter_;
+
+ base::TimeDelta session_length_limit_;
+ scoped_ptr<base::TimeDelta> remaining_;
+};
+
+// Verifies that during login, the session start time is written to prefs if no
+// session start time is present in prefs yet.
+TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeUnset) {
+ SetHasBrowserRestarted(false);
+
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during login, the session start time is written to prefs if an
+// invalid value is currently present in prefs.
+TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeInvalid) {
+ SetHasBrowserRestarted(false);
+
+ SetSessionStartTimePref(0);
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during login, the session start time is written to prefs if a
+// value lying in the future is currently present in prefs.
+TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeFuture) {
+ SetHasBrowserRestarted(false);
+
+ SetSessionStartTimePref(
+ (now_ + base::TimeDelta::FromHours(2)).ToInternalValue());
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during login, the session start time is written to prefs if a
+// previously stored valid value is currently present in prefs.
+TEST_F(SessionLengthLimiterTest, StartWithSessionStartTimeValid) {
+ SetHasBrowserRestarted(false);
+
+ const base::Time previous_start_time = now_ - base::TimeDelta::FromHours(2);
+ SetSessionStartTimePref(previous_start_time.ToInternalValue());
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during restart after a crash, the current time is written to
+// prefs as the session start time if no session start time is present in prefs
+// yet.
+TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeUnset) {
+ SetHasBrowserRestarted(true);
+
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during restart after a crash, the current time is written to
+// prefs as the session start time if an invalid value is currently present in
+// prefs.
+TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeInvalid) {
+ SetHasBrowserRestarted(true);
+
+ SetSessionStartTimePref(0);
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during restart after a crash, the current time is written to
+// prefs as the session start time if a value lying in the future is currently
+// present in prefs.
+TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeFuture) {
+ SetHasBrowserRestarted(true);
+
+ SetSessionStartTimePref(
+ (now_ + base::TimeDelta::FromHours(2)).ToInternalValue());
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Verifies that during restart after a crash, the current time is *not* written
+// to prefs as the session start time if a previously stored valid value is
+// currently present in prefs.
+TEST_F(SessionLengthLimiterTest, RestartWithSessionStartTimeValid) {
+ SetHasBrowserRestarted(true);
+
+ session_start_time_ -= base::TimeDelta::FromHours(2);
+ SetSessionStartTimePref(session_start_time_.ToInternalValue());
+ CreateSessionLengthLimiter();
+ VerifySessionStartTimePref();
+}
+
+// Creates a SessionLengthLimiter without setting a limit. Verifies that the
+// limiter does not start a timer and notifies an observer that there is no
+// limit.
+TEST_F(SessionLengthLimiterTest, RunWithoutSessionLengthLimit) {
+ SetHasBrowserRestarted(false);
+
+ base::ThreadTaskRunnerHandle runner_handler(runner_);
+
+ // Do not set any session time limit.
+ UpdateRemainingTime(0);
+
+ // Create a SessionLengthLimiter and check that no timer tick has been
+ // enqueued.
+ CreateSessionLengthLimiter();
+ EXPECT_TRUE(runner_->tasks().empty());
+
+ // Add an observer and check that a callback is immediately received.
+ ExpectSessionTimeRemainingChangedCallback();
+ session_length_limiter_->AddObserver(&observer_);
+
+ session_length_limiter_->RemoveObserver(&observer_);
+}
+
+// Creates a SessionLengthLimiter after setting a limit. Verifies that the
+// limiter starts a timer and notifies an observer about the remaining time as
+// session time passes. Verifies that when the session time reaches the limit,
+// a logout occurs.
+TEST_F(SessionLengthLimiterTest, RunWithSessionLengthLimit) {
+ SetHasBrowserRestarted(false);
+
+ base::ThreadTaskRunnerHandle runner_handler(runner_);
+
+ // Set a 60 second session time limit.
+ const int session_length_limit = 60 * 1000; // 60 seconds.
+ UpdateRemainingTime(session_length_limit);
+ SetSessionLengthLimitPref(session_length_limit);
+
+ // Create a SessionLengthLimiter and check that a first timer tick has been
+ // enqueued.
+ CreateSessionLengthLimiter();
+ VerifyTimerTickIsEnqueued();
+
+ // Add an observer and check that a first callback is immediately received.
+ ExpectSessionTimeRemainingChangedCallback();
+ session_length_limiter_->AddObserver(&observer_);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check timer ticks until the remaining session time reaches zero.
+ while (*remaining_ > kZeroTimeDelta)
+ VerifyTimerTick();
+
+ // Check that the next timer tick leads to a logout.
+ ExpectLogout();
+ VerifyTimerTick();
+
+ session_length_limiter_->RemoveObserver(&observer_);
+}
+
+// Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
+// seconds of session time to pass, then increases the limit to 90 seconds.
+// Verifies that the limiter starts a timer and notifies an observer about the
+// remaining time as session time passes and the limit changes. Verifies that
+// when the session time reaches the 90 second limit, a logout occurs.
+TEST_F(SessionLengthLimiterTest, RunAndIncreaseSessionLengthLimit) {
+ SetHasBrowserRestarted(false);
+
+ base::ThreadTaskRunnerHandle runner_handler(runner_);
+
+ // Set a 60 second session time limit.
+ int session_length_limit = 60 * 1000; // 60 seconds.
+ UpdateRemainingTime(session_length_limit);
+ SetSessionLengthLimitPref(session_length_limit);
+
+ // Create a SessionLengthLimiter and check that a first timer tick has been
+ // enqueued.
+ CreateSessionLengthLimiter();
+ VerifyTimerTickIsEnqueued();
+
+ // Add an observer and check that a first callback is immediately received.
+ ExpectSessionTimeRemainingChangedCallback();
+ session_length_limiter_->AddObserver(&observer_);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check timer ticks for 50 seconds of session time.
+ while (*remaining_ > kTenSeconds)
+ VerifyTimerTick();
+
+ // Check that increasing the session length limit to 90 seconds leads to an
+ // immediate callback.
+ session_length_limit = 90 * 1000; // 90 seconds.
+ UpdateRemainingTime(session_length_limit);
+ ExpectSessionTimeRemainingChangedCallback();
+ SetSessionLengthLimitPref(session_length_limit);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check that a timer tick is still enqueued.
+ VerifyTimerTickIsEnqueued();
+
+ // Check timer ticks until the remaining session time reaches zero.
+ while (*remaining_ > kZeroTimeDelta)
+ VerifyTimerTick();
+
+ // Check that the next timer tick leads to a logout.
+ ExpectLogout();
+ VerifyTimerTick();
+
+ session_length_limiter_->RemoveObserver(&observer_);
+}
+
+// Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
+// seconds of session time to pass, then decreases the limit to 40 seconds.
+// Verifies that the limiter starts a timer and notifies an observer about the
+// remaining time as session time passes and the limit changes. Verifies that
+// when the limit is decreased to 40 seconds after 50 seconds of session time
+// has passed, an immediate logout occurs.
+TEST_F(SessionLengthLimiterTest, RunAndDecreaseSessionLengthLimit) {
+ SetHasBrowserRestarted(false);
+
+ base::ThreadTaskRunnerHandle runner_handler(runner_);
+
+ // Set a 60 second session time limit.
+ int session_length_limit = 60 * 1000; // 60 seconds.
+ UpdateRemainingTime(session_length_limit);
+ SetSessionLengthLimitPref(session_length_limit);
+
+ // Create a SessionLengthLimiter and check that a first timer tick has been
+ // enqueued.
+ CreateSessionLengthLimiter();
+ VerifyTimerTickIsEnqueued();
+
+ // Add an observer and check that a first callback is immediately received.
+ ExpectSessionTimeRemainingChangedCallback();
+ session_length_limiter_->AddObserver(&observer_);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check timer ticks for 50 seconds of session time.
+ while (*remaining_ > kTenSeconds)
+ VerifyTimerTick();
+
+ // Check that reducing the session length limit below the 50 seconds that
+ // have already elapsed leads to an immediate logout.
+ session_length_limit = 40 * 1000; // 40 seconds.
+ UpdateRemainingTime(session_length_limit);
+ ExpectSessionTimeRemainingChangedCallback();
+ ExpectLogout();
+ SetSessionLengthLimitPref(session_length_limit);
+
+ session_length_limiter_->RemoveObserver(&observer_);
+}
+
+// Creates a SessionLengthLimiter after setting a 60 second limit, allows 50
+// seconds of session time to pass, then removes the limit. Verifies that the
+// limiter starts a timer and notifies an observer about the remaining time as
+// session time passes and the limit changes. Verifies that when the limit is
+// removed, no further notifications and no logout occur.
+TEST_F(SessionLengthLimiterTest, RunAndRemoveSessionLengthLimit) {
+ SetHasBrowserRestarted(false);
+
+ base::ThreadTaskRunnerHandle runner_handler(runner_);
+
+ // Set a 60 second session time limit.
+ int session_length_limit = 60 * 1000; // 60 seconds.
+ UpdateRemainingTime(session_length_limit);
+ SetSessionLengthLimitPref(session_length_limit);
+
+ // Create a SessionLengthLimiter and check that a first timer tick has been
+ // enqueued.
+ CreateSessionLengthLimiter();
+ VerifyTimerTickIsEnqueued();
+
+ // Add an observer and check that a first callback is immediately received.
+ ExpectSessionTimeRemainingChangedCallback();
+ session_length_limiter_->AddObserver(&observer_);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check timer ticks for 50 seconds of session time.
+ while (*remaining_ > kTenSeconds)
+ VerifyTimerTick();
+
+ // Check that removing the session length limit leads to an immediate
+ // callback.
+ UpdateRemainingTime(0);
+ ExpectSessionTimeRemainingChangedCallback();
+ prefs_.RemoveUserPref(prefs::kSessionLengthLimit);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ // Check that the next timer tick does not lead to a callback or logout.
+ EXPECT_CALL(observer_, SessionTimeRemainingChanged(_)).Times(0);
+ now_ += kSessionLengthLimitTimerInterval;
+ runner_->RunTasks();
+
+ session_length_limiter_->RemoveObserver(&observer_);
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698