mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-06 00:18:39 +00:00
[Core] [Tests] Changes to component.shutdown and unit tests
* component registry shutdown() now cleans up the component list this ensures that no old components are left when running unit tests. * Added class BaseTestCase that all tests that create components should inherit from. It verifies the compoent list before and after the tests are run.
This commit is contained in:
parent
a9e7aec5b6
commit
178c417fb0
9 changed files with 100 additions and 39 deletions
|
@ -385,8 +385,13 @@ class ComponentRegistry(object):
|
||||||
:rtype: twisted.internet.defer.Deferred
|
:rtype: twisted.internet.defer.Deferred
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
def on_success(result, key):
|
||||||
|
del _ComponentRegistry.components[key]
|
||||||
|
return succeed(result)
|
||||||
|
|
||||||
def on_stopped(result):
|
def on_stopped(result):
|
||||||
return DeferredList(map(lambda c: c._component_shutdown(), self.components.values()))
|
return DeferredList(map(lambda t: t[1]._component_shutdown().addCallback(on_success, t[0]),
|
||||||
|
self.components.items()))
|
||||||
|
|
||||||
return self.stop(self.components.keys()).addCallback(on_stopped)
|
return self.stop(self.components.keys()).addCallback(on_stopped)
|
||||||
|
|
||||||
|
|
37
deluge/tests/basetest.py
Normal file
37
deluge/tests/basetest.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
if len(component._ComponentRegistry.components) != 0:
|
||||||
|
warnings.warn("The component._ComponentRegistry.components is not empty on test setup."
|
||||||
|
"This is probably caused by another test that didn't clean up after finishing!: %s" %
|
||||||
|
component._ComponentRegistry.components)
|
||||||
|
return self.set_up()
|
||||||
|
|
||||||
|
def tearDown(self): # NOQA
|
||||||
|
d = maybeDeferred(self.tear_down)
|
||||||
|
|
||||||
|
def on_teared_down(result):
|
||||||
|
if len(component._ComponentRegistry.components) != 0:
|
||||||
|
warnings.warn("The component._ComponentRegistry.components is not empty after the test finished!: %s" %
|
||||||
|
component._ComponentRegistry.components)
|
||||||
|
return d.addCallback(on_teared_down)
|
||||||
|
|
||||||
|
def set_up(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tear_down(self):
|
||||||
|
pass
|
|
@ -1,8 +1,9 @@
|
||||||
from twisted.internet import threads
|
from twisted.internet import threads
|
||||||
from twisted.trial import unittest
|
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
|
||||||
|
from .basetest import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestComponent(component.Component):
|
class TestComponent(component.Component):
|
||||||
def __init__(self, name, depend=None):
|
def __init__(self, name, depend=None):
|
||||||
|
@ -56,10 +57,9 @@ class TestComponentShutdown(component.Component):
|
||||||
self.stop_count += 1
|
self.stop_count += 1
|
||||||
|
|
||||||
|
|
||||||
class ComponentTestClass(unittest.TestCase):
|
class ComponentTestClass(BaseTestCase):
|
||||||
def tearDown(self): # NOQA
|
def tear_down(self):
|
||||||
component.stop()
|
return component.shutdown()
|
||||||
component._ComponentRegistry.components = {}
|
|
||||||
|
|
||||||
def test_start_component(self):
|
def test_start_component(self):
|
||||||
def on_start(result, c):
|
def on_start(result, c):
|
||||||
|
|
|
@ -5,7 +5,6 @@ from hashlib import sha1 as sha
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
from twisted.internet.error import CannotListenError
|
from twisted.internet.error import CannotListenError
|
||||||
from twisted.python.failure import Failure
|
from twisted.python.failure import Failure
|
||||||
from twisted.trial import unittest
|
|
||||||
from twisted.web.http import FORBIDDEN
|
from twisted.web.http import FORBIDDEN
|
||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
from twisted.web.server import Site
|
from twisted.web.server import Site
|
||||||
|
@ -18,6 +17,7 @@ from deluge.core.rpcserver import RPCServer
|
||||||
from deluge.ui.web.common import compress
|
from deluge.ui.web.common import compress
|
||||||
|
|
||||||
from . import common
|
from . import common
|
||||||
|
from .basetest import BaseTestCase
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", category=RuntimeWarning)
|
warnings.filterwarnings("ignore", category=RuntimeWarning)
|
||||||
warnings.resetwarnings()
|
warnings.resetwarnings()
|
||||||
|
@ -67,7 +67,7 @@ class TopLevelResource(Resource):
|
||||||
File(common.rpath("ubuntu-9.04-desktop-i386.iso.torrent")))
|
File(common.rpath("ubuntu-9.04-desktop-i386.iso.torrent")))
|
||||||
|
|
||||||
|
|
||||||
class CoreTestCase(unittest.TestCase):
|
class CoreTestCase(BaseTestCase):
|
||||||
def setUp(self): # NOQA
|
def setUp(self): # NOQA
|
||||||
common.set_tmp_config_dir()
|
common.set_tmp_config_dir()
|
||||||
self.rpcserver = RPCServer(listen=False)
|
self.rpcserver = RPCServer(listen=False)
|
||||||
|
@ -96,7 +96,6 @@ class CoreTestCase(unittest.TestCase):
|
||||||
def tearDown(self): # NOQA
|
def tearDown(self): # NOQA
|
||||||
|
|
||||||
def on_shutdown(result):
|
def on_shutdown(result):
|
||||||
component._ComponentRegistry.components = {}
|
|
||||||
del self.rpcserver
|
del self.rpcserver
|
||||||
del self.core
|
del self.core
|
||||||
return self.webserver.stopListening()
|
return self.webserver.stopListening()
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
|
||||||
from twisted.trial import unittest
|
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.error
|
import deluge.error
|
||||||
from deluge.core import rpcserver
|
from deluge.core import rpcserver
|
||||||
|
@ -17,6 +15,8 @@ from deluge.core.rpcserver import DelugeRPCProtocol, RPCServer
|
||||||
from deluge.log import setup_logger
|
from deluge.log import setup_logger
|
||||||
from deluge.ui.common import get_localhost_auth
|
from deluge.ui.common import get_localhost_auth
|
||||||
|
|
||||||
|
from .basetest import BaseTestCase
|
||||||
|
|
||||||
setup_logger("none")
|
setup_logger("none")
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ class DelugeRPCProtocolTester(DelugeRPCProtocol):
|
||||||
self.messages.append(data)
|
self.messages.append(data)
|
||||||
|
|
||||||
|
|
||||||
class RPCServerTestCase(unittest.TestCase):
|
class RPCServerTestCase(BaseTestCase):
|
||||||
|
|
||||||
def setUp(self): # NOQA
|
def set_up(self):
|
||||||
self.rpcserver = RPCServer(listen=False)
|
self.rpcserver = RPCServer(listen=False)
|
||||||
self.rpcserver.factory.protocol = DelugeRPCProtocolTester
|
self.rpcserver.factory.protocol = DelugeRPCProtocolTester
|
||||||
self.factory = self.rpcserver.factory
|
self.factory = self.rpcserver.factory
|
||||||
|
@ -45,9 +45,8 @@ class RPCServerTestCase(unittest.TestCase):
|
||||||
self.protocol.sessionno = self.session_id
|
self.protocol.sessionno = self.session_id
|
||||||
return component.start()
|
return component.start()
|
||||||
|
|
||||||
def tearDown(self): # NOQA
|
def tear_down(self):
|
||||||
def on_shutdown(result):
|
def on_shutdown(result):
|
||||||
component._ComponentRegistry.components = {}
|
|
||||||
del self.rpcserver
|
del self.rpcserver
|
||||||
return component.shutdown().addCallback(on_shutdown)
|
return component.shutdown().addCallback(on_shutdown)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from twisted.internet.defer import maybeDeferred, succeed
|
from twisted.internet.defer import maybeDeferred, succeed
|
||||||
from twisted.trial import unittest
|
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.ui.sessionproxy
|
import deluge.ui.sessionproxy
|
||||||
|
|
||||||
|
from .basetest import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
class Core(object):
|
class Core(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -89,8 +90,9 @@ client = Client()
|
||||||
deluge.ui.sessionproxy.client = client
|
deluge.ui.sessionproxy.client = client
|
||||||
|
|
||||||
|
|
||||||
class SessionProxyTestCase(unittest.TestCase):
|
class SessionProxyTestCase(BaseTestCase):
|
||||||
def setUp(self): # NOQA
|
|
||||||
|
def set_up(self):
|
||||||
self.sp = deluge.ui.sessionproxy.SessionProxy()
|
self.sp = deluge.ui.sessionproxy.SessionProxy()
|
||||||
client.core.reset()
|
client.core.reset()
|
||||||
d = self.sp.start()
|
d = self.sp.start()
|
||||||
|
@ -101,7 +103,7 @@ class SessionProxyTestCase(unittest.TestCase):
|
||||||
d.addCallback(do_get_torrents_status)
|
d.addCallback(do_get_torrents_status)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def tearDown(self): # NOQA
|
def tear_down(self):
|
||||||
return component.deregister(self.sp)
|
return component.deregister(self.sp)
|
||||||
|
|
||||||
def test_startup(self):
|
def test_startup(self):
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import pytest
|
||||||
import gobject
|
import gobject
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
|
@ -8,10 +9,13 @@ from deluge.ui.gtkui.menubar import MenuBar
|
||||||
from deluge.ui.gtkui.torrentdetails import TorrentDetails
|
from deluge.ui.gtkui.torrentdetails import TorrentDetails
|
||||||
from deluge.ui.gtkui.torrentview import TorrentView
|
from deluge.ui.gtkui.torrentview import TorrentView
|
||||||
|
|
||||||
|
from .basetest import BaseTestCase
|
||||||
|
|
||||||
deluge.common.setup_translations()
|
deluge.common.setup_translations()
|
||||||
|
|
||||||
|
|
||||||
class TorrentviewTestCase(unittest.TestCase):
|
@pytest.mark.gtkui
|
||||||
|
class TorrentviewTestCase(BaseTestCase):
|
||||||
|
|
||||||
default_column_index = ['filter', 'torrent_id', 'dirty', '#', u'Name', u'Size',
|
default_column_index = ['filter', 'torrent_id', 'dirty', '#', u'Name', u'Size',
|
||||||
u'Downloaded', u'Uploaded', u'Remaining', u'Progress',
|
u'Downloaded', u'Uploaded', u'Remaining', u'Progress',
|
||||||
|
@ -25,16 +29,14 @@ class TorrentviewTestCase(unittest.TestCase):
|
||||||
float, float, int, float, float, float, float,
|
float, float, int, float, float, float, float,
|
||||||
float, str, str, str, str, bool]
|
float, str, str, str, str, bool]
|
||||||
|
|
||||||
def setUp(self): # NOQA
|
def set_up(self):
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = MainWindow()
|
||||||
self.torrentview = TorrentView()
|
self.torrentview = TorrentView()
|
||||||
self.torrentdetails = TorrentDetails()
|
self.torrentdetails = TorrentDetails()
|
||||||
self.menubar = MenuBar()
|
self.menubar = MenuBar()
|
||||||
|
|
||||||
def tearDown(self): # NOQA
|
def tear_down(self):
|
||||||
def on_shutdown(result):
|
return component.shutdown()
|
||||||
component._ComponentRegistry.components = {}
|
|
||||||
return component.shutdown().addCallback(on_shutdown)
|
|
||||||
|
|
||||||
def test_torrentview_columns(self):
|
def test_torrentview_columns(self):
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,29 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from twisted.trial import unittest
|
import deluge.component as component
|
||||||
|
|
||||||
import deluge.ui.tracker_icons
|
import deluge.ui.tracker_icons
|
||||||
from deluge.ui.tracker_icons import TrackerIcon, TrackerIcons
|
from deluge.ui.tracker_icons import TrackerIcon, TrackerIcons
|
||||||
|
|
||||||
|
from .basetest import BaseTestCase
|
||||||
from .common import set_tmp_config_dir
|
from .common import set_tmp_config_dir
|
||||||
|
|
||||||
set_tmp_config_dir()
|
set_tmp_config_dir()
|
||||||
icons = TrackerIcons()
|
|
||||||
|
|
||||||
dirname = os.path.dirname(__file__)
|
dirname = os.path.dirname(__file__)
|
||||||
|
|
||||||
deluge.ui.tracker_icons.PIL_INSTALLED = False
|
deluge.ui.tracker_icons.PIL_INSTALLED = False
|
||||||
|
|
||||||
|
|
||||||
class TrackerIconsTestCase(unittest.TestCase):
|
class TrackerIconsTestCase(BaseTestCase):
|
||||||
|
|
||||||
|
def set_up(self):
|
||||||
|
self.icons = TrackerIcons()
|
||||||
|
|
||||||
|
def tear_down(self):
|
||||||
|
return component.shutdown()
|
||||||
|
|
||||||
def test_get_deluge_png(self):
|
def test_get_deluge_png(self):
|
||||||
# Deluge has a png favicon link
|
# Deluge has a png favicon link
|
||||||
icon = TrackerIcon(os.path.join(dirname, "deluge.png"))
|
icon = TrackerIcon(os.path.join(dirname, "deluge.png"))
|
||||||
d = icons.fetch("deluge-torrent.org")
|
d = self.icons.fetch("deluge-torrent.org")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
@ -29,7 +32,7 @@ class TrackerIconsTestCase(unittest.TestCase):
|
||||||
# Google doesn't have any icon links
|
# Google doesn't have any icon links
|
||||||
# So instead we'll grab its favicon.ico
|
# So instead we'll grab its favicon.ico
|
||||||
icon = TrackerIcon(os.path.join(dirname, "google.ico"))
|
icon = TrackerIcon(os.path.join(dirname, "google.ico"))
|
||||||
d = icons.fetch("www.google.com")
|
d = self.icons.fetch("www.google.com")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
@ -37,7 +40,7 @@ class TrackerIconsTestCase(unittest.TestCase):
|
||||||
def test_get_google_ico_with_redirect(self):
|
def test_get_google_ico_with_redirect(self):
|
||||||
# google.com redirects to www.google.com
|
# google.com redirects to www.google.com
|
||||||
icon = TrackerIcon(os.path.join(dirname, "google.ico"))
|
icon = TrackerIcon(os.path.join(dirname, "google.ico"))
|
||||||
d = icons.fetch("google.com")
|
d = self.icons.fetch("google.com")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
@ -45,7 +48,7 @@ class TrackerIconsTestCase(unittest.TestCase):
|
||||||
def test_get_ubuntu_ico(self):
|
def test_get_ubuntu_ico(self):
|
||||||
# ubuntu.com has inline css which causes HTMLParser issues
|
# ubuntu.com has inline css which causes HTMLParser issues
|
||||||
icon = TrackerIcon(os.path.join(dirname, "ubuntu.ico"))
|
icon = TrackerIcon(os.path.join(dirname, "ubuntu.ico"))
|
||||||
d = icons.fetch("www.ubuntu.com")
|
d = self.icons.fetch("www.ubuntu.com")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
@ -53,19 +56,19 @@ class TrackerIconsTestCase(unittest.TestCase):
|
||||||
def test_get_openbt_png(self):
|
def test_get_openbt_png(self):
|
||||||
# openbittorrent.com has an incorrect type (image/gif)
|
# openbittorrent.com has an incorrect type (image/gif)
|
||||||
icon = TrackerIcon(os.path.join(dirname, "openbt.png"))
|
icon = TrackerIcon(os.path.join(dirname, "openbt.png"))
|
||||||
d = icons.fetch("openbittorrent.com")
|
d = self.icons.fetch("openbittorrent.com")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test_get_publicbt_ico(self):
|
def test_get_publicbt_ico(self):
|
||||||
icon = TrackerIcon(os.path.join(dirname, "publicbt.ico"))
|
icon = TrackerIcon(os.path.join(dirname, "publicbt.ico"))
|
||||||
d = icons.fetch("publicbt.org")
|
d = self.icons.fetch("publicbt.org")
|
||||||
d.addCallback(self.assertNotIdentical, None)
|
d.addCallback(self.assertNotIdentical, None)
|
||||||
d.addCallback(self.assertEquals, icon)
|
d.addCallback(self.assertEquals, icon)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test_get_empty_string_tracker(self):
|
def test_get_empty_string_tracker(self):
|
||||||
d = icons.fetch("")
|
d = self.icons.fetch("")
|
||||||
d.addCallback(self.assertIdentical, None)
|
d.addCallback(self.assertIdentical, None)
|
||||||
return d
|
return d
|
||||||
|
|
16
tox.ini
16
tox.ini
|
@ -52,7 +52,21 @@ commands =
|
||||||
[testenv:pydef]
|
[testenv:pydef]
|
||||||
commands =
|
commands =
|
||||||
python -c "import libtorrent as lt; print lt.version"
|
python -c "import libtorrent as lt; print lt.version"
|
||||||
py.test deluge/tests
|
py.test -v -s -m "not (todo or gtkui)" deluge/tests
|
||||||
|
|
||||||
|
[testenv:pygtkui]
|
||||||
|
commands =
|
||||||
|
py.test -v -s -m "gtkui" deluge/tests
|
||||||
|
|
||||||
|
[testenv:todo]
|
||||||
|
commands =
|
||||||
|
py.test -v -s -m "todo" deluge/tests
|
||||||
|
|
||||||
|
[testenv:trial]
|
||||||
|
setenv = {[testenv]setenv}:{env:PWD}/deluge/tests
|
||||||
|
whitelist_externals = trial
|
||||||
|
commands =
|
||||||
|
trial --reporter=deluge-reporter deluge/tests
|
||||||
|
|
||||||
[testenv:plugins]
|
[testenv:plugins]
|
||||||
commands = py.test deluge/plugins
|
commands = py.test deluge/plugins
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue