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
339 lines
9.4 KiB
Python
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)
|