blob: b00bfbcb22cc0ef4946c55b5baac689a0bde6717 [file] [log] [blame]
# Copyright 2021 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Test wireless charge port functionality.
Description
-----------
Verify wireless charging port functionality by asking operator to follow the
instructions by occupy/free charging port then probe the port status.
Test Procedure
--------------
1. Show instruction on screen and instruct operator to occupy port with
peripheral, then press SPACE to probe state.
2. Show instruction on screen and instruct operator to free port with
peripheral, then press SPACE to probe state.
Dependency
----------
- Based on ectool pchg <port>
Examples
--------
To test charging port 0::
{
"pytest_name": "wireless_charge",
"args": {
"port": 0,
"occupy_instruction": "Attach stylus on the DUT right side",
"release_instruction": "Remove stylus from the DUT right side"
}
}
"""
import enum
from cros.factory.device import device_utils
from cros.factory.test.i18n import _
from cros.factory.test.i18n import arg_utils as i18n_arg_utils
from cros.factory.test import session
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils.string_utils import ParseDict
class ChargeState(enum.Enum):
"""A subset of ectool pchg output state."""
ENABLED = enum.auto()
CHARGING = enum.auto()
FULL = enum.auto()
class PortState(enum.Enum):
Unknown = enum.auto()
Occupied = enum.auto()
Available = enum.auto()
def GetPortStateFromChargeState(charge_state):
"""Converts charge state to port state.
CHARGING and FULL in ChargeState map to Occupied, whereas ENABLED maps to
Available.
"""
if charge_state in [ChargeState.CHARGING, ChargeState.FULL]:
return PortState.Occupied
if charge_state == ChargeState.ENABLED:
return PortState.Available
return PortState.Unknown
class WirelessChargeArgs:
port: int
occupy_instruction: str
release_instruction: str
timeout: int
class WirelessChargeTest(test_case.TestCase):
related_components = tuple()
ARGS = [
Arg('port', int, 'Wireless charging port to test.', default=0),
i18n_arg_utils.I18nArg(
'occupy_instruction',
'Text to display the instruction to operator to occupy port',
default='Attach peripheral to charging port'),
i18n_arg_utils.I18nArg(
'release_instruction',
'Text to display the instruction to operator to release port',
default='Remove peripheral from charging port'),
Arg('timeout', int, 'Timeout of the test.', default=200)
]
args: WirelessChargeArgs
ui: test_ui.StandardUI
def setUp(self):
self._dut = device_utils.CreateDUTInterface()
self.ui.SetState(_('Wireless Charge Port testing...'))
def runTest(self):
self.ui.StartFailingCountdownTimer(self.args.timeout)
# test port charge ability
self.InstructAndWaitStateFulfilled(self.args.occupy_instruction,
PortState.Occupied)
# test idling port
self.InstructAndWaitStateFulfilled(self.args.release_instruction,
PortState.Available)
def InstructAndWaitStateFulfilled(self, instruction, desired_state):
"""Waits until desired state is fulfilled.
Args:
instruction: test instruction displayed to operator
desired_state: the desired PortState
"""
self.ui.SetInstruction(
_('{instruction} then hit SPACE', instruction=instruction))
while True:
self.ui.WaitKeysOnce(test_ui.SPACE_KEY)
charge_state = self.GetPortChargingState()
charge_state_info = f'Current port state: {charge_state.name}'
self.ui.SetState(charge_state_info)
session.console.info(charge_state_info)
if GetPortStateFromChargeState(charge_state) == desired_state:
break
def GetPortChargingState(self): # pylint: disable=inconsistent-return-statements
cmd = f'ectool pchg {self.args.port}'
output = self._dut.CheckOutput(cmd, log=True)
parsed_dict = ParseDict(output.split('\n'))
self.assertIn('State', parsed_dict, msg=f'State not in output: {output}')
# state field is composed of a state and a number, e.g. FULL (4)
state_field_tokens = parsed_dict['State'].split()
self.assertGreaterEqual(
len(state_field_tokens), 1,
msg=f'Invalid State field: {parsed_dict["State"]}')
state = state_field_tokens[0]
try:
return ChargeState[state]
except KeyError:
self.FailTask(
f'The state of port {self.args.port}: {state} is unsupported!')