[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:
bendikro 2014-10-13 16:38:51 +02:00 committed by Calum Lind
parent a9e7aec5b6
commit 178c417fb0
9 changed files with 100 additions and 39 deletions

View File

@ -385,8 +385,13 @@ class ComponentRegistry(object):
:rtype: twisted.internet.defer.Deferred
"""
def on_success(result, key):
del _ComponentRegistry.components[key]
return succeed(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)

37
deluge/tests/basetest.py Normal file
View 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

View File

@ -1,8 +1,9 @@
from twisted.internet import threads
from twisted.trial import unittest
import deluge.component as component
from .basetest import BaseTestCase
class TestComponent(component.Component):
def __init__(self, name, depend=None):
@ -56,10 +57,9 @@ class TestComponentShutdown(component.Component):
self.stop_count += 1
class ComponentTestClass(unittest.TestCase):
def tearDown(self): # NOQA
component.stop()
component._ComponentRegistry.components = {}
class ComponentTestClass(BaseTestCase):
def tear_down(self):
return component.shutdown()
def test_start_component(self):
def on_start(result, c):

View File

@ -5,7 +5,6 @@ from hashlib import sha1 as sha
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.http import FORBIDDEN
from twisted.web.resource import Resource
from twisted.web.server import Site
@ -18,6 +17,7 @@ from deluge.core.rpcserver import RPCServer
from deluge.ui.web.common import compress
from . import common
from .basetest import BaseTestCase
warnings.filterwarnings("ignore", category=RuntimeWarning)
warnings.resetwarnings()
@ -67,7 +67,7 @@ class TopLevelResource(Resource):
File(common.rpath("ubuntu-9.04-desktop-i386.iso.torrent")))
class CoreTestCase(unittest.TestCase):
class CoreTestCase(BaseTestCase):
def setUp(self): # NOQA
common.set_tmp_config_dir()
self.rpcserver = RPCServer(listen=False)
@ -96,7 +96,6 @@ class CoreTestCase(unittest.TestCase):
def tearDown(self): # NOQA
def on_shutdown(result):
component._ComponentRegistry.components = {}
del self.rpcserver
del self.core
return self.webserver.stopListening()

View File

@ -7,8 +7,6 @@
# See LICENSE for more details.
#
from twisted.trial import unittest
import deluge.component as component
import deluge.error
from deluge.core import rpcserver
@ -17,6 +15,8 @@ from deluge.core.rpcserver import DelugeRPCProtocol, RPCServer
from deluge.log import setup_logger
from deluge.ui.common import get_localhost_auth
from .basetest import BaseTestCase
setup_logger("none")
@ -28,9 +28,9 @@ class DelugeRPCProtocolTester(DelugeRPCProtocol):
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.factory.protocol = DelugeRPCProtocolTester
self.factory = self.rpcserver.factory
@ -45,9 +45,8 @@ class RPCServerTestCase(unittest.TestCase):
self.protocol.sessionno = self.session_id
return component.start()
def tearDown(self): # NOQA
def tear_down(self):
def on_shutdown(result):
component._ComponentRegistry.components = {}
del self.rpcserver
return component.shutdown().addCallback(on_shutdown)

View File

@ -1,11 +1,12 @@
import time
from twisted.internet.defer import maybeDeferred, succeed
from twisted.trial import unittest
import deluge.component as component
import deluge.ui.sessionproxy
from .basetest import BaseTestCase
class Core(object):
def __init__(self):
@ -89,8 +90,9 @@ client = Client()
deluge.ui.sessionproxy.client = client
class SessionProxyTestCase(unittest.TestCase):
def setUp(self): # NOQA
class SessionProxyTestCase(BaseTestCase):
def set_up(self):
self.sp = deluge.ui.sessionproxy.SessionProxy()
client.core.reset()
d = self.sp.start()
@ -101,7 +103,7 @@ class SessionProxyTestCase(unittest.TestCase):
d.addCallback(do_get_torrents_status)
return d
def tearDown(self): # NOQA
def tear_down(self):
return component.deregister(self.sp)
def test_startup(self):

View File

@ -1,3 +1,4 @@
import pytest
import gobject
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.torrentview import TorrentView
from .basetest import BaseTestCase
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',
u'Downloaded', u'Uploaded', u'Remaining', u'Progress',
@ -25,16 +29,14 @@ class TorrentviewTestCase(unittest.TestCase):
float, float, int, float, float, float, float,
float, str, str, str, str, bool]
def setUp(self): # NOQA
def set_up(self):
self.mainwindow = MainWindow()
self.torrentview = TorrentView()
self.torrentdetails = TorrentDetails()
self.menubar = MenuBar()
def tearDown(self): # NOQA
def on_shutdown(result):
component._ComponentRegistry.components = {}
return component.shutdown().addCallback(on_shutdown)
def tear_down(self):
return component.shutdown()
def test_torrentview_columns(self):

View File

@ -1,26 +1,29 @@
import os
from twisted.trial import unittest
import deluge.component as component
import deluge.ui.tracker_icons
from deluge.ui.tracker_icons import TrackerIcon, TrackerIcons
from .basetest import BaseTestCase
from .common import set_tmp_config_dir
set_tmp_config_dir()
icons = TrackerIcons()
dirname = os.path.dirname(__file__)
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):
# Deluge has a png favicon link
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.assertEquals, icon)
return d
@ -29,7 +32,7 @@ class TrackerIconsTestCase(unittest.TestCase):
# Google doesn't have any icon links
# So instead we'll grab its favicon.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.assertEquals, icon)
return d
@ -37,7 +40,7 @@ class TrackerIconsTestCase(unittest.TestCase):
def test_get_google_ico_with_redirect(self):
# google.com redirects to www.google.com
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.assertEquals, icon)
return d
@ -45,7 +48,7 @@ class TrackerIconsTestCase(unittest.TestCase):
def test_get_ubuntu_ico(self):
# ubuntu.com has inline css which causes HTMLParser issues
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.assertEquals, icon)
return d
@ -53,19 +56,19 @@ class TrackerIconsTestCase(unittest.TestCase):
def test_get_openbt_png(self):
# openbittorrent.com has an incorrect type (image/gif)
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.assertEquals, icon)
return d
def test_get_publicbt_ico(self):
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.assertEquals, icon)
return d
def test_get_empty_string_tracker(self):
d = icons.fetch("")
d = self.icons.fetch("")
d.addCallback(self.assertIdentical, None)
return d

16
tox.ini
View File

@ -52,7 +52,21 @@ commands =
[testenv:pydef]
commands =
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]
commands = py.test deluge/plugins