Files
allhaileris afb81b8278
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
init
2026-02-16 15:50:16 +03:00

339 lines
9.4 KiB
Python

# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is formatted with Python Black
import tests as xdp
import dbus
import pytest
SETTINGS_DATA_TEST1 = {
"org.freedesktop.appearance": dbus.Dictionary(
{
"color-scheme": dbus.UInt32(1),
"accent-color": dbus.Struct((0.0, 0.1, 0.33), signature="ddd"),
},
signature="sv",
),
}
SETTINGS_DATA_TEST2 = {
"org.freedesktop.appearance": dbus.Dictionary(
{
"color-scheme": dbus.UInt32(2),
"contrast": dbus.UInt32(0),
},
signature="sv",
),
"org.example.custom": dbus.Dictionary(
{
"foo": "bar",
},
signature="sv",
),
}
SETTINGS_DATA_BAD = {
"org.freedesktop.appearance": dbus.Dictionary(
{
"color-scheme": dbus.UInt32(99),
"accent-color": dbus.Struct((11.11, 22.22, 33.33), signature="ddd"),
},
signature="sv",
),
"org.example.custom": dbus.Dictionary(
{
"foo": "baz",
},
signature="sv",
),
"org.example.custom.bad": dbus.Dictionary(
{
"bad": "bad",
},
signature="sv",
),
}
# This is the expected data, merged SETTINGS_DATA_TEST1 and SETTINGS_DATA_TEST2
SETTINGS_DATA = {
"org.freedesktop.appearance": dbus.Dictionary(
{
"color-scheme": dbus.UInt32(1),
"accent-color": dbus.Struct((0.0, 0.1, 0.33), signature="ddd"),
"contrast": dbus.UInt32(0),
},
signature="sv",
),
"org.example.custom": dbus.Dictionary(
{
"foo": "bar",
},
signature="sv",
),
}
@pytest.fixture
def required_templates():
return {
"settings:org.freedesktop.impl.portal.Test1": {
"settings": SETTINGS_DATA_TEST1,
},
"settings:org.freedesktop.impl.portal.Test2": {
"settings": SETTINGS_DATA_TEST2,
},
"settings:org.freedesktop.impl.portal.TestBad": {
"settings": SETTINGS_DATA_BAD,
},
}
PORTAL_CONFIG_FILES = {
"test1.portal": b"""
[portal]
DBusName=org.freedesktop.impl.portal.Test1
Interfaces=org.freedesktop.impl.portal.Settings;
""",
"test2.portal": b"""
[portal]
DBusName=org.freedesktop.impl.portal.Test2
Interfaces=org.freedesktop.impl.portal.Settings;
""",
"test_bad.portal": b"""
[portal]
DBusName=org.freedesktop.impl.portal.TestBad
Interfaces=org.freedesktop.impl.portal.Settings;
""",
"test_noimpl.portal": b"""
[portal]
DBusName=org.freedesktop.impl.portal.TestBad
Interfaces=org.freedesktop.impl.portal.NonExistant;
""",
}
def portal_config_good():
# test1 merged with test2 should result in the correct output
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test1;test2;
"""
yield files
# a portal without the settings impl does not affect the result
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test1;test_noimpl;test2;
"""
yield files
# the default should be ignored when the interface is configured
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test_bad;
org.freedesktop.impl.portal.Settings=test1;test2
"""
yield files
# use * which should expand to test1;test2;test_noimpl
files = PORTAL_CONFIG_FILES.copy()
del files["test_bad.portal"]
files["test-portals.conf"] = b"""
[preferred]
default=test_noimpl;
org.freedesktop.impl.portal.Settings=*;
"""
yield files
def portal_config_bad():
# test1 alone should result in bad output
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test1;
"""
yield files
# test2 merged with test1 is the wrong order
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test2;test1;
"""
yield files
# test_noimpl does not affect anything
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test_noimpl;test2;test1;
"""
yield files
# default should get ignored, test2 alone should result in bad output
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test1;test2
org.freedesktop.impl.portal.Settings=test2;test_noimpl
"""
yield files
# test_bad anywhere in the active config should result in bad output
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test1;test2
org.freedesktop.impl.portal.Settings=test_bad;test1;test2
"""
yield files
# use * which expands to test1;test2;test_bad;test_no_impl
# contains test_bad which should result in bad output
files = PORTAL_CONFIG_FILES.copy()
files["test-portals.conf"] = b"""
[preferred]
default=test_noimpl;
org.freedesktop.impl.portal.Settings=*;
"""
yield files
def portal_config_twice():
# check that test1 gets picked up only once
files = PORTAL_CONFIG_FILES.copy()
del files["test_bad.portal"]
files["test-portals.conf"] = b"""
[preferred]
default=test_noimpl;
org.freedesktop.impl.portal.Settings=test1;*;
"""
yield files
@pytest.fixture
def xdg_desktop_portal_dir_default_files():
return next(portal_config_good())
class TestSettings:
def test_version(self, portals, dbus_con):
xdp.check_version(dbus_con, "Settings", 2)
@pytest.mark.parametrize(
"xdg_desktop_portal_dir_default_files",
portal_config_good(),
)
def test_read_all(self, portals, dbus_con):
settings_intf = xdp.get_portal_iface(dbus_con, "Settings")
value = settings_intf.ReadAll([])
assert value == SETTINGS_DATA
value = settings_intf.ReadAll([""])
assert value == SETTINGS_DATA
value = settings_intf.ReadAll(["does-not-exist"])
assert value == {}
value = settings_intf.ReadAll(["org."])
assert value == {}
value = settings_intf.ReadAll(["org.*"])
assert value == SETTINGS_DATA
value = settings_intf.ReadAll(
["org.freedesktop.appearance", "org.example.custom"]
)
assert value == SETTINGS_DATA
value = settings_intf.ReadAll(["org.freedesktop.appearance"])
assert len(value) == 1
assert "org.freedesktop.appearance" in value
assert (
value["org.freedesktop.appearance"]
== SETTINGS_DATA["org.freedesktop.appearance"]
)
@pytest.mark.parametrize(
"xdg_desktop_portal_dir_default_files",
portal_config_bad(),
)
def test_read_all_bad_config(self, portals, dbus_con):
settings_intf = xdp.get_portal_iface(dbus_con, "Settings")
value = settings_intf.ReadAll([])
assert value != SETTINGS_DATA
@pytest.mark.parametrize(
"xdg_desktop_portal_dir_default_files",
portal_config_twice(),
)
def test_config_twice(self, portals, dbus_con):
settings_intf = xdp.get_portal_iface(dbus_con, "Settings")
mock_intf = xdp.get_mock_iface(dbus_con, "org.freedesktop.impl.portal.Test1")
value = settings_intf.ReadAll([])
assert value == SETTINGS_DATA
# The config is `test1;*`, make sure we only get a single call to Test1
method_calls = mock_intf.GetMethodCalls("ReadAll")
assert len(method_calls) == 1
def test_read(self, portals, dbus_con):
settings_intf = xdp.get_portal_iface(dbus_con, "Settings")
color_scheme = SETTINGS_DATA["org.freedesktop.appearance"]["color-scheme"]
value = settings_intf.ReadOne("org.freedesktop.appearance", "color-scheme")
assert isinstance(value, dbus.UInt32)
assert value.variant_level == 1
assert value == color_scheme
with pytest.raises(dbus.exceptions.DBusException) as excinfo:
settings_intf.ReadOne("org.does.not.exist", "color-scheme")
assert excinfo.value.get_dbus_name() == "org.freedesktop.portal.Error.NotFound"
with pytest.raises(dbus.exceptions.DBusException) as excinfo:
settings_intf.ReadOne("org.freedesktop.appearance", "xcolor-scheme")
assert excinfo.value.get_dbus_name() == "org.freedesktop.portal.Error.NotFound"
# deprecated but should still check that it works
# the crucial detail here is that the variant_level is 2
value = settings_intf.Read("org.freedesktop.appearance", "color-scheme")
assert isinstance(value, dbus.UInt32)
assert value.variant_level == 2
assert value == color_scheme
def test_changed(self, portals, dbus_con):
settings_intf = xdp.get_portal_iface(dbus_con, "Settings")
mock_intf = xdp.get_mock_iface(dbus_con, "org.freedesktop.impl.portal.Test1")
changed_count = 0
ns = "org.freedesktop.appearance"
key = "color-scheme"
current_value = SETTINGS_DATA[ns][key]
new_value = 2
assert current_value != new_value
value = settings_intf.ReadOne(ns, key)
assert value == current_value
def cb_settings_changed(changed_ns, changed_key, changed_value):
nonlocal changed_count
changed_count += 1
assert changed_ns == ns
assert changed_key == key
assert changed_value == new_value
settings_intf.connect_to_signal("SettingChanged", cb_settings_changed)
mock_intf.SetSetting(ns, key, new_value)
xdp.wait_for(lambda: changed_count == 1)