[Tests] Transition tests to pure pytest

Convert all the twisted.trial tests to pytest_twisted. Also move off of unittest.TestCase as well. Seems there were several tests which weren't actually testing what they should, and also some code that wasn't doing what the broken test said it should.

Goals:

    Remove twisted.trial tests
    Move to pytest fixtures, rather than many classess and subclasses with setup and teardown functions
    Move away from self.assertX to assert style tests
    FIx broken tests

Going forward I think these should be the goals when adding/modifying tests:

* Don't use BaseTest or set_up tear_down methods any more. Fixtures should be used either in the test module/class, or make/improve the ones available in conftest.py
* For sure don't use unittest or twisted.trial, they mess up the pytest stuff.
* Prefer pytest_twisted.ensureDeferred with an async function over inlineCallbacks.
  - I think the async function syntax is nicer, and it helps catch silly mistakes, e.g. await None is invalid, but yield None isn't, so if some function returns an unexpected thing we try to await on, it will be caught earlier. (I struggled debugging a test for quite a while, then caught it immediately when switching to the new syntax)
  - Once the maybe_coroutine PR goes in, using the async syntax can also improve tracebacks when debugging tests.

Things that should probably be cleaned up going forward:

* Remove BaseTestCase
* Remove the subclasses like DaemonBase in favor of new fixtures.
  * I think there are some other utility subclasses that could be removed too
* Perhaps use parameterization in the ui_entry tests, rather that the weird combination of subclasses and the set_var fixture I mixed in.
* Convert some of the callback stuff to pytest_twisted.ensureDeferred tests, just for nicer readability

Details relating to pytest fixtures conftest.py in root dir:
 * https://github.com/pytest-dev/pytest/issues/5822#issuecomment-697331920
 * https://docs.pytest.org/en/latest/deprecations.html#pytest-plugins-in-non-top-level-conftest-files

Closes: https://github.com/deluge-torrent/deluge/pull/354
This commit is contained in:
Chase Sterling 2022-01-29 14:59:19 -05:00 committed by Calum Lind
parent 0fbb3882f2
commit ece31cf3cf
No known key found for this signature in database
GPG Key ID: 90597A687B836BA3
43 changed files with 1144 additions and 1410 deletions

158
deluge/conftest.py Normal file
View File

@ -0,0 +1,158 @@
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import warnings
import pytest
import pytest_twisted
from twisted.internet.defer import maybeDeferred
from twisted.internet.error import CannotListenError
from twisted.python.failure import Failure
import deluge.component as _component
import deluge.configmanager
from deluge.common import get_localhost_auth
from deluge.tests import common
from deluge.ui.client import client as _client
DEFAULT_LISTEN_PORT = 58900
@pytest.fixture
def listen_port(request):
if request and 'daemon' in request.fixturenames:
try:
return request.getfixturevalue('daemon').listen_port
except Exception:
pass
return DEFAULT_LISTEN_PORT
@pytest.fixture
def config_dir(tmp_path):
deluge.configmanager.set_config_dir(tmp_path)
yield tmp_path
@pytest_twisted.async_yield_fixture()
async def client(request, config_dir, monkeypatch, listen_port):
# monkeypatch.setattr(
# _client, 'connect', functools.partial(_client.connect, port=listen_port)
# )
try:
username, password = get_localhost_auth()
except Exception:
username, password = '', ''
await _client.connect(
'localhost',
port=listen_port,
username=username,
password=password,
)
yield _client
if _client.connected():
await _client.disconnect()
@pytest_twisted.async_yield_fixture
async def daemon(request, config_dir):
listen_port = DEFAULT_LISTEN_PORT
logfile = f'daemon_{request.node.name}.log'
if hasattr(request.cls, 'daemon_custom_script'):
custom_script = request.cls.daemon_custom_script
else:
custom_script = ''
for dummy in range(10):
try:
d, daemon = common.start_core(
listen_port=listen_port,
logfile=logfile,
timeout=5,
timeout_msg='Timeout!',
custom_script=custom_script,
print_stdout=True,
print_stderr=True,
config_directory=config_dir,
)
await d
except CannotListenError as ex:
exception_error = ex
listen_port += 1
except (KeyboardInterrupt, SystemExit):
raise
else:
break
else:
raise exception_error
daemon.listen_port = listen_port
yield daemon
await daemon.kill()
@pytest.fixture(autouse=True)
def common_fixture(config_dir, request, monkeypatch, listen_port):
"""Adds some instance attributes to test classes for backwards compatibility with old testing."""
def fail(self, reason):
if isinstance(reason, Failure):
reason = reason.value
return pytest.fail(str(reason))
if request.instance:
request.instance.patch = monkeypatch.setattr
request.instance.config_dir = config_dir
request.instance.listen_port = listen_port
request.instance.id = lambda: request.node.name
request.cls.fail = fail
@pytest_twisted.async_yield_fixture(scope='function')
async def component(request):
"""Verify component registry is clean, and clean up after test."""
if len(_component._ComponentRegistry.components) != 0:
warnings.warn(
'The component._ComponentRegistry.components is not empty on test setup.\n'
'This is probably caused by another test that did not clean up after finishing!: %s'
% _component._ComponentRegistry.components
)
yield _component
await _component.shutdown()
_component._ComponentRegistry.components.clear()
_component._ComponentRegistry.dependents.clear()
@pytest_twisted.async_yield_fixture(scope='function')
async def base_fixture(common_fixture, component, request):
"""This fixture is autoused on all tests that subclass BaseTestCase"""
self = request.instance
if hasattr(self, 'set_up'):
try:
await maybeDeferred(self.set_up)
except Exception as exc:
warnings.warn('Error caught in test setup!\n%s' % exc)
pytest.fail('Error caught in test setup!\n%s' % exc)
yield
if hasattr(self, 'tear_down'):
try:
await maybeDeferred(self.tear_down)
except Exception as exc:
pytest.fail('Error caught in test teardown!\n%s' % exc)
@pytest.mark.usefixtures('base_fixture')
class BaseTestCase:
"""This is the base class that should be used for all test classes
that create classes that inherit from deluge.component.Component. It
ensures that the component registry has been cleaned up when tests
have finished.
"""

View File

@ -16,7 +16,7 @@ from twisted.internet.defer import Deferred
from twisted.python.failure import Failure
from twisted.web import client, http
from twisted.web._newclient import HTTPClientParser
from twisted.web.error import PageRedirect
from twisted.web.error import Error, PageRedirect
from twisted.web.http_headers import Headers
from twisted.web.iweb import IAgent
from zope.interface import implementer
@ -122,6 +122,9 @@ class HTTPDownloaderAgent:
location = response.headers.getRawHeaders(b'location')[0]
error = PageRedirect(response.code, location=location)
finished.errback(Failure(error))
elif response.code >= 400:
error = Error(response.code)
finished.errback(Failure(error))
else:
headers = response.headers
body_length = int(headers.getRawHeaders(b'content-length', default=[0])[0])

View File

@ -4,13 +4,12 @@
# See LICENSE for more details.
#
import pytest
import pytest_twisted
from twisted.internet import defer
from twisted.trial import unittest
import deluge.component as component
from deluge.common import fsize, fspeed
from deluge.tests import common as tests_common
from deluge.tests.basetest import BaseTestCase
from deluge.ui.client import client
@ -23,17 +22,17 @@ def print_totals(totals):
print('down:', fsize(totals['total_download'] - totals['total_payload_download']))
class StatsTestCase(BaseTestCase):
def set_up(self):
@pytest.mark.usefixtures('component')
class TestStatsPlugin:
@pytest_twisted.async_yield_fixture(autouse=True)
async def set_up(self):
defer.setDebugging(True)
tests_common.set_tmp_config_dir()
client.start_standalone()
client.core.enable_plugin('Stats')
return component.start()
def tear_down(self):
await component.start()
yield
client.stop_standalone()
return component.shutdown()
await component.shutdown()
@defer.inlineCallbacks
def test_client_totals(self):
@ -42,10 +41,10 @@ class StatsTestCase(BaseTestCase):
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_totals()
self.assertEqual(totals['total_upload'], 0)
self.assertEqual(totals['total_payload_upload'], 0)
self.assertEqual(totals['total_payload_download'], 0)
self.assertEqual(totals['total_download'], 0)
assert totals['total_upload'] == 0
assert totals['total_payload_upload'] == 0
assert totals['total_payload_download'] == 0
assert totals['total_download'] == 0
# print_totals(totals)
@defer.inlineCallbacks
@ -55,10 +54,10 @@ class StatsTestCase(BaseTestCase):
raise unittest.SkipTest('WebUi plugin not available for testing')
totals = yield client.stats.get_session_totals()
self.assertEqual(totals['total_upload'], 0)
self.assertEqual(totals['total_payload_upload'], 0)
self.assertEqual(totals['total_payload_download'], 0)
self.assertEqual(totals['total_download'], 0)
assert totals['total_upload'] == 0
assert totals['total_payload_upload'] == 0
assert totals['total_payload_download'] == 0
assert totals['total_download'] == 0
# print_totals(totals)
@pytest.mark.gtkui

View File

@ -5,31 +5,34 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import pytest
import pytest_twisted
from twisted.trial import unittest
import deluge.component as component
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.tests import common
from deluge.tests.basetest import BaseTestCase
common.disable_new_release_check()
class WebUIPluginTestCase(BaseTestCase):
def set_up(self):
common.set_tmp_config_dir()
@pytest.mark.usefixtures('component')
class TestWebUIPlugin:
@pytest_twisted.async_yield_fixture(autouse=True)
async def set_up(self, request):
self = request.instance
self.rpcserver = RPCServer(listen=False)
self.core = Core()
return component.start()
await component.start()
yield
def tear_down(self):
def on_shutdown(result):
del self.rpcserver
del self.core
return component.shutdown().addCallback(on_shutdown)
await component.shutdown().addCallback(on_shutdown)
def test_enable_webui(self):
if 'WebUi' not in self.core.get_available_plugins():
@ -40,7 +43,7 @@ class WebUIPluginTestCase(BaseTestCase):
def result_cb(result):
if 'WebUi' not in self.core.get_enabled_plugins():
self.fail('Failed to enable WebUi plugin')
self.assertTrue(result)
assert result
d.addBoth(result_cb)
return d

View File

@ -1,55 +0,0 @@
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import warnings
from twisted.internet.defer import maybeDeferred
from twisted.trial import unittest
import deluge.component as component
class BaseTestCase(unittest.TestCase):
"""This is the base class that should be used for all test classes
that create classes that inherit from deluge.component.Component. It
ensures that the component registry has been cleaned up when tests
have finished.
"""
def setUp(self): # NOQA: N803
if len(component._ComponentRegistry.components) != 0:
warnings.warn(
'The component._ComponentRegistry.components is not empty on test setup.\n'
'This is probably caused by another test that did not clean up after finishing!: %s'
% component._ComponentRegistry.components
)
d = maybeDeferred(self.set_up)
def on_setup_error(error):
warnings.warn('Error caught in test setup!\n%s' % error.getTraceback())
self.fail()
return d.addErrback(on_setup_error)
def tearDown(self): # NOQA: N803
d = maybeDeferred(self.tear_down)
def on_teardown_failed(error):
self.fail('Error caught in test teardown!\n%s' % error.getTraceback())
def on_teardown_complete(result):
component._ComponentRegistry.components.clear()
component._ComponentRegistry.dependents.clear()
return d.addCallbacks(on_teardown_complete, on_teardown_failed)
def set_up(self):
pass
def tear_down(self):
pass

View File

@ -8,13 +8,12 @@
import os
import sys
import tempfile
import traceback
import pytest
from twisted.internet import defer, protocol, reactor
from twisted.internet.defer import Deferred
from twisted.internet.error import CannotListenError
from twisted.trial import unittest
import deluge.configmanager
import deluge.core.preferencesmanager
@ -31,12 +30,6 @@ def disable_new_release_check():
deluge.core.preferencesmanager.DEFAULT_PREFS['new_release_check'] = False
def set_tmp_config_dir():
config_directory = tempfile.mkdtemp()
deluge.configmanager.set_config_dir(config_directory)
return config_directory
def setup_test_logger(level='info', prefix='deluge'):
deluge.log.setup_logger(level, filename='%s.log' % prefix, twisted_observer=False)
@ -54,7 +47,7 @@ def todo_test(caller):
filename = os.path.basename(traceback.extract_stack(None, 2)[0][0])
funcname = traceback.extract_stack(None, 2)[0][2]
raise unittest.SkipTest(f'TODO: {filename}:{funcname}')
pytest.skip(f'TODO: {filename}:{funcname}')
def add_watchdog(deferred, timeout=0.05, message=None):
@ -219,7 +212,7 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
def start_core(
listen_port=58846,
listen_port=58900,
logfile=None,
timeout=10,
timeout_msg=None,
@ -227,6 +220,7 @@ def start_core(
print_stdout=True,
print_stderr=True,
extra_callbacks=None,
config_directory='',
):
"""Start the deluge core as a daemon.
@ -248,7 +242,6 @@ def start_core(
or upon timeout expiry. The ProcessOutputHandler is the handler for the deluged process.
"""
config_directory = set_tmp_config_dir()
daemon_script = """
import sys
import deluge.core.daemon_entry
@ -268,7 +261,7 @@ except Exception:
import traceback
sys.stderr.write('Exception raised:\\n %%s' %% traceback.format_exc())
""" % {
'dir': config_directory.replace('\\', '\\\\'),
'dir': config_directory.as_posix(),
'port': listen_port,
'script': custom_script,
}

View File

@ -6,19 +6,20 @@
# See LICENSE for more details.
#
import pytest
import deluge.common
import deluge.component as component
import deluge.ui.web.auth
import deluge.ui.web.server
from deluge import configmanager
from deluge.conftest import BaseTestCase
from deluge.ui.web.server import DelugeWeb
from .basetest import BaseTestCase
from .common import ReactorOverride
from .daemon_base import DaemonBase
class WebServerTestBase(BaseTestCase, DaemonBase):
@pytest.mark.usefixtures('daemon', 'component')
class WebServerTestBase(BaseTestCase):
"""
Base class for tests that need a running webapi
@ -27,10 +28,7 @@ class WebServerTestBase(BaseTestCase, DaemonBase):
def set_up(self):
self.host_id = None
deluge.ui.web.server.reactor = ReactorOverride()
d = self.common_set_up()
d.addCallback(self.start_core)
d.addCallback(self.start_webapi)
return d
return self.start_webapi(None)
def start_webapi(self, arg):
self.webserver_listen_port = 8999
@ -47,11 +45,6 @@ class WebServerTestBase(BaseTestCase, DaemonBase):
self.host_id = host[0]
self.deluge_web.start()
def tear_down(self):
d = component.shutdown()
d.addCallback(self.terminate_core)
return d
class WebServerMockBase:
"""

View File

@ -15,16 +15,9 @@ import deluge.component as component
from . import common
@pytest.mark.usefixtures('get_pytest_basetemp')
@pytest.mark.usefixtures('config_dir')
class DaemonBase:
basetemp = None
@pytest.fixture
def get_pytest_basetemp(self, request):
self.basetemp = request.config.option.basetemp
def common_set_up(self):
common.set_tmp_config_dir()
self.listen_port = 58900
self.core = None
return component.start()
@ -71,6 +64,7 @@ class DaemonBase:
print_stdout=print_stdout,
print_stderr=print_stderr,
extra_callbacks=extra_callbacks,
config_directory=self.config_dir,
)
yield d
except CannotListenError as ex:

View File

@ -5,12 +5,11 @@
#
import deluge.component as component
from deluge.conftest import BaseTestCase
from deluge.core.core import Core
from .basetest import BaseTestCase
class AlertManagerTestCase(BaseTestCase):
class TestAlertManager(BaseTestCase):
def set_up(self):
self.core = Core()
self.core.config.config['lsd'] = False
@ -25,7 +24,7 @@ class AlertManagerTestCase(BaseTestCase):
return
self.am.register_handler('dummy_alert', handler)
self.assertEqual(self.am.handlers['dummy_alert'], [handler])
assert self.am.handlers['dummy_alert'] == [handler]
def test_deregister_handler(self):
def handler(alert):
@ -33,4 +32,4 @@ class AlertManagerTestCase(BaseTestCase):
self.am.register_handler('dummy_alert', handler)
self.am.deregister_handler(handler)
self.assertEqual(self.am.handlers['dummy_alert'], [])
assert self.am.handlers['dummy_alert'] == []

View File

@ -6,12 +6,11 @@
import deluge.component as component
from deluge.common import get_localhost_auth
from deluge.conftest import BaseTestCase
from deluge.core.authmanager import AUTH_LEVEL_ADMIN, AuthManager
from .basetest import BaseTestCase
class AuthManagerTestCase(BaseTestCase):
class TestAuthManager(BaseTestCase):
def set_up(self):
self.auth = AuthManager()
self.auth.start()
@ -21,4 +20,4 @@ class AuthManagerTestCase(BaseTestCase):
return component.shutdown()
def test_authorize(self):
self.assertEqual(self.auth.authorize(*get_localhost_auth()), AUTH_LEVEL_ADMIN)
assert self.auth.authorize(*get_localhost_auth()) == AUTH_LEVEL_ADMIN

View File

@ -3,14 +3,15 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
from twisted.trial import unittest
import pytest
from deluge import bencode
from . import common
class BencodeTestCase(unittest.TestCase):
class TestBencode:
def test_bencode_unicode_metainfo(self):
filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file:
@ -18,14 +19,14 @@ class BencodeTestCase(unittest.TestCase):
bencode.bencode({b'info': metainfo})
def test_bencode_unicode_value(self):
self.assertEqual(bencode.bencode(b'abc'), b'3:abc')
self.assertEqual(bencode.bencode('abc'), b'3:abc')
assert bencode.bencode(b'abc') == b'3:abc'
assert bencode.bencode('abc') == b'3:abc'
def test_bdecode(self):
self.assertEqual(bencode.bdecode(b'3:dEf'), b'dEf')
with self.assertRaises(bencode.BTFailure):
assert bencode.bdecode(b'3:dEf') == b'dEf'
with pytest.raises(bencode.BTFailure):
bencode.bdecode('dEf')
with self.assertRaises(bencode.BTFailure):
with pytest.raises(bencode.BTFailure):
bencode.bdecode(b'dEf')
with self.assertRaises(bencode.BTFailure):
with pytest.raises(bencode.BTFailure):
bencode.bdecode({'dEf': 123})

View File

