linux: integration-test: Test for battery charging threshold

Signed-off-by: Kate Hsuan <hpa@redhat.com>
This commit is contained in:
Jelle van der Waa 2024-07-23 15:40:50 +08:00 committed by Kate Hsuan
parent aed03b0705
commit 5b656780ff

View file

@ -176,7 +176,7 @@ class Tests(dbusmock.DBusTestCase):
# Daemon control and D-BUS I/O
#
def start_daemon(self, cfgfile=None, warns=False):
def start_daemon(self, cfgfile=None, warns=False, history_dir_override=None):
'''Start daemon and create DBus proxy.
Do this after adding the devices you want to test with. At the moment
@ -190,8 +190,14 @@ class Tests(dbusmock.DBusTestCase):
_, cfgfile = tempfile.mkstemp(prefix='upower-cfg-')
self.addCleanup(os.unlink, cfgfile)
env['UPOWER_CONF_FILE_NAME'] = cfgfile
env['UPOWER_HISTORY_DIR'] = tempfile.mkdtemp(prefix='upower-history-')
if history_dir_override is not None:
self.upower_history_dir = env['UPOWER_HISTORY_DIR'] = history_dir_override
env['UPOWER_STATE_DIR'] = history_dir_override
else:
self.upower_history_dir = env['UPOWER_HISTORY_DIR'] = tempfile.mkdtemp(prefix='upower-history-')
env['UPOWER_STATE_DIR'] = self.upower_history_dir
self.addCleanup(shutil.rmtree, env['UPOWER_HISTORY_DIR'])
env['G_DEBUG'] = 'fatal-criticals' if warns else 'fatal-warnings'
# note: Python doesn't propagate the setenv from Testbed.new(), so we
# have to do that ourselves
@ -287,6 +293,16 @@ class Tests(dbusmock.DBusTestCase):
Gio.DBusCallFlags.NO_AUTO_START,
-1, None).unpack()[0]
def enable_charge_limits(self, device, enable):
self.dbus.call_sync(UP, device,
'org.freedesktop.UPower.Device',
'EnableChargeThreshold',
GLib.Variant('(b)', (enable,)),
None,
Gio.DBusCallFlags.NO_AUTO_START,
-1, None)
def assertDevs(self, expected):
devs = self.proxy.EnumerateDevices()
names = sorted(n.split('/')[-1] for n in devs)
@ -995,6 +1011,161 @@ class Tests(dbusmock.DBusTestCase):
self.assertEqual(self.get_dbus_display_property('IsPresent'), True)
self.stop_daemon()
def test_battery_charge_limit_multiple_batteries(self):
'''Battery with charge limits with multiple batteries'''
self.testbed.add_device('power_supply', 'BAT0', None,
['type', 'Battery',
'present', '1',
'status', 'unknown',
'energy_full', '60000000',
'energy_full_design', '80000000',
'energy_now', '48000000',
'voltage_now', '12000000',
'charge_control_start_threshold', '0',
'charge_control_end_threshold', '100',
], [])
self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80')
self.testbed.add_device('power_supply', 'BAT1', None,
['type', 'Battery',
'present', '1',
'status', 'unknown',
'energy_full', '60000000',
'energy_full_design', '80000000',
'energy_now', '48000000',
'voltage_now', '12000000',
'charge_control_start_threshold', '0',
'charge_control_end_threshold', '100',
], [])
self.testbed.set_property("/sys/class/power_supply/BAT1", 'CHARGE_LIMIT', '70,80')
self.start_daemon()
devs = self.proxy.EnumerateDevices()
self.assertEqual(len(devs), 2)
bat0_up = devs[0]
bat1_up = devs[0]
for bat in [bat0_up, bat1_up]:
self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdSupported'), True)
self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), False)
self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeStartThreshold'), 70)
self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeEndThreshold'), 80)
self.enable_charge_limits(bat0_up, True)
self.enable_charge_limits(bat1_up, True)
for bat in [bat0_up, bat1_up]:
self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), True)
battery_name = bat.split('_')[-1]
with open(f'/sys/class/power_supply/{battery_name}/charge_control_start_threshold') as fp:
self.assertEqual(fp.read(), '70')
with open(f'/sys/class/power_supply/{battery_name}/charge_control_end_threshold') as fp:
self.assertEqual(fp.read(), '80')
def test_battery_charge_limit_supported(self):
'''Battery with charge_control_start/end_threshold supported'''
self.testbed.add_device('power_supply', 'BAT0', None,
['type', 'Battery',
'present', '1',
'model_name', 'test',
'serial_number', '12',
'status', 'unknown',
'energy_full', '60000000',
'energy_full_design', '80000000',
'energy_now', '48000000',
'voltage_now', '12000000',
'charge_control_start_threshold', '0',
'charge_control_end_threshold', '100',
], [])
self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80')
def start_daemon(charge_threshold_value=None):
upower_history_dir_override = tempfile.mkdtemp(prefix='upower-history-')
if charge_threshold_value is not None:
with open(os.path.join(upower_history_dir_override, f"charging-threshold-status") , 'w') as fp:
fp.write(charge_threshold_value)
self.start_daemon(history_dir_override=upower_history_dir_override)
devs = self.proxy.EnumerateDevices()
self.assertEqual(len(devs), 1)
return devs[0]
bat0_up = start_daemon()
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 70)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 80)
self.enable_charge_limits(bat0_up, True)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), True)
# charge limits enabled?
with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp:
self.assertEqual(fp.read(), '70')
with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp:
self.assertEqual(fp.read(), '80')
self.enable_charge_limits(bat0_up, False)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False)
with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp:
self.assertEqual(fp.read(), '0')
with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp:
self.assertEqual(fp.read(), '100')
# TODO: Test changing CHARGE_LIMIT
# self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '20,30')
# self.testbed.uevent("/sys/class/power_supply/BAT0", 'change')
# devs = self.proxy.EnumerateDevices()
# bat0_up = devs[0]
# self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 20)
# self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 30)
self.stop_daemon()
# On startup with threshold set
self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '90,100')
bat0_up = start_daemon(charge_threshold_value='1')
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), True)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 90)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 100)
with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp:
self.assertEqual(fp.read(), '90')
with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp:
self.assertEqual(fp.read(), '100')
def test_battery_charge_threshold_unsupported(self):
'''Battery with only end_threshold supported'''
self.testbed.add_device('power_supply', 'BAT0', None,
['type', 'Battery',
'present', '1',
'model_name', 'test',
'serial_number', '12',
'status', 'unknown',
'energy_full', '60000000',
'energy_full_design', '80000000',
'energy_now', '48000000',
'voltage_now', '12000000',
'charge_control_start_threshold', '80',
], [])
self.start_daemon()
devs = self.proxy.EnumerateDevices()
self.assertEqual(len(devs), 1)
bat0_up = devs[0]
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), False)
self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False)
try:
self.enable_charge_limits(bat0_up, True)
except Exception as err:
self.assertIn("setting battery charge thresholds", str(err))
self.stop_daemon()
def test_battery_zero_power_draw(self):
'''Battery with zero power draw, e.g. in a dual-battery system'''