1 // Copyright 2018 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 #include "chrome/browser/chromeos/policy/device_auto_update_time_restrictions_utils.h"
5 
6 #include <memory>
7 #include <string>
8 #include <tuple>
9 #include <utility>
10 
11 #include "base/strings/string16.h"
12 #include "base/test/simple_test_clock.h"
13 #include "base/time/time.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
16 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
17 #include "chromeos/policy/weekly_time/weekly_time.h"
18 #include "chromeos/policy/weekly_time/weekly_time_interval.h"
19 #include "chromeos/settings/cros_settings_names.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/icu/source/i18n/unicode/timezone.h"
22 
23 using base::ListValue;
24 using base::Time;
25 using base::Value;
26 using std::tuple;
27 using std::vector;
28 
29 namespace policy {
30 
31 namespace {
32 
33 enum {
34   kMonday = 1,
35   kTuesday = 2,
36   kWednesday = 3,
37   kThursday = 4,
38   kFriday = 5,
39   kSaturday = 6,
40   kSunday = 7,
41 };
42 
DayToString(int day_of_week)43 std::string DayToString(int day_of_week) {
44   switch (day_of_week) {
45     case kMonday:
46       return "Monday";
47     case kTuesday:
48       return "Tuesday";
49     case kWednesday:
50       return "Wednesday";
51     case kThursday:
52       return "Thursday";
53     case kFriday:
54       return "Friday";
55     case kSaturday:
56       return "Saturday";
57     case kSunday:
58       return "Sunday";
59   }
60   return "";
61 }
62 
63 const char* kNewYorkTimezone = "America/New_York";
64 constexpr int kMillisecondsInMinute = 60000;
65 constexpr int kMillisecondsInHour = 3600000;
66 constexpr int kNewYorkOffset = -4 * kMillisecondsInHour;
67 constexpr Time::Exploded kDaylightTime{2018, 8, 3, 8, 15, 0, 0, 0};
68 
69 }  // namespace
70 
71 class DeviceAutoUpdateTimeRestrictionsUtilTest : public testing::Test {
72  protected:
SetUp()73   void SetUp() override {
74     timezone_.reset(icu::TimeZone::createDefault());
75     icu::TimeZone::adoptDefault(
76         icu::TimeZone::createTimeZone(kNewYorkTimezone));
77     // Use Daylight savings to use EDT.
78     Time test_time;
79     ASSERT_TRUE(base::Time::FromUTCExploded(kDaylightTime, &test_time));
80     test_clock_.SetNow(test_time);
81   }
82 
TearDown()83   void TearDown() override { icu::TimeZone::adoptDefault(timezone_.release()); }
84 
GetIntervalsAsList(const vector<WeeklyTimeInterval> & intervals)85   ListValue GetIntervalsAsList(const vector<WeeklyTimeInterval>& intervals) {
86     ListValue list_val;
87     for (const auto& interval : intervals) {
88       base::DictionaryValue start;
89       int start_hours = interval.start().milliseconds() / kMillisecondsInHour;
90       int start_minutes = (interval.start().milliseconds() -
91                            start_hours * kMillisecondsInHour) /
92                           kMillisecondsInMinute;
93       start.SetKey("day_of_week",
94                    Value(DayToString(interval.start().day_of_week())));
95       start.SetKey("hours", Value(start_hours));
96       start.SetKey("minutes", Value(start_minutes));
97 
98       base::DictionaryValue end;
99       int end_hours = interval.end().milliseconds() / kMillisecondsInHour;
100       int end_minutes =
101           (interval.end().milliseconds() - end_hours * kMillisecondsInHour) /
102           kMillisecondsInMinute;
103       end.SetKey("day_of_week",
104                  Value(DayToString(interval.end().day_of_week())));
105       end.SetKey("hours", Value(end_hours));
106       end.SetKey("minutes", Value(end_minutes));
107 
108       base::DictionaryValue time_dict;
109       time_dict.SetKey("start", std::move(start));
110       time_dict.SetKey("end", std::move(end));
111       list_val.Append(std::move(time_dict));
112     }
113     return list_val;
114   }
115 
116   base::SimpleTestClock test_clock_;
117   // These initialize CrosSettings and then tear down when the test is done.
118   chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
119 
120  private:
121   std::unique_ptr<icu::TimeZone> timezone_;
122 };
123 
TEST_F(DeviceAutoUpdateTimeRestrictionsUtilTest,GetDeviceAutoUpdateTimeRestrictionsIntervalsInLocalTimezone)124 TEST_F(DeviceAutoUpdateTimeRestrictionsUtilTest,
125        GetDeviceAutoUpdateTimeRestrictionsIntervalsInLocalTimezone) {
126   const vector<WeeklyTimeInterval> kExpected{
127       WeeklyTimeInterval(
128           WeeklyTime(kMonday, 5 * kMillisecondsInHour, kNewYorkOffset),
129           WeeklyTime(kTuesday, 10 * kMillisecondsInHour, kNewYorkOffset)),
130       WeeklyTimeInterval(
131           WeeklyTime(kWednesday, 10 * kMillisecondsInHour, kNewYorkOffset),
132           WeeklyTime(kWednesday, 15 * kMillisecondsInHour, kNewYorkOffset))};
133 
134   scoped_testing_cros_settings_.device_settings()->Set(
135       chromeos::kDeviceAutoUpdateTimeRestrictions,
136       GetIntervalsAsList(kExpected));
137 
138   vector<WeeklyTimeInterval> result;
139   ASSERT_TRUE(GetDeviceAutoUpdateTimeRestrictionsIntervalsInLocalTimezone(
140       &test_clock_, &result));
141   EXPECT_EQ(result, kExpected);
142 }
143 
144 }  // namespace policy
145