summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDjLegolas <djlegolas@protonmail.com>2022-02-11 12:40:47 +0200
committerCalum Lind <calumlind+deluge@gmail.com>2022-02-12 17:14:19 +0000
commitf8f997a6ebe74409c824b4b56e9ba19e015e9013 (patch)
tree5317276b2f2b287fec3c8f1f9e89d1e9240a745c
parent374997a8d7fec910a3a63d4171a6a64bab08d3ef (diff)
downloaddeluge-f8f997a6ebe74409c824b4b56e9ba19e015e9013.tar.gz
deluge-f8f997a6ebe74409c824b4b56e9ba19e015e9013.tar.bz2
deluge-f8f997a6ebe74409c824b4b56e9ba19e015e9013.zip
[Config] Fix callLater func missing args
In a6840296, a refactor to the `config` class was introduced. The change included an internal wrapper for `reactor.callLater`, for lazy import, but didn't wrap it correctly and therefor, no args/kwargs were passed to the wrapped method. Furthermore, the exception was silently ignored. This caused changes to be ignored and not applied, including `preferencesmanager._on_config_value_change` callback. Closes: https://github.com/deluge-torrent/deluge/pull/372
-rw-r--r--deluge/config.py4
-rw-r--r--deluge/conftest.py27
-rw-r--r--deluge/tests/test_config.py28
3 files changed, 56 insertions, 3 deletions
diff --git a/deluge/config.py b/deluge/config.py
index 8671bc330..abf46d71b 100644
--- a/deluge/config.py
+++ b/deluge/config.py
@@ -144,11 +144,11 @@ class Config:
self.load()
- def callLater(self, period, func): # noqa: N802 ignore camelCase
+ def callLater(self, period, func, *args, **kwargs): # noqa: N802 ignore camelCase
"""Wrapper around reactor.callLater for test purpose."""
from twisted.internet import reactor
- return reactor.callLater(period, func)
+ return reactor.callLater(period, func, *args, **kwargs)
def __contains__(self, item):
return item in self.__config
diff --git a/deluge/conftest.py b/deluge/conftest.py
index ad7c8b30f..4266938fa 100644
--- a/deluge/conftest.py
+++ b/deluge/conftest.py
@@ -4,11 +4,13 @@
# See LICENSE for more details.
#
+import unittest.mock
import warnings
import pytest
import pytest_twisted
-from twisted.internet.defer import maybeDeferred
+from twisted.internet import reactor
+from twisted.internet.defer import Deferred, maybeDeferred
from twisted.internet.error import CannotListenError
from twisted.python.failure import Failure
@@ -32,6 +34,29 @@ def listen_port(request):
@pytest.fixture
+def mock_callback():
+ """Returns a `Mock` object which can be registered as a callback to test against.
+
+ If callback was not called within `timeout` seconds, it will raise a TimeoutError.
+ The returned Mock instance will have a `deferred` attribute which will complete when the callback has been called.
+ """
+
+ def reset():
+ if mock.called:
+ original_reset_mock()
+ deferred = Deferred()
+ deferred.addTimeout(0.5, reactor)
+ mock.side_effect = lambda *args, **kw: deferred.callback((args, kw))
+ mock.deferred = deferred
+
+ mock = unittest.mock.Mock()
+ original_reset_mock = mock.reset_mock
+ mock.reset_mock = reset
+ mock.reset_mock()
+ return mock
+
+
+@pytest.fixture
def config_dir(tmp_path):
deluge.configmanager.set_config_dir(tmp_path)
yield tmp_path
diff --git a/deluge/tests/test_config.py b/deluge/tests/test_config.py
index 8bf470dbc..2840dbf5b 100644
--- a/deluge/tests/test_config.py
+++ b/deluge/tests/test_config.py
@@ -10,6 +10,7 @@ import os
from codecs import getwriter
import pytest
+import pytest_twisted
from twisted.internet import task
from deluge.common import JSON_FORMAT
@@ -83,6 +84,33 @@ class TestConfig:
config._save_timer.cancel()
+ @pytest_twisted.ensureDeferred
+ async def test_on_changed_callback(self, mock_callback):
+ config = Config('test.conf', config_dir=self.config_dir)
+ config.register_change_callback(mock_callback)
+ config['foo'] = 1
+ assert config['foo'] == 1
+ await mock_callback.deferred
+ mock_callback.assert_called_once_with('foo', 1)
+
+ @pytest_twisted.ensureDeferred
+ async def test_key_function_callback(self, mock_callback):
+ config = Config(
+ 'test.conf', defaults={'foo': 1, 'bar': 1}, config_dir=self.config_dir
+ )
+
+ assert config['foo'] == 1
+ config.register_set_function('foo', mock_callback)
+ await mock_callback.deferred
+ mock_callback.assert_called_once_with('foo', 1)
+
+ mock_callback.reset_mock()
+ config.register_set_function('bar', mock_callback, apply_now=False)
+ mock_callback.assert_not_called()
+ config['bar'] = 2
+ await mock_callback.deferred
+ mock_callback.assert_called_once_with('bar', 2)
+
def test_get(self):
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = 1