Skip to content

Commit ad85ae7

Browse files
add regulator test (New) (#2016)
* add regulator test add regulator test * fixed pep8 error fixed pep8 error * revised regulator tests revised regulator tests * revised the regulator test scripts revised the regulator test scripts * revised regulator test scripts revised regulator test scripts * add regulator test plan into ce-oem test plan add regulator test plan into ce-oem test plan
1 parent a836b68 commit ad85ae7

File tree

6 files changed

+306
-0
lines changed

6 files changed

+306
-0
lines changed
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#!/usr/bin/env python3
2+
import sys
3+
import logging
4+
import argparse
5+
import copy
6+
7+
from collections import Counter
8+
from enum import Enum
9+
from pathlib import Path
10+
11+
12+
def init_logger():
13+
"""
14+
Set the logger to log DEBUG and INFO to stdout, and
15+
WARNING, ERROR, CRITICAL to stderr.
16+
"""
17+
root_logger = logging.getLogger()
18+
root_logger.setLevel(logging.INFO)
19+
logger_format = "%(message)s"
20+
21+
# Log DEBUG and INFO to stdout, others to stderr
22+
stdout_handler = logging.StreamHandler(sys.stdout)
23+
stdout_handler.setFormatter(logging.Formatter(logger_format))
24+
25+
stderr_handler = logging.StreamHandler(sys.stderr)
26+
stderr_handler.setFormatter(logging.Formatter(logger_format))
27+
28+
stdout_handler.setLevel(logging.DEBUG)
29+
stderr_handler.setLevel(logging.WARNING)
30+
31+
# Add a filter to the stdout handler to limit log records to
32+
# INFO level and below
33+
stdout_handler.addFilter(lambda record: record.levelno <= logging.INFO)
34+
35+
root_logger.addHandler(stderr_handler)
36+
root_logger.addHandler(stdout_handler)
37+
38+
return root_logger
39+
40+
41+
SYS_REGULATOR_PATH = "/sys/class/regulator"
42+
43+
44+
class RegulatorTypeEnum(Enum):
45+
VOLTAGE = "voltage"
46+
CURRENT = "current"
47+
48+
def __str__(self):
49+
return self.value
50+
51+
52+
class RegulatorAttribute:
53+
54+
def __init__(self):
55+
self.name = "name"
56+
self.type = "type"
57+
58+
59+
def read_node_text(node):
60+
try:
61+
value = node.read_text().strip()
62+
except FileNotFoundError:
63+
logging.error("'%s' does not exists", str(node))
64+
return None
65+
except OSError as err:
66+
logging.error(
67+
"Unexpected error while accessing %s. %s", str(node), err
68+
)
69+
return None
70+
71+
return value
72+
73+
74+
class RegulatorBase:
75+
76+
def __init__(self, regulator_type):
77+
self.regulator_type = regulator_type
78+
self.raw_regulators = {}
79+
self.regulators = {}
80+
self.duplicated_regulators = []
81+
82+
def collect_data(self, node):
83+
regulator_attr = RegulatorAttribute()
84+
rg_type_text = read_node_text(node.joinpath(regulator_attr.type))
85+
if not rg_type_text:
86+
return None
87+
88+
try:
89+
RegulatorTypeEnum(rg_type_text)
90+
data = {}
91+
for key in regulator_attr.__dict__:
92+
value = read_node_text(node.joinpath(key))
93+
if value is not None:
94+
data[key] = value
95+
logging.info("%s: %s", key, value)
96+
97+
return data
98+
except ValueError:
99+
logging.error(
100+
"Unexpected type for '%s' regulator: %s",
101+
node.name,
102+
rg_type_text,
103+
)
104+
105+
def dump_sysfs_regulator(self):
106+
for rg_dev in sorted(Path(SYS_REGULATOR_PATH).glob("regulator*")):
107+
logging.info("- %s", rg_dev.name)
108+
data = self.collect_data(rg_dev)
109+
if data:
110+
self.raw_regulators[rg_dev.name] = data
111+
112+
def filter_regulators_by_type(self):
113+
logging.info("\n# filtering %s regulator ..", self.regulator_type)
114+
for dev in self.raw_regulators.values():
115+
if RegulatorTypeEnum(dev["type"]) != self.regulator_type:
116+
logging.info("skip '%s' regulator", dev["name"])
117+
continue
118+
119+
rg = copy.deepcopy(dev)
120+
key = rg.pop("name")
121+
self.regulators[key] = rg
122+
123+
def has_duplicated_regulators(self):
124+
logging.info("\n# checking duplicated regulators ..")
125+
name_counts = Counter(
126+
[attrs["name"] for attrs in self.raw_regulators.values()]
127+
)
128+
result = {
129+
node: attrs["name"]
130+
for node, attrs in self.raw_regulators.items()
131+
if name_counts[attrs["name"]] > 1
132+
}
133+
134+
if result:
135+
logging.error("# Some regulators has the same name")
136+
for node, name in result.items():
137+
logging.error("- node: %s, name: %s", node, name)
138+
return True
139+
140+
return False
141+
142+
def is_regulator_available(self, name):
143+
if name in self.regulators.keys():
144+
return True
145+
logging.error("%s regulator not found", name)
146+
return False
147+
148+
def is_regulator_attr_available(self, regulator, attr):
149+
if attr in self.regulators[regulator].keys():
150+
return True
151+
logging.error("%s attribute not exists", attr)
152+
return False
153+
154+
def get_regulator_attr(self, regulator, attr):
155+
return self.regulators[regulator][attr]
156+
157+
158+
def summarize_test_results(details_logs):
159+
logging.info("\n# Details Test Results")
160+
for regulator, msgs in details_logs.items():
161+
log = "## '{}' regulator: ".format(regulator)
162+
log += "Failed" if msgs else "Passed"
163+
log += msgs
164+
logging.info(log)
165+
166+
167+
def check_difference(exp_regulators, sysfs_regulators):
168+
logging.info("\n# comparing regulators ..")
169+
test_results = {"result": False, "logs": {}}
170+
171+
for regulator in exp_regulators:
172+
details = ""
173+
if not sysfs_regulators.is_regulator_available(regulator):
174+
details += "\n- regulator device not exists"
175+
test_results["result"] = True
176+
test_results["logs"][regulator] = details
177+
178+
return test_results
179+
180+
181+
def compare_regulators(args):
182+
type = args.type
183+
184+
exp_regulator_devs = args.devices.split("|")
185+
if not exp_regulator_devs:
186+
raise SystemExit("Invalid input argument for devices")
187+
188+
regulator = RegulatorBase(type)
189+
regulator.dump_sysfs_regulator()
190+
regulator.filter_regulators_by_type()
191+
duplicated = regulator.has_duplicated_regulators()
192+
193+
results = check_difference(exp_regulator_devs, regulator)
194+
summarize_test_results(results["logs"])
195+
if results["result"]:
196+
logging.error(
197+
"\nFailed: the expected %s regulators does not match", type
198+
)
199+
else:
200+
logging.info(
201+
"\nPassed: the expected %s regulators are all available", type
202+
)
203+
204+
if duplicated or results["result"]:
205+
raise SystemExit(1)
206+
207+
208+
def register_arguments():
209+
parser = argparse.ArgumentParser(
210+
description="Voltage Regulator detection Tests",
211+
)
212+
parser.add_argument(
213+
"devices",
214+
type=str,
215+
help=(
216+
"provides expected regulator information with following format.\n"
217+
"format: name|...\n"
218+
" e.g. LO1|LO2"
219+
),
220+
)
221+
parser.add_argument(
222+
"-t",
223+
"--type",
224+
type=RegulatorTypeEnum,
225+
choices=list(RegulatorTypeEnum),
226+
help="the regulator type",
227+
)
228+
229+
args = parser.parse_args()
230+
return args
231+
232+
233+
def main():
234+
init_logger()
235+
args = register_arguments()
236+
compare_regulators(args)
237+
238+
239+
if __name__ == "__main__":
240+
main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
unit: category
2+
id: regulator
3+
_name: Regulator Device Test
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
id: ce-oem-regulator/check-voltage-regulators
2+
category_id: regulator
3+
_summary: Verify the voltage regulators match regulators defined in VOLTAGE_REGULATORS VAR
4+
_description:
5+
Check the regulator name and voltage for the platform, relies on the user specifying the information of regualtor.
6+
Usage of parameter: {name|name|...}
7+
VOLTAGE_REGULATORS="LDO5|BUCK4"
8+
plugin: shell
9+
flags: also-after-suspend
10+
estimated_duration: 5
11+
requires: manifest.has_voltage_regulator == 'True'
12+
environ: VOLTAGE_REGULATORS
13+
imports: from com.canonical.plainbox import manifest
14+
command:
15+
regulator_test.py --type voltage "$VOLTAGE_REGULATORS"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
unit: manifest entry
2+
id: has_voltage_regulator
3+
_name: Does platfrom supported Voltage Regulator Device?
4+
value-type: bool
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
id: ce-oem-regulaotr-full
2+
unit: test plan
3+
_name: Regulator tests
4+
_description: Full Regulator tests for devices
5+
include:
6+
nested_part:
7+
ce-oem-regulator-manual
8+
ce-oem-regulator-automated
9+
after-suspend-ce-oem-regulator-manual
10+
after-suspend-ce-oem-regulator-automated
11+
12+
13+
id: ce-oem-regulator-manual
14+
unit: test plan
15+
_name: Regulator manual tests
16+
_description: Manual regulator tests for devices
17+
include:
18+
19+
20+
id: ce-oem-regulator-automated
21+
unit: test plan
22+
_name: Regulator auto tests
23+
_description: Automated led tests for devices
24+
include:
25+
ce-oem-regulator/check-voltage-regulators
26+
27+
28+
id: after-suspend-ce-oem-regulator-manual
29+
unit: test plan
30+
_name: Post suspend Regulator manual tests
31+
_description: Manual Regulator tests for devices
32+
include:
33+
34+
35+
id: after-suspend-ce-oem-regulator-automated
36+
unit: test plan
37+
_name: Post suspend regulator auto tests
38+
_description: Automated Regulator tests for devices
39+
include:
40+
after-suspend-ce-oem-regulator/check-voltage-regulators

contrib/checkbox-ce-oem/checkbox-provider-ce-oem/units/test-plan-ce-oem.pxu

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ nested_part:
4848
ce-oem-iio-sensors-manual
4949
ce-oem-digital-io-manual
5050
ce-oem-secure-boot-manual
51+
ce-oem-regulator-manual
5152
certification_status_overrides:
5253
apply blocker to .*
5354

@@ -90,6 +91,7 @@ nested_part:
9091
ce-oem-gadget-automated
9192
ce-oem-mir-automated
9293
ce-oem-wifi-ap-automated
94+
ce-oem-regulator-automated
9395
ce-oem-power-automated-by-pdu
9496
certification_status_overrides:
9597
apply blocker to .*
@@ -123,6 +125,7 @@ nested_part:
123125
after-suspend-ce-oem-iio-sensors-manual
124126
after-suspend-ce-oem-digital-io-manual
125127
after-suspend-ce-oem-mir-automated
128+
after-suspend-ce-oem-regulator-manual
126129
certification_status_overrides:
127130
apply blocker to .*
128131

@@ -158,6 +161,7 @@ nested_part:
158161
after-suspend-ce-oem-iio-sensors-automated
159162
after-suspend-ce-oem-digital-io-automated
160163
after-suspend-ce-oem-spi-automated
164+
after-suspend-ce-oem-regulator-automated
161165
certification_status_overrides:
162166
apply blocker to .*
163167

0 commit comments

Comments
 (0)