diff --git a/bluez-agent-template.patch b/bluez-agent-template.patch new file mode 100644 index 0000000..789c9a7 --- /dev/null +++ b/bluez-agent-template.patch @@ -0,0 +1,189 @@ +From 9bf4215782517c21ac40e7bfca9e3a43b1b31c5e Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 16 Feb 2021 14:39:47 +0100 +Subject: [PATCH 1/3] bluez: Implement Pair() method on the Device interface + +Tested successfully against gnome-bluetooth. Note that pairing does not +currently use agents at all, and always succeeds. +--- + dbusmock/templates/bluez5.py | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/dbusmock/templates/bluez5.py b/dbusmock/templates/bluez5.py +index 75e8dcf..5d9676b 100644 +--- a/dbusmock/templates/bluez5.py ++++ b/dbusmock/templates/bluez5.py +@@ -18,6 +18,7 @@ This supports BlueZ 5 only. + __author__ = 'Philip Withnall' + __copyright__ = '(c) 2013 Collabora Ltd.' + ++import os + import dbus + + from dbusmock import OBJECT_MANAGER_IFACE, mockobject +@@ -123,6 +124,18 @@ def AddAdapter(self, device_name, system_name): + return path + + ++@dbus.service.method(DEVICE_IFACE, ++ in_signature='', out_signature='') ++def Pair(device): ++ if device.paired: ++ raise dbus.exceptions.DBusException( ++ 'Device already paired', ++ name='org.bluez.Error.AlreadyExists') ++ device_address = device.props[DEVICE_IFACE]['Address'] ++ adapter_device_name = os.path.basename(device.props[DEVICE_IFACE]['Adapter']) ++ device.PairDevice(adapter_device_name, device_address) ++ ++ + @dbus.service.method(BLUEZ_MOCK_IFACE, + in_signature='sss', out_signature='s') + def AddDevice(self, adapter_device_name, device_address, alias): +@@ -171,8 +184,10 @@ def AddDevice(self, adapter_device_name, device_address, alias): + ('ConnectProfile', 's', '', ''), + ('Disconnect', '', '', ''), + ('DisconnectProfile', 's', '', ''), +- ('Pair', '', '', ''), ++ ('Pair', '', '', Pair), + ]) ++ device = mockobject.objects[path] ++ device.paired = False + + manager = mockobject.objects['/'] + manager.EmitSignal(OBJECT_MANAGER_IFACE, 'InterfacesAdded', +@@ -214,6 +229,7 @@ def PairDevice(_self, adapter_device_name, device_address, class_=5898764): + name=BLUEZ_MOCK_IFACE + '.NoSuchDevice') + + device = mockobject.objects[device_path] ++ device.paired = True + + # Based off pairing with an Android phone. + uuids = [ +-- +2.30.2 + + +From 2454e9fbfa9d0da3042c51d1a3241b9940a6f1c0 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 17 Feb 2021 16:11:17 +0100 +Subject: [PATCH 2/3] tests: Fix bluez server never being closed down + +The same variable was used to store the obex server's process +information so it was closed, and the bluez server's information was +lost. +--- + tests/test_bluez5.py | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tests/test_bluez5.py b/tests/test_bluez5.py +index b40950f..cbbc0f7 100644 +--- a/tests/test_bluez5.py ++++ b/tests/test_bluez5.py +@@ -205,7 +205,7 @@ class TestBlueZObex(dbusmock.DBusTestCase): + self.dbusmock_bluez = dbus.Interface(self.obj_bluez, 'org.bluez.Mock') + + # obexd +- (self.p_mock, self.obj_obex) = self.spawn_server_template( ++ (self.p_mock_obex, self.obj_obex) = self.spawn_server_template( + 'bluez5-obex', {}, stdout=subprocess.PIPE) + self.dbusmock = dbus.Interface(self.obj_obex, dbusmock.MOCK_IFACE) + self.dbusmock_obex = dbus.Interface(self.obj_obex, +@@ -216,6 +216,10 @@ class TestBlueZObex(dbusmock.DBusTestCase): + self.p_mock.terminate() + self.p_mock.wait() + ++ self.p_mock_obex.stdout.close() ++ self.p_mock_obex.terminate() ++ self.p_mock_obex.wait() ++ + def test_everything(self): + # Set up an adapter and device. + adapter_name = 'hci0' +-- +2.30.2 + + +From 49f493784cf288c95bb90870c8e3a603c64865d3 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 17 Feb 2021 16:10:08 +0100 +Subject: [PATCH 3/3] bluez: Implement the AgentManager1 interface methods + +The pairing agent still doesn't call into those, but this is good enough +to register and unregister a pairing agent in gnome-bluetooth's test +suite. +--- + dbusmock/templates/bluez5.py | 55 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 52 insertions(+), 3 deletions(-) + +diff --git a/dbusmock/templates/bluez5.py b/dbusmock/templates/bluez5.py +index 5d9676b..6a2f85a 100644 +--- a/dbusmock/templates/bluez5.py ++++ b/dbusmock/templates/bluez5.py +@@ -37,11 +37,60 @@ NETWORK_SERVER_IFACE = 'org.bluez.Network1' + DEVICE_IFACE = 'org.bluez.Device1' + + ++@dbus.service.method(AGENT_MANAGER_IFACE, ++ in_signature='os', out_signature='') ++def RegisterAgent(manager, agent_path, capability): ++ all_caps = ['DisplayOnly', 'DisplayYesNo', 'KeyboardOnly', ++ 'NoInputNoOutput', 'KeyboardDisplay'] ++ ++ if agent_path in manager.agent_paths: ++ raise dbus.exceptions.DBusException( ++ 'Another agent is already registered ' + manager.agent_path, ++ name='org.bluez.Error.AlreadyExists') ++ ++ if capability not in all_caps: ++ raise dbus.exceptions.DBusException( ++ 'Unsupported capability ' + capability, ++ name='org.bluez.Error.InvalidArguments') ++ ++ if not manager.default_agent: ++ manager.default_agent = agent_path ++ manager.agent_paths += [agent_path] ++ manager.capabilities[agent_path] = capability ++ ++ ++@dbus.service.method(AGENT_MANAGER_IFACE, ++ in_signature='o', out_signature='') ++def UnregisterAgent(manager, agent_path): ++ if agent_path not in manager.agent_paths: ++ raise dbus.exceptions.DBusException( ++ 'Agent not registered ' + agent_path, ++ name='org.bluez.Error.DoesNotExist') ++ ++ manager.agent_paths.remove(agent_path) ++ del manager.capabilities[agent_path] ++ if manager.default_agent == agent_path: ++ if len(manager.agent_paths) > 0: ++ manager.default_agent = manager.agent_paths[-1] ++ else: ++ manager.default_agent = None ++ ++ ++@dbus.service.method(AGENT_MANAGER_IFACE, ++ in_signature='o', out_signature='') ++def RequestDefaultAgent(manager, agent_path): ++ if agent_path not in manager.agent_paths: ++ raise dbus.exceptions.DBusException( ++ 'Agent not registered ' + agent_path, ++ name='org.bluez.Error.DoesNotExist') ++ manager.default_agent = agent_path ++ ++ + def load(mock, _parameters): + mock.AddObject('/org/bluez', AGENT_MANAGER_IFACE, {}, [ +- ('RegisterAgent', 'os', '', ''), +- ('RequestDefaultAgent', 'o', '', ''), +- ('UnregisterAgent', 'o', '', ''), ++ ('RegisterAgent', 'os', '', RegisterAgent), ++ ('RequestDefaultAgent', 'o', '', RequestDefaultAgent), ++ ('UnregisterAgent', 'o', '', UnregisterAgent), + ]) + + bluez = mockobject.objects['/org/bluez'] +-- +2.30.2 + diff --git a/python-dbusmock.spec b/python-dbusmock.spec index d8e8ef2..52ed929 100644 --- a/python-dbusmock.spec +++ b/python-dbusmock.spec @@ -2,7 +2,7 @@ Name: python-%{modname} Version: 0.22.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Mock D-Bus objects License: LGPLv3+ @@ -18,6 +18,9 @@ BuildRequires: python3-gobject BuildRequires: dbus-x11 BuildRequires: upower +# https://github.com/martinpitt/python-dbusmock/pull/66 +Patch0: bluez-agent-template.patch + %global _description\ With this program/Python library you can easily create mock objects on\ D-Bus. This is useful for writing tests for software which talks to\ @@ -51,6 +54,10 @@ rm -rf python-%{modname}.egg-info %{python3_sitelib}/*%{modname}* %changelog +* Mon Mar 22 2021 Bastien Nocera - 0.22.0-3 ++ python-dbusmock-0.22.0-3 +- Add bluez agent templates for the benefit of gnome-bluetooth + * Mon Mar 01 2021 Charalampos Stratakis - 0.22.0-2 - Remove redundant dependency on python3-nose