@ -3,18 +3,15 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import pytest
import pytest_twisted
from twisted.internet import defer
import deluge.component as component
from deluge import error
from deluge.common import AUTH_LEVEL_NORMAL, get_localhost_auth
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.ui.client import Client, DaemonSSLProxy, client
from .basetest import BaseTestCase
from .daemon_base import DaemonBase
class NoVersionSendingDaemonSSLProxy(DaemonSSLProxy):
def authenticate(self, username, password):
@ -75,24 +72,13 @@ class NoVersionSendingClient(Client):
self.disconnect_callback()
class ClientTestCase(BaseTestCase, DaemonBase):
def set_up(self):
d = self.common_set_up()
d.addCallback(self.start_core)
d.addErrback(self.terminate_core)
return d
def tear_down(self):
d = component.shutdown()
d.addCallback(self.terminate_core)
return d
@pytest.mark.usefixtures('daemon', 'client')
class TestClient:
def test_connect_no_credentials(self):
d = client.connect('localhost', self.listen_port, username='', password='')
def on_connect(result):
self.assertEqual(client.get_auth_level(), AUTH_LEVEL_ADMIN)
self.addCleanup(client.disconnect)
assert client.get_auth_level() == AUTH_LEVEL_ADMIN
return result
d.addCallbacks(on_connect, self.fail)
@ -105,8 +91,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
)
def on_connect(result):
self.assertEqual(client.get_auth_level(), AUTH_LEVEL_ADMIN)
self.addCleanup(client.disconnect)
assert client.get_auth_level() == AUTH_LEVEL_ADMIN
return result
d.addCallbacks(on_connect, self.fail)
@ -119,21 +104,18 @@ class ClientTestCase(BaseTestCase, DaemonBase):
)
def on_failure(failure):
self.assertEqual(failure.trap(error.BadLoginError), error.BadLoginError)
self.assertEqual(failure.value.message, 'Password does not match')
self.addCleanup(client.disconnect)
assert failure.trap(error.BadLoginError) == error.BadLoginError
assert failure.value.message == 'Password does not match'
d.addCallbacks(self.fail, on_failure)
return d
def test_connect_invalid_user(self):
username, password = get_localhost_auth()
d = client.connect('localhost', self.listen_port, username='invalid-user')
def on_failure(failure):
self.assertEqual(failure.trap(error.BadLoginError), error.BadLoginError)
self.assertEqual(failure.value.message, 'Username does not exist')
self.addCleanup(client.disconnect)
assert failure.trap(error.BadLoginError) == error.BadLoginError
assert failure.value.message == 'Username does not exist'
d.addCallbacks(self.fail, on_failure)
return d
@ -143,16 +125,16 @@ class ClientTestCase(BaseTestCase, DaemonBase):
d = client.connect('localhost', self.listen_port, username=username)
def on_failure(failure):
self.assertEqual(
failure.trap(error.AuthenticationRequired), error.AuthenticationRequired
assert (
failure.trap(error.AuthenticationRequired)
== error.AuthenticationRequired
)
self.assertEqual(failure.value.username, username)
self.addCleanup(client.disconnect)
assert failure.value.username == username
d.addCallbacks(self.fail, on_failure)
return d
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_connect_with_password(self):
username, password = get_localhost_auth()
yield client.connect(
@ -163,19 +145,15 @@ class ClientTestCase(BaseTestCase, DaemonBase):
ret = yield client.connect(
'localhost', self.listen_port, username='testuser', password='testpw'
)
self.assertEqual(ret, AUTH_LEVEL_NORMAL)
yield
assert ret == AUTH_LEVEL_NORMAL
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_invalid_rpc_method_call(self):
yield client.connect('localhost', self.listen_port, username='', password='')
d = client.core.invalid_method()
def on_failure(failure):
self.assertEqual(
failure.trap(error.WrappedException), error.WrappedException
)
self.addCleanup(client.disconnect)
assert failure.trap(error.WrappedException) == error.WrappedException
d.addCallbacks(self.fail, on_failure)
yield d
@ -188,10 +166,7 @@ class ClientTestCase(BaseTestCase, DaemonBase):
)
def on_failure(failure):
self.assertEqual(
failure.trap(error.IncompatibleClient), error.IncompatibleClient
)
self.addCleanup(no_version_sending_client.disconnect)
assert failure.trap(error.IncompatibleClient) == error.IncompatibleClient
d.addCallbacks(self.fail, on_failure)
return d

View File

@ -8,7 +8,7 @@ import os
import sys
import tarfile
from twisted.trial import unittest
import pytest
from deluge.common import (
VersionSplit,
@ -30,93 +30,83 @@ from deluge.common import (
is_url,
windows_check,
)
from deluge.i18n import setup_translation
from .common import get_test_data_file, set_tmp_config_dir
from .common import get_test_data_file
class CommonTestCase(unittest.TestCase):
def setUp(self): # NOQA
self.config_dir = set_tmp_config_dir()
setup_translation()
def tearDown(self): # NOQA
pass
class TestCommon:
def test_fsize(self):
self.assertEqual(fsize(0), '0 B')
self.assertEqual(fsize(100), '100 B')
self.assertEqual(fsize(1023), '1023 B')
self.assertEqual(fsize(1024), '1.0 KiB')
self.assertEqual(fsize(1048575), '1024.0 KiB')
self.assertEqual(fsize(1048576), '1.0 MiB')
self.assertEqual(fsize(1073741823), '1024.0 MiB')
self.assertEqual(fsize(1073741824), '1.0 GiB')
self.assertEqual(fsize(112245), '109.6 KiB')
self.assertEqual(fsize(110723441824), '103.1 GiB')
self.assertEqual(fsize(1099511627775), '1024.0 GiB')
self.assertEqual(fsize(1099511627777), '1.0 TiB')
self.assertEqual(fsize(766148267453245), '696.8 TiB')
assert fsize(0) == '0 B'
assert fsize(100) == '100 B'
assert fsize(1023) == '1023 B'
assert fsize(1024) == '1.0 KiB'
assert fsize(1048575) == '1024.0 KiB'
assert fsize(1048576) == '1.0 MiB'
assert fsize(1073741823) == '1024.0 MiB'
assert fsize(1073741824) == '1.0 GiB'
assert fsize(112245) == '109.6 KiB'
assert fsize(110723441824) == '103.1 GiB'
assert fsize(1099511627775) == '1024.0 GiB'
assert fsize(1099511627777) == '1.0 TiB'
assert fsize(766148267453245) == '696.8 TiB'
def test_fpcnt(self):
self.assertTrue(fpcnt(0.9311) == '93.11%')
assert fpcnt(0.9311) == '93.11%'
def test_fspeed(self):
self.assertTrue(fspeed(43134) == '42.1 KiB/s')
assert fspeed(43134) == '42.1 KiB/s'
def test_fpeer(self):
self.assertTrue(fpeer(10, 20) == '10 (20)')
self.assertTrue(fpeer(10, -1) == '10')
assert fpeer(10, 20) == '10 (20)'
assert fpeer(10, -1) == '10'
def test_ftime(self):
self.assertEqual(ftime(0), '')
self.assertEqual(ftime(5), '5s')
self.assertEqual(ftime(100), '1m 40s')
self.assertEqual(ftime(3789), '1h 3m')
self.assertEqual(ftime(23011), '6h 23m')
self.assertEqual(ftime(391187), '4d 12h')
self.assertEqual(ftime(604800), '1w 0d')
self.assertEqual(ftime(13893086), '22w 6d')
self.assertEqual(ftime(59740269), '1y 46w')
self.assertEqual(ftime(61.25), '1m 1s')
self.assertEqual(ftime(119.9), '1m 59s')
assert ftime(0) == ''
assert ftime(5) == '5s'
assert ftime(100) == '1m 40s'
assert ftime(3789) == '1h 3m'
assert ftime(23011) == '6h 23m'
assert ftime(391187) == '4d 12h'
assert ftime(604800) == '1w 0d'
assert ftime(13893086) == '22w 6d'
assert ftime(59740269) == '1y 46w'
assert ftime(61.25) == '1m 1s'
assert ftime(119.9) == '1m 59s'
def test_fdate(self):
self.assertTrue(fdate(-1) == '')
assert fdate(-1) == ''
def test_is_url(self):
self.assertTrue(is_url('http://deluge-torrent.org'))
self.assertFalse(is_url('file://test.torrent'))
assert is_url('http://deluge-torrent.org')
assert not is_url('file://test.torrent')
def test_is_magnet(self):
self.assertTrue(
is_magnet('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN')
)
self.assertFalse(is_magnet(None))
assert is_magnet('magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN')
assert not is_magnet(None)
def test_is_infohash(self):
self.assertTrue(is_infohash('2dc5d0e71a66fe69649a640d39cb00a259704973'))
assert is_infohash('2dc5d0e71a66fe69649a640d39cb00a259704973')
def test_get_path_size(self):
if windows_check() and sys.version_info < (3, 8):
# https://bugs.python.org/issue1311
raise unittest.SkipTest('os.devnull returns False on Windows')
self.assertTrue(get_path_size(os.devnull) == 0)
self.assertTrue(get_path_size('non-existant.file') == -1)
pytest.skip('os.devnull returns False on Windows')
assert get_path_size(os.devnull) == 0
assert get_path_size('non-existant.file') == -1
def test_is_ip(self):
self.assertTrue(is_ip('192.0.2.0'))
self.assertFalse(is_ip('192..0.0'))
self.assertTrue(is_ip('2001:db8::'))
self.assertFalse(is_ip('2001:db8:'))
assert is_ip('192.0.2.0')
assert not is_ip('192..0.0')
assert is_ip('2001:db8::')
assert not is_ip('2001:db8:')
def test_is_ipv4(self):
self.assertTrue(is_ipv4('192.0.2.0'))
self.assertFalse(is_ipv4('192..0.0'))
assert is_ipv4('192.0.2.0')
assert not is_ipv4('192..0.0')
def test_is_ipv6(self):
self.assertTrue(is_ipv6('2001:db8::'))
self.assertFalse(is_ipv6('2001:db8:'))
assert is_ipv6('2001:db8::')
assert not is_ipv6('2001:db8:')
def get_windows_interface_name(self):
import winreg
@ -126,9 +116,7 @@ class CommonTestCase(unittest.TestCase):
winreg.HKEY_LOCAL_MACHINE,
r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards',
) as key:
self.assertTrue(
winreg.QueryInfoKey(key)[0] > 0
) # must have at least 1 network card
assert winreg.QueryInfoKey(key)[0] > 0 # must have at least 1 network card
network_card = winreg.EnumKey(key, 0)
# get GUID of network card
with winreg.OpenKey(
@ -144,48 +132,46 @@ class CommonTestCase(unittest.TestCase):
def test_is_interface_name(self):
if windows_check():
interface_name = self.get_windows_interface_name()
self.assertFalse(is_interface_name('2001:db8:'))
self.assertFalse(
is_interface_name('{THIS0000-IS00-ONLY-FOR0-TESTING00000}')
)
self.assertTrue(is_interface_name(interface_name))
assert not is_interface_name('2001:db8:')
assert not is_interface_name('{THIS0000-IS00-ONLY-FOR0-TESTING00000}')
assert is_interface_name(interface_name)
else:
self.assertTrue(is_interface_name('lo'))
self.assertFalse(is_interface_name('127.0.0.1'))
self.assertFalse(is_interface_name('eth01101'))
assert is_interface_name('lo')
assert not is_interface_name('127.0.0.1')
assert not is_interface_name('eth01101')
def test_is_interface(self):
if windows_check():
interface_name = self.get_windows_interface_name()
self.assertTrue(is_interface('127.0.0.1'))
self.assertTrue(is_interface(interface_name))
self.assertFalse(is_interface('127'))
self.assertFalse(is_interface('{THIS0000-IS00-ONLY-FOR0-TESTING00000}'))
assert is_interface('127.0.0.1')
assert is_interface(interface_name)
assert not is_interface('127')
assert not is_interface('{THIS0000-IS00-ONLY-FOR0-TESTING00000}')
else:
self.assertTrue(is_interface('lo'))
self.assertTrue(is_interface('127.0.0.1'))
self.assertFalse(is_interface('127.'))
self.assertFalse(is_interface('eth01101'))
assert is_interface('lo')
assert is_interface('127.0.0.1')
assert not is_interface('127.')
assert not is_interface('eth01101')
def test_version_split(self):
self.assertTrue(VersionSplit('1.2.2') == VersionSplit('1.2.2'))
self.assertTrue(VersionSplit('1.2.1') < VersionSplit('1.2.2'))
self.assertTrue(VersionSplit('1.1.9') < VersionSplit('1.2.2'))
self.assertTrue(VersionSplit('1.2.2') > VersionSplit('1.2.1'))
self.assertTrue(VersionSplit('1.2.2') > VersionSplit('1.2.2-dev0'))
self.assertTrue(VersionSplit('1.2.2-dev') < VersionSplit('1.3.0-rc2'))
self.assertTrue(VersionSplit('1.2.2') > VersionSplit('1.2.2-rc2'))
self.assertTrue(VersionSplit('1.2.2-rc2-dev') < VersionSplit('1.2.2-rc2'))
self.assertTrue(VersionSplit('1.2.2-rc3') > VersionSplit('1.2.2-rc2'))
self.assertTrue(VersionSplit('0.14.9') == VersionSplit('0.14.9'))
self.assertTrue(VersionSplit('0.14.9') > VersionSplit('0.14.5'))
self.assertTrue(VersionSplit('0.14.10') >= VersionSplit('0.14.9'))
self.assertTrue(VersionSplit('1.4.0') > VersionSplit('1.3.900.dev123'))
self.assertTrue(VersionSplit('1.3.2rc2.dev1') < VersionSplit('1.3.2-rc2'))
self.assertTrue(VersionSplit('1.3.900.dev888') > VersionSplit('1.3.900.dev123'))
self.assertTrue(VersionSplit('1.4.0') > VersionSplit('1.4.0.dev123'))
self.assertTrue(VersionSplit('1.4.0.dev1') < VersionSplit('1.4.0'))
self.assertTrue(VersionSplit('1.4.0a1') < VersionSplit('1.4.0'))
assert VersionSplit('1.2.2') == VersionSplit('1.2.2')
assert VersionSplit('1.2.1') < VersionSplit('1.2.2')
assert VersionSplit('1.1.9') < VersionSplit('1.2.2')
assert VersionSplit('1.2.2') > VersionSplit('1.2.1')
assert VersionSplit('1.2.2') > VersionSplit('1.2.2-dev0')
assert VersionSplit('1.2.2-dev') < VersionSplit('1.3.0-rc2')
assert VersionSplit('1.2.2') > VersionSplit('1.2.2-rc2')
assert VersionSplit('1.2.2-rc2-dev') < VersionSplit('1.2.2-rc2')
assert VersionSplit('1.2.2-rc3') > VersionSplit('1.2.2-rc2')
assert VersionSplit('0.14.9') == VersionSplit('0.14.9')
assert VersionSplit('0.14.9') > VersionSplit('0.14.5')
assert VersionSplit('0.14.10') >= VersionSplit('0.14.9')
assert VersionSplit('1.4.0') > VersionSplit('1.3.900.dev123')
assert VersionSplit('1.3.2rc2.dev1') < VersionSplit('1.3.2-rc2')
assert VersionSplit('1.3.900.dev888') > VersionSplit('1.3.900.dev123')
assert VersionSplit('1.4.0') > VersionSplit('1.4.0.dev123')
assert VersionSplit('1.4.0.dev1') < VersionSplit('1.4.0')
assert VersionSplit('1.4.0a1') < VersionSplit('1.4.0')
def test_parse_human_size(self):
from deluge.common import parse_human_size
@ -206,9 +192,7 @@ class CommonTestCase(unittest.TestCase):
for human_size, byte_size in sizes:
parsed = parse_human_size(human_size)
self.assertEqual(
parsed, byte_size, 'Mismatch when converting: %s' % human_size
)
assert parsed == byte_size, 'Mismatch when converting: %s' % human_size
def test_archive_files(self):
arc_filelist = [
@ -219,10 +203,10 @@ class CommonTestCase(unittest.TestCase):
with tarfile.open(arc_filepath, 'r') as tar:
for tar_info in tar:
self.assertTrue(tar_info.isfile())
self.assertTrue(
tar_info.name in [os.path.basename(arcf) for arcf in arc_filelist]
)
assert tar_info.isfile()
assert tar_info.name in [
os.path.basename(arcf) for arcf in arc_filelist
]
def test_archive_files_missing(self):
"""Archive exists even with file not found."""
@ -233,8 +217,8 @@ class CommonTestCase(unittest.TestCase):
filelist.remove('missing.file')
with tarfile.open(arc_filepath, 'r') as tar:
self.assertEqual(tar.getnames(), filelist)
self.assertTrue(all(tarinfo.isfile() for tarinfo in tar))
assert tar.getnames() == filelist
assert all(tarinfo.isfile() for tarinfo in tar)
def test_archive_files_message(self):
filelist = ['test.torrent', 'deluge.png']
@ -244,9 +228,9 @@ class CommonTestCase(unittest.TestCase):
result_files = filelist + ['archive_message.txt']
with tarfile.open(arc_filepath, 'r') as tar:
self.assertEqual(tar.getnames(), result_files)
assert tar.getnames() == result_files
for tar_info in tar:
self.assertTrue(tar_info.isfile())
assert tar_info.isfile()
if tar_info.name == 'archive_message.txt':
result = tar.extractfile(tar_info).read().decode()
self.assertEqual(result, 'test')
assert result == 'test'

View File

@ -4,13 +4,12 @@
# See LICENSE for more details.
#
import pytest
import pytest_twisted
from twisted.internet import defer, threads
from twisted.trial.unittest import SkipTest
import deluge.component as component
from .basetest import BaseTestCase
class ComponentTester(component.Component):
def __init__(self, name, depend=None):
@ -67,14 +66,15 @@ class ComponentTesterShutdown(component.Component):
self.stop_count += 1
class ComponentTestClass(BaseTestCase):
@pytest.mark.usefixtures('component')
class TestComponent:
def tear_down(self):
return component.shutdown()
def test_start_component(self):
def on_start(result, c):
self.assertEqual(c._component_state, 'Started')
self.assertEqual(c.start_count, 1)
assert c._component_state == 'Started'
assert c.start_count == 1
c = ComponentTester('test_start_c1')
d = component.start(['test_start_c1'])
@ -83,16 +83,16 @@ class ComponentTestClass(BaseTestCase):
def test_start_stop_depends(self):
def on_stop(result, c1, c2):
self.assertEqual(c1._component_state, 'Stopped')
self.assertEqual(c2._component_state, 'Stopped')
self.assertEqual(c1.stop_count, 1)
self.assertEqual(c2.stop_count, 1)
assert c1._component_state == 'Stopped'
assert c2._component_state == 'Stopped'
assert c1.stop_count == 1
assert c2.stop_count == 1
def on_start(result, c1, c2):
self.assertEqual(c1._component_state, 'Started')
self.assertEqual(c2._component_state, 'Started')
self.assertEqual(c1.start_count, 1)
self.assertEqual(c2.start_count, 1)
assert c1._component_state == 'Started'
assert c2._component_state == 'Started'
assert c1.start_count == 1
assert c2.start_count == 1
return component.stop(['test_start_depends_c1']).addCallback(
on_stop, c1, c2
)
@ -123,8 +123,8 @@ class ComponentTestClass(BaseTestCase):
def test_start_all(self):
def on_start(*args):
for c in args[1:]:
self.assertEqual(c._component_state, 'Started')
self.assertEqual(c.start_count, 1)
assert c._component_state == 'Started'
assert c.start_count == 1
ret = self.start_with_depends()
ret[0].addCallback(on_start, *ret[1:])
@ -133,20 +133,19 @@ class ComponentTestClass(BaseTestCase):
def test_register_exception(self):
ComponentTester('test_register_exception_c1')
self.assertRaises(
component.ComponentAlreadyRegistered,
ComponentTester,
'test_register_exception_c1',
)
with pytest.raises(component.ComponentAlreadyRegistered):
ComponentTester(
'test_register_exception_c1',
)
def test_stop_component(self):
def on_stop(result, c):
self.assertEqual(c._component_state, 'Stopped')
self.assertFalse(c._component_timer.running)
self.assertEqual(c.stop_count, 1)
assert c._component_state == 'Stopped'
assert not c._component_timer.running
assert c.stop_count == 1
def on_start(result, c):
self.assertEqual(c._component_state, 'Started')
assert c._component_state == 'Started'
return component.stop(['test_stop_component_c1']).addCallback(on_stop, c)
c = ComponentTesterUpdate('test_stop_component_c1')
@ -157,12 +156,12 @@ class ComponentTestClass(BaseTestCase):
def test_stop_all(self):
def on_stop(result, *args):
for c in args:
self.assertEqual(c._component_state, 'Stopped')
self.assertEqual(c.stop_count, 1)
assert c._component_state == 'Stopped'
assert c.stop_count == 1
def on_start(result, *args):
for c in args:
self.assertEqual(c._component_state, 'Started')
assert c._component_state == 'Started'
return component.stop().addCallback(on_stop, *args)
ret = self.start_with_depends()
@ -172,9 +171,9 @@ class ComponentTestClass(BaseTestCase):
def test_update(self):
def on_start(result, c1, counter):
self.assertTrue(c1._component_timer)
self.assertTrue(c1._component_timer.running)
self.assertNotEqual(c1.counter, counter)
assert c1._component_timer
assert c1._component_timer.running
assert c1.counter != counter
return component.stop()
c1 = ComponentTesterUpdate('test_update_c1')
@ -186,13 +185,13 @@ class ComponentTestClass(BaseTestCase):
def test_pause(self):
def on_pause(result, c1, counter):
self.assertEqual(c1._component_state, 'Paused')
self.assertNotEqual(c1.counter, counter)
self.assertFalse(c1._component_timer.running)
assert c1._component_state == 'Paused'
assert c1.counter != counter
assert not c1._component_timer.running
def on_start(result, c1, counter):
self.assertTrue(c1._component_timer)
self.assertNotEqual(c1.counter, counter)
assert c1._component_timer
assert c1.counter != counter
d = component.pause(['test_pause_c1'])
d.addCallback(on_pause, c1, counter)
return d
@ -204,23 +203,16 @@ class ComponentTestClass(BaseTestCase):
d.addCallback(on_start, c1, cnt)
return d
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_component_start_error(self):
ComponentTesterUpdate('test_pause_c1')
yield component.start(['test_pause_c1'])
yield component.pause(['test_pause_c1'])
test_comp = component.get('test_pause_c1')
try:
result = self.failureResultOf(test_comp._component_start())
except AttributeError:
raise SkipTest(
'This test requires trial failureResultOf() in Twisted version >= 13'
)
self.assertEqual(
result.check(component.ComponentException), component.ComponentException
)
with pytest.raises(component.ComponentException, match='Current state: Paused'):
yield test_comp._component_start()
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_start_paused_error(self):
ComponentTesterUpdate('test_pause_c1')
yield component.start(['test_pause_c1'])
@ -229,29 +221,26 @@ class ComponentTestClass(BaseTestCase):
# Deferreds that fail in component have to error handler which results in
# twisted doing a log.err call which causes the test to fail.
# Prevent failure by ignoring the exception
self._observer._ignoreErrors(component.ComponentException)
# self._observer._ignoreErrors(component.ComponentException)
result = yield component.start()
self.assertEqual(
[(result[0][0], result[0][1].value)],
[
(
defer.FAILURE,
component.ComponentException(
'Trying to start component "%s" but it is '
'not in a stopped state. Current state: %s'
% ('test_pause_c1', 'Paused'),
'',
),
)
],
)
assert [(result[0][0], result[0][1].value)] == [
(
defer.FAILURE,
component.ComponentException(
'Trying to start component "%s" but it is '
'not in a stopped state. Current state: %s'
% ('test_pause_c1', 'Paused'),
'',
),
)
]
def test_shutdown(self):
def on_shutdown(result, c1):
self.assertTrue(c1.shutdowned)
self.assertEqual(c1._component_state, 'Stopped')
self.assertEqual(c1.stop_count, 1)
assert c1.shutdowned
assert c1._component_state == 'Stopped'
assert c1.stop_count == 1
def on_start(result, c1):
d = component.shutdown()

View File

@ -7,15 +7,13 @@
import os
from codecs import getwriter
import pytest
from twisted.internet import task
from twisted.trial import unittest
import deluge.config
from deluge.common import JSON_FORMAT
from deluge.config import Config
from .common import set_tmp_config_dir
DEFAULTS = {
'string': 'foobar',
'int': 1,
@ -26,34 +24,32 @@ DEFAULTS = {
}
class ConfigTestCase(unittest.TestCase):
def setUp(self): # NOQA: N803
self.config_dir = set_tmp_config_dir()
class TestConfig:
def test_init(self):
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEqual(DEFAULTS, config.config)
assert DEFAULTS == config.config
config = Config('test.conf', config_dir=self.config_dir)
self.assertEqual({}, config.config)
assert {} == config.config
def test_set_get_item(self):
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = 1
self.assertEqual(config['foo'], 1)
self.assertRaises(ValueError, config.set_item, 'foo', 'bar')
assert config['foo'] == 1
with pytest.raises(ValueError):
config.set_item('foo', 'bar')
config['foo'] = 2
self.assertEqual(config.get_item('foo'), 2)
assert config.get_item('foo') == 2
config['foo'] = '3'
self.assertEqual(config.get_item('foo'), 3)
assert config.get_item('foo') == 3
config['unicode'] = 'ВИДЕОФИЛЬМЫ'
self.assertEqual(config['unicode'], 'ВИДЕОФИЛЬМЫ')
assert config['unicode'] == 'ВИДЕОФИЛЬМЫ'
config['unicode'] = b'foostring'
self.assertFalse(isinstance(config.get_item('unicode'), bytes))
assert not isinstance(config.get_item('unicode'), bytes)
config._save_timer.cancel()
@ -61,39 +57,39 @@ class ConfigTestCase(unittest.TestCase):
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = None
self.assertIsNone(config['foo'])
self.assertIsInstance(config['foo'], type(None))
assert config['foo'] is None
assert isinstance(config['foo'], type(None))
config['foo'] = 1
self.assertEqual(config.get('foo'), 1)
assert config.get('foo') == 1
config['foo'] = None
self.assertIsNone(config['foo'])
assert config['foo'] is None
config['bar'] = None
self.assertIsNone(config['bar'])
assert config['bar'] is None
config['bar'] = None
self.assertIsNone(config['bar'])
assert config['bar'] is None
config._save_timer.cancel()
def test_get(self):
config = Config('test.conf', config_dir=self.config_dir)
config['foo'] = 1
self.assertEqual(config.get('foo'), 1)
self.assertEqual(config.get('foobar'), None)
self.assertEqual(config.get('foobar', 2), 2)
assert config.get('foo') == 1
assert config.get('foobar') is None
assert config.get('foobar', 2) == 2
config['foobar'] = 5
self.assertEqual(config.get('foobar', 2), 5)
assert config.get('foobar', 2) == 5
def test_load(self):
def check_config():
config = Config('test.conf', config_dir=self.config_dir)
self.assertEqual(config['string'], 'foobar')
self.assertEqual(config['float'], 0.435)
self.assertEqual(config['password'], 'abc123*\\[!]?/<>#{@}=|"+$%(^)~')
assert config['string'] == 'foobar'
assert config['float'] == 0.435
assert config['password'] == 'abc123*\\[!]?/<>#{@}=|"+$%(^)~'
# Test opening a previous 1.2 config file of just a json object
import json
@ -125,19 +121,19 @@ class ConfigTestCase(unittest.TestCase):
# We do this twice because the first time we need to save the file to disk
# and the second time we do a compare and we should not write
ret = config.save()
self.assertTrue(ret)
assert ret
ret = config.save()
self.assertTrue(ret)
assert ret
config['string'] = 'baz'
config['int'] = 2
ret = config.save()
self.assertTrue(ret)
assert ret
del config
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEqual(config['string'], 'baz')
self.assertEqual(config['int'], 2)
assert config['string'] == 'baz'
assert config['int'] == 2
def test_save_timer(self):
self.clock = task.Clock()
@ -146,17 +142,17 @@ class ConfigTestCase(unittest.TestCase):
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
config['string'] = 'baz'
config['int'] = 2
self.assertTrue(config._save_timer.active())
assert config._save_timer.active()
# Timeout set for 5 seconds in config, so lets move clock by 5 seconds
self.clock.advance(5)
def check_config(config):
self.assertTrue(not config._save_timer.active())
assert not config._save_timer.active()
del config
config = Config('test.conf', defaults=DEFAULTS, config_dir=self.config_dir)
self.assertEqual(config['string'], 'baz')
self.assertEqual(config['int'], 2)
assert config['string'] == 'baz'
assert config['int'] == 2
check_config(config)
@ -173,7 +169,7 @@ class ConfigTestCase(unittest.TestCase):
from deluge.config import find_json_objects
objects = find_json_objects(s)
self.assertEqual(len(objects), 2)
assert len(objects) == 2
def test_find_json_objects_curly_brace(self):
"""Test with string containing curly brace"""
@ -190,7 +186,7 @@ class ConfigTestCase(unittest.TestCase):
from deluge.config import find_json_objects
objects = find_json_objects(s)
self.assertEqual(len(objects), 2)
assert len(objects) == 2
def test_find_json_objects_double_quote(self):
"""Test with string containing double quote"""
@ -208,4 +204,4 @@ class ConfigTestCase(unittest.TestCase):
from deluge.config import find_json_objects
objects = find_json_objects(s)
self.assertEqual(len(objects), 2)
assert len(objects) == 2

View File

@ -8,9 +8,9 @@ from base64 import b64encode
from hashlib import sha1 as sha
import pytest
import pytest_twisted
from twisted.internet import defer, reactor, task
from twisted.internet.error import CannotListenError
from twisted.python.failure import Failure
from twisted.web.http import FORBIDDEN
from twisted.web.resource import EncodingResourceWrapper, Resource
from twisted.web.server import GzipEncoderFactory, Site
@ -20,12 +20,12 @@ import deluge.common
import deluge.component as component
import deluge.core.torrent
from deluge._libtorrent import lt
from deluge.conftest import BaseTestCase
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.error import AddTorrentError, InvalidTorrentError
from . import common
from .basetest import BaseTestCase
common.disable_new_release_check()
@ -76,9 +76,8 @@ class TopLevelResource(Resource):
)
class CoreTestCase(BaseTestCase):
class TestCore(BaseTestCase):
def set_up(self):
common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
self.core = Core()
self.core.config.config['lsd'] = False
@ -127,7 +126,7 @@ class CoreTestCase(BaseTestCase):
torrent_id = self.core.add_torrent_file(filename, filedump, options)
return torrent_id
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_add_torrent_files(self):
options = {}
filenames = ['test.torrent', 'test_torrent.file.torrent']
@ -138,9 +137,9 @@ class CoreTestCase(BaseTestCase):
filedump = b64encode(_file.read())
files_to_add.append((filename, filedump, options))
errors = yield self.core.add_torrent_files(files_to_add)
self.assertEqual(len(errors), 0)
assert len(errors) == 0
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_add_torrent_files_error_duplicate(self):
options = {}
filenames = ['test.torrent', 'test.torrent']
@ -151,10 +150,10 @@ class CoreTestCase(BaseTestCase):
filedump = b64encode(_file.read())
files_to_add.append((filename, filedump, options))
errors = yield self.core.add_torrent_files(files_to_add)
self.assertEqual(len(errors), 1)
self.assertTrue(str(errors[0]).startswith('Torrent already in session'))
assert len(errors) == 1
assert str(errors[0]).startswith('Torrent already in session')
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_add_torrent_file(self):
options = {}
filename = common.get_test_data_file('test.torrent')
@ -167,16 +166,15 @@ class CoreTestCase(BaseTestCase):
with open(filename, 'rb') as _file:
info_hash = sha(bencode(bdecode(_file.read())[b'info'])).hexdigest()
self.assertEqual(torrent_id, info_hash)
assert torrent_id == info_hash
def test_add_torrent_file_invalid_filedump(self):
options = {}
filename = common.get_test_data_file('test.torrent')
self.assertRaises(
AddTorrentError, self.core.add_torrent_file, filename, False, options
)
with pytest.raises(AddTorrentError):
self.core.add_torrent_file(filename, False, options)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_add_torrent_url(self):
url = (
'http://localhost:%d/ubuntu-9.04-desktop-i386.iso.torrent'
@ -186,78 +184,77 @@ class CoreTestCase(BaseTestCase):
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
torrent_id = yield self.core.add_torrent_url(url, options)
self.assertEqual(torrent_id, info_hash)
assert torrent_id == info_hash
def test_add_torrent_url_with_cookie(self):
@pytest_twisted.ensureDeferred
async def test_add_torrent_url_with_cookie(self):
url = 'http://localhost:%d/cookie' % self.listen_port
options = {}
headers = {'Cookie': 'password=deluge'}
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
d = self.core.add_torrent_url(url, options)
d.addCallbacks(self.fail, self.assertIsInstance, errbackArgs=(Failure,))
with pytest.raises(Exception):
await self.core.add_torrent_url(url, options)
d = self.core.add_torrent_url(url, options, headers)
d.addCallbacks(self.assertEqual, self.fail, callbackArgs=(info_hash,))
result = await self.core.add_torrent_url(url, options, headers)
assert result == info_hash
return d
def test_add_torrent_url_with_redirect(self):
@pytest_twisted.ensureDeferred
async def test_add_torrent_url_with_redirect(self):
url = 'http://localhost:%d/redirect' % self.listen_port
options = {}
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
d = self.core.add_torrent_url(url, options)
d.addCallback(self.assertEqual, info_hash)
return d
result = await self.core.add_torrent_url(url, options)
assert result == info_hash
def test_add_torrent_url_with_partial_download(self):
@pytest_twisted.ensureDeferred
async def test_add_torrent_url_with_partial_download(self):
url = 'http://localhost:%d/partial' % self.listen_port
options = {}
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
d = self.core.add_torrent_url(url, options)
d.addCallback(self.assertEqual, info_hash)
return d
result = await self.core.add_torrent_url(url, options)
assert result == info_hash
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_add_torrent_magnet(self):
info_hash = '60d5d82328b4547511fdeac9bf4d0112daa0ce00'
uri = deluge.common.create_magnet_uri(info_hash)
options = {}
torrent_id = yield self.core.add_torrent_magnet(uri, options)
self.assertEqual(torrent_id, info_hash)
assert torrent_id == info_hash
def test_resume_torrent(self):
tid1 = self.add_torrent('test.torrent', paused=True)
tid2 = self.add_torrent('test_torrent.file.torrent', paused=True)
# Assert paused
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertTrue(r1['paused'])
assert r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertTrue(r2['paused'])
assert r2['paused']
self.core.resume_torrent(tid2)
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertTrue(r1['paused'])
assert r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertFalse(r2['paused'])
assert not r2['paused']
def test_resume_torrent_list(self):
"""Backward compatibility for list of torrent_ids."""
torrent_id = self.add_torrent('test.torrent', paused=True)
self.core.resume_torrent([torrent_id])
result = self.core.get_torrent_status(torrent_id, ['paused'])
self.assertFalse(result['paused'])
assert not result['paused']
def test_resume_torrents(self):
tid1 = self.add_torrent('test.torrent', paused=True)
tid2 = self.add_torrent('test_torrent.file.torrent', paused=True)
self.core.resume_torrents([tid1, tid2])
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertFalse(r1['paused'])
assert not r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertFalse(r2['paused'])
assert not r2['paused']
def test_resume_torrents_all(self):
"""With no torrent_ids param, resume all torrents"""
@ -265,33 +262,33 @@ class CoreTestCase(BaseTestCase):
tid2 = self.add_torrent('test_torrent.file.torrent', paused=True)
self.core.resume_torrents()
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertFalse(r1['paused'])
assert not r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertFalse(r2['paused'])
assert not r2['paused']
def test_pause_torrent(self):
tid1 = self.add_torrent('test.torrent')
tid2 = self.add_torrent('test_torrent.file.torrent')
# Assert not paused
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertFalse(r1['paused'])
assert not r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertFalse(r2['paused'])
assert not r2['paused']
self.core.pause_torrent(tid2)
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertFalse(r1['paused'])
assert not r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertTrue(r2['paused'])
assert r2['paused']
def test_pause_torrent_list(self):
"""Backward compatibility for list of torrent_ids."""
torrent_id = self.add_torrent('test.torrent')
result = self.core.get_torrent_status(torrent_id, ['paused'])
self.assertFalse(result['paused'])
assert not result['paused']
self.core.pause_torrent([torrent_id])
result = self.core.get_torrent_status(torrent_id, ['paused'])
self.assertTrue(result['paused'])
assert result['paused']
def test_pause_torrents(self):
tid1 = self.add_torrent('test.torrent')
@ -299,9 +296,9 @@ class CoreTestCase(BaseTestCase):
self.core.pause_torrents([tid1, tid2])
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertTrue(r1['paused'])
assert r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertTrue(r2['paused'])
assert r2['paused']
def test_pause_torrents_all(self):
"""With no torrent_ids param, pause all torrents"""
@ -310,9 +307,9 @@ class CoreTestCase(BaseTestCase):
self.core.pause_torrents()
r1 = self.core.get_torrent_status(tid1, ['paused'])
self.assertTrue(r1['paused'])
assert r1['paused']
r2 = self.core.get_torrent_status(tid2, ['paused'])
self.assertTrue(r2['paused'])
assert r2['paused']
def test_prefetch_metadata_existing(self):
"""Check another call with same magnet returns existing deferred."""
@ -320,7 +317,7 @@ class CoreTestCase(BaseTestCase):
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', b'')
def on_result(result):
self.assertEqual(result, expected)
assert result == expected
d = self.core.prefetch_magnet_metadata(magnet)
d.addCallback(on_result)
@ -329,7 +326,7 @@ class CoreTestCase(BaseTestCase):
self.clock.advance(30)
return defer.DeferredList([d, d2])
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_remove_torrent(self):
options = {}
filename = common.get_test_data_file('test.torrent')
@ -337,18 +334,17 @@ class CoreTestCase(BaseTestCase):
filedump = b64encode(_file.read())
torrent_id = yield self.core.add_torrent_file_async(filename, filedump, options)
removed = self.core.remove_torrent(torrent_id, True)
self.assertTrue(removed)
self.assertEqual(len(self.core.get_session_state()), 0)
assert removed
assert len(self.core.get_session_state()) == 0
def test_remove_torrent_invalid(self):
self.assertRaises(
InvalidTorrentError,
self.core.remove_torrent,
'torrentidthatdoesntexist',
True,
)
with pytest.raises(InvalidTorrentError):
self.core.remove_torrent(
'torrentidthatdoesntexist',
True,
)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_remove_torrents(self):
options = {}
filename = common.get_test_data_file('test.torrent')
@ -365,17 +361,17 @@ class CoreTestCase(BaseTestCase):
d = self.core.remove_torrents([torrent_id, torrent_id2], True)
def test_ret(val):
self.assertTrue(val == [])
assert val == []
d.addCallback(test_ret)
def test_session_state(val):
self.assertEqual(len(self.core.get_session_state()), 0)
assert len(self.core.get_session_state()) == 0
d.addCallback(test_session_state)
yield d
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_remove_torrents_invalid(self):
options = {}
filename = common.get_test_data_file('test.torrent')
@ -387,57 +383,53 @@ class CoreTestCase(BaseTestCase):
val = yield self.core.remove_torrents(
['invalidid1', 'invalidid2', torrent_id], False
)
self.assertEqual(len(val), 2)
self.assertEqual(
val[0], ('invalidid1', 'torrent_id invalidid1 not in session.')
)
self.assertEqual(
val[1], ('invalidid2', 'torrent_id invalidid2 not in session.')
)
assert len(val) == 2
assert val[0] == ('invalidid1', 'torrent_id invalidid1 not in session.')
assert val[1] == ('invalidid2', 'torrent_id invalidid2 not in session.')
def test_get_session_status(self):
status = self.core.get_session_status(
['net.recv_tracker_bytes', 'net.sent_tracker_bytes']
)
self.assertIsInstance(status, dict)
self.assertEqual(status['net.recv_tracker_bytes'], 0)
self.assertEqual(status['net.sent_tracker_bytes'], 0)
assert isinstance(status, dict)
assert status['net.recv_tracker_bytes'] == 0
assert status['net.sent_tracker_bytes'] == 0
def test_get_session_status_all(self):
status = self.core.get_session_status([])
self.assertIsInstance(status, dict)
self.assertIn('upload_rate', status)
self.assertIn('net.recv_bytes', status)
assert isinstance(status, dict)
assert 'upload_rate' in status
assert 'net.recv_bytes' in status
def test_get_session_status_depr(self):
status = self.core.get_session_status(['num_peers', 'num_unchoked'])
self.assertIsInstance(status, dict)
self.assertEqual(status['num_peers'], 0)
self.assertEqual(status['num_unchoked'], 0)
assert isinstance(status, dict)
assert status['num_peers'] == 0
assert status['num_unchoked'] == 0
def test_get_session_status_rates(self):
status = self.core.get_session_status(['upload_rate', 'download_rate'])
self.assertIsInstance(status, dict)
self.assertEqual(status['upload_rate'], 0)
assert isinstance(status, dict)
assert status['upload_rate'] == 0
def test_get_session_status_ratio(self):
status = self.core.get_session_status(['write_hit_ratio', 'read_hit_ratio'])
self.assertIsInstance(status, dict)
self.assertEqual(status['write_hit_ratio'], 0.0)
self.assertEqual(status['read_hit_ratio'], 0.0)
assert isinstance(status, dict)
assert status['write_hit_ratio'] == 0.0
assert status['read_hit_ratio'] == 0.0
def test_get_free_space(self):
space = self.core.get_free_space('.')
self.assertTrue(isinstance(space, int))
self.assertTrue(space >= 0)
self.assertEqual(self.core.get_free_space('/someinvalidpath'), -1)
assert isinstance(space, int)
assert space >= 0
assert self.core.get_free_space('/someinvalidpath') == -1
@pytest.mark.slow
def test_test_listen_port(self):
d = self.core.test_listen_port()
def result(r):
self.assertTrue(r in (True, False))
assert r in (True, False)
d.addCallback(result)
return d
@ -455,24 +447,22 @@ class CoreTestCase(BaseTestCase):
}
for key in pathlist:
self.assertEqual(
deluge.core.torrent.sanitize_filepath(key, folder=False), pathlist[key]
assert (
deluge.core.torrent.sanitize_filepath(key, folder=False)
== pathlist[key]
)
self.assertEqual(
deluge.core.torrent.sanitize_filepath(key, folder=True),
pathlist[key] + '/',
assert (
deluge.core.torrent.sanitize_filepath(key, folder=True)
== pathlist[key] + '/'
)
def test_get_set_config_values(self):
self.assertEqual(
self.core.get_config_values(['abc', 'foo']), {'foo': None, 'abc': None}
)
self.assertEqual(self.core.get_config_value('foobar'), None)
assert self.core.get_config_values(['abc', 'foo']) == {'foo': None, 'abc': None}
assert self.core.get_config_value('foobar') is None
self.core.set_config({'abc': 'def', 'foo': 10, 'foobar': 'barfoo'})
self.assertEqual(
self.core.get_config_values(['foo', 'abc']), {'foo': 10, 'abc': 'def'}
)
self.assertEqual(self.core.get_config_value('foobar'), 'barfoo')
assert self.core.get_config_values(['foo', 'abc']) == {'foo': 10, 'abc': 'def'}
assert self.core.get_config_value('foobar') == 'barfoo'
def test_read_only_config_keys(self):
key = 'max_upload_speed'
@ -481,13 +471,13 @@ class CoreTestCase(BaseTestCase):
old_value = self.core.get_config_value(key)
self.core.set_config({key: old_value + 10})
new_value = self.core.get_config_value(key)
self.assertEqual(old_value, new_value)
assert old_value == new_value
self.core.read_only_config_keys = None
def test__create_peer_id(self):
self.assertEqual(self.core._create_peer_id('2.0.0'), '-DE200s-')
self.assertEqual(self.core._create_peer_id('2.0.0.dev15'), '-DE200D-')
self.assertEqual(self.core._create_peer_id('2.0.1rc1'), '-DE201r-')
self.assertEqual(self.core._create_peer_id('2.11.0b2'), '-DE2B0b-')
self.assertEqual(self.core._create_peer_id('2.4.12b2.dev3'), '-DE24CD-')
assert self.core._create_peer_id('2.0.0') == '-DE200s-'
assert self.core._create_peer_id('2.0.0.dev15') == '-DE200D-'
assert self.core._create_peer_id('2.0.1rc1') == '-DE201r-'
assert self.core._create_peer_id('2.11.0b2') == '-DE2B0b-'
assert self.core._create_peer_id('2.4.12b2.dev3') == '-DE24CD-'

View File

@ -4,12 +4,11 @@
# See LICENSE for more details.
#
from twisted.trial import unittest
from deluge.decorators import proxy
class DecoratorsTestCase(unittest.TestCase):
class TestDecorators:
def test_proxy_with_simple_functions(self):
def negate(func, *args, **kwargs):
return not func(*args, **kwargs)
@ -23,10 +22,10 @@ class DecoratorsTestCase(unittest.TestCase):
def double_nothing(_bool):
return _bool
self.assertTrue(something(False))
self.assertFalse(something(True))
self.assertTrue(double_nothing(True))
self.assertFalse(double_nothing(False))
assert something(False)
assert not something(True)
assert double_nothing(True)
assert not double_nothing(False)
def test_proxy_with_class_method(self):
def negate(func, *args, **kwargs):
@ -45,5 +44,5 @@ class DecoratorsTestCase(unittest.TestCase):
return self.diff(number)
t = Test(5)
self.assertEqual(t.diff(1), -4)
self.assertEqual(t.no_diff(1), 4)
assert t.diff(1) == -4
assert t.no_diff(1) == 4

View File

@ -4,48 +4,36 @@
# See LICENSE for more details.
#
from twisted.trial import unittest
import deluge.error
class ErrorTestCase(unittest.TestCase):
def setUp(self): # NOQA: N803
pass
def tearDown(self): # NOQA: N803
pass
class TestError:
def test_deluge_error(self):
msg = 'Some message'
e = deluge.error.DelugeError(msg)
self.assertEqual(str(e), msg)
assert str(e) == msg
from twisted.internet.defer import DebugInfo
del DebugInfo.__del__ # Hides all errors
self.assertEqual(e._args, (msg,))
self.assertEqual(e._kwargs, {})
assert e._args == (msg,)
assert e._kwargs == {}
def test_incompatible_client(self):
version = '1.3.6'
e = deluge.error.IncompatibleClient(version)
self.assertEqual(
str(e),
'Your deluge client is not compatible with the daemon. \
Please upgrade your client to %s'
% version,
assert (
str(e) == 'Your deluge client is not compatible with the daemon. '
'Please upgrade your client to %s' % version
)
def test_not_authorized_error(self):
current_level = 5
required_level = 10
e = deluge.error.NotAuthorizedError(current_level, required_level)
self.assertEqual(
str(e), 'Auth level too low: %d < %d' % (current_level, required_level)
)
assert str(e) == 'Auth level too low: %d < %d' % (current_level, required_level)
def test_bad_login_error(self):
message = 'Login failed'
username = 'deluge'
e = deluge.error.BadLoginError(message, username)
self.assertEqual(str(e), message)
assert str(e) == message

View File

@ -5,15 +5,12 @@
#
import pytest
from twisted.trial import unittest
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.conftest import BaseTestCase
from deluge.i18n import setup_translation
from . import common
from .basetest import BaseTestCase
libs_available = True
# Allow running other tests without GTKUI dependencies available
try:
@ -28,12 +25,11 @@ setup_translation()
@pytest.mark.gtkui
class FilesTabTestCase(BaseTestCase):
class TestFilesTab(BaseTestCase):
def set_up(self):
if libs_available is False:
raise unittest.SkipTest('GTKUI dependencies not available')
pytest.skip('GTKUI dependencies not available')
common.set_tmp_config_dir()
ConfigManager('gtk3ui.conf', defaults=DEFAULT_PREFS)
self.mainwindow = MainWindow()
self.filestab = FilesTab()
@ -94,7 +90,7 @@ class FilesTabTestCase(BaseTestCase):
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
assert ret
def test_files_tab2(self):
self.filestab.files_list[self.t_id] = (
@ -112,7 +108,7 @@ class FilesTabTestCase(BaseTestCase):
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
assert ret
def test_files_tab3(self):
self.filestab.files_list[self.t_id] = (
@ -129,7 +125,7 @@ class FilesTabTestCase(BaseTestCase):
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
assert ret
def test_files_tab4(self):
self.filestab.files_list[self.t_id] = (
@ -147,7 +143,7 @@ class FilesTabTestCase(BaseTestCase):
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
assert ret
def test_files_tab5(self):
self.filestab.files_list[self.t_id] = (
@ -164,4 +160,4 @@ class FilesTabTestCase(BaseTestCase):
)
if not ret:
self.print_treestore('Treestore not expected:', self.filestab.treestore)
self.assertTrue(ret)
assert ret

View File

@ -8,11 +8,11 @@ import os
import tempfile
from email.utils import formatdate
import pytest
import pytest_twisted
from twisted.internet import reactor
from twisted.internet.error import CannotListenError
from twisted.python.failure import Failure
from twisted.trial import unittest
from twisted.web.error import PageRedirect
from twisted.web.error import Error, PageRedirect
from twisted.web.http import NOT_MODIFIED
from twisted.web.resource import EncodingResourceWrapper, Resource
from twisted.web.server import GzipEncoderFactory, Site
@ -134,11 +134,13 @@ class TopLevelResource(Resource):
return b'<h1>Deluge HTTP Downloader tests webserver here</h1>'
class DownloadFileTestCase(unittest.TestCase):
class TestDownloadFile:
def get_url(self, path=''):
return 'http://localhost:%d/%s' % (self.listen_port, path)
def setUp(self): # NOQA
@pytest_twisted.async_yield_fixture(autouse=True)
async def setUp(self, request): # NOQA
self = request.instance
setup_logger('warning', fname('log_file'))
self.website = Site(TopLevelResource())
self.listen_port = 51242
@ -154,140 +156,136 @@ class DownloadFileTestCase(unittest.TestCase):
else:
raise error
def tearDown(self): # NOQA
return self.webserver.stopListening()
yield
def assertContains(self, filename, contents): # NOQA
await self.webserver.stopListening()
def assert_contains(self, filename, contents):
with open(filename, encoding='utf8') as _file:
try:
self.assertEqual(_file.read(), contents)
assert _file.read() == contents
except Exception as ex:
self.fail(ex)
pytest.fail(ex)
return filename
def assertNotContains(self, filename, contents, file_mode=''): # NOQA
def assert_not_contains(self, filename, contents, file_mode=''):
with open(filename, encoding='utf8') as _file:
try:
self.assertNotEqual(_file.read(), contents)
assert _file.read() != contents
except Exception as ex:
self.fail(ex)
pytest.fail(ex)
return filename
def test_download(self):
d = download_file(self.get_url(), fname('index.html'))
d.addCallback(self.assertEqual, fname('index.html'))
return d
@pytest_twisted.ensureDeferred
async def test_download(self):
filename = await download_file(self.get_url(), fname('index.html'))
assert filename == fname('index.html')
def test_download_without_required_cookies(self):
@pytest_twisted.ensureDeferred
async def test_download_without_required_cookies(self):
url = self.get_url('cookie')
d = download_file(url, fname('none'))
d.addCallback(self.fail)
d.addErrback(self.assertIsInstance, Failure)
return d
filename = await download_file(url, fname('none'))
self.assert_contains(filename, 'Password cookie not set!')
def test_download_with_required_cookies(self):
@pytest_twisted.ensureDeferred
async def test_download_with_required_cookies(self):
url = self.get_url('cookie')
cookie = {'cookie': 'password=deluge'}
d = download_file(url, fname('monster'), headers=cookie)
d.addCallback(self.assertEqual, fname('monster'))
d.addCallback(self.assertContains, 'COOKIE MONSTER!')
return d
filename = await download_file(url, fname('monster'), headers=cookie)
assert filename == fname('monster')
self.assert_contains(filename, 'COOKIE MONSTER!')
def test_download_with_rename(self):
@pytest_twisted.ensureDeferred
async def test_download_with_rename(self):
url = self.get_url('rename?filename=renamed')
d = download_file(url, fname('original'))
d.addCallback(self.assertEqual, fname('renamed'))
d.addCallback(self.assertContains, 'This file should be called renamed')
return d
filename = await download_file(url, fname('original'))
assert filename == fname('renamed')
self.assert_contains(filename, 'This file should be called renamed')
def test_download_with_rename_exists(self):
@pytest_twisted.ensureDeferred
async def test_download_with_rename_exists(self):
open(fname('renamed'), 'w').close()
url = self.get_url('rename?filename=renamed')
d = download_file(url, fname('original'))
d.addCallback(self.assertEqual, fname('renamed-1'))
d.addCallback(self.assertContains, 'This file should be called renamed')
return d
filename = await download_file(url, fname('original'))
assert filename == fname('renamed-1')
self.assert_contains(filename, 'This file should be called renamed')
def test_download_with_rename_sanitised(self):
@pytest_twisted.ensureDeferred
async def test_download_with_rename_sanitised(self):
url = self.get_url('rename?filename=/etc/passwd')
d = download_file(url, fname('original'))
d.addCallback(self.assertEqual, fname('passwd'))
d.addCallback(self.assertContains, 'This file should be called /etc/passwd')
return d
filename = await download_file(url, fname('original'))
assert filename == fname('passwd')
self.assert_contains(filename, 'This file should be called /etc/passwd')
def test_download_with_attachment_no_filename(self):
@pytest_twisted.ensureDeferred
async def test_download_with_attachment_no_filename(self):
url = self.get_url('attachment')
d = download_file(url, fname('original'))
d.addCallback(self.assertEqual, fname('original'))
d.addCallback(self.assertContains, 'Attachment with no filename set')
return d
filename = await download_file(url, fname('original'))
assert filename == fname('original')
self.assert_contains(filename, 'Attachment with no filename set')
def test_download_with_rename_prevented(self):
@pytest_twisted.ensureDeferred
async def test_download_with_rename_prevented(self):
url = self.get_url('rename?filename=spam')
d = download_file(url, fname('forced'), force_filename=True)
d.addCallback(self.assertEqual, fname('forced'))
d.addCallback(self.assertContains, 'This file should be called spam')
return d
filename = await download_file(url, fname('forced'), force_filename=True)
assert filename == fname('forced')
self.assert_contains(filename, 'This file should be called spam')
def test_download_with_gzip_encoding(self):
@pytest_twisted.ensureDeferred
async def test_download_with_gzip_encoding(self):
url = self.get_url('gzip?msg=success')
d = download_file(url, fname('gzip_encoded'))
d.addCallback(self.assertContains, 'success')
return d
filename = await download_file(url, fname('gzip_encoded'))
self.assert_contains(filename, 'success')
def test_download_with_gzip_encoding_disabled(self):
@pytest_twisted.ensureDeferred
async def test_download_with_gzip_encoding_disabled(self):
url = self.get_url('gzip?msg=unzip')
d = download_file(url, fname('gzip_encoded'), allow_compression=False)
d.addCallback(self.assertContains, 'unzip')
return d
filename = await download_file(
url, fname('gzip_encoded'), allow_compression=False
)
self.assert_contains(filename, 'unzip')
def test_page_redirect_unhandled(self):
@pytest_twisted.ensureDeferred
async def test_page_redirect_unhandled(self):
url = self.get_url('redirect')
d = download_file(url, fname('none'))
d.addCallback(self.fail)
with pytest.raises(PageRedirect):
await download_file(url, fname('none'), handle_redirects=False)
def on_redirect(failure):
self.assertTrue(type(failure), PageRedirect)
d.addErrback(on_redirect)
return d
def test_page_redirect(self):
@pytest_twisted.ensureDeferred
async def test_page_redirect(self):
url = self.get_url('redirect')
d = download_file(url, fname('none'), handle_redirects=True)
d.addCallback(self.assertEqual, fname('none'))
d.addErrback(self.fail)
return d
filename = await download_file(url, fname('none'), handle_redirects=True)
assert filename == fname('none')
def test_page_not_found(self):
d = download_file(self.get_url('page/not/found'), fname('none'))
d.addCallback(self.fail)
d.addErrback(self.assertIsInstance, Failure)
return d
@pytest_twisted.ensureDeferred
async def test_page_not_found(self):
with pytest.raises(Error):
await download_file(self.get_url('page/not/found'), fname('none'))
def test_page_not_modified(self):
@pytest.mark.xfail(reason="Doesn't seem like httpdownloader ever implemented this.")
@pytest_twisted.ensureDeferred
async def test_page_not_modified(self):
headers = {'If-Modified-Since': formatdate(usegmt=True)}
d = download_file(self.get_url(), fname('index.html'), headers=headers)
d.addCallback(self.fail)
d.addErrback(self.assertIsInstance, Failure)
return d
with pytest.raises(Error) as exc_info:
await download_file(self.get_url(), fname('index.html'), headers=headers)
assert exc_info.value.status == NOT_MODIFIED
def test_download_text_reencode_charset(self):
@pytest_twisted.ensureDeferred
async def test_download_text_reencode_charset(self):
"""Re-encode as UTF-8 specified charset for text content-type header"""
url = self.get_url('attachment')
filepath = fname('test.txt')
headers = {'content-charset': 'Windows-1251', 'content-append': 'бвгде'}
d = download_file(url, filepath, headers=headers)
d.addCallback(self.assertEqual, filepath)
d.addCallback(self.assertContains, 'Attachment with no filename setбвгде')
return d
filename = await download_file(url, filepath, headers=headers)
assert filename == filepath
self.assert_contains(filename, 'Attachment with no filename setбвгде')
def test_download_binary_ignore_charset(self):
@pytest_twisted.ensureDeferred
async def test_download_binary_ignore_charset(self):
"""Ignore charset for binary content-type header e.g. torrent files"""
url = self.get_url('torrent')
headers = {'content-charset': 'Windows-1251'}
filepath = fname('test.torrent')
d = download_file(url, fname('test.torrent'), headers=headers)
d.addCallback(self.assertEqual, filepath)
d.addCallback(self.assertContains, 'Binary attachment ignore charset 世丕且\n')
return d
filename = await download_file(url, fname('test.torrent'), headers=headers)
assert filename == filepath
self.assert_contains(filename, 'Binary attachment ignore charset 世丕且\n')

View File

@ -9,59 +9,32 @@
import json as json_lib
from unittest.mock import MagicMock
from twisted.internet import defer
import pytest
import pytest_twisted
from twisted.web import server
from twisted.web.http import Request
import deluge.common
import deluge.component as component
import deluge.ui.web.auth
import deluge.ui.web.json_api
from deluge.error import DelugeError
from deluge.ui.client import client
from deluge.ui.web.auth import Auth
from deluge.ui.web.json_api import JSON, JSONException
from . import common
from .basetest import BaseTestCase
from .common_web import WebServerMockBase
from .daemon_base import DaemonBase
common.disable_new_release_check()
class JSONBase(BaseTestCase, DaemonBase):
def connect_client(self, *args, **kwargs):
return client.connect(
'localhost',
self.listen_port,
username=kwargs.get('user', ''),
password=kwargs.get('password', ''),
)
def disconnect_client(self, *args):
return client.disconnect()
def tear_down(self):
d = component.shutdown()
d.addCallback(self.disconnect_client)
d.addCallback(self.terminate_core)
return d
class JSONTestCase(JSONBase):
def set_up(self):
d = self.common_set_up()
d.addCallback(self.start_core)
d.addCallbacks(self.connect_client, self.terminate_core)
return d
@defer.inlineCallbacks
def test_get_remote_methods(self):
@pytest.mark.usefixtures('daemon', 'client', 'component')
class TestJSON:
@pytest_twisted.ensureDeferred
async def test_get_remote_methods(self):
json = JSON()
methods = yield json.get_remote_methods()
self.assertEqual(type(methods), tuple)
self.assertTrue(len(methods) > 0)
methods = await json.get_remote_methods()
assert type(methods) == tuple
assert len(methods) > 0
def test_render_fail_disconnected(self):
json = JSON()
@ -69,7 +42,7 @@ class JSONTestCase(JSONBase):
request.method = b'POST'
request._disconnected = True
# When disconnected, returns empty string
self.assertEqual(json.render(request), '')
assert json.render(request) == ''
def test_render_fail(self):
json = JSON()
@ -79,19 +52,17 @@ class JSONTestCase(JSONBase):
def write(response_str):
request.write_was_called = True
response = json_lib.loads(response_str.decode())
self.assertEqual(response['result'], None)
self.assertEqual(response['id'], None)
self.assertEqual(
response['error']['message'], 'JSONException: JSON not decodable'
)
self.assertEqual(response['error']['code'], 5)
assert response['result'] is None
assert response['id'] is None
assert response['error']['message'] == 'JSONException: JSON not decodable'
assert response['error']['code'] == 5
request.write = write
request.write_was_called = False
request._disconnected = False
request.getHeader.return_value = b'application/json'
self.assertEqual(json.render(request), server.NOT_DONE_YET)
self.assertTrue(request.write_was_called)
assert json.render(request) == server.NOT_DONE_YET
assert request.write_was_called
def test_handle_request_invalid_method(self):
json = JSON()
@ -99,20 +70,23 @@ class JSONTestCase(JSONBase):
json_data = {'method': 'no-existing-module.test', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data).encode()
request_id, result, error = json._handle_request(request)
self.assertEqual(error, {'message': 'Unknown method', 'code': 2})
assert error == {'message': 'Unknown method', 'code': 2}
def test_handle_request_invalid_json_request(self):
json = JSON()
request = MagicMock()
json_data = {'id': 0, 'params': []}
request.json = json_lib.dumps(json_data).encode()
self.assertRaises(JSONException, json._handle_request, request)
with pytest.raises(JSONException):
json._handle_request(request)
json_data = {'method': 'some.method', 'params': []}
request.json = json_lib.dumps(json_data).encode()
self.assertRaises(JSONException, json._handle_request, request)
with pytest.raises(JSONException):
json._handle_request(request)
json_data = {'method': 'some.method', 'id': 0}
request.json = json_lib.dumps(json_data).encode()
self.assertRaises(JSONException, json._handle_request, request)
with pytest.raises(JSONException):
json._handle_request(request)
def test_on_json_request_invalid_content_type(self):
"""Test for exception with content type not application/json"""
@ -121,18 +95,14 @@ class JSONTestCase(JSONBase):
request.getHeader.return_value = b'text/plain'
json_data = {'method': 'some.method', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data).encode()
self.assertRaises(JSONException, json._on_json_request, request)
with pytest.raises(JSONException):
json._on_json_request(request)
class JSONCustomUserTestCase(JSONBase):
def set_up(self):
d = self.common_set_up()
d.addCallback(self.start_core)
return d
@defer.inlineCallbacks
@pytest.mark.usefixtures('daemon', 'client', 'component')
class TestJSONCustomUserTestCase:
@pytest_twisted.inlineCallbacks
def test_handle_request_auth_error(self):
yield self.connect_client()
json = JSON()
auth_conf = {'session_timeout': 10, 'sessions': {}}
Auth(auth_conf) # Must create the component
@ -145,13 +115,12 @@ class JSONCustomUserTestCase(JSONBase):
json_data = {'method': 'core.get_libtorrent_version', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data).encode()
request_id, result, error = json._handle_request(request)
self.assertEqual(error, {'message': 'Not authenticated', 'code': 1})
assert error == {'message': 'Not authenticated', 'code': 1}
class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
def set_up(self):
d = self.common_set_up()
custom_script = """
@pytest.mark.usefixtures('daemon', 'client', 'component')
class TestRPCRaiseDelugeErrorJSON:
daemon_custom_script = """
from deluge.error import DelugeError
from deluge.core.rpcserver import export
class TestClass(object):
@ -162,12 +131,9 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
test = TestClass()
daemon.rpcserver.register_object(test)
"""
d.addCallback(self.start_core, custom_script=custom_script)
d.addCallbacks(self.connect_client, self.terminate_core)
return d
@defer.inlineCallbacks
def test_handle_request_method_raise_delugeerror(self):
@pytest_twisted.ensureDeferred
async def test_handle_request_method_raise_delugeerror(self):
json = JSON()
def get_session_id(s_id):
@ -179,9 +145,9 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
request = Request(MagicMock(), False)
request.base = b''
auth._create_session(request)
methods = yield json.get_remote_methods()
methods = await json.get_remote_methods()
# Verify the function has been registered
self.assertTrue('testclass.test' in methods)
assert 'testclass.test' in methods
request = MagicMock()
session_id = list(auth.config['sessions'])[0]
@ -189,18 +155,13 @@ class RPCRaiseDelugeErrorJSONTestCase(JSONBase):
json_data = {'method': 'testclass.test', 'id': 0, 'params': []}
request.json = json_lib.dumps(json_data).encode()
request_id, result, error = json._handle_request(request)
result.addCallback(self.fail)
def on_error(error):
self.assertEqual(error.type, DelugeError)
result.addErrback(on_error)
yield result
with pytest.raises(DelugeError):
await result
class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
def set_up(self):
d = self.common_set_up()
class TestJSONRequestFailed(WebServerMockBase):
@pytest_twisted.async_yield_fixture(autouse=True)
async def set_up(self, config_dir):
custom_script = """
from deluge.error import DelugeError
from deluge.core.rpcserver import export
@ -231,28 +192,29 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
}
def on_test_raise(*args):
self.assertTrue('Unhandled error in Deferred:' in self.core.stderr_out)
self.assertTrue('in test_raise_error' in self.core.stderr_out)
assert 'Unhandled error in Deferred:' in self.core.stderr_out
assert 'in test_raise_error' in self.core.stderr_out
extra_callback['deferred'].addCallback(on_test_raise)
d.addCallback(
self.start_core,
d, daemon = common.start_core(
custom_script=custom_script,
print_stdout=False,
print_stderr=False,
timeout=5,
extra_callbacks=[extra_callback],
config_directory=config_dir,
)
d.addCallbacks(self.connect_client, self.terminate_core)
return d
await d
yield
await daemon.kill()
@defer.inlineCallbacks
def test_render_on_rpc_request_failed(self):
@pytest_twisted.inlineCallbacks
def test_render_on_rpc_request_failed(self, component, client):
json = JSON()
methods = yield json.get_remote_methods()
# Verify the function has been registered
self.assertTrue('testclass.test' in methods)
assert 'testclass.test' in methods
request = MagicMock()
@ -263,14 +225,14 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
def write(response_str):
request.write_was_called = True
response = json_lib.loads(response_str.decode())
self.assertEqual(response['result'], None, 'BAD RESULT')
self.assertEqual(response['id'], 0)
self.assertEqual(
response['error']['message'],
'Failure: [Failure instance: Traceback (failure with no frames):'
" <class 'deluge.error.DelugeError'>: DelugeERROR\n]",
assert response['result'] is None, 'BAD RESULT'
assert response['id'] == 0
assert (
response['error']['message']
== 'Failure: [Failure instance: Traceback (failure with no frames):'
" <class 'deluge.error.DelugeError'>: DelugeERROR\n]"
)
self.assertEqual(response['error']['code'], 4)
assert response['error']['code'] == 4
request.write = write
request.write_was_called = False
@ -281,8 +243,8 @@ class JSONRequestFailedTestCase(JSONBase, WebServerMockBase):
d = json._on_json_request(request)
def on_success(arg):
self.assertEqual(arg, server.NOT_DONE_YET)
assert arg == server.NOT_DONE_YET
return True
d.addCallbacks(on_success, self.fail)
d.addCallbacks(on_success, pytest.fail)
yield d

View File

@ -10,12 +10,11 @@
import logging
import warnings
from deluge.conftest import BaseTestCase
from deluge.log import setup_logger
from .basetest import BaseTestCase
class LogTestCase(BaseTestCase):
class TestLog(BaseTestCase):
def set_up(self):
setup_logger(logging.DEBUG)
@ -29,7 +28,7 @@ class LogTestCase(BaseTestCase):
# Cause all warnings to always be triggered.
warnings.simplefilter('always')
LOG.debug('foo')
self.assertEqual(w[-1].category, DeprecationWarning)
assert w[-1].category == DeprecationWarning
# def test_twisted_error_log(self):
# from twisted.internet import defer

View File

@ -7,8 +7,6 @@
import os
import tempfile
from twisted.trial import unittest
from deluge import maketorrent
@ -24,7 +22,7 @@ def check_torrent(filename):
TorrentInfo(filename)
class MakeTorrentTestCase(unittest.TestCase):
class TestMakeTorrent:
def test_save_multifile(self):
# Create a temporary folder for torrent creation
tmp_path = tempfile.mkdtemp()

View File

@ -7,8 +7,6 @@
import os
import tempfile
from twisted.trial import unittest
from deluge import metafile
@ -24,7 +22,7 @@ def check_torrent(filename):
TorrentInfo(filename)
class MetafileTestCase(unittest.TestCase):
class TestMetafile:
def test_save_multifile(self):
# Create a temporary folder for torrent creation
tmp_path = tempfile.mkdtemp()

View File

@ -8,26 +8,20 @@
from deluge.pluginmanagerbase import PluginManagerBase
from . import common
from .basetest import BaseTestCase
class PluginManagerBaseTestCase(BaseTestCase):
def set_up(self):
common.set_tmp_config_dir()
class TestPluginManagerBase:
def test_get_plugin_info(self):
pm = PluginManagerBase('core.conf', 'deluge.plugin.core')
for p in pm.get_available_plugins():
for key, value in pm.get_plugin_info(p).items():
self.assertIsInstance(key, str)
self.assertIsInstance(value, str)
assert isinstance(key, str)
assert isinstance(value, str)
def test_get_plugin_info_invalid_name(self):
pm = PluginManagerBase('core.conf', 'deluge.plugin.core')
for key, value in pm.get_plugin_info('random').items():
result = 'not available' if key in ('Name', 'Version') else ''
self.assertEqual(value, result)
assert value == result
def test_parse_pkg_info_metadata_2_1(self):
pkg_info = """Metadata-Version: 2.1
@ -44,6 +38,6 @@ Monitors folders for .torrent files.
"""
plugin_info = PluginManagerBase.parse_pkg_info(pkg_info)
for value in plugin_info.values():
self.assertNotEqual(value, '')
assert value != ''
result = 'Monitors folders for .torrent files.'
self.assertEqual(plugin_info['Description'], result)
assert plugin_info['Description'] == result

View File

@ -9,13 +9,12 @@
import deluge.component as component
import deluge.error
from deluge.common import get_localhost_auth
from deluge.conftest import BaseTestCase
from deluge.core import rpcserver
from deluge.core.authmanager import AuthManager
from deluge.core.rpcserver import DelugeRPCProtocol, RPCServer
from deluge.log import setup_logger
from .basetest import BaseTestCase
setup_logger('none')
@ -27,7 +26,7 @@ class DelugeRPCProtocolTester(DelugeRPCProtocol):
self.messages.append(data)
class RPCServerTestCase(BaseTestCase):
class TestRPCServer(BaseTestCase):
def set_up(self):
self.rpcserver = RPCServer(listen=False)
self.rpcserver.factory.protocol = DelugeRPCProtocolTester
@ -57,15 +56,15 @@ class RPCServerTestCase(BaseTestCase):
e = TorrentFolderRenamedEvent(*data)
self.rpcserver.emit_event_for_session_id(self.session_id, e)
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_EVENT, str(msg))
self.assertEqual(msg[1], 'TorrentFolderRenamedEvent', str(msg))
self.assertEqual(msg[2], data, str(msg))
assert msg[0] == rpcserver.RPC_EVENT, str(msg)
assert msg[1] == 'TorrentFolderRenamedEvent', str(msg)
assert msg[2] == data, str(msg)
def test_invalid_client_login(self):
self.protocol.dispatch(self.request_id, 'daemon.login', [1], {})
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_ERROR)
self.assertEqual(msg[1], self.request_id)
assert msg[0] == rpcserver.RPC_ERROR
assert msg[1] == self.request_id
def test_valid_client_login(self):
self.authmanager = AuthManager()
@ -74,9 +73,9 @@ class RPCServerTestCase(BaseTestCase):
self.request_id, 'daemon.login', auth, {'client_version': 'Test'}
)
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_RESPONSE, str(msg))
self.assertEqual(msg[1], self.request_id, str(msg))
self.assertEqual(msg[2], rpcserver.AUTH_LEVEL_ADMIN, str(msg))
assert msg[0] == rpcserver.RPC_RESPONSE, str(msg)
assert msg[1] == self.request_id, str(msg)
assert msg[2] == rpcserver.AUTH_LEVEL_ADMIN, str(msg)
def test_client_login_error(self):
# This test causes error log prints while running the test...
@ -87,24 +86,24 @@ class RPCServerTestCase(BaseTestCase):
self.request_id, 'daemon.login', auth, {'client_version': 'Test'}
)
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_ERROR)
self.assertEqual(msg[1], self.request_id)
self.assertEqual(msg[2], 'WrappedException')
self.assertEqual(msg[3][1], 'AttributeError')
assert msg[0] == rpcserver.RPC_ERROR
assert msg[1] == self.request_id
assert msg[2] == 'WrappedException'
assert msg[3][1] == 'AttributeError'
def test_client_invalid_method_call(self):
self.authmanager = AuthManager()
auth = get_localhost_auth()
self.protocol.dispatch(self.request_id, 'invalid_function', auth, {})
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_ERROR)
self.assertEqual(msg[1], self.request_id)
self.assertEqual(msg[2], 'WrappedException')
self.assertEqual(msg[3][1], 'AttributeError')
assert msg[0] == rpcserver.RPC_ERROR
assert msg[1] == self.request_id
assert msg[2] == 'WrappedException'
assert msg[3][1] == 'AttributeError'
def test_daemon_info(self):
self.protocol.dispatch(self.request_id, 'daemon.info', [], {})
msg = self.protocol.messages.pop()
self.assertEqual(msg[0], rpcserver.RPC_RESPONSE, str(msg))
self.assertEqual(msg[1], self.request_id, str(msg))
self.assertEqual(msg[2], deluge.common.get_version(), str(msg))
assert msg[0] == rpcserver.RPC_RESPONSE, str(msg)
assert msg[1] == self.request_id, str(msg)
assert msg[2] == deluge.common.get_version(), str(msg)

View File

@ -13,9 +13,9 @@ import deluge.component as component
import deluge.ui.web.server
from deluge import configmanager
from deluge.common import windows_check
from deluge.conftest import BaseTestCase
from deluge.ui.web.server import DelugeWeb
from .basetest import BaseTestCase
from .common import get_test_data_file
from .common_web import WebServerTestBase
from .daemon_base import DaemonBase
@ -23,15 +23,10 @@ from .daemon_base import DaemonBase
SECURITY_TESTS = bool(os.getenv('SECURITY_TESTS', False))
# TODO: This whole module has not been tested since migrating tests fully to pytest
class SecurityBaseTestCase:
if windows_check():
skip = 'windows cannot run .sh files'
elif not SECURITY_TESTS:
skip = 'Skipping security tests'
http_err = 'cannot run http tests on daemon'
def __init__(self):
@pytest.fixture(autouse=True)
def setvars(self):
self.home_dir = os.path.expanduser('~')
self.port = 8112
@ -54,10 +49,10 @@ class SecurityBaseTestCase:
if test == '-e':
results = results[0].split(b'\n')[7:-6]
self.assertTrue(len(results) > 3)
assert len(results) > 3
else:
self.assertIn(b'OK', results[0])
self.assertNotIn(b'NOT ok', results[0])
assert b'OK' in results[0]
assert b'NOT ok' not in results[0]
d.addCallback(on_result)
return d
@ -74,18 +69,12 @@ class SecurityBaseTestCase:
def test_secured_webserver_css_injection_vulnerability(self):
return self._run_test('-I')
def test_secured_webserver_ticketbleed_vulnerability(self):
return self._run_test('-T')
def test_secured_webserver_renegotiation_vulnerabilities(self):
return self._run_test('-R')
def test_secured_webserver_crime_vulnerability(self):
return self._run_test('-C')
def test_secured_webserver_breach_vulnerability(self):
return self._run_test('-B')
def test_secured_webserver_poodle_vulnerability(self):
return self._run_test('-O')
@ -119,33 +108,14 @@ class SecurityBaseTestCase:
def test_secured_webserver_preference(self):
return self._run_test('-P')
def test_secured_webserver_headers(self):
return self._run_test('-h')
def test_secured_webserver_ciphers(self):
return self._run_test('-e')
@pytest.mark.skipif(windows_check(), reason='windows cannot run .sh files')
@pytest.mark.skipif(not SECURITY_TESTS, reason='skipping security tests')
@pytest.mark.security
class DaemonSecurityTestCase(BaseTestCase, DaemonBase, SecurityBaseTestCase):
if windows_check():
skip = 'windows cannot start_core not enough arguments for format string'
def __init__(self, testname):
super().__init__(testname)
DaemonBase.__init__(self)
SecurityBaseTestCase.__init__(self)
def setUp(self):
skip = False
for not_http_test in ('breach', 'headers', 'ticketbleed'):
if not_http_test in self.id().split('.')[-1]:
self.skipTest(SecurityBaseTestCase.http_err)
skip = True
if not skip:
super().setUp()
class TestDaemonSecurity(BaseTestCase, DaemonBase, SecurityBaseTestCase):
def set_up(self):
d = self.common_set_up()
self.port = self.listen_port
@ -159,12 +129,10 @@ class DaemonSecurityTestCase(BaseTestCase, DaemonBase, SecurityBaseTestCase):
return d
@pytest.mark.skipif(windows_check(), reason='windows cannot run .sh files')
@pytest.mark.skipif(not SECURITY_TESTS, reason='skipping security tests')
@pytest.mark.security
class WebUISecurityTestBase(WebServerTestBase, SecurityBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
SecurityBaseTestCase.__init__(self)
class TestWebUISecurity(WebServerTestBase, SecurityBaseTestCase):
def start_webapi(self, arg):
self.port = self.webserver_listen_port = 8999
@ -180,3 +148,12 @@ class WebUISecurityTestBase(WebServerTestBase, SecurityBaseTestCase):
self.deluge_web.web_api.hostlist.config['hosts'][0] = tuple(host)
self.host_id = host[0]
self.deluge_web.start()
def test_secured_webserver_headers(self):
return self._run_test('-h')
def test_secured_webserver_breach_vulnerability(self):
return self._run_test('-B')
def test_secured_webserver_ticketbleed_vulnerability(self):
return self._run_test('-T')

View File

@ -5,14 +5,13 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import pytest_twisted
from twisted.internet.defer import maybeDeferred, succeed
from twisted.internet.task import Clock
import deluge.component as component
import deluge.ui.sessionproxy
from .basetest import BaseTestCase
from deluge.conftest import BaseTestCase
class Core:
@ -102,7 +101,7 @@ class Client:
client = Client()
class SessionProxyTestCase(BaseTestCase):
class TestSessionProxy(BaseTestCase):
def set_up(self):
self.clock = Clock()
self.patch(deluge.ui.sessionproxy, 'time', self.clock.seconds)
@ -124,38 +123,38 @@ class SessionProxyTestCase(BaseTestCase):
return component.deregister(self.sp)
def test_startup(self):
self.assertEqual(client.core.torrents['a'], self.sp.torrents['a'][1])
assert client.core.torrents['a'] == self.sp.torrents['a'][1]
def test_get_torrent_status_no_change(self):
d = self.sp.get_torrent_status('a', [])
d.addCallback(self.assertEqual, client.core.torrents['a'])
return d
@pytest_twisted.ensureDeferred
async def test_get_torrent_status_no_change(self):
result = await self.sp.get_torrent_status('a', [])
assert result == client.core.torrents['a']
def test_get_torrent_status_change_with_cache(self):
@pytest_twisted.ensureDeferred
async def test_get_torrent_status_change_with_cache(self):
client.core.torrents['a']['key1'] = 2
d = self.sp.get_torrent_status('a', ['key1'])
d.addCallback(self.assertEqual, {'key1': 1})
return d
result = await self.sp.get_torrent_status('a', ['key1'])
assert result == {'key1': 1}
def test_get_torrent_status_change_without_cache(self):
@pytest_twisted.ensureDeferred
async def test_get_torrent_status_change_without_cache(self):
client.core.torrents['a']['key1'] = 2
self.clock.advance(self.sp.cache_time + 0.1)
d = self.sp.get_torrent_status('a', [])
d.addCallback(self.assertEqual, client.core.torrents['a'])
return d
result = await self.sp.get_torrent_status('a', [])
assert result == client.core.torrents['a']
def test_get_torrent_status_key_not_updated(self):
@pytest_twisted.ensureDeferred
async def test_get_torrent_status_key_not_updated(self):
self.clock.advance(self.sp.cache_time + 0.1)
self.sp.get_torrent_status('a', ['key1'])
client.core.torrents['a']['key2'] = 99
d = self.sp.get_torrent_status('a', ['key2'])
d.addCallback(self.assertEqual, {'key2': 99})
return d
result = await self.sp.get_torrent_status('a', ['key2'])
assert result == {'key2': 99}
def test_get_torrents_status_key_not_updated(self):
@pytest_twisted.ensureDeferred
async def test_get_torrents_status_key_not_updated(self):
self.clock.advance(self.sp.cache_time + 0.1)
self.sp.get_torrents_status({'id': ['a']}, ['key1'])
client.core.torrents['a']['key2'] = 99
d = self.sp.get_torrents_status({'id': ['a']}, ['key2'])
d.addCallback(self.assertEqual, {'a': {'key2': 99}})
return d
result = await self.sp.get_torrents_status({'id': ['a']}, ['key2'])
assert result == {'a': {'key2': 99}}

View File

@ -9,30 +9,28 @@ import time
from base64 import b64encode
from unittest import mock
import pytest
from twisted.internet import defer, reactor
from twisted.internet.task import deferLater
from twisted.trial import unittest
import deluge.component as component
import deluge.core.torrent
import deluge.tests.common as common
from deluge._libtorrent import lt
from deluge.common import VersionSplit, utf8_encode_structure
from deluge.conftest import BaseTestCase
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.core.torrent import Torrent
from deluge.core.torrentmanager import TorrentManager, TorrentState
from .basetest import BaseTestCase
class TorrentTestCase(BaseTestCase):
class TestTorrent(BaseTestCase):
def setup_config(self):
config_dir = common.set_tmp_config_dir()
core_config = deluge.config.Config(
'core.conf',
defaults=deluge.core.preferencesmanager.DEFAULT_PREFS,
config_dir=config_dir,
config_dir=self.config_dir,
)
core_config.save()
@ -64,7 +62,7 @@ class TorrentTestCase(BaseTestCase):
def assert_state(self, torrent, state):
torrent.update_state()
self.assertEqual(torrent.state, state)
assert torrent.state == state
def get_torrent_atp(self, filename):
filename = common.get_test_data_file(filename)
@ -88,11 +86,11 @@ class TorrentTestCase(BaseTestCase):
torrent = Torrent(handle, {})
result = torrent.get_file_priorities()
self.assertTrue(all(x == 4 for x in result))
assert all(x == 4 for x in result)
new_priorities = [3, 1, 2, 0, 5, 6, 7]
torrent.set_file_priorities(new_priorities)
self.assertEqual(torrent.get_file_priorities(), new_priorities)
assert torrent.get_file_priorities() == new_priorities
# Test with handle.piece_priorities as handle.file_priorities async
# updates and will return old value. Also need to remove a priority
@ -100,7 +98,7 @@ class TorrentTestCase(BaseTestCase):
time.sleep(0.6) # Delay to wait for alert from lt
piece_prio = handle.piece_priorities()
result = all(p in piece_prio for p in [3, 2, 0, 5, 6, 7])
self.assertTrue(result)
assert result
def test_set_prioritize_first_last_pieces(self):
piece_indexes = [
@ -145,14 +143,14 @@ class TorrentTestCase(BaseTestCase):
priorities = handle.piece_priorities()
# The length of the list of new priorites is the same as the original
self.assertEqual(len(priorities_original), len(priorities))
assert len(priorities_original) == len(priorities)
# Test the priority of all the pieces against the calculated indexes.
for idx, priority in enumerate(priorities):
if idx in prioritized_piece_indexes:
self.assertEqual(priorities[idx], 7)
assert priorities[idx] == 7
else:
self.assertEqual(priorities[idx], 4)
assert priorities[idx] == 4
# self.print_priority_list(priorities)
@ -168,7 +166,7 @@ class TorrentTestCase(BaseTestCase):
# Test the priority of the prioritized pieces
for i in priorities:
self.assertEqual(priorities[i], 4)
assert priorities[i] == 4
# self.print_priority_list(priorities)
@ -209,7 +207,7 @@ class TorrentTestCase(BaseTestCase):
def test_torrent_error_resume_data_unaltered(self):
if VersionSplit(lt.__version__) >= VersionSplit('1.2.0.0'):
raise unittest.SkipTest('Test not working as expected on lt 1.2 or greater')
pytest.skip('Test not working as expected on lt 1.2 or greater')
resume_data = {
'active_time': 13399,
@ -277,7 +275,7 @@ class TorrentTestCase(BaseTestCase):
tm_resume_data = lt.bdecode(
self.core.torrentmanager.resume_data[torrent.torrent_id]
)
self.assertEqual(tm_resume_data, resume_data)
assert tm_resume_data == resume_data
return deferLater(reactor, 0.5, assert_resume_data)
@ -285,7 +283,7 @@ class TorrentTestCase(BaseTestCase):
atp = self.get_torrent_atp('test_torrent.file.torrent')
handle = self.session.add_torrent(atp)
self.torrent = Torrent(handle, {})
self.assertEqual(self.torrent.get_eta(), 0)
assert self.torrent.get_eta() == 0
self.torrent.status = mock.MagicMock()
self.torrent.status.upload_payload_rate = 5000
@ -295,18 +293,18 @@ class TorrentTestCase(BaseTestCase):
self.torrent.is_finished = True
self.torrent.options = {'stop_at_ratio': False}
# Test finished and uploading but no stop_at_ratio set.
self.assertEqual(self.torrent.get_eta(), 0)
assert self.torrent.get_eta() == 0
self.torrent.options = {'stop_at_ratio': True, 'stop_ratio': 1.5}
result = self.torrent.get_eta()
self.assertEqual(result, 2)
self.assertIsInstance(result, int)
assert result == 2
assert isinstance(result, int)
def test_get_eta_downloading(self):
atp = self.get_torrent_atp('test_torrent.file.torrent')
handle = self.session.add_torrent(atp)
self.torrent = Torrent(handle, {})
self.assertEqual(self.torrent.get_eta(), 0)
assert self.torrent.get_eta() == 0
self.torrent.status = mock.MagicMock()
self.torrent.status.download_payload_rate = 50
@ -314,15 +312,15 @@ class TorrentTestCase(BaseTestCase):
self.torrent.status.total_wanted_done = 5000
result = self.torrent.get_eta()
self.assertEqual(result, 100)
self.assertIsInstance(result, int)
assert result == 100
assert isinstance(result, int)
def test_get_name_unicode(self):
"""Test retrieving a unicode torrent name from libtorrent."""
atp = self.get_torrent_atp('unicode_file.torrent')
handle = self.session.add_torrent(atp)
self.torrent = Torrent(handle, {})
self.assertEqual(self.torrent.get_name(), 'সুকুমার রায়.txt')
assert self.torrent.get_name() == 'সুকুমার রায়.txt'
def test_rename_unicode(self):
"""Test renaming file/folders with unicode filenames."""
@ -333,15 +331,15 @@ class TorrentTestCase(BaseTestCase):
TorrentManager.save_resume_data = mock.MagicMock
result = self.torrent.rename_folder('unicode_filenames', 'Горбачёв')
self.assertIsInstance(result, defer.DeferredList)
assert isinstance(result, defer.DeferredList)
result = self.torrent.rename_files([[0, 'new_рбачёв']])
self.assertIsNone(result)
assert result is None
def test_connect_peer_port(self):
"""Test to ensure port is int for libtorrent"""
atp = self.get_torrent_atp('test_torrent.file.torrent')
handle = self.session.add_torrent(atp)
self.torrent = Torrent(handle, {})
self.assertFalse(self.torrent.connect_peer('127.0.0.1', 'text'))
self.assertTrue(self.torrent.connect_peer('127.0.0.1', '1234'))
assert not self.torrent.connect_peer('127.0.0.1', 'text')
assert self.torrent.connect_peer('127.0.0.1', '1234')

View File

@ -11,24 +11,24 @@ from base64 import b64encode
from unittest import mock
import pytest
from twisted.internet import defer, task
import pytest_twisted
from twisted.internet import task
from deluge import component
from deluge.bencode import bencode
from deluge.conftest import BaseTestCase
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.error import InvalidTorrentError
from . import common
from .basetest import BaseTestCase
warnings.filterwarnings('ignore', category=RuntimeWarning)
warnings.resetwarnings()
class TorrentmanagerTestCase(BaseTestCase):
class TestTorrentmanager(BaseTestCase):
def set_up(self):
self.config_dir = common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
self.core = Core()
self.core.config.config['lsd'] = False
@ -44,7 +44,7 @@ class TorrentmanagerTestCase(BaseTestCase):
return component.shutdown().addCallback(on_shutdown)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_remove_torrent(self):
filename = common.get_test_data_file('test.torrent')
with open(filename, 'rb') as _file:
@ -52,9 +52,9 @@ class TorrentmanagerTestCase(BaseTestCase):
torrent_id = yield self.core.add_torrent_file_async(
filename, b64encode(filedump), {}
)
self.assertTrue(self.tm.remove(torrent_id, False))
assert self.tm.remove(torrent_id, False)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_remove_magnet(self):
"""Test remove magnet before received metadata and delete_copies is True"""
magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173'
@ -62,9 +62,10 @@ class TorrentmanagerTestCase(BaseTestCase):
self.core.config.config['copy_torrent_file'] = True
self.core.config.config['del_copy_torrent_file'] = True
torrent_id = yield self.core.add_torrent_magnet(magnet, options)
self.assertTrue(self.tm.remove(torrent_id, False))
assert self.tm.remove(torrent_id, False)
def test_prefetch_metadata(self):
@pytest_twisted.ensureDeferred
async def test_prefetch_metadata(self):
from deluge._libtorrent import lt
with open(common.get_test_data_file('test.torrent'), 'rb') as _file:
@ -114,14 +115,16 @@ class TorrentmanagerTestCase(BaseTestCase):
)
),
)
self.assertEqual(expected, self.successResultOf(d))
assert expected == await d
def test_prefetch_metadata_timeout(self):
@pytest_twisted.ensureDeferred
async def test_prefetch_metadata_timeout(self):
magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173'
d = self.tm.prefetch_metadata(magnet, 30)
self.clock.advance(30)
result = await d
expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', b'')
return d.addCallback(self.assertEqual, expected)
assert result == expected
@pytest.mark.todo
def test_remove_torrent_false(self):
@ -129,9 +132,8 @@ class TorrentmanagerTestCase(BaseTestCase):
common.todo_test(self)
def test_remove_invalid_torrent(self):
self.assertRaises(
InvalidTorrentError, self.tm.remove, 'torrentidthatdoesntexist'
)
with pytest.raises(InvalidTorrentError):
self.tm.remove('torrentidthatdoesntexist')
def test_open_state(self):
"""Open a state with a UTF-8 encoded torrent filename."""
@ -141,4 +143,4 @@ class TorrentmanagerTestCase(BaseTestCase):
)
state = self.tm.open_state()
self.assertEqual(len(state.torrents), 1)
assert len(state.torrents) == 1

View File

@ -8,15 +8,12 @@
#
import pytest
from twisted.trial import unittest
import deluge.component as component
from deluge.configmanager import ConfigManager
from deluge.conftest import BaseTestCase
from deluge.i18n import setup_translation
from . import common
from .basetest import BaseTestCase
# Allow running other tests without GTKUI dependencies available
try:
# pylint: disable=ungrouped-imports
@ -37,7 +34,7 @@ setup_translation()
@pytest.mark.gtkui
class TorrentviewTestCase(BaseTestCase):
class TestTorrentview(BaseTestCase):
default_column_index = [
'filter',
@ -107,9 +104,8 @@ class TorrentviewTestCase(BaseTestCase):
def set_up(self):
if libs_available is False:
raise unittest.SkipTest('GTKUI dependencies not available')
pytest.skip('GTKUI dependencies not available')
common.set_tmp_config_dir()
# MainWindow loads this config file, so lets make sure it contains the defaults
ConfigManager('gtk3ui.conf', defaults=DEFAULT_PREFS)
self.mainwindow = MainWindow()
@ -121,36 +117,23 @@ class TorrentviewTestCase(BaseTestCase):
return component.shutdown()
def test_torrentview_columns(self):
self.assertEqual(
self.torrentview.column_index, TorrentviewTestCase.default_column_index
)
self.assertEqual(
self.torrentview.liststore_columns,
TorrentviewTestCase.default_liststore_columns,
)
self.assertEqual(
self.torrentview.columns['Download Folder'].column_indices, [30]
)
assert self.torrentview.column_index == self.default_column_index
assert self.torrentview.liststore_columns == self.default_liststore_columns
assert self.torrentview.columns['Download Folder'].column_indices == [30]
def test_add_column(self):
# Add a text column
test_col = 'Test column'
self.torrentview.add_text_column(test_col, status_field=['label'])
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1,
assert (
len(self.torrentview.liststore_columns)
== len(self.default_liststore_columns) + 1
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col)
self.assertEqual(self.torrentview.columns[test_col].column_indices, [33])
assert len(self.torrentview.column_index) == len(self.default_column_index) + 1
assert self.torrentview.column_index[-1] == test_col
assert self.torrentview.columns[test_col].column_indices == [33]
def test_add_columns(self):
# Add a text column
test_col = 'Test column'
self.torrentview.add_text_column(test_col, status_field=['label'])
@ -159,50 +142,35 @@ class TorrentviewTestCase(BaseTestCase):
test_col2 = 'Test column2'
self.torrentview.add_text_column(test_col2, status_field=['label2'])
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2,
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 2,
assert (
len(self.torrentview.liststore_columns)
== len(self.default_liststore_columns) + 2
)
assert len(self.torrentview.column_index) == len(self.default_column_index) + 2
# test_col
self.assertEqual(self.torrentview.column_index[-2], test_col)
self.assertEqual(self.torrentview.columns[test_col].column_indices, [33])
assert self.torrentview.column_index[-2] == test_col
assert self.torrentview.columns[test_col].column_indices == [33]
# test_col2
self.assertEqual(self.torrentview.column_index[-1], test_col2)
self.assertEqual(self.torrentview.columns[test_col2].column_indices, [34])
assert self.torrentview.column_index[-1] == test_col2
assert self.torrentview.columns[test_col2].column_indices == [34]
def test_remove_column(self):
# Add and remove text column
test_col = 'Test column'
self.torrentview.add_text_column(test_col, status_field=['label'])
self.torrentview.remove_column(test_col)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns),
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index),
)
self.assertEqual(
self.torrentview.column_index[-1],
TorrentviewTestCase.default_column_index[-1],
)
self.assertEqual(
self.torrentview.columns[
TorrentviewTestCase.default_column_index[-1]
].column_indices,
[32],
assert len(self.torrentview.liststore_columns) == len(
self.default_liststore_columns
)
assert len(self.torrentview.column_index) == len(self.default_column_index)
assert self.torrentview.column_index[-1] == self.default_column_index[-1]
assert self.torrentview.columns[
self.default_column_index[-1]
].column_indices == [32]
def test_remove_columns(self):
# Add two columns
test_col = 'Test column'
self.torrentview.add_text_column(test_col, status_field=['label'])
@ -211,74 +179,47 @@ class TorrentviewTestCase(BaseTestCase):
# Remove test_col
self.torrentview.remove_column(test_col)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 1,
assert (
len(self.torrentview.liststore_columns)
== len(self.default_liststore_columns) + 1
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col2)
self.assertEqual(self.torrentview.columns[test_col2].column_indices, [33])
assert len(self.torrentview.column_index) == len(self.default_column_index) + 1
assert self.torrentview.column_index[-1] == test_col2
assert self.torrentview.columns[test_col2].column_indices == [33]
# Remove test_col2
self.torrentview.remove_column(test_col2)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns),
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index),
)
self.assertEqual(
self.torrentview.column_index[-1],
TorrentviewTestCase.default_column_index[-1],
)
self.assertEqual(
self.torrentview.columns[
TorrentviewTestCase.default_column_index[-1]
].column_indices,
[32],
assert len(self.torrentview.liststore_columns) == len(
self.default_liststore_columns
)
assert len(self.torrentview.column_index) == len(self.default_column_index)
assert self.torrentview.column_index[-1] == self.default_column_index[-1]
assert self.torrentview.columns[
self.default_column_index[-1]
].column_indices == [32]
def test_add_remove_column_multiple_types(self):
# Add a column with multiple column types
test_col3 = 'Test column3'
self.torrentview.add_progress_column(
test_col3, status_field=['progress', 'label3'], col_types=[float, str]
)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns) + 2,
assert (
len(self.torrentview.liststore_columns)
== len(self.default_liststore_columns) + 2
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index) + 1,
)
self.assertEqual(self.torrentview.column_index[-1], test_col3)
self.assertEqual(self.torrentview.columns[test_col3].column_indices, [33, 34])
assert len(self.torrentview.column_index) == len(self.default_column_index) + 1
assert self.torrentview.column_index[-1] == test_col3
assert self.torrentview.columns[test_col3].column_indices == [33, 34]
# Remove multiple column-types column
self.torrentview.remove_column(test_col3)
self.assertEqual(
len(self.torrentview.liststore_columns),
len(TorrentviewTestCase.default_liststore_columns),
)
self.assertEqual(
len(self.torrentview.column_index),
len(TorrentviewTestCase.default_column_index),
)
self.assertEqual(
self.torrentview.column_index[-1],
TorrentviewTestCase.default_column_index[-1],
)
self.assertEqual(
self.torrentview.columns[
TorrentviewTestCase.default_column_index[-1]
].column_indices,
[32],
assert len(self.torrentview.liststore_columns) == len(
self.default_liststore_columns
)
assert len(self.torrentview.column_index) == len(self.default_column_index)
assert self.torrentview.column_index[-1] == self.default_column_index[-1]
assert self.torrentview.columns[
self.default_column_index[-1]
].column_indices == [32]

View File

@ -5,20 +5,20 @@
#
import pytest
import pytest_twisted
import deluge.component as component
import deluge.ui.tracker_icons
from deluge.conftest import BaseTestCase
from deluge.ui.tracker_icons import TrackerIcon, TrackerIcons
from . import common
from .basetest import BaseTestCase
common.set_tmp_config_dir()
common.disable_new_release_check()
@pytest.mark.internet
class TrackerIconsTestCase(BaseTestCase):
class TestTrackerIcons(BaseTestCase):
def set_up(self):
# Disable resizing with Pillow for consistency.
self.patch(deluge.ui.tracker_icons, 'Image', None)
@ -27,48 +27,43 @@ class TrackerIconsTestCase(BaseTestCase):
def tear_down(self):
return component.shutdown()
def test_get_deluge_png(self):
@pytest_twisted.ensureDeferred
async def test_get_deluge_png(self):
# Deluge has a png favicon link
icon = TrackerIcon(common.get_test_data_file('deluge.png'))
d = self.icons.fetch('deluge-torrent.org')
d.addCallback(self.assertNotIdentical, None)
d.addCallback(self.assertEqual, icon)
return d
result = await self.icons.fetch('deluge-torrent.org')
assert result == icon
def test_get_google_ico(self):
@pytest_twisted.ensureDeferred
async def test_get_google_ico(self):
# Google doesn't have any icon links
# So instead we'll grab its favicon.ico
icon = TrackerIcon(common.get_test_data_file('google.ico'))
d = self.icons.fetch('www.google.com')
d.addCallback(self.assertNotIdentical, None)
d.addCallback(self.assertEqual, icon)
return d
result = await self.icons.fetch('www.google.com')
assert result == icon
def test_get_google_ico_hebrew(self):
@pytest_twisted.ensureDeferred
async def test_get_google_ico_hebrew(self):
"""Test that Google.co.il page is read as UTF-8"""
icon = TrackerIcon(common.get_test_data_file('google.ico'))
d = self.icons.fetch('www.google.co.il')
d.addCallback(self.assertNotIdentical, None)
d.addCallback(self.assertEqual, icon)
return d
result = await self.icons.fetch('www.google.co.il')
assert result == icon
def test_get_google_ico_with_redirect(self):
@pytest_twisted.ensureDeferred
async def test_get_google_ico_with_redirect(self):
# google.com redirects to www.google.com
icon = TrackerIcon(common.get_test_data_file('google.ico'))
d = self.icons.fetch('google.com')
d.addCallback(self.assertNotIdentical, None)
d.addCallback(self.assertEqual, icon)
return d
result = await self.icons.fetch('google.com')
assert result == icon
def test_get_seo_svg_with_sni(self):
@pytest_twisted.ensureDeferred
async def test_get_seo_svg_with_sni(self):
# seo using certificates with SNI support only
icon = TrackerIcon(common.get_test_data_file('seo.svg'))
d = self.icons.fetch('www.seo.com')
d.addCallback(self.assertNotIdentical, None)
d.addCallback(self.assertEqual, icon)
return d
result = await self.icons.fetch('www.seo.com')
assert result == icon
def test_get_empty_string_tracker(self):
d = self.icons.fetch('')
d.addCallback(self.assertIdentical, None)
return d
@pytest_twisted.ensureDeferred
async def test_get_empty_string_tracker(self):
result = await self.icons.fetch('')
assert result is None

View File

@ -8,8 +8,8 @@
import base64
import pytest
import rencode
from twisted.trial import unittest
import deluge.log
from deluge.transfer import DelugeTransferProtocol
@ -109,8 +109,9 @@ class TransferTestClass(DelugeTransferProtocol):
self.message_received(request)
class DelugeTransferProtocolTestCase(unittest.TestCase):
def setUp(self): # NOQA: N803
class TestDelugeTransferProtocol:
@pytest.fixture(autouse=True)
def set_up(self):
"""
The expected messages corresponds to the test messages (msg1, msg2) after they've been processed
by DelugeTransferProtocol.send, which means that they've first been encoded with rencode,
@ -157,7 +158,7 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
# Get the data as sent by DelugeTransferProtocol
messages = self.transfer.get_messages_out_joined()
base64_encoded = base64.b64encode(messages)
self.assertEqual(base64_encoded, self.msg1_expected_compressed_base64)
assert base64_encoded == self.msg1_expected_compressed_base64
def test_receive_one_message(self):
"""
@ -170,7 +171,7 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
)
# Get the data as sent by DelugeTransferProtocol
messages = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(messages))
assert rencode.dumps(self.msg1) == rencode.dumps(messages)
def test_receive_old_message(self):
"""
@ -178,9 +179,9 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
"""
self.transfer.dataReceived(rencode.dumps(self.msg1))
self.assertEqual(len(self.transfer.get_messages_in()), 0)
self.assertEqual(self.transfer._message_length, 0)
self.assertEqual(len(self.transfer._buffer), 0)
assert len(self.transfer.get_messages_in()) == 0
assert self.transfer._message_length == 0
assert len(self.transfer._buffer) == 0
def test_receive_two_concatenated_messages(self):
"""
@ -195,9 +196,9 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
# Get the data as sent by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message1))
assert rencode.dumps(self.msg1) == rencode.dumps(message1)
message2 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg2), rencode.dumps(message2))
assert rencode.dumps(self.msg2) == rencode.dumps(message2)
def test_receive_three_messages_in_parts(self):
"""
@ -234,17 +235,15 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
else:
expected_msgs_received_count = 0
# Verify that the expected number of complete messages has arrived
self.assertEqual(
expected_msgs_received_count, len(self.transfer.get_messages_in())
)
assert expected_msgs_received_count == len(self.transfer.get_messages_in())
# Get the data as received by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message1))
assert rencode.dumps(self.msg1) == rencode.dumps(message1)
message2 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg2), rencode.dumps(message2))
assert rencode.dumps(self.msg2) == rencode.dumps(message2)
message3 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message3))
assert rencode.dumps(self.msg1) == rencode.dumps(message3)
# Remove underscore to enable test, or run the test directly:
# tests $ trial test_transfer.DelugeTransferProtocolTestCase._test_rencode_fail_protocol
@ -314,11 +313,11 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
# Get the data as received by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message1))
assert rencode.dumps(self.msg1) == rencode.dumps(message1)
message2 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg2), rencode.dumps(message2))
assert rencode.dumps(self.msg2) == rencode.dumps(message2)
message3 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message3))
assert rencode.dumps(self.msg1) == rencode.dumps(message3)
def test_receive_middle_of_header(self):
"""
@ -341,19 +340,19 @@ class DelugeTransferProtocolTestCase(unittest.TestCase):
self.transfer.dataReceived(two_concatenated[: first_len + 2])
# Should be 1 message in the list
self.assertEqual(1, len(self.transfer.get_messages_in()))
assert 1 == len(self.transfer.get_messages_in())
# Send the rest
self.transfer.dataReceived(two_concatenated[first_len + 2 :])
# Should be 2 messages in the list
self.assertEqual(2, len(self.transfer.get_messages_in()))
assert 2 == len(self.transfer.get_messages_in())
# Get the data as sent by DelugeTransferProtocol
message1 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg1), rencode.dumps(message1))
assert rencode.dumps(self.msg1) == rencode.dumps(message1)
message2 = self.transfer.get_messages_in().pop(0)
self.assertEqual(rencode.dumps(self.msg2), rencode.dumps(message2))
assert rencode.dumps(self.msg2) == rencode.dumps(message2)
# Needs file containing big data structure e.g. like thetorrent list as it is transfered by the daemon
# def test_simulate_big_transfer(self):

View File

@ -5,26 +5,19 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
from twisted.trial import unittest
from deluge.ui.common import TorrentInfo
from . import common
class UICommonTestCase(unittest.TestCase):
def setUp(self): # NOQA: N803
pass
def tearDown(self): # NOQA: N803
pass
class TestUICommon:
def test_hash_optional_single_file(self):
"""Ensure single file with `ed2k` and `sha1` keys are not in filetree output."""
filename = common.get_test_data_file('test.torrent')
files_tree = {'azcvsupdater_2.6.2.jar': (0, 307949, True)}
ti = TorrentInfo(filename, filetree=1)
self.assertEqual(ti.files_tree, files_tree)
assert ti.files_tree == files_tree
files_tree2 = {
'contents': {
@ -37,7 +30,7 @@ class UICommonTestCase(unittest.TestCase):
}
}
ti = TorrentInfo(filename, filetree=2)
self.assertEqual(ti.files_tree, files_tree2)
assert ti.files_tree == files_tree2
def test_hash_optional_multi_file(self):
"""Ensure multi-file with `filehash` and `ed2k` are keys not in filetree output."""
@ -49,7 +42,7 @@ class UICommonTestCase(unittest.TestCase):
}
}
ti = TorrentInfo(filename, filetree=1)
self.assertEqual(ti.files_tree, files_tree)
assert ti.files_tree == files_tree
filestree2 = {
'contents': {
@ -78,14 +71,14 @@ class UICommonTestCase(unittest.TestCase):
'type': 'dir',
}
ti = TorrentInfo(filename, filetree=2)
self.assertEqual(ti.files_tree, filestree2)
assert ti.files_tree == filestree2
def test_hash_optional_md5sum(self):
# Ensure `md5sum` key is not included in filetree output
filename = common.get_test_data_file('md5sum.torrent')
files_tree = {'test': {'lol': (0, 4, True), 'rofl': (1, 5, True)}}
ti = TorrentInfo(filename, filetree=1)
self.assertEqual(ti.files_tree, files_tree)
assert ti.files_tree == files_tree
ti = TorrentInfo(filename, filetree=2)
files_tree2 = {
'contents': {
@ -113,12 +106,12 @@ class UICommonTestCase(unittest.TestCase):
},
'type': 'dir',
}
self.assertEqual(ti.files_tree, files_tree2)
assert ti.files_tree == files_tree2
def test_utf8_encoded_paths(self):
filename = common.get_test_data_file('test.torrent')
ti = TorrentInfo(filename)
self.assertTrue('azcvsupdater_2.6.2.jar' in ti.files_tree)
assert 'azcvsupdater_2.6.2.jar' in ti.files_tree
def test_utf8_encoded_paths2(self):
filename = common.get_test_data_file('unicode_filenames.torrent')
@ -133,11 +126,11 @@ class UICommonTestCase(unittest.TestCase):
ti = TorrentInfo(filename)
files_tree = ti.files_tree['unicode_filenames']
self.assertIn(filepath1, files_tree)
self.assertIn(filepath2, files_tree)
self.assertIn(filepath3, files_tree)
self.assertIn(filepath4, files_tree)
self.assertIn(filepath5, files_tree)
assert filepath1 in files_tree
assert filepath2 in files_tree
assert filepath3 in files_tree
assert filepath4 in files_tree
assert filepath5 in files_tree
result_files = [
{
@ -163,4 +156,4 @@ class UICommonTestCase(unittest.TestCase):
{'download': True, 'path': 'unicode_filenames/' + filepath1, 'size': 1771},
]
self.assertCountEqual(ti.files, result_files)
assert len(ti.files) == len(result_files)

View File

@ -6,12 +6,12 @@
import argparse
import pytest
from deluge.ui.console.cmdline.commands.add import Command
from deluge.ui.console.cmdline.commands.config import json_eval
from deluge.ui.console.widgets.fields import TextInput
from .basetest import BaseTestCase
class MockParent:
def __init__(self):
@ -20,13 +20,11 @@ class MockParent:
self.encoding = 'utf8'
class UIConsoleFieldTestCase(BaseTestCase):
def setUp(self): # NOQA: N803
class TestUIConsoleField:
@pytest.fixture(autouse=True)
def set_up(self):
self.parent = MockParent()
def tearDown(self): # NOQA: N803
pass
def test_text_input(self):
def move_func(self, r, c):
self._cursor_row = r
@ -41,48 +39,42 @@ class UIConsoleFieldTestCase(BaseTestCase):
'/text/field/file/path',
complete=False,
)
self.assertTrue(t)
self.assertTrue(t.handle_read(33))
assert t
assert t.handle_read(33)
class UIConsoleCommandsTestCase(BaseTestCase):
def setUp(self):
pass
def tearDown(self):
pass
class TestUIConsoleCommands:
def test_add_move_completed(self):
completed_path = 'completed_path'
parser = argparse.ArgumentParser()
cmd = Command()
cmd.add_arguments(parser)
args = parser.parse_args(['torrent', '-m', completed_path])
self.assertEqual(args.move_completed_path, completed_path)
assert args.move_completed_path == completed_path
args = parser.parse_args(['torrent', '--move-path', completed_path])
self.assertEqual(args.move_completed_path, completed_path)
assert args.move_completed_path == completed_path
def test_config_json_eval(self):
self.assertEqual(json_eval('/downloads'), '/downloads')
self.assertEqual(json_eval('/dir/with space'), '/dir/with space')
self.assertEqual(json_eval('c:\\\\downloads'), 'c:\\\\downloads')
self.assertEqual(json_eval('c:/downloads'), 'c:/downloads')
assert json_eval('/downloads') == '/downloads'
assert json_eval('/dir/with space') == '/dir/with space'
assert json_eval('c:\\\\downloads') == 'c:\\\\downloads'
assert json_eval('c:/downloads') == 'c:/downloads'
# Ensure newlines are split and only first setting is used.
self.assertEqual(json_eval('setting\nwithneline'), 'setting')
assert json_eval('setting\nwithneline') == 'setting'
# Allow both parentheses and square brackets.
self.assertEqual(json_eval('(8000, 8001)'), [8000, 8001])
self.assertEqual(json_eval('[8000, 8001]'), [8000, 8001])
self.assertEqual(json_eval('["abc", "def"]'), ['abc', 'def'])
self.assertEqual(json_eval('{"foo": "bar"}'), {'foo': 'bar'})
self.assertEqual(json_eval('{"number": 1234}'), {'number': 1234})
assert json_eval('(8000, 8001)') == [8000, 8001]
assert json_eval('[8000, 8001]') == [8000, 8001]
assert json_eval('["abc", "def"]') == ['abc', 'def']
assert json_eval('{"foo": "bar"}') == {'foo': 'bar'}
assert json_eval('{"number": 1234}') == {'number': 1234}
# Hex string for peer_tos.
self.assertEqual(json_eval('0x00'), '0x00')
self.assertEqual(json_eval('1000'), 1000)
self.assertEqual(json_eval('-6'), -6)
self.assertEqual(json_eval('10.5'), 10.5)
self.assertEqual(json_eval('True'), True)
self.assertEqual(json_eval('false'), False)
self.assertEqual(json_eval('none'), None)
assert json_eval('0x00') == '0x00'
assert json_eval('1000') == 1000
assert json_eval('-6') == -6
assert json_eval('10.5') == 10.5
assert json_eval('True')
assert not json_eval('false')
assert json_eval('none') is None
# Empty values to clear config key.
self.assertEqual(json_eval('[]'), [])
self.assertEqual(json_eval(''), '')
assert json_eval('[]') == []
assert json_eval('') == ''

View File

@ -12,6 +12,7 @@ from io import StringIO
from unittest import mock
import pytest
import pytest_twisted
from twisted.internet import defer
import deluge
@ -21,11 +22,11 @@ import deluge.ui.console.cmdline.commands.quit
import deluge.ui.console.main
import deluge.ui.web.server
from deluge.common import get_localhost_auth, windows_check
from deluge.conftest import BaseTestCase
from deluge.ui import ui_entry
from deluge.ui.web.server import DelugeWeb
from . import common
from .basetest import BaseTestCase
from .daemon_base import DaemonBase
DEBUG_COMMAND = False
@ -56,11 +57,7 @@ class StringFileDescriptor:
class UIBaseTestCase:
def __init__(self):
self.var = {}
def set_up(self):
common.set_tmp_config_dir()
common.setup_test_logger(level='info', prefix=self.id())
return component.start()
@ -76,24 +73,14 @@ class UIBaseTestCase:
class UIWithDaemonBaseTestCase(UIBaseTestCase, DaemonBase):
"""Subclass for test that require a deluged daemon"""
def __init__(self):
UIBaseTestCase.__init__(self)
def set_up(self):
d = self.common_set_up()
common.setup_test_logger(level='info', prefix=self.id())
d.addCallback(self.start_core)
return d
def tear_down(self):
d = UIBaseTestCase.tear_down(self)
d.addCallback(self.terminate_core)
return d
class DelugeEntryTestCase(BaseTestCase):
class TestDelugeEntry(BaseTestCase):
def set_up(self):
common.set_tmp_config_dir()
return component.start()
def tear_down(self):
@ -109,10 +96,11 @@ class DelugeEntryTestCase(BaseTestCase):
self.patch(argparse._sys, 'stdout', fd)
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.assertRaises(SystemExit, ui_entry.start_ui)
self.assertTrue('usage: deluge' in fd.out.getvalue())
self.assertTrue('UI Options:' in fd.out.getvalue())
self.assertTrue('* console' in fd.out.getvalue())
with pytest.raises(SystemExit):
ui_entry.start_ui()
assert 'usage: deluge' in fd.out.getvalue()
assert 'UI Options:' in fd.out.getvalue()
assert '* console' in fd.out.getvalue()
def test_start_default(self):
self.patch(sys, 'argv', ['./deluge'])
@ -147,17 +135,12 @@ class DelugeEntryTestCase(BaseTestCase):
# Just test that no exception is raised
ui_entry.start_ui()
self.assertEqual(_level[0], 'info')
assert _level[0] == 'info'
class GtkUIBaseTestCase(UIBaseTestCase):
"""Implement all GtkUI tests here"""
if windows_check():
skip = (
'Gtk tests on Windows have some issue with the mutex already being created'
)
def test_start_gtk3ui(self):
self.patch(sys, 'argv', self.var['sys_arg_cmd'])
@ -168,38 +151,27 @@ class GtkUIBaseTestCase(UIBaseTestCase):
@pytest.mark.gtkui
class GtkUIDelugeScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
GtkUIBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge gtk'
self.var['start_cmd'] = ui_entry.start_ui
self.var['sys_arg_cmd'] = ['./deluge', 'gtk']
def set_up(self):
return GtkUIBaseTestCase.set_up(self)
def tear_down(self):
return GtkUIBaseTestCase.tear_down(self)
class TestGtkUIDelugeScriptEntry(BaseTestCase, GtkUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge gtk',
'start_cmd': ui_entry.start_ui,
'sys_arg_cmd': ['./deluge', 'gtk'],
}
@pytest.mark.gtkui
class GtkUIScriptEntryTestCase(BaseTestCase, GtkUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
GtkUIBaseTestCase.__init__(self)
class TestGtkUIScriptEntry(BaseTestCase, GtkUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
from deluge.ui import gtk3
self.var['cmd_name'] = 'deluge-gtk'
self.var['start_cmd'] = gtk3.start
self.var['sys_arg_cmd'] = ['./deluge-gtk']
def set_up(self):
return GtkUIBaseTestCase.set_up(self)
def tear_down(self):
return GtkUIBaseTestCase.tear_down(self)
request.cls.var = {
'cmd_name': 'deluge-gtk',
'start_cmd': gtk3.start,
'sys_arg_cmd': ['./deluge-gtk'],
}
class DelugeWebMock(DelugeWeb):
@ -237,41 +209,31 @@ class WebUIBaseTestCase(UIBaseTestCase):
self.patch(deluge.ui.web.server, 'DelugeWeb', DelugeWebMock)
self.exec_command()
self.assertEqual(_level[0], 'info')
assert _level[0] == 'info'
class WebUIScriptEntryTestCase(BaseTestCase, WebUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
WebUIBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge-web'
self.var['start_cmd'] = deluge.ui.web.start
self.var['sys_arg_cmd'] = ['./deluge-web']
class TestWebUIScriptEntry(BaseTestCase, WebUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge-web',
'start_cmd': deluge.ui.web.start,
'sys_arg_cmd': ['./deluge-web'],
}
if not windows_check():
self.var['sys_arg_cmd'].append('--do-not-daemonize')
def set_up(self):
return WebUIBaseTestCase.set_up(self)
def tear_down(self):
return WebUIBaseTestCase.tear_down(self)
request.cls.var['sys_arg_cmd'].append('--do-not-daemonize')
class WebUIDelugeScriptEntryTestCase(BaseTestCase, WebUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
WebUIBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge web'
self.var['start_cmd'] = ui_entry.start_ui
self.var['sys_arg_cmd'] = ['./deluge', 'web']
class TestWebUIDelugeScriptEntry(BaseTestCase, WebUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge web',
'start_cmd': ui_entry.start_ui,
'sys_arg_cmd': ['./deluge', 'web'],
}
if not windows_check():
self.var['sys_arg_cmd'].append('--do-not-daemonize')
def set_up(self):
return WebUIBaseTestCase.set_up(self)
def tear_down(self):
return WebUIBaseTestCase.tear_down(self)
request.cls.var['sys_arg_cmd'].append('--do-not-daemonize')
class ConsoleUIBaseTestCase(UIBaseTestCase):
@ -282,7 +244,7 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.exec_command()
def test_start_console_with_log_level(self):
def test_start_console_with_log_level(self, request):
_level = []
def setup_logger(
@ -305,7 +267,7 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
# Just test that no exception is raised
self.exec_command()
self.assertEqual(_level[0], 'info')
assert _level[0] == 'info'
def test_console_help(self):
self.patch(sys, 'argv', self.var['sys_arg_cmd'] + ['-h'])
@ -313,18 +275,19 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
self.patch(argparse._sys, 'stdout', fd)
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.assertRaises(SystemExit, self.exec_command)
with pytest.raises(SystemExit):
self.exec_command()
std_output = fd.out.getvalue()
self.assertTrue(
('usage: %s' % self.var['cmd_name']) in std_output
) # Check command name
self.assertTrue('Common Options:' in std_output)
self.assertTrue('Console Options:' in std_output)
self.assertIn(
'Console Commands:\n The following console commands are available:',
std_output,
assert (
'usage: %s' % self.var['cmd_name']
) in std_output # Check command name
assert 'Common Options:' in std_output
assert 'Console Options:' in std_output
assert (
'Console Commands:\n The following console commands are available:'
in std_output
)
self.assertIn('The following console commands are available:', std_output)
assert 'The following console commands are available:' in std_output
def test_console_command_info(self):
self.patch(sys, 'argv', self.var['sys_arg_cmd'] + ['info'])
@ -340,10 +303,11 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
self.patch(argparse._sys, 'stdout', fd)
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.assertRaises(SystemExit, self.exec_command)
with pytest.raises(SystemExit):
self.exec_command()
std_output = fd.out.getvalue()
self.assertIn('usage: info', std_output)
self.assertIn('Show information about the torrents', std_output)
assert 'usage: info' in std_output
assert 'Show information about the torrents' in std_output
def test_console_unrecognized_arguments(self):
self.patch(
@ -352,8 +316,9 @@ class ConsoleUIBaseTestCase(UIBaseTestCase):
fd = StringFileDescriptor(sys.stdout)
self.patch(argparse._sys, 'stderr', fd)
with mock.patch('deluge.ui.console.main.ConsoleUI'):
self.assertRaises(SystemExit, self.exec_command)
self.assertIn('unrecognized arguments: --ui', fd.out.getvalue())
with pytest.raises(SystemExit):
self.exec_command()
assert 'unrecognized arguments: --ui' in fd.out.getvalue()
class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
@ -381,7 +346,7 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
+ command,
)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_console_command_add(self):
filename = common.get_test_data_file('test.torrent')
self.patch_arg_command([f'add "{filename}"'])
@ -391,11 +356,12 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
yield self.exec_command()
std_output = fd.out.getvalue()
self.assertEqual(
std_output, 'Attempting to add torrent: ' + filename + '\nTorrent added!\n'
assert (
std_output
== 'Attempting to add torrent: ' + filename + '\nTorrent added!\n'
)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_console_command_add_move_completed(self):
filename = common.get_test_data_file('test.torrent')
tmp_path = 'c:\\tmp' if windows_check() else '/tmp'
@ -414,26 +380,23 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
yield self.exec_command()
std_output = fd.out.getvalue()
self.assertTrue(
std_output.endswith(
f'move_completed: True\nmove_completed_path: {tmp_path}\n'
)
or std_output.endswith(
f'move_completed_path: {tmp_path}\nmove_completed: True\n'
)
assert std_output.endswith(
f'move_completed: True\nmove_completed_path: {tmp_path}\n'
) or std_output.endswith(
f'move_completed_path: {tmp_path}\nmove_completed: True\n'
)
@defer.inlineCallbacks
def test_console_command_status(self):
@pytest_twisted.ensureDeferred
async def test_console_command_status(self):
fd = StringFileDescriptor(sys.stdout)
self.patch_arg_command(['status'])
self.patch(sys, 'stdout', fd)
yield self.exec_command()
await self.exec_command()
std_output = fd.out.getvalue()
self.assertTrue(std_output.startswith('Total upload: '))
self.assertTrue(std_output.endswith(' Moving: 0\n'))
assert std_output.startswith('Total upload: ')
assert std_output.endswith(' Moving: 0\n')
@defer.inlineCallbacks
def test_console_command_config_set_download_location(self):
@ -443,63 +406,36 @@ class ConsoleUIWithDaemonBaseTestCase(UIWithDaemonBaseTestCase):
yield self.exec_command()
std_output = fd.out.getvalue()
self.assertTrue(
std_output.startswith('Setting "download_location" to: \'/downloads\'')
)
self.assertTrue(
std_output.endswith('Configuration value successfully updated.\n')
)
assert std_output.startswith('Setting "download_location" to: \'/downloads\'')
assert std_output.endswith('Configuration value successfully updated.\n')
class ConsoleScriptEntryWithDaemonTestCase(
BaseTestCase, ConsoleUIWithDaemonBaseTestCase
):
def __init__(self, testname):
super().__init__(testname)
ConsoleUIWithDaemonBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge-console'
self.var['sys_arg_cmd'] = ['./deluge-console']
def set_up(self):
from deluge.ui.console.console import Console
def start_console():
return Console().start()
self.patch(deluge.ui.console, 'start', start_console)
self.var['start_cmd'] = deluge.ui.console.start
return ConsoleUIWithDaemonBaseTestCase.set_up(self)
def tear_down(self):
return ConsoleUIWithDaemonBaseTestCase.tear_down(self)
@pytest.mark.usefixtures('daemon', 'client')
class TestConsoleScriptEntryWithDaemon(BaseTestCase, ConsoleUIWithDaemonBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge-console',
'start_cmd': deluge.ui.console.start,
'sys_arg_cmd': ['./deluge-console'],
}
class ConsoleScriptEntryTestCase(BaseTestCase, ConsoleUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
ConsoleUIBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge-console'
self.var['start_cmd'] = deluge.ui.console.start
self.var['sys_arg_cmd'] = ['./deluge-console']
def set_up(self):
return ConsoleUIBaseTestCase.set_up(self)
def tear_down(self):
return ConsoleUIBaseTestCase.tear_down(self)
class TestConsoleScriptEntry(BaseTestCase, ConsoleUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge-console',
'start_cmd': deluge.ui.console.start,
'sys_arg_cmd': ['./deluge-console'],
}
class ConsoleDelugeScriptEntryTestCase(BaseTestCase, ConsoleUIBaseTestCase):
def __init__(self, testname):
super().__init__(testname)
ConsoleUIBaseTestCase.__init__(self)
self.var['cmd_name'] = 'deluge console'
self.var['start_cmd'] = ui_entry.start_ui
self.var['sys_arg_cmd'] = ['./deluge', 'console']
def set_up(self):
return ConsoleUIBaseTestCase.set_up(self)
def tear_down(self):
return ConsoleUIBaseTestCase.tear_down(self)
class TestConsoleDelugeScriptEntry(BaseTestCase, ConsoleUIBaseTestCase):
@pytest.fixture(autouse=True)
def set_var(self, request):
request.cls.var = {
'cmd_name': 'deluge console',
'start_cmd': ui_entry.start_ui,
'sys_arg_cmd': ['./deluge', 'console'],
}

View File

@ -8,11 +8,10 @@ import sys
from unittest import mock
import pytest
from twisted.trial import unittest
@pytest.mark.gtkui
class GTK3CommonTestCase(unittest.TestCase):
class TestGTK3Common:
def setUp(self):
sys.modules['gi.repository'] = mock.MagicMock()
@ -22,10 +21,10 @@ class GTK3CommonTestCase(unittest.TestCase):
def test_cmp(self):
from deluge.ui.gtk3.common import cmp
self.assertEqual(cmp(None, None), 0)
self.assertEqual(cmp(1, None), 1)
self.assertEqual(cmp(0, None), 1)
self.assertEqual(cmp(None, 7), -1)
self.assertEqual(cmp(None, 'bar'), -1)
self.assertEqual(cmp('foo', None), 1)
self.assertEqual(cmp('', None), 1)
assert cmp(None, None) == 0
assert cmp(1, None) == 1
assert cmp(0, None) == 1
assert cmp(None, 7) == -1
assert cmp(None, 'bar') == -1
assert cmp('foo', None) == 1
assert cmp('', None) == 1

View File

@ -9,14 +9,14 @@
import json
from io import BytesIO
import pytest
import pytest_twisted
from twisted.internet import defer, reactor
from twisted.python.failure import Failure
from twisted.web.client import Agent, FileBodyProducer
from twisted.web.http_headers import Headers
from twisted.web.static import File
import deluge.component as component
from deluge.ui.client import client
from . import common
from .common_web import WebServerTestBase
@ -24,20 +24,19 @@ from .common_web import WebServerTestBase
common.disable_new_release_check()
class WebAPITestCase(WebServerTestBase):
def test_connect_invalid_host(self):
d = self.deluge_web.web_api.connect('id')
d.addCallback(self.fail)
d.addErrback(self.assertIsInstance, Failure)
return d
class TestWebAPI(WebServerTestBase):
@pytest.mark.xfail(reason='This just logs an error at the moment.')
@pytest_twisted.ensureDeferred
async def test_connect_invalid_host(self):
with pytest.raises(Exception):
await self.deluge_web.web_api.connect('id')
def test_connect(self):
def test_connect(self, client):
d = self.deluge_web.web_api.connect(self.host_id)
def on_connect(result):
self.assertEqual(type(result), tuple)
self.assertTrue(len(result) > 0)
self.addCleanup(client.disconnect)
assert type(result) == tuple
assert len(result) > 0
return result
d.addCallback(on_connect)
@ -49,9 +48,9 @@ class WebAPITestCase(WebServerTestBase):
@defer.inlineCallbacks
def on_connect(result):
self.assertTrue(self.deluge_web.web_api.connected())
assert self.deluge_web.web_api.connected()
yield self.deluge_web.web_api.disconnect()
self.assertFalse(self.deluge_web.web_api.connected())
assert not self.deluge_web.web_api.connected()
d.addCallback(on_connect)
d.addErrback(self.fail)
@ -59,7 +58,7 @@ class WebAPITestCase(WebServerTestBase):
def test_get_config(self):
config = self.deluge_web.web_api.get_config()
self.assertEqual(self.webserver_listen_port, config['port'])
assert self.webserver_listen_port == config['port']
def test_set_config(self):
config = self.deluge_web.web_api.get_config()
@ -74,9 +73,9 @@ class WebAPITestCase(WebServerTestBase):
}
self.deluge_web.web_api.set_config(config)
web_config = component.get('DelugeWeb').config.config
self.assertNotEqual(config['pwd_salt'], web_config['pwd_salt'])
self.assertNotEqual(config['pwd_sha1'], web_config['pwd_sha1'])
self.assertNotEqual(config['sessions'], web_config['sessions'])
assert config['pwd_salt'] != web_config['pwd_salt']
assert config['pwd_sha1'] != web_config['pwd_sha1']
assert config['sessions'] != web_config['sessions']
@defer.inlineCallbacks
def get_host_status(self):
@ -84,49 +83,49 @@ class WebAPITestCase(WebServerTestBase):
host[3] = 'Online'
host[4] = '2.0.0.dev562'
status = yield self.deluge_web.web_api.get_host_status(self.host_id)
self.assertEqual(status, tuple(status))
assert status == tuple(status)
def test_get_host(self):
self.assertFalse(self.deluge_web.web_api._get_host('invalid_id'))
assert not self.deluge_web.web_api._get_host('invalid_id')
conn = list(self.deluge_web.web_api.hostlist.get_hosts_info()[0])
self.assertEqual(self.deluge_web.web_api._get_host(conn[0]), conn[0:4])
assert self.deluge_web.web_api._get_host(conn[0]) == conn[0:4]
def test_add_host(self):
conn = ['abcdef', '10.0.0.1', 0, 'user123', 'pass123']
self.assertFalse(self.deluge_web.web_api._get_host(conn[0]))
assert not self.deluge_web.web_api._get_host(conn[0])
# Add valid host
result, host_id = self.deluge_web.web_api.add_host(
conn[1], conn[2], conn[3], conn[4]
)
self.assertEqual(result, True)
assert result
conn[0] = host_id
self.assertEqual(self.deluge_web.web_api._get_host(conn[0]), conn[0:4])
assert self.deluge_web.web_api._get_host(conn[0]) == conn[0:4]
# Add already existing host
ret = self.deluge_web.web_api.add_host(conn[1], conn[2], conn[3], conn[4])
self.assertEqual(ret, (False, 'Host details already in hostlist'))
assert ret == (False, 'Host details already in hostlist')
# Add invalid port
conn[2] = 'bad port'
ret = self.deluge_web.web_api.add_host(conn[1], conn[2], conn[3], conn[4])
self.assertEqual(ret, (False, 'Invalid port. Must be an integer'))
assert ret == (False, 'Invalid port. Must be an integer')
def test_remove_host(self):
conn = ['connection_id', '', 0, '', '']
self.deluge_web.web_api.hostlist.config['hosts'].append(conn)
self.assertEqual(self.deluge_web.web_api._get_host(conn[0]), conn[0:4])
assert self.deluge_web.web_api._get_host(conn[0]) == conn[0:4]
# Remove valid host
self.assertTrue(self.deluge_web.web_api.remove_host(conn[0]))
self.assertFalse(self.deluge_web.web_api._get_host(conn[0]))
assert self.deluge_web.web_api.remove_host(conn[0])
assert not self.deluge_web.web_api._get_host(conn[0])
# Remove non-existing host
self.assertFalse(self.deluge_web.web_api.remove_host(conn[0]))
assert not self.deluge_web.web_api.remove_host(conn[0])
def test_get_torrent_info(self):
filename = common.get_test_data_file('test.torrent')
ret = self.deluge_web.web_api.get_torrent_info(filename)
self.assertEqual(ret['name'], 'azcvsupdater_2.6.2.jar')
self.assertEqual(ret['info_hash'], 'ab570cdd5a17ea1b61e970bb72047de141bce173')
self.assertTrue('files_tree' in ret)
assert ret['name'] == 'azcvsupdater_2.6.2.jar'
assert ret['info_hash'] == 'ab570cdd5a17ea1b61e970bb72047de141bce173'
assert 'files_tree' in ret
def test_get_torrent_info_with_md5(self):
filename = common.get_test_data_file('md5sum.torrent')
@ -134,19 +133,19 @@ class WebAPITestCase(WebServerTestBase):
# JSON dumping happens during response creation in normal usage
# JSON serialization may fail if any of the dictionary items are byte arrays rather than strings
ret = json.loads(json.dumps(ret))
self.assertEqual(ret['name'], 'test')
self.assertEqual(ret['info_hash'], 'f6408ba9944cf9fe01b547b28f336b3ee6ec32c5')
self.assertTrue('files_tree' in ret)
assert ret['name'] == 'test'
assert ret['info_hash'] == 'f6408ba9944cf9fe01b547b28f336b3ee6ec32c5'
assert 'files_tree' in ret
def test_get_magnet_info(self):
ret = self.deluge_web.web_api.get_magnet_info(
'magnet:?xt=urn:btih:SU5225URMTUEQLDXQWRB2EQWN6KLTYKN'
)
self.assertEqual(ret['name'], '953bad769164e8482c7785a21d12166f94b9e14d')
self.assertEqual(ret['info_hash'], '953bad769164e8482c7785a21d12166f94b9e14d')
self.assertTrue('files_tree' in ret)
assert ret['name'] == '953bad769164e8482c7785a21d12166f94b9e14d'
assert ret['info_hash'] == '953bad769164e8482c7785a21d12166f94b9e14d'
assert 'files_tree' in ret
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_get_torrent_files(self):
yield self.deluge_web.web_api.connect(self.host_id)
filename = common.get_test_data_file('test.torrent')
@ -157,23 +156,20 @@ class WebAPITestCase(WebServerTestBase):
ret = yield self.deluge_web.web_api.get_torrent_files(
'ab570cdd5a17ea1b61e970bb72047de141bce173'
)
self.assertEqual(ret['type'], 'dir')
self.assertEqual(
ret['contents'],
{
'azcvsupdater_2.6.2.jar': {
'priority': 4,
'index': 0,
'offset': 0,
'progress': 0.0,
'path': 'azcvsupdater_2.6.2.jar',
'type': 'file',
'size': 307949,
}
},
)
assert ret['type'] == 'dir'
assert ret['contents'] == {
'azcvsupdater_2.6.2.jar': {
'priority': 4,
'index': 0,
'offset': 0,
'progress': 0.0,
'path': 'azcvsupdater_2.6.2.jar',
'type': 'file',
'size': 307949,
}
}
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_download_torrent_from_url(self):
filename = 'ubuntu-9.04-desktop-i386.iso.torrent'
self.deluge_web.top_level.putChild(
@ -181,9 +177,9 @@ class WebAPITestCase(WebServerTestBase):
)
url = 'http://localhost:%d/%s' % (self.webserver_listen_port, filename)
res = yield self.deluge_web.web_api.download_torrent_from_url(url)
self.assertTrue(res.endswith(filename))
assert res.endswith(filename)
@defer.inlineCallbacks
@pytest_twisted.inlineCallbacks
def test_invalid_json(self):
"""
If json_api._send_response does not return server.NOT_DONE_YET

