Commit 3ccdaef7 authored by Sergey Poromov's avatar Sergey Poromov Committed by Commit Bot

Add DeviceOffHoursController unittests

Add FakeClock classes
Add unittests for:
* basic DeviceOffHoursController
* Convert*
* Apply*
* UpdateOffHoursMode
* SuspendDone observer method

Original CL written by Daria Yakovleva: https://crrev.com/c/675243

Bug: 739713

Author: Daria Yakovleva <yakovleva@google.com>
Change-Id: I35929e374d05713066027b86946f77c4c50f8473
Reviewed-on: https://chromium-review.googlesource.com/723744
Commit-Queue: Sergey Poromov <poromov@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#510202}
parent 2c09b844
...@@ -1862,6 +1862,8 @@ source_set("unit_tests") { ...@@ -1862,6 +1862,8 @@ source_set("unit_tests") {
"policy/network_configuration_updater_unittest.cc", "policy/network_configuration_updater_unittest.cc",
"policy/off_hours/device_off_hours_controller_unittest.cc", "policy/off_hours/device_off_hours_controller_unittest.cc",
"policy/off_hours/off_hours_interval_unittest.cc", "policy/off_hours/off_hours_interval_unittest.cc",
"policy/off_hours/off_hours_policy_applier_unittest.cc",
"policy/off_hours/off_hours_proto_parser_unittest.cc",
"policy/off_hours/weekly_time_unittest.cc", "policy/off_hours/weekly_time_unittest.cc",
"policy/pre_signin_policy_fetcher_unittest.cc", "policy/pre_signin_policy_fetcher_unittest.cc",
"policy/recommendation_restorer_unittest.cc", "policy/recommendation_restorer_unittest.cc",
......
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
#include "chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h" #include "chrome/browser/chromeos/policy/off_hours/device_off_hours_controller.h"
#include <string> #include <string>
#include <tuple>
#include <utility> #include <utility>
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/default_clock.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/chromeos/policy/off_hours/off_hours_proto_parser.h" #include "chrome/browser/chromeos/policy/off_hours/off_hours_proto_parser.h"
#include "chrome/browser/chromeos/policy/off_hours/time_utils.h" #include "chrome/browser/chromeos/policy/off_hours/time_utils.h"
...@@ -22,7 +25,9 @@ namespace em = enterprise_management; ...@@ -22,7 +25,9 @@ namespace em = enterprise_management;
namespace policy { namespace policy {
namespace off_hours { namespace off_hours {
DeviceOffHoursController::DeviceOffHoursController() { DeviceOffHoursController::DeviceOffHoursController()
: timer_(base::MakeUnique<base::OneShotTimer>()),
clock_(base::MakeUnique<base::DefaultClock>()) {
// IsInitialized() check is used for testing. Otherwise it has to be already // IsInitialized() check is used for testing. Otherwise it has to be already
// initialized. // initialized.
if (chromeos::DBusThreadManager::IsInitialized()) { if (chromeos::DBusThreadManager::IsInitialized()) {
...@@ -57,6 +62,13 @@ void DeviceOffHoursController::RemoveObserver(Observer* observer) { ...@@ -57,6 +62,13 @@ void DeviceOffHoursController::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void DeviceOffHoursController::SetClockForTesting(
std::unique_ptr<base::Clock> clock,
base::TickClock* timer_clock) {
clock_ = std::move(clock);
timer_ = base::MakeUnique<base::OneShotTimer>(timer_clock);
}
void DeviceOffHoursController::UpdateOffHoursPolicy( void DeviceOffHoursController::UpdateOffHoursPolicy(
const em::ChromeDeviceSettingsProto& device_settings_proto) { const em::ChromeDeviceSettingsProto& device_settings_proto) {
std::vector<OffHoursInterval> off_hours_intervals; std::vector<OffHoursInterval> off_hours_intervals;
...@@ -65,8 +77,9 @@ void DeviceOffHoursController::UpdateOffHoursPolicy( ...@@ -65,8 +77,9 @@ void DeviceOffHoursController::UpdateOffHoursPolicy(
device_settings_proto.device_off_hours()); device_settings_proto.device_off_hours());
base::Optional<std::string> timezone = ExtractTimezoneFromProto(container); base::Optional<std::string> timezone = ExtractTimezoneFromProto(container);
if (timezone) { if (timezone) {
off_hours_intervals = ConvertIntervalsToGmt( off_hours_intervals =
ExtractOffHoursIntervalsFromProto(container), *timezone); ConvertIntervalsToGmt(ExtractOffHoursIntervalsFromProto(container),
clock_.get(), *timezone);
} }
} }
off_hours_intervals_.swap(off_hours_intervals); off_hours_intervals_.swap(off_hours_intervals);
...@@ -101,7 +114,7 @@ void DeviceOffHoursController::UpdateOffHoursMode() { ...@@ -101,7 +114,7 @@ void DeviceOffHoursController::UpdateOffHoursMode() {
SetOffHoursMode(false); SetOffHoursMode(false);
return; return;
} }
WeeklyTime current_time = WeeklyTime::GetCurrentWeeklyTime(); WeeklyTime current_time = WeeklyTime::GetCurrentWeeklyTime(clock_.get());
for (const auto& interval : off_hours_intervals_) { for (const auto& interval : off_hours_intervals_) {
if (interval.Contains(current_time)) { if (interval.Contains(current_time)) {
base::TimeDelta remaining_off_hours_duration = base::TimeDelta remaining_off_hours_duration =
...@@ -138,13 +151,13 @@ void DeviceOffHoursController::SetOffHoursMode(bool off_hours_enabled) { ...@@ -138,13 +151,13 @@ void DeviceOffHoursController::SetOffHoursMode(bool off_hours_enabled) {
void DeviceOffHoursController::StartOffHoursTimer(base::TimeDelta delay) { void DeviceOffHoursController::StartOffHoursTimer(base::TimeDelta delay) {
DCHECK_GT(delay, base::TimeDelta()); DCHECK_GT(delay, base::TimeDelta());
DVLOG(1) << "OffHours mode timer starts for " << delay; DVLOG(1) << "OffHours mode timer starts for " << delay;
timer_.Start(FROM_HERE, delay, timer_->Start(FROM_HERE, delay,
base::Bind(&DeviceOffHoursController::UpdateOffHoursMode, base::Bind(&DeviceOffHoursController::UpdateOffHoursMode,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
void DeviceOffHoursController::StopOffHoursTimer() { void DeviceOffHoursController::StopOffHoursTimer() {
timer_.Stop(); timer_->Stop();
} }
void DeviceOffHoursController::SystemClockUpdated() { void DeviceOffHoursController::SystemClockUpdated() {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/time/clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "chrome/browser/chromeos/policy/off_hours/off_hours_interval.h" #include "chrome/browser/chromeos/policy/off_hours/off_hours_interval.h"
...@@ -75,6 +76,11 @@ class DeviceOffHoursController : public chromeos::SystemClockClient::Observer, ...@@ -75,6 +76,11 @@ class DeviceOffHoursController : public chromeos::SystemClockClient::Observer,
// chromeos::SystemClockClient::Observer: // chromeos::SystemClockClient::Observer:
void SystemClockUpdated() override; void SystemClockUpdated() override;
// |timer_clock| is not owned and its lifetime should cover lifetime of
// DeviceOffHoursContoller.
void SetClockForTesting(std::unique_ptr<base::Clock> clock,
base::TickClock* timer_clock);
private: private:
// Run OnOffHoursEndTimeChanged() for observers. // Run OnOffHoursEndTimeChanged() for observers.
void NotifyOffHoursEndTimeChanged() const; void NotifyOffHoursEndTimeChanged() const;
...@@ -119,7 +125,11 @@ class DeviceOffHoursController : public chromeos::SystemClockClient::Observer, ...@@ -119,7 +125,11 @@ class DeviceOffHoursController : public chromeos::SystemClockClient::Observer,
// Timer for updating device settings at the begin of next “OffHours” interval // Timer for updating device settings at the begin of next “OffHours” interval
// or at the end of current "OffHours" interval. // or at the end of current "OffHours" interval.
base::OneShotTimer timer_; std::unique_ptr<base::OneShotTimer> timer_;
// Used for testing purposes, otherwise it's an instance of
// base::DefaultClock.
std::unique_ptr<base::Clock> clock_;
// Value is false until the system time is synchronized with network time. // Value is false until the system time is synchronized with network time.
bool network_synchronized_ = false; bool network_synchronized_ = false;
......
...@@ -7,15 +7,24 @@ ...@@ -7,15 +7,24 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h" #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_power_manager_client.h"
#include "chromeos/dbus/fake_system_clock_client.h" #include "chromeos/dbus/fake_system_clock_client.h"
namespace em = enterprise_management; namespace em = enterprise_management;
namespace chromeos { namespace policy {
namespace off_hours {
using base::TimeDelta;
namespace { namespace {
...@@ -28,175 +37,358 @@ constexpr em::WeeklyTimeProto_DayOfWeek kWeekdays[] = { ...@@ -28,175 +37,358 @@ constexpr em::WeeklyTimeProto_DayOfWeek kWeekdays[] = {
em::WeeklyTimeProto::FRIDAY, em::WeeklyTimeProto::FRIDAY,
em::WeeklyTimeProto::SATURDAY, em::WeeklyTimeProto::SATURDAY,
em::WeeklyTimeProto::SUNDAY}; em::WeeklyTimeProto::SUNDAY};
constexpr base::TimeDelta kHour = base::TimeDelta::FromHours(1);
constexpr base::TimeDelta kDay = base::TimeDelta::FromDays(1); constexpr TimeDelta kHour = TimeDelta::FromHours(1);
constexpr TimeDelta kDay = TimeDelta::FromDays(1);
const char kUtcTimezone[] = "UTC";
const int kDeviceAllowNewUsersPolicyTag = 3;
const int kDeviceGuestModeEnabledPolicyTag = 8;
struct OffHoursPolicy {
std::string timezone;
std::vector<OffHoursInterval> intervals;
std::vector<int> ignored_policy_proto_tags;
OffHoursPolicy(const std::string& timezone,
const std::vector<OffHoursInterval>& intervals,
const std::vector<int>& ignored_policy_proto_tags)
: timezone(timezone),
intervals(intervals),
ignored_policy_proto_tags(ignored_policy_proto_tags) {}
OffHoursPolicy(const std::string& timezone,
const std::vector<OffHoursInterval>& intervals)
: timezone(timezone),
intervals(intervals),
ignored_policy_proto_tags({kDeviceAllowNewUsersPolicyTag,
kDeviceGuestModeEnabledPolicyTag}) {}
};
em::DeviceOffHoursIntervalProto ConvertOffHoursIntervalToProto(
const OffHoursInterval& off_hours_interval) {
em::DeviceOffHoursIntervalProto interval_proto;
em::WeeklyTimeProto* start = interval_proto.mutable_start();
em::WeeklyTimeProto* end = interval_proto.mutable_end();
start->set_day_of_week(kWeekdays[off_hours_interval.start().day_of_week()]);
start->set_time(off_hours_interval.start().milliseconds());
end->set_day_of_week(kWeekdays[off_hours_interval.end().day_of_week()]);
end->set_time(off_hours_interval.end().milliseconds());
return interval_proto;
}
void RemoveOffHoursPolicyFromProto(em::ChromeDeviceSettingsProto* proto) {
proto->clear_device_off_hours();
}
void SetOffHoursPolicyToProto(em::ChromeDeviceSettingsProto* proto,
const OffHoursPolicy& off_hours_policy) {
RemoveOffHoursPolicyFromProto(proto);
auto* off_hours = proto->mutable_device_off_hours();
for (auto interval : off_hours_policy.intervals) {
auto interval_proto = ConvertOffHoursIntervalToProto(interval);
auto* cur = off_hours->add_intervals();
*cur = interval_proto;
}
off_hours->set_timezone(off_hours_policy.timezone);
for (auto p : off_hours_policy.ignored_policy_proto_tags) {
off_hours->add_ignored_policy_proto_tags(p);
}
}
} // namespace } // namespace
class DeviceOffHoursControllerTest : public DeviceSettingsTestBase { class DeviceOffHoursControllerSimpleTest
: public chromeos::DeviceSettingsTestBase {
protected: protected:
DeviceOffHoursControllerTest() {} DeviceOffHoursControllerSimpleTest() {}
void SetUp() override { void SetUp() override {
DeviceSettingsTestBase::SetUp(); chromeos::DeviceSettingsTestBase::SetUp();
system_clock_client_ = new chromeos::FakeSystemClockClient(); system_clock_client_ = new chromeos::FakeSystemClockClient();
dbus_setter_->SetSystemClockClient(base::WrapUnique(system_clock_client_)); dbus_setter_->SetSystemClockClient(base::WrapUnique(system_clock_client_));
power_manager_client_ = new chromeos::FakePowerManagerClient();
dbus_setter_->SetPowerManagerClient(
base::WrapUnique(power_manager_client_));
device_settings_service_.SetDeviceOffHoursControllerForTesting( device_settings_service_.SetDeviceOffHoursControllerForTesting(
base::MakeUnique<policy::off_hours::DeviceOffHoursController>()); base::MakeUnique<policy::off_hours::DeviceOffHoursController>());
device_off_hours_controller_ =
device_settings_service_.device_off_hours_controller();
} }
void SetDeviceSettings() { void UpdateDeviceSettings() {
device_policy_.Build(); device_policy_.Build();
session_manager_client_.set_device_policy(device_policy_.GetBlob()); session_manager_client_.set_device_policy(device_policy_.GetBlob());
ReloadDeviceSettings(); ReloadDeviceSettings();
} }
void SetOffHoursProto( // Return number of weekday from 1 to 7 in |input_time|. (1 = Monday etc.)
const std::vector<em::DeviceOffHoursIntervalProto>& intervals, int ExtractDayOfWeek(base::Time input_time) {
const std::string& timezone, base::Time::Exploded exploded;
const std::vector<int>& ignored_policy_proto_tags) { input_time.UTCExplode(&exploded);
em::ChromeDeviceSettingsProto& proto(device_policy_.payload()); int current_day_of_week = exploded.day_of_week;
auto* off_hours = proto.mutable_device_off_hours(); if (current_day_of_week == 0)
for (auto interval : intervals) { current_day_of_week = 7;
auto* cur = off_hours->add_intervals(); return current_day_of_week;
*cur = interval;
}
off_hours->set_timezone(timezone);
for (auto p : ignored_policy_proto_tags) {
off_hours->add_ignored_policy_proto_tags(p);
}
SetDeviceSettings();
} }
void UnsetOffHoursProto() { // Return next day of week. |day_of_week| and return value are from 1 to 7. (1
em::ChromeDeviceSettingsProto& proto(device_policy_.payload()); // = Monday etc.)
proto.clear_device_off_hours(); int NextDayOfWeek(int day_of_week) { return day_of_week % 7 + 1; }
SetDeviceSettings();
}
em::DeviceOffHoursIntervalProto CreateInterval(int start_day_of_week, chromeos::FakeSystemClockClient* system_clock_client() {
base::TimeDelta start_time, return system_clock_client_;
int end_day_of_week,
base::TimeDelta end_time) {
em::DeviceOffHoursIntervalProto interval =
em::DeviceOffHoursIntervalProto();
em::WeeklyTimeProto* start = interval.mutable_start();
em::WeeklyTimeProto* end = interval.mutable_end();
start->set_day_of_week(kWeekdays[start_day_of_week]);
start->set_time(start_time.InMilliseconds());
end->set_day_of_week(kWeekdays[end_day_of_week]);
end->set_time(end_time.InMilliseconds());
return interval;
} }
// Create and set "OffHours" interval which starts in |delay| time and with chromeos::FakePowerManagerClient* power_manager() {
// |duration|. Zero delay means that "OffHours" mode start right now. return power_manager_client_;
void CreateAndSetOffHours(base::TimeDelta delay, base::TimeDelta duration) {
base::Time::Exploded exploded;
base::Time::Now().UTCExplode(&exploded);
int cur_day_of_week = exploded.day_of_week;
if (cur_day_of_week == 0)
cur_day_of_week = 7;
base::TimeDelta the_time = base::TimeDelta::FromDays(cur_day_of_week - 1) +
base::TimeDelta::FromHours(exploded.hour) +
base::TimeDelta::FromMinutes(exploded.minute) +
base::TimeDelta::FromSeconds(exploded.second);
the_time += delay;
base::TimeDelta start_time = the_time % kDay;
int start_day_of_week = the_time.InDays() % 7 + 1;
the_time += duration;
base::TimeDelta end_time = the_time % kDay;
int end_day_of_week = the_time.InDays() % 7 + 1;
std::vector<em::DeviceOffHoursIntervalProto> intervals;
intervals.push_back(CreateInterval(start_day_of_week, start_time,
end_day_of_week, end_time));
std::vector<int> ignored_policy_proto_tags = {
3 /*DeviceGuestModeEnabled policy*/};
SetOffHoursProto(intervals, "GMT", ignored_policy_proto_tags);
} }
chromeos::FakeSystemClockClient* system_clock_client() { policy::off_hours::DeviceOffHoursController* device_off_hours_controller() {
return system_clock_client_; return device_off_hours_controller_;
} }
private: private:
std::unique_ptr<policy::off_hours::DeviceOffHoursController>
device_off_hours_controller_;
// The object is owned by DeviceSettingsTestBase class. // The object is owned by DeviceSettingsTestBase class.
chromeos::FakeSystemClockClient* system_clock_client_; chromeos::FakeSystemClockClient* system_clock_client_;
DISALLOW_COPY_AND_ASSIGN(DeviceOffHoursControllerTest); // The object is owned by DeviceSettingsTestBase class.
chromeos::FakePowerManagerClient* power_manager_client_;
// The object is owned by DeviceSettingsService class.
policy::off_hours::DeviceOffHoursController* device_off_hours_controller_;
DISALLOW_COPY_AND_ASSIGN(DeviceOffHoursControllerSimpleTest);
}; };
TEST_F(DeviceOffHoursControllerTest, CheckOffHoursUnset) { TEST_F(DeviceOffHoursControllerSimpleTest, CheckOffHoursUnset) {
system_clock_client()->set_network_synchronized(true); system_clock_client()->set_network_synchronized(true);
system_clock_client()->NotifyObserversSystemClockUpdated(); system_clock_client()->NotifyObserversSystemClockUpdated();
enterprise_management::ChromeDeviceSettingsProto& proto( em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
device_policy_.payload());
proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false); proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false);
SetDeviceSettings(); UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
UnsetOffHoursProto(); RemoveOffHoursPolicyFromProto(&proto);
UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
} }
TEST_F(DeviceOffHoursControllerTest, CheckOffHoursModeOff) { TEST_F(DeviceOffHoursControllerSimpleTest, CheckOffHoursModeOff) {
system_clock_client()->set_network_synchronized(true); system_clock_client()->set_network_synchronized(true);
system_clock_client()->NotifyObserversSystemClockUpdated(); system_clock_client()->NotifyObserversSystemClockUpdated();
em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
enterprise_management::ChromeDeviceSettingsProto& proto(
device_policy_.payload());
proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false); proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false);
SetDeviceSettings(); UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
CreateAndSetOffHours(kHour, kHour); int current_day_of_week = ExtractDayOfWeek(base::Time::Now());
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(NextDayOfWeek(current_day_of_week),
TimeDelta::FromHours(10).InMilliseconds()),
WeeklyTime(NextDayOfWeek(current_day_of_week),
TimeDelta::FromHours(15).InMilliseconds()))}));
UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
} }
TEST_F(DeviceOffHoursControllerTest, CheckOffHoursModeOn) { TEST_F(DeviceOffHoursControllerSimpleTest, CheckOffHoursModeOn) {
system_clock_client()->set_network_synchronized(true); system_clock_client()->set_network_synchronized(true);
system_clock_client()->NotifyObserversSystemClockUpdated(); system_clock_client()->NotifyObserversSystemClockUpdated();
enterprise_management::ChromeDeviceSettingsProto& proto( em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
device_policy_.payload());
proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false); proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false);
SetDeviceSettings(); UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
CreateAndSetOffHours(base::TimeDelta(), kHour); int current_day_of_week = ExtractDayOfWeek(base::Time::Now());
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(current_day_of_week, 0),
WeeklyTime(NextDayOfWeek(current_day_of_week),
TimeDelta::FromHours(10).InMilliseconds()))}));
UpdateDeviceSettings();
EXPECT_TRUE(device_settings_service_.device_settings() EXPECT_TRUE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
} }
TEST_F(DeviceOffHoursControllerTest, NoNetworkSynchronization) { TEST_F(DeviceOffHoursControllerSimpleTest, NoNetworkSynchronization) {
system_clock_client()->set_network_synchronized(false); system_clock_client()->set_network_synchronized(false);
system_clock_client()->NotifyObserversSystemClockUpdated(); system_clock_client()->NotifyObserversSystemClockUpdated();
enterprise_management::ChromeDeviceSettingsProto& proto( em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
device_policy_.payload());
proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false); proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false);
SetDeviceSettings(); UpdateDeviceSettings();
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
CreateAndSetOffHours(base::TimeDelta(), kHour); int current_day_of_week = ExtractDayOfWeek(base::Time::Now());
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(current_day_of_week, 0),
WeeklyTime(NextDayOfWeek(current_day_of_week),
TimeDelta::FromHours(10).InMilliseconds()))}));
EXPECT_FALSE(device_settings_service_.device_settings() EXPECT_FALSE(device_settings_service_.device_settings()
->guest_mode_enabled() ->guest_mode_enabled()
.guest_mode_enabled()); .guest_mode_enabled());
} }
// TODO(yakovleva): Add tests for PowerManagerClient observer, SuspendDone class DeviceOffHoursControllerFakeClockTest
// calls. : public DeviceOffHoursControllerSimpleTest {
protected:
DeviceOffHoursControllerFakeClockTest() {}
void SetUp() override {
DeviceOffHoursControllerSimpleTest::SetUp();
system_clock_client()->set_network_synchronized(true);
system_clock_client()->NotifyObserversSystemClockUpdated();
std::unique_ptr<base::SimpleTestClock> test_clock =
base::MakeUnique<base::SimpleTestClock>();
test_clock_ = test_clock.get();
// Clocks are set to 1970-01-01 00:00:00 UTC, Thursday.
test_clock_->SetNow(base::Time::UnixEpoch());
test_tick_clock_.SetNowTicks(base::TimeTicks::UnixEpoch());
device_off_hours_controller()->SetClockForTesting(std::move(test_clock),
&test_tick_clock_);
}
void AdvanceTestClock(TimeDelta duration) {
test_clock_->Advance(duration);
test_tick_clock_.Advance(duration);
}
base::Clock* clock() { return test_clock_; }
private:
// The object is owned by DeviceOffHoursController class.
base::SimpleTestClock* test_clock_;
base::SimpleTestTickClock test_tick_clock_;
DISALLOW_COPY_AND_ASSIGN(DeviceOffHoursControllerFakeClockTest);
};
TEST_F(DeviceOffHoursControllerFakeClockTest, FakeClock) {
EXPECT_FALSE(device_off_hours_controller()->is_off_hours_mode());
int current_day_of_week = ExtractDayOfWeek(clock()->Now());
em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(current_day_of_week,
TimeDelta::FromHours(14).InMilliseconds()),
WeeklyTime(current_day_of_week,
TimeDelta::FromHours(15).InMilliseconds()))}));
AdvanceTestClock(TimeDelta::FromHours(14));
UpdateDeviceSettings();
EXPECT_TRUE(device_off_hours_controller()->is_off_hours_mode());
AdvanceTestClock(TimeDelta::FromHours(1));
UpdateDeviceSettings();
EXPECT_FALSE(device_off_hours_controller()->is_off_hours_mode());
}
TEST_F(DeviceOffHoursControllerFakeClockTest, CheckSendSuspendDone) {
int current_day_of_week = ExtractDayOfWeek(clock()->Now());
LOG(ERROR) << "day " << current_day_of_week;
em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
SetOffHoursPolicyToProto(
&proto,
OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(WeeklyTime(NextDayOfWeek(current_day_of_week), 0),
WeeklyTime(NextDayOfWeek(current_day_of_week),
kHour.InMilliseconds()))}));
UpdateDeviceSettings();
EXPECT_FALSE(device_off_hours_controller()->is_off_hours_mode());
AdvanceTestClock(kDay);
power_manager()->SendSuspendDone();
EXPECT_TRUE(device_off_hours_controller()->is_off_hours_mode());
AdvanceTestClock(kHour);
power_manager()->SendSuspendDone();
EXPECT_FALSE(device_off_hours_controller()->is_off_hours_mode());
}
class DeviceOffHoursControllerUpdateTest
: public DeviceOffHoursControllerFakeClockTest,
public testing::WithParamInterface<
std::tuple<OffHoursPolicy, TimeDelta, bool>> {
public:
OffHoursPolicy off_hours_policy() const { return std::get<0>(GetParam()); }
TimeDelta advance_clock() const { return std::get<1>(GetParam()); }
bool is_off_hours_expected() const { return std::get<2>(GetParam()); }
};
TEST_P(DeviceOffHoursControllerUpdateTest, CheckUpdateOffHoursPolicy) {
em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
SetOffHoursPolicyToProto(&proto, off_hours_policy());
AdvanceTestClock(advance_clock());
UpdateDeviceSettings();
EXPECT_EQ(device_off_hours_controller()->is_off_hours_mode(),
is_off_hours_expected());
}
INSTANTIATE_TEST_CASE_P(
TestCases,
DeviceOffHoursControllerUpdateTest,
testing::Values(
std::make_tuple(
OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(1).InMilliseconds()),
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(2).InMilliseconds()))}),
kHour,
true),
std::make_tuple(
OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(1).InMilliseconds()),
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(2).InMilliseconds()))}),
kHour * 2,
false),
std::make_tuple(
OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(1).InMilliseconds()),
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(2).InMilliseconds()))}),
kHour * 1.5,
true),
std::make_tuple(
OffHoursPolicy(
kUtcTimezone,
{OffHoursInterval(
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(1).InMilliseconds()),
WeeklyTime(em::WeeklyTimeProto::THURSDAY,
TimeDelta::FromHours(2).InMilliseconds()))}),
kHour * 3,
false)));
} // namespace chromeos } // namespace off_hours
} // namespace policy
...@@ -11,10 +11,8 @@ ...@@ -11,10 +11,8 @@
#include "base/values.h" #include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace chromeos { namespace policy {
namespace off_hours {
using policy::off_hours::WeeklyTime;
using policy::off_hours::OffHoursInterval;
namespace { namespace {
...@@ -182,4 +180,5 @@ INSTANTIATE_TEST_CASE_P(RandomInterval, ...@@ -182,4 +180,5 @@ INSTANTIATE_TEST_CASE_P(RandomInterval,
14 * kMinutesInHour, 14 * kMinutesInHour,
false))); false)));
} // namespace chromeos } // namespace off_hours
} // namespace policy
// Copyright 2017 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/policy/off_hours/off_hours_policy_applier.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/chromeos/policy/off_hours/off_hours_interval.h"
#include "chrome/browser/chromeos/policy/off_hours/weekly_time.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
namespace policy {
namespace off_hours {
namespace {
constexpr em::WeeklyTimeProto_DayOfWeek kWeekdays[] = {
em::WeeklyTimeProto::DAY_OF_WEEK_UNSPECIFIED,
em::WeeklyTimeProto::MONDAY,
em::WeeklyTimeProto::TUESDAY,
em::WeeklyTimeProto::WEDNESDAY,
em::WeeklyTimeProto::THURSDAY,
em::WeeklyTimeProto::FRIDAY,
em::WeeklyTimeProto::SATURDAY,
em::WeeklyTimeProto::SUNDAY};
const char kUtcTimezone[] = "UTC";
const int kDeviceAllowNewUsersTag = 3;
const int kDeviceGuestModeEnabledTag = 8;
const std::vector<int> kDefaultIgnoredPolicies = {kDeviceAllowNewUsersTag,
kDeviceGuestModeEnabledTag};
struct OffHoursPolicy {
std::string timezone;
std::vector<OffHoursInterval> intervals;
std::vector<int> ignored_policy_proto_tags;
OffHoursPolicy(const std::string& timezone,
const std::vector<OffHoursInterval>& intervals,
const std::vector<int>& ignored_policy_proto_tags)
: timezone(timezone),
intervals(intervals),
ignored_policy_proto_tags(ignored_policy_proto_tags) {}
};
em::DeviceOffHoursIntervalProto ConvertOffHoursIntervalToProto(
const OffHoursInterval& off_hours_interval) {
em::DeviceOffHoursIntervalProto interval_proto;
em::WeeklyTimeProto* start = interval_proto.mutable_start();
em::WeeklyTimeProto* end = interval_proto.mutable_end();
start->set_day_of_week(kWeekdays[off_hours_interval.start().day_of_week()]);
start->set_time(off_hours_interval.start().milliseconds());
end->set_day_of_week(kWeekdays[off_hours_interval.end().day_of_week()]);
end->set_time(off_hours_interval.end().milliseconds());
return interval_proto;
}
void RemoveOffHoursPolicyFromProto(em::ChromeDeviceSettingsProto* proto) {
proto->clear_device_off_hours();
}
void SetOffHoursPolicyToProto(em::ChromeDeviceSettingsProto* proto,
const OffHoursPolicy& off_hours_policy) {
RemoveOffHoursPolicyFromProto(proto);
auto* off_hours = proto->mutable_device_off_hours();
for (auto interval : off_hours_policy.intervals) {
auto interval_proto = ConvertOffHoursIntervalToProto(interval);
auto* cur = off_hours->add_intervals();
*cur = interval_proto;
}
off_hours->set_timezone(off_hours_policy.timezone);
for (auto p : off_hours_policy.ignored_policy_proto_tags) {
off_hours->add_ignored_policy_proto_tags(p);
}
}
} // namespace
class ApplyOffHoursPolicyToProtoTest : public testing::Test {
protected:
ApplyOffHoursPolicyToProtoTest() = default;
private:
DISALLOW_COPY_AND_ASSIGN(ApplyOffHoursPolicyToProtoTest);
};
TEST_F(ApplyOffHoursPolicyToProtoTest, Test) {
em::ChromeDeviceSettingsProto proto;
proto.mutable_guest_mode_enabled()->set_guest_mode_enabled(false);
proto.mutable_allow_new_users()->set_allow_new_users(false);
proto.mutable_camera_enabled()->set_camera_enabled(false);
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(kUtcTimezone, {}, kDefaultIgnoredPolicies));
std::unique_ptr<em::ChromeDeviceSettingsProto> off_hours_proto =
policy::off_hours::ApplyOffHoursPolicyToProto(proto);
EXPECT_TRUE(off_hours_proto->guest_mode_enabled().guest_mode_enabled());
EXPECT_TRUE(off_hours_proto->allow_new_users().allow_new_users());
EXPECT_FALSE(off_hours_proto->camera_enabled().camera_enabled());
}
} // namespace off_hours
} // namespace policy
// Copyright 2017 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/policy/off_hours/off_hours_proto_parser.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/policy/off_hours/off_hours_interval.h"
#include "chrome/browser/chromeos/policy/off_hours/weekly_time.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace em = enterprise_management;
namespace policy {
namespace off_hours {
namespace {
constexpr em::WeeklyTimeProto_DayOfWeek kWeekdays[] = {
em::WeeklyTimeProto::DAY_OF_WEEK_UNSPECIFIED,
em::WeeklyTimeProto::MONDAY,
em::WeeklyTimeProto::TUESDAY,
em::WeeklyTimeProto::WEDNESDAY,
em::WeeklyTimeProto::THURSDAY,
em::WeeklyTimeProto::FRIDAY,
em::WeeklyTimeProto::SATURDAY,
em::WeeklyTimeProto::SUNDAY};
constexpr base::TimeDelta kHour = base::TimeDelta::FromHours(1);
const char kUtcTimezone[] = "UTC";
const int kDeviceAllowNewUsersTag = 3;
const int kDeviceGuestModeEnabledTag = 8;
const std::vector<int> kDefaultIgnoredPolicies = {kDeviceAllowNewUsersTag,
kDeviceGuestModeEnabledTag};
struct OffHoursPolicy {
std::string timezone;
std::vector<OffHoursInterval> intervals;
std::vector<int> ignored_policy_proto_tags;
OffHoursPolicy(const std::string& timezone,
const std::vector<OffHoursInterval>& intervals,
const std::vector<int>& ignored_policy_proto_tags)
: timezone(timezone),
intervals(intervals),
ignored_policy_proto_tags(ignored_policy_proto_tags) {}
};
em::DeviceOffHoursIntervalProto ConvertOffHoursIntervalToProto(
const OffHoursInterval& off_hours_interval) {
em::DeviceOffHoursIntervalProto interval_proto;
em::WeeklyTimeProto* start = interval_proto.mutable_start();
em::WeeklyTimeProto* end = interval_proto.mutable_end();
start->set_day_of_week(kWeekdays[off_hours_interval.start().day_of_week()]);
start->set_time(off_hours_interval.start().milliseconds());
end->set_day_of_week(kWeekdays[off_hours_interval.end().day_of_week()]);
end->set_time(off_hours_interval.end().milliseconds());
return interval_proto;
}
void RemoveOffHoursPolicyFromProto(em::ChromeDeviceSettingsProto* proto) {
proto->clear_device_off_hours();
}
void SetOffHoursPolicyToProto(em::ChromeDeviceSettingsProto* proto,
const OffHoursPolicy& off_hours_policy) {
RemoveOffHoursPolicyFromProto(proto);
auto* off_hours = proto->mutable_device_off_hours();
for (auto interval : off_hours_policy.intervals) {
auto interval_proto = ConvertOffHoursIntervalToProto(interval);
auto* cur = off_hours->add_intervals();
*cur = interval_proto;
}
off_hours->set_timezone(off_hours_policy.timezone);
for (auto p : off_hours_policy.ignored_policy_proto_tags) {
off_hours->add_ignored_policy_proto_tags(p);
}
}
} // namespace
class ConvertOffHoursProtoToValueTest : public testing::Test {
protected:
ConvertOffHoursProtoToValueTest() {}
private:
DISALLOW_COPY_AND_ASSIGN(ConvertOffHoursProtoToValueTest);
};
TEST_F(ConvertOffHoursProtoToValueTest, Test) {
WeeklyTime start = WeeklyTime(1, kHour.InMilliseconds());
WeeklyTime end = WeeklyTime(3, kHour.InMilliseconds() * 2);
std::vector<OffHoursInterval> intervals = {OffHoursInterval(start, end)};
em::ChromeDeviceSettingsProto proto;
SetOffHoursPolicyToProto(
&proto, OffHoursPolicy(kUtcTimezone, intervals, kDefaultIgnoredPolicies));
std::unique_ptr<base::DictionaryValue> off_hours_value =
policy::off_hours::ConvertOffHoursProtoToValue(proto.device_off_hours());
base::DictionaryValue off_hours_expected;
off_hours_expected.SetString("timezone", kUtcTimezone);
auto intervals_value = base::MakeUnique<base::ListValue>();
for (const auto& interval : intervals)
intervals_value->Append(interval.ToValue());
off_hours_expected.SetList("intervals", std::move(intervals_value));
auto ignored_policies_value = base::MakeUnique<base::ListValue>();
for (const auto& policy : kDefaultIgnoredPolicies)
ignored_policies_value->GetList().emplace_back(policy);
off_hours_expected.SetList("ignored_policy_proto_tags",
std::move(ignored_policies_value));
EXPECT_EQ(*off_hours_value, off_hours_expected);
}
} // namespace off_hours
} // namespace policy
...@@ -20,7 +20,9 @@ namespace { ...@@ -20,7 +20,9 @@ namespace {
constexpr base::TimeDelta kWeek = base::TimeDelta::FromDays(7); constexpr base::TimeDelta kWeek = base::TimeDelta::FromDays(7);
} // namespace } // namespace
bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) { bool GetOffsetFromTimezoneToGmt(const std::string& timezone,
base::Clock* clock,
int* offset) {
auto zone = base::WrapUnique( auto zone = base::WrapUnique(
icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(timezone))); icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(timezone)));
if (*zone == icu::TimeZone::getUnknown()) { if (*zone == icu::TimeZone::getUnknown()) {
...@@ -39,6 +41,14 @@ bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) { ...@@ -39,6 +41,14 @@ bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) {
LOG(ERROR) << "Gregorian calendar error = " << u_errorName(status); LOG(ERROR) << "Gregorian calendar error = " << u_errorName(status);
return false; return false;
} }
UDate cur_date = static_cast<UDate>(clock->Now().ToDoubleT() *
base::Time::kMillisecondsPerSecond);
status = U_ZERO_ERROR;
gregorian_calendar->setTime(cur_date, status);
if (U_FAILURE(status)) {
LOG(ERROR) << "Gregorian calendar set time error = " << u_errorName(status);
return false;
}
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
UBool day_light = gregorian_calendar->inDaylightTime(status); UBool day_light = gregorian_calendar->inDaylightTime(status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
...@@ -52,11 +62,13 @@ bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) { ...@@ -52,11 +62,13 @@ bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset) {
return true; return true;
} }
std::vector<OffHoursInterval> ConvertIntervalsToGmt( std::vector<off_hours::OffHoursInterval> ConvertIntervalsToGmt(
const std::vector<OffHoursInterval>& intervals, const std::vector<off_hours::OffHoursInterval>& intervals,
base::Clock* clock,
const std::string& timezone) { const std::string& timezone) {
int gmt_offset = 0; int gmt_offset = 0;
bool no_offset_error = GetOffsetFromTimezoneToGmt(timezone, &gmt_offset); bool no_offset_error =
GetOffsetFromTimezoneToGmt(timezone, clock, &gmt_offset);
if (!no_offset_error) if (!no_offset_error)
return {}; return {};
std::vector<OffHoursInterval> gmt_intervals; std::vector<OffHoursInterval> gmt_intervals;
......
...@@ -15,13 +15,16 @@ namespace policy { ...@@ -15,13 +15,16 @@ namespace policy {
namespace off_hours { namespace off_hours {
// Put time in milliseconds which is added to local time to get GMT time to // Put time in milliseconds which is added to local time to get GMT time to
// |offset| considering current daylight time. Return true if there was no // |offset| considering daylight from |clock|. Return true if there was no
// error. // error.
bool GetOffsetFromTimezoneToGmt(const std::string& timezone, int* offset); bool GetOffsetFromTimezoneToGmt(const std::string& timezone,
base::Clock* clock,
int* offset);
// Convert time intervals from |timezone| to GMT timezone. // Convert time intervals from |timezone| to GMT timezone.
std::vector<OffHoursInterval> ConvertIntervalsToGmt( std::vector<OffHoursInterval> ConvertIntervalsToGmt(
const std::vector<OffHoursInterval>& intervals, const std::vector<OffHoursInterval>& intervals,
base::Clock* clock,
const std::string& timezone); const std::string& timezone);
// Return duration till next "OffHours" time interval. // Return duration till next "OffHours" time interval.
......
...@@ -57,9 +57,9 @@ WeeklyTime WeeklyTime::AddMilliseconds(int milliseconds) const { ...@@ -57,9 +57,9 @@ WeeklyTime WeeklyTime::AddMilliseconds(int milliseconds) const {
} }
// static // static
WeeklyTime WeeklyTime::GetCurrentWeeklyTime() { WeeklyTime WeeklyTime::GetCurrentWeeklyTime(base::Clock* clock) {
base::Time::Exploded exploded; base::Time::Exploded exploded;
base::Time::Now().UTCExplode(&exploded); clock->Now().UTCExplode(&exploded);
int day_of_week = exploded.day_of_week; int day_of_week = exploded.day_of_week;
// Exploded contains 0-based day of week (0 = Sunday, etc.) // Exploded contains 0-based day of week (0 = Sunday, etc.)
if (day_of_week == 0) if (day_of_week == 0)
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/time/clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
...@@ -40,7 +41,7 @@ class WeeklyTime { ...@@ -40,7 +41,7 @@ class WeeklyTime {
WeeklyTime AddMilliseconds(int milliseconds) const; WeeklyTime AddMilliseconds(int milliseconds) const;
// Return current time in WeeklyTime structure. // Return current time in WeeklyTime structure.
static WeeklyTime GetCurrentWeeklyTime(); static WeeklyTime GetCurrentWeeklyTime(base::Clock* clock);
private: private:
// Number of weekday (1 = Monday, 2 = Tuesday, etc.) // Number of weekday (1 = Monday, 2 = Tuesday, etc.)
......
...@@ -11,9 +11,8 @@ ...@@ -11,9 +11,8 @@
#include "base/values.h" #include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace chromeos { namespace policy {
namespace off_hours {
using policy::off_hours::WeeklyTime;
namespace { namespace {
...@@ -199,4 +198,5 @@ INSTANTIATE_TEST_CASE_P( ...@@ -199,4 +198,5 @@ INSTANTIATE_TEST_CASE_P(
kThursday, kThursday,
15 * kMinutesInHour + 24))); 15 * kMinutesInHour + 24)));
} // namespace chromeos } // namespace off_hours
} // namespace policy
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment