1# Copyright 2018 The Chromium OS 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
5from autotest_lib.client.common_lib import error
6from autotest_lib.client.common_lib import utils
7from autotest_lib.client.cros.enterprise import enterprise_policy_base
8
9import logging
10import time
11
12
13class policy_SystemTimezone(
14        enterprise_policy_base.EnterprisePolicyTest):
15    """
16    Test effect of SystemTimezone policy on Chrome OS behavior.
17
18    This will test that both the timezone can be set by the policy, and that
19    when the policy is not set a user can change the settings.
20
21    """
22    version = 1
23    POLICY_NAME = 'SystemTimezone'
24
25    def _navigate_chromeos_settings_to_timezone(self):
26        """
27        Will navigate the ChromeOS Settings (New as of R79) to the 'Time zone'
28        page.
29
30        """
31        self.ui.click_and_wait_for_item_with_retries('/tray/', 'Settings', True)
32        self.ui.click_and_wait_for_item_with_retries('Settings', 'Advanced')
33        self.ui.click_and_wait_for_item_with_retries('Advanced',
34                                                     'Date and time')
35        self.ui.click_and_wait_for_item_with_retries('Date and time',
36                                                     'Time zone')
37        self.ui.click_and_wait_for_item_with_retries('Time zone',
38                                                     'Choose from list',
39                                                     click_role='link')
40
41    def _is_timezone_selectable(self):
42        """
43        Check if the timezone is selectable via the UI. If the timezone
44        dropdown is greyed out, then it is not selectable.
45
46        @returns: True if dropdown is usable, False if not.
47
48        """
49        self._navigate_chromeos_settings_to_timezone()
50        self.ui.doDefault_on_obj('Choose from list')
51
52        # Give the dropdown a second to load (there is no object to wait on).
53        time.sleep(2)
54        return not self.ui.is_obj_restricted('Time zone', role='popUpButton')
55
56    def _set_timezone(self):
57        """Sets the timezone to the first option in the list."""
58        self.ui.doDefault_on_obj('/(UTC-10:00)/',
59                                 isRegex=True,
60                                 role='menuListOption')
61
62    def _test_timezone(self, expected):
63        """
64        Verify the Timezone set on the device.
65
66        This is done by running the UNIX date command (%z) and verifying the
67        timezone matches the expected result.
68
69        """
70        def check_timezone(expected):
71            result = utils.system_output('date +%z')
72            logging.info('date result {}'.format(result))
73            return result == expected
74
75        utils.poll_for_condition(
76            lambda: check_timezone(expected),
77            exception=error.TestFail('Time zone was not set! Expected {}'
78                                     .format(expected)),
79            timeout=30,
80            sleep_interval=1,
81            desc='Polling for timezone change')
82
83    def set_timezones(self):
84        """
85        Iterate through different time zones, and verify they can be set.
86
87        This is specifically being done to verify the timezone via seeing
88        the reported timezone is changing, and not just on the first one via
89        luck.
90
91        """
92        case = {'policy': 'Asia/Kathmandu', 'expected': '+0545'}
93
94        policy_value = case['policy']
95        expected = case['expected']
96        policies = {self.POLICY_NAME: policy_value}
97        self.setup_case(device_policies=policies, enroll=True)
98        self.ui.start_ui_root(self.cr)
99        # Logout so the policy can take effect
100        if self._is_timezone_selectable():
101            raise error.TestError(
102                'Timezone is selectable when the policy is set')
103        self.log_out_via_keyboard()
104        self._test_timezone(expected)
105
106
107    def set_empty_timezone(self):
108        """
109        Set and verify the timezone when the policy is empty.
110
111        This will be done by adjusting the setting on the ://settings page,
112        and verifying the date reported. Additionally log out, then verify the
113        timezone matches as well.
114
115        """
116
117        policies = {self.POLICY_NAME: ''}
118        self.setup_case(device_policies=policies, enroll=True)
119        self.ui.start_ui_root(self.cr)
120
121        # Check if the Timezone is changable in the settings.
122        if not self._is_timezone_selectable():
123            raise error.TestError('User cannot change timezone')
124        self._set_timezone()
125
126        self._test_timezone('-1000')
127
128        self.log_out_via_keyboard()
129        self._test_timezone('-1000')
130
131    def run_once(self, case):
132        """
133        Run the proper test based on the selected case.
134
135        @param case: bool or None, value of the test case to run.
136
137        """
138        if case:
139            self.set_timezones()
140        else:
141            self.set_empty_timezone()
142