View File

@ -3,9 +3,8 @@
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
from unittest.mock import patch
from twisted.trial import unittest
from unittest.mock import patch
from deluge.ui.web import auth
@ -21,7 +20,7 @@ class MockConfig:
self.config[key] = value
class WebAuthTestCase(unittest.TestCase):
class TestWebAuth:
@patch('deluge.ui.web.auth.JSONComponent.__init__', return_value=None)
def test_change_password(self, mock_json):
config = MockConfig(
@ -31,4 +30,4 @@ class WebAuthTestCase(unittest.TestCase):
}
)
webauth = auth.Auth(config)
self.assertTrue(webauth.change_password('deluge', 'deluge_new'))
assert webauth.change_password('deluge', 'deluge_new')

View File

@ -9,8 +9,9 @@
import json as json_lib
from io import BytesIO
import pytest_twisted
import twisted.web.client
from twisted.internet import defer, reactor
from twisted.internet import reactor
from twisted.web.client import Agent, FileBodyProducer
from twisted.web.http_headers import Headers
@ -21,8 +22,8 @@ from .common_web import WebServerMockBase, WebServerTestBase
common.disable_new_release_check()
class WebServerTestCase(WebServerTestBase, WebServerMockBase):
@defer.inlineCallbacks
class TestWebServer(WebServerTestBase, WebServerMockBase):
@pytest_twisted.inlineCallbacks
def test_get_torrent_info(self):
agent = Agent(reactor)
@ -49,9 +50,11 @@ class WebServerTestCase(WebServerTestBase, WebServerMockBase):
Headers(headers),
FileBodyProducer(BytesIO(input_file.encode('utf-8'))),
)
body = yield twisted.web.client.readBody(d)
json = json_lib.loads(body.decode())
self.assertEqual(None, json['error'])
self.assertEqual('torrent_filehash', json['result']['name'])
try:
json = json_lib.loads(body.decode())
except Exception:
print('aoeu')
assert json['error'] is None
assert 'torrent_filehash' == json['result']['name']

View File

@ -1,47 +0,0 @@
#! /usr/bin/env python
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import os
from twisted.plugin import IPlugin
from twisted.trial.itrial import IReporter
from twisted.trial.reporter import TreeReporter
from zope.interface import implements
class _Reporter:
implements(IPlugin, IReporter)
def __init__(
self, name, module, description, longOpt, shortOpt, klass # noqa: N803
):
self.name = name
self.module = module
self.description = description
self.longOpt = longOpt
self.shortOpt = shortOpt
self.klass = klass
deluge = _Reporter(
'Deluge reporter that suppresses Stacktrace from TODO tests',
'twisted.plugins.delugereporter',
description='Deluge Reporter',
longOpt='deluge-reporter',
shortOpt=None,
klass='DelugeReporter',
)
class DelugeReporter(TreeReporter):
def __init__(self, *args, **kwargs):
os.environ['DELUGE_REPORTER'] = 'true'
TreeReporter.__init__(self, *args, **kwargs)
def addExpectedFailure(self, *args): # NOQA: N802
# super(TreeReporter, self).addExpectedFailure(*args)
self.endLine('[TODO]', self.TODO)

View File

@ -612,7 +612,7 @@ class Client:
d.addErrback(on_authenticate_fail)
return d
d.addCallback(on_connected)
d.addCallbacks(on_connected)
d.addErrback(on_connect_fail)
if not skip_authentication:
d.addCallback(authenticate, username, password)

View File

@ -13,4 +13,4 @@ UI_PATH = __path__[0]
def start():
Console().start()
return Console().start()