xref: /linux/tools/testing/selftests/power_supply/helpers.sh (revision 71dfa617ea9f18e4585fe78364217cd32b1fc382)
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Copyright (c) 2022, 2024 Collabora Ltd
5SYSFS_SUPPLIES=/sys/class/power_supply
6
7calc() {
8	awk "BEGIN { print $* }";
9}
10
11test_sysfs_prop() {
12	PROP="$1"
13	VALUE="$2" # optional
14
15	PROP_PATH="$SYSFS_SUPPLIES"/"$DEVNAME"/"$PROP"
16	TEST_NAME="$DEVNAME".sysfs."$PROP"
17
18	if [ -z "$VALUE" ]; then
19		ktap_test_result "$TEST_NAME" [ -f "$PROP_PATH" ]
20	else
21		ktap_test_result "$TEST_NAME" grep -q "$VALUE" "$PROP_PATH"
22	fi
23}
24
25to_human_readable_unit() {
26	VALUE="$1"
27	UNIT="$2"
28
29	case "$VALUE" in
30		*[!0-9]* ) return ;; # Not a number
31	esac
32
33	if [ "$UNIT" = "uA" ]; then
34		new_unit="mA"
35		div=1000
36	elif [ "$UNIT" = "uV" ]; then
37		new_unit="V"
38		div=1000000
39	elif [ "$UNIT" = "uAh" ]; then
40		new_unit="Ah"
41		div=1000000
42	elif [ "$UNIT" = "uW" ]; then
43		new_unit="mW"
44		div=1000
45	elif [ "$UNIT" = "uWh" ]; then
46		new_unit="Wh"
47		div=1000000
48	else
49		return
50	fi
51
52	value_converted=$(calc "$VALUE"/"$div")
53	echo "$value_converted" "$new_unit"
54}
55
56_check_sysfs_prop_available() {
57	PROP=$1
58
59	PROP_PATH="$SYSFS_SUPPLIES"/"$DEVNAME"/"$PROP"
60	TEST_NAME="$DEVNAME".sysfs."$PROP"
61
62	if [ ! -e "$PROP_PATH" ] ; then
63		ktap_test_skip "$TEST_NAME"
64		return 1
65	fi
66
67	if ! cat "$PROP_PATH" >/dev/null; then
68		ktap_print_msg "Failed to read"
69		ktap_test_fail "$TEST_NAME"
70		return 1
71	fi
72
73	return 0
74}
75
76test_sysfs_prop_optional() {
77	PROP=$1
78	UNIT=$2 # optional
79
80	TEST_NAME="$DEVNAME".sysfs."$PROP"
81
82	_check_sysfs_prop_available "$PROP" || return
83	DATA=$(cat "$SYSFS_SUPPLIES"/"$DEVNAME"/"$PROP")
84
85	ktap_print_msg "Reported: '$DATA' $UNIT ($(to_human_readable_unit "$DATA" "$UNIT"))"
86	ktap_test_pass "$TEST_NAME"
87}
88
89test_sysfs_prop_optional_range() {
90	PROP=$1
91	MIN=$2
92	MAX=$3
93	UNIT=$4 # optional
94
95	TEST_NAME="$DEVNAME".sysfs."$PROP"
96
97	_check_sysfs_prop_available "$PROP" || return
98	DATA=$(cat "$SYSFS_SUPPLIES"/"$DEVNAME"/"$PROP")
99
100	if [ "$DATA" -lt "$MIN" ] || [ "$DATA" -gt "$MAX" ]; then
101		ktap_print_msg "'$DATA' is out of range (min=$MIN, max=$MAX)"
102		ktap_test_fail "$TEST_NAME"
103	else
104		ktap_print_msg "Reported: '$DATA' $UNIT ($(to_human_readable_unit "$DATA" "$UNIT"))"
105		ktap_test_pass "$TEST_NAME"
106	fi
107}
108
109test_sysfs_prop_optional_list() {
110	PROP=$1
111	LIST=$2
112
113	TEST_NAME="$DEVNAME".sysfs."$PROP"
114
115	_check_sysfs_prop_available "$PROP" || return
116	DATA=$(cat "$SYSFS_SUPPLIES"/"$DEVNAME"/"$PROP")
117
118	valid=0
119
120	OLDIFS=$IFS
121	IFS=","
122	for item in $LIST; do
123		if [ "$DATA" = "$item" ]; then
124			valid=1
125			break
126		fi
127	done
128	if [ "$valid" -eq 1 ]; then
129		ktap_print_msg "Reported: '$DATA'"
130		ktap_test_pass "$TEST_NAME"
131	else
132		ktap_print_msg "'$DATA' is not a valid value for this property"
133		ktap_test_fail "$TEST_NAME"
134	fi
135	IFS=$OLDIFS
136}
137
138dump_file() {
139	FILE="$1"
140	while read -r line; do
141		ktap_print_msg "$line"
142	done < "$FILE"
143}
144
145__test_uevent_prop() {
146	PROP="$1"
147	OPTIONAL="$2"
148	VALUE="$3" # optional
149
150	UEVENT_PATH="$SYSFS_SUPPLIES"/"$DEVNAME"/uevent
151	TEST_NAME="$DEVNAME".uevent."$PROP"
152
153	if ! grep -q "POWER_SUPPLY_$PROP=" "$UEVENT_PATH"; then
154		if [ "$OPTIONAL" -eq 1 ]; then
155			ktap_test_skip "$TEST_NAME"
156		else
157			ktap_print_msg "Missing property"
158			ktap_test_fail "$TEST_NAME"
159		fi
160		return
161	fi
162
163	if ! grep -q "POWER_SUPPLY_$PROP=$VALUE" "$UEVENT_PATH"; then
164		ktap_print_msg "Invalid value for uevent property, dumping..."
165		dump_file "$UEVENT_PATH"
166		ktap_test_fail "$TEST_NAME"
167	else
168		ktap_test_pass "$TEST_NAME"
169	fi
170}
171
172test_uevent_prop() {
173	__test_uevent_prop "$1" 0 "$2"
174}
175
176test_uevent_prop_optional() {
177	__test_uevent_prop "$1" 1 "$2"
178}
179