Add support to make legacy interface optional

If a distribution has migrated all applications over to the modern
interface they can compile without the legacy interface.
This commit is contained in:
Mario Limonciello 2024-02-15 00:17:19 -06:00 committed by Mario Limonciello
parent d08683ecf1
commit d23c29fb33
7 changed files with 163 additions and 67 deletions

View file

@ -71,8 +71,12 @@ endif
bus_names = {
'org.freedesktop.UPower.PowerProfiles': '/org/freedesktop/UPower/PowerProfiles',
'net.hadess.PowerProfiles': '/net/hadess/PowerProfiles',
}
if get_option('legacy')
bus_names += {
'net.hadess.PowerProfiles': '/net/hadess/PowerProfiles'
}
endif
address_sanitizer = get_option('b_sanitize') == 'address' or \
get_option('b_sanitize') == 'address,undefined' or \
@ -155,6 +159,7 @@ meson.add_dist_script(
summary({
'tests': get_option('tests'),
'legacy interface': get_option('legacy'),
'bash-completion': bashcomp,
'zsh-completion': zshcomp,
'manpages': argparse_manpage.found(),

View file

@ -1,3 +1,7 @@
option('legacy',
description: 'advertise legacy interface',
type: 'boolean',
value: 'true')
option('systemdsystemunitdir',
description: 'systemd unit directory',
type: 'string',

View file

@ -9,6 +9,9 @@ deps = [
config_h = configuration_data()
config_h.set_quoted('VERSION', meson.project_version())
config_h.set('POLKIT_HAS_AUTOPOINTERS', polkit_gobject_dep.version().version_compare('>= 0.114'))
if get_option('legacy')
config_h.set('HAVE_LEGACY', 1)
endif
config_h_files = configure_file(
output: 'config.h',
configuration: config_h

View file

@ -428,9 +428,11 @@ send_dbus_event (PpdApp *data,
send_dbus_event_iface (data, mask,
POWER_PROFILES_IFACE_NAME,
POWER_PROFILES_DBUS_PATH);
#ifdef HAVE_LEGACY
send_dbus_event_iface (data, mask,
POWER_PROFILES_LEGACY_IFACE_NAME,
POWER_PROFILES_LEGACY_DBUS_PATH);
#endif
}
static void
@ -1134,6 +1136,7 @@ name_lost_handler (GDBusConnection *connection,
g_main_loop_quit (app->main_loop);
}
#ifdef HAVE_LEGACY
static void
legacy_name_acquired_handler (GDBusConnection *connection,
const gchar *name,
@ -1141,6 +1144,7 @@ legacy_name_acquired_handler (GDBusConnection *connection,
{
g_debug ("Name '%s' acquired", name);
}
#endif
static void
bus_acquired_handler (GDBusConnection *connection,
@ -1157,6 +1161,7 @@ bus_acquired_handler (GDBusConnection *connection,
NULL,
NULL);
#ifdef HAVE_LEGACY
g_dbus_connection_register_object (connection,
POWER_PROFILES_LEGACY_DBUS_PATH,
data->legacy_interface,
@ -1172,6 +1177,7 @@ bus_acquired_handler (GDBusConnection *connection,
name_lost_handler,
data,
NULL);
#endif
data->app->connection = g_object_ref (connection);
}
@ -1818,6 +1824,12 @@ setup_dbus (PpdApp *data,
if (!iface_data)
return FALSE;
introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (iface_data, NULL),
error);
if (!introspection_data)
return FALSE;
#ifdef HAVE_LEGACY
legacy_iface_data = g_resources_lookup_data (POWER_PROFILES_RESOURCES_PATH "/"
POWER_PROFILES_LEGACY_DBUS_NAME ".xml",
G_RESOURCE_LOOKUP_FLAGS_NONE,
@ -1825,20 +1837,18 @@ setup_dbus (PpdApp *data,
if (!legacy_iface_data)
return FALSE;
introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (iface_data, NULL),
error);
if (!introspection_data)
return FALSE;
legacy_introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (legacy_iface_data, NULL),
error);
if (!legacy_introspection_data)
return FALSE;
#endif
own_data = g_new0 (PpdBusOwnData, 1);
own_data->app = data;
own_data->interface = g_dbus_interface_info_ref (introspection_data->interfaces[0]);
#ifdef HAVE_LEGACY
own_data->legacy_interface = g_dbus_interface_info_ref (legacy_introspection_data->interfaces[0]);
#endif
own_data->flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
if (data->debug_options->replace)

View file

@ -2666,67 +2666,6 @@ class Tests(dbusmock.DBusTestCase):
return prop_str
class LegacyDBusNameTests(Tests):
"""This will repeats all the tests in the Tests class using the legacy dbus name"""
PP = "net.hadess.PowerProfiles"
PP_PATH = "/net/hadess/PowerProfiles"
PP_INTERFACE = "net.hadess.PowerProfiles"
def test_vanishing_hold(self):
# Let's not block because of this CI failure, the test isn't relying on
# the old name anyways.
pass
def test_amdgpu_dpm(self):
amdgpu_dpm = "device/power_dpm_force_performance_level"
self.testbed.add_device(
"drm",
"card0",
None,
[amdgpu_dpm, "auto\n"],
["DEVTYPE", "drm_minor"],
)
self.create_amd_apu()
self.start_daemon()
# verify can't enable it on legacy interface
with self.assertRaises(gi.repository.GLib.GError) as error:
self.call_dbus_method(
"SetActionEnabled", GLib.Variant("(sb)", ("amdgpu_dpm", True))
)
self.assertIn("UnknownMethod", str(error.exception))
def test_amdgpu_dpm_manual(self):
# should fail same way as test_amdgpu_dpm
self.test_amdgpu_dpm()
def test_amdgpu_panel_power(self):
amdgpu_panel_power_savings = "amdgpu/panel_power_savings"
self.testbed.add_device(
"drm",
"card1-eDP",
None,
["status", "connected\n", amdgpu_panel_power_savings, "0"],
["DEVTYPE", "drm_connector"],
)
self.create_amd_apu()
self.start_daemon()
# verify it starts off disabled
self.assert_action_disabled("amdgpu_panel_power")
# verify can't enable it on legacy interface
with self.assertRaises(gi.repository.GLib.GError) as error:
self.call_dbus_method(
"SetActionEnabled", GLib.Variant("(sb)", ("amdgpu_panel_power", True))
)
self.assertIn("UnknownMethod", str(error.exception))
if __name__ == "__main__":
# run ourselves under umockdev
if "umockdev" not in os.environ.get("LD_PRELOAD", ""):

View file

@ -0,0 +1,110 @@
#!/usr/bin/python3
# power-profiles-daemon integration test suite
#
# Run in built tree to test local built binaries, or from anywhere else to test
# system installed binaries.
#
# Copyright: (C) 2011 Martin Pitt <martin.pitt@ubuntu.com>
# (C) 2020 Bastien Nocera <hadess@hadess.net>
# (C) 2021 David Redondo <kde@david-redondo.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import os
import sys
import unittest
from integration_test import Tests
try:
import gi
from gi.repository import GLib
except ImportError as e:
sys.stderr.write(
f"Skipping tests, PyGobject not available for Python 3, or missing GI typelibs: {str(e)}\n"
)
sys.exit(77)
class LegacyDBusNameTests(Tests):
"""This will repeats all the tests in the Tests class using the legacy dbus name"""
PP = "net.hadess.PowerProfiles"
PP_PATH = "/net/hadess/PowerProfiles"
PP_INTERFACE = "net.hadess.PowerProfiles"
def test_vanishing_hold(self):
# Let's not block because of this CI failure, the test isn't relying on
# the old name anyways.
pass
def test_amdgpu_dpm(self):
amdgpu_dpm = "device/power_dpm_force_performance_level"
self.testbed.add_device(
"drm",
"card0",
None,
[amdgpu_dpm, "auto\n"],
["DEVTYPE", "drm_minor"],
)
self.create_amd_apu()
self.start_daemon()
# verify can't enable it on legacy interface
with self.assertRaises(gi.repository.GLib.GError) as error:
self.call_dbus_method(
"SetActionEnabled", GLib.Variant("(sb)", ("amdgpu_dpm", True))
)
self.assertIn("UnknownMethod", str(error.exception))
def test_amdgpu_dpm_manual(self):
# should fail same way as test_amdgpu_dpm
self.test_amdgpu_dpm()
def test_amdgpu_panel_power(self):
amdgpu_panel_power_savings = "amdgpu/panel_power_savings"
self.testbed.add_device(
"drm",
"card1-eDP",
None,
["status", "connected\n", amdgpu_panel_power_savings, "0"],
["DEVTYPE", "drm_connector"],
)
self.create_amd_apu()
self.start_daemon()
# verify it starts off disabled
self.assert_action_disabled("amdgpu_panel_power")
# verify can't enable it on legacy interface
with self.assertRaises(gi.repository.GLib.GError) as error:
self.call_dbus_method(
"SetActionEnabled", GLib.Variant("(sb)", ("amdgpu_panel_power", True))
)
self.assertIn("UnknownMethod", str(error.exception))
if __name__ == "__main__":
# run ourselves under umockdev
if "umockdev" not in os.environ.get("LD_PRELOAD", ""):
os.execvp("umockdev-wrapper", ["umockdev-wrapper", sys.executable] + sys.argv)
prog = unittest.main(exit=False)
if prog.result.errors or prog.result.failures:
sys.exit(1)
# Translate to skip error
if prog.result.testsRun == len(prog.result.skipped):
sys.exit(77)

View file

@ -93,3 +93,28 @@ if pylint.found()
env: nomalloc,
)
endif
if get_option('legacy')
legacy_integration_tests = files('legacy_integration_test.py')
r = run_command(python3, unittest_inspector, legacy_integration_tests, check: true)
legacy_unit_tests = r.stdout().strip().split('\n')
foreach ut: legacy_unit_tests
test(ut,
python3,
args: [
legacy_integration_tests,
ut,
],
env: envs,
)
endforeach
if pylint.found()
test('pylint-legacy-integration-tests',
pylint,
args: integration_pylint_flags + legacy_integration_tests,
env: nomalloc,
)
endif
endif