From b24f7b704725402fe19ce5af42273d87036d95dc Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 23 Feb 2024 12:20:31 +0100 Subject: [PATCH] Add upower_power_profiles_daemon template This works like the existing power_profiles_daemon template, but for the new D-Bus name/object path introduced in https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/releases/0.20 Enable integration test on Ubuntu, which has version 0.13 in 22.04 LTS. --- dbusmock/templates/power_profiles_daemon.py | 4 +- .../templates/upower_power_profiles_daemon.py | 75 +++++++++++++++++++ tests/run-debian | 8 +- tests/test_power_profiles_daemon.py | 14 +++- 4 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 dbusmock/templates/upower_power_profiles_daemon.py diff --git a/dbusmock/templates/power_profiles_daemon.py b/dbusmock/templates/power_profiles_daemon.py index 9211050c..5986cdbc 100644 --- a/dbusmock/templates/power_profiles_daemon.py +++ b/dbusmock/templates/power_profiles_daemon.py @@ -1,9 +1,11 @@ -"""power-profiles-daemon mock template +"""power-profiles-daemon < 0.20 mock template This creates the expected methods and properties of the main net.hadess.PowerProfiles object. This provides only the non-deprecated D-Bus API as of version 0.9. +Note that this template is deprecated: Version 0.20 listens on a different +bus name/object path, it is provided in upower_power_profiles_daemon.py """ # This program is free software; you can redistribute it and/or modify it under diff --git a/dbusmock/templates/upower_power_profiles_daemon.py b/dbusmock/templates/upower_power_profiles_daemon.py new file mode 100644 index 00000000..2c945eb0 --- /dev/null +++ b/dbusmock/templates/upower_power_profiles_daemon.py @@ -0,0 +1,75 @@ +"""power-profiles-daemon >= 0.20 mock template + +This creates the expected methods and properties of the main +org.freedesktop.UPower.PowerProfiles object. + +This provides the D-Bus API as of version 0.20. +""" + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = "Bastien Nocera" +__copyright__ = """ +(c) 2021, Red Hat Inc. +(c) 2017 - 2024 Martin Pitt +""" + +import dbus + +BUS_NAME = "org.freedesktop.UPower.PowerProfiles" +MAIN_OBJ = "/org/freedesktop/UPower/PowerProfiles" +MAIN_IFACE = "org.freedesktop.UPower.PowerProfiles" +SYSTEM_BUS = True + + +def hold_profile(self, profile, reason, application_id): + self.cookie += 1 + element = {"Profile": profile, "Reason": reason, "ApplicationId": application_id} + self.holds[self.cookie] = element + self.props[MAIN_IFACE]["ActiveProfileHolds"] = [] + for value in self.holds.values(): + self.props[MAIN_IFACE]["ActiveProfileHolds"].append(value) + return self.cookie + + +def release_profile(self, cookie): + self.holds.pop(cookie) + self.props[MAIN_IFACE]["ActiveProfileHolds"] = [] + for value in self.holds.values(): + self.props[MAIN_IFACE]["ActiveProfileHolds"].append(value) + if len(self.props[MAIN_IFACE]["ActiveProfileHolds"]) == 0: + self.props[MAIN_IFACE]["ActiveProfileHolds"] = dbus.Array([], signature="(aa{sv})") + + +def load(mock, parameters): + # Loaded! + mock.loaded = True + mock.cookie = 0 + mock.hold_profile = hold_profile + mock.release_profile = release_profile + mock.holds = {} + + props = { + "ActiveProfile": parameters.get("ActiveProfile", "balanced"), + "PerformanceDegraded": parameters.get("PerformanceDegraded", ""), + "Profiles": [ + dbus.Dictionary({"Profile": "power-saver", "Driver": "dbusmock"}, signature="sv"), + dbus.Dictionary({"Profile": "balanced", "Driver": "dbusmock"}, signature="sv"), + dbus.Dictionary({"Profile": "performance", "Driver": "dbusmock"}, signature="sv"), + ], + "Actions": dbus.Array([], signature="s"), + "ActiveProfileHolds": dbus.Array([], signature="(aa{sv})"), + } + mock.AddProperties(MAIN_IFACE, dbus.Dictionary(props, signature="sv")) + + mock.AddMethods( + MAIN_IFACE, + [ + ("HoldProfile", "sss", "u", "ret = self.hold_profile(self, args[0], args[1], args[2])"), + ("ReleaseProfile", "u", "", "self.release_profile(self, args[0])"), + ], + ) diff --git a/tests/run-debian b/tests/run-debian index bcd9456c..fc2170dc 100644 --- a/tests/run-debian +++ b/tests/run-debian @@ -14,13 +14,7 @@ eatmydata apt-get -y --purge dist-upgrade eatmydata apt-get install --no-install-recommends -y git \ python3-all python3-setuptools python3-setuptools-scm python3-build python3-venv \ python3-dbus python3-pytest python3-gi gir1.2-glib-2.0 \ - dbus libnotify-bin upower network-manager bluez ofono ofono-scripts - -# power-profiles-daemon 0.20 did not yet land in Ubuntu 24.04 -. /etc/os-release -if [ "$ID" = "debian" ]; then - eatmydata apt-get install -y power-profiles-daemon -fi + dbus libnotify-bin upower network-manager bluez ofono ofono-scripts power-profiles-daemon # systemd's tools otherwise fail on "not been booted with systemd" mkdir -p /run/systemd/system diff --git a/tests/test_power_profiles_daemon.py b/tests/test_power_profiles_daemon.py index 889f4b48..639831b8 100644 --- a/tests/test_power_profiles_daemon.py +++ b/tests/test_power_profiles_daemon.py @@ -38,7 +38,19 @@ def setUpClass(cls): cls.dbus_con = cls.get_dbus(True) def setUp(self): - (self.p_mock, self.obj_ppd) = self.spawn_server_template("power_profiles_daemon", {}, stdout=subprocess.PIPE) + # depending on the installed client version, we need to pick the right template + try: + version = subprocess.run( + ["powerprofilesctl", "version"], capture_output=True, text=True, check=True + ).stdout + version = ".".join(version.strip().split(".")[:2]) + template = "power_profiles_daemon" if float(version) < 0.2 else "upower_power_profiles_daemon" + except subprocess.CalledProcessError as e: + # 0.20 crashes without daemon: https://gitlab.freedesktop.org/upower/power-profiles-daemon/-/issues/139 + print("Failed to get powerprofilesctl version, assuming >= 0.20:", e, file=sys.stderr) + template = "upower_power_profiles_daemon" + + (self.p_mock, self.obj_ppd) = self.spawn_server_template(template, {}, stdout=subprocess.PIPE) # set log to nonblocking flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)