[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
This commit is contained in:
DjLegolas 2022-02-11 12:40:47 +02:00 committed by Calum Lind
parent 374997a8d7
commit f8f997a6eb
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
3 changed files with 56 additions and 3 deletions

View File

@ -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

View File

@ -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
@ -31,6 +33,29 @@ def listen_port(request):
return DEFAULT_LISTEN_PORT
@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)

View File

@ -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