1# Copyright 2019 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.cros.enterprise import enterprise_policy_base
7from autotest_lib.client.cros.power import power_status
8
9
10class ChargingPolicyTest(enterprise_policy_base.EnterprisePolicyTest):
11    """
12    A Client test that verifies that AC usage and battery charging is consistent
13    with policy settings. As of this writing, these features are only present on
14    the Wilco platform.
15    """
16    # The Wilco EC updates it's charging behavior every 60 seconds,
17    # so give ourselves 120 seconds to notice a change in behavior.
18    POLICY_CHANGE_TIMEOUT = 120
19
20    def run_once(self, test_cases, min_battery_level, prep_policies):
21        """
22        Test a collection of cases.
23
24        @param test_cases: Collection of (policies, expected_behavior) pairs,
25                           where expected_behavior is one of values accepted by
26                           power_status.poll_for_charging_behavior().
27        @param min_battery_level: For the policy to affect the behavior
28                                  correctly, the battery level may need to be
29                                  above a certain percentage.
30        @param prep_policies: To test that policies P1 cause behavior B1, we
31                              need to start in a state P2 where behavior B2 is
32                              not B1, so we can notice the change to B1.
33                              prep_policies is a dict that maps B1 => (P2, B2),
34                              so that we can look up how to prep for testing
35                              P1.
36        """
37        self.setup_case(enroll=True)
38
39        failures = []
40        for policies, expected_behavior in test_cases:
41            setup_policies, prep_behavior = prep_policies[expected_behavior]
42            err = self._test_policies(setup_policies, prep_behavior,
43                                      min_battery_level)
44            if err is not None:
45                failures.append(err)
46
47            # Now that we are set up, test the actual test case.
48            err = self._test_policies(policies, expected_behavior,
49                                      min_battery_level)
50            if err is not None:
51                failures.append(err)
52        if failures:
53            raise error.TestFail('Failed the following cases: {}'.format(
54                    str(failures)))
55
56    def _test_policies(self, policies, expected_behavior, min_battery_level):
57        self.update_policies(device_policies=policies)
58        try:
59            self._assert_battery_is_testable(min_battery_level)
60            power_status.poll_for_charging_behavior(expected_behavior,
61                                                    self.POLICY_CHANGE_TIMEOUT)
62        except BaseException as e:
63            msg = ('Expected to be {} using policies {}. Got this instead: {}'.
64                   format(expected_behavior, policies, str(e)))
65            return msg
66        return None
67
68    def _assert_battery_is_testable(self, min_battery_level):
69        status = power_status.get_status()
70        if status.battery_full():
71            raise error.TestError('The battery is full, but should not be')
72        status.assert_battery_in_range(min_battery_level, 100)
73