summaryrefslogtreecommitdiffstats
path: root/deluge/tests/test_component.py
diff options
context:
space:
mode:
Diffstat (limited to 'deluge/tests/test_component.py')
-rw-r--r--deluge/tests/test_component.py267
1 files changed, 267 insertions, 0 deletions
diff --git a/deluge/tests/test_component.py b/deluge/tests/test_component.py
new file mode 100644
index 0000000..26f24ad
--- /dev/null
+++ b/deluge/tests/test_component.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+#
+# 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.
+#
+
+from __future__ import unicode_literals
+
+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):
+ component.Component.__init__(self, name, depend=depend)
+ self.start_count = 0
+ self.stop_count = 0
+
+ def start(self):
+ self.start_count += 1
+
+ def stop(self):
+ self.stop_count += 1
+
+
+class ComponentTesterDelayStart(ComponentTester):
+ def start(self):
+ def do_sleep():
+ import time
+
+ time.sleep(1)
+
+ d = threads.deferToThread(do_sleep)
+
+ def on_done(result):
+ self.start_count += 1
+
+ return d.addCallback(on_done)
+
+
+class ComponentTesterUpdate(component.Component):
+ def __init__(self, name):
+ component.Component.__init__(self, name)
+ self.counter = 0
+ self.start_count = 0
+ self.stop_count = 0
+
+ def update(self):
+ self.counter += 1
+
+ def stop(self):
+ self.stop_count += 1
+
+
+class ComponentTesterShutdown(component.Component):
+ def __init__(self, name):
+ component.Component.__init__(self, name)
+ self.shutdowned = False
+ self.stop_count = 0
+
+ def shutdown(self):
+ self.shutdowned = True
+
+ def stop(self):
+ self.stop_count += 1
+
+
+class ComponentTestClass(BaseTestCase):
+ 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)
+
+ c = ComponentTester('test_start_c1')
+ d = component.start(['test_start_c1'])
+ d.addCallback(on_start, c)
+ return d
+
+ 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)
+
+ 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)
+ return component.stop(['test_start_depends_c1']).addCallback(
+ on_stop, c1, c2
+ )
+
+ c1 = ComponentTester('test_start_depends_c1')
+ c2 = ComponentTester('test_start_depends_c2', depend=['test_start_depends_c1'])
+
+ d = component.start(['test_start_depends_c2'])
+ d.addCallback(on_start, c1, c2)
+ return d
+
+ def start_with_depends(self):
+ c1 = ComponentTesterDelayStart('test_start_all_c1')
+ c2 = ComponentTester('test_start_all_c2', depend=['test_start_all_c4'])
+ c3 = ComponentTesterDelayStart(
+ 'test_start_all_c3', depend=['test_start_all_c5', 'test_start_all_c1']
+ )
+ c4 = ComponentTester('test_start_all_c4', depend=['test_start_all_c3'])
+ c5 = ComponentTester('test_start_all_c5')
+
+ d = component.start()
+ return (d, c1, c2, c3, c4, c5)
+
+ def finish_start_with_depends(self, *args):
+ for c in args[1:]:
+ component.deregister(c)
+
+ 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)
+
+ ret = self.start_with_depends()
+ ret[0].addCallback(on_start, *ret[1:])
+ ret[0].addCallback(self.finish_start_with_depends, *ret[1:])
+ return ret[0]
+
+ def test_register_exception(self):
+ ComponentTester('test_register_exception_c1')
+ self.assertRaises(
+ 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)
+
+ def on_start(result, c):
+ self.assertEqual(c._component_state, 'Started')
+ return component.stop(['test_stop_component_c1']).addCallback(on_stop, c)
+
+ c = ComponentTesterUpdate('test_stop_component_c1')
+ d = component.start(['test_stop_component_c1'])
+ d.addCallback(on_start, c)
+ return d
+
+ 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)
+
+ def on_start(result, *args):
+ for c in args:
+ self.assertEqual(c._component_state, 'Started')
+ return component.stop().addCallback(on_stop, *args)
+
+ ret = self.start_with_depends()
+ ret[0].addCallback(on_start, *ret[1:])
+ ret[0].addCallback(self.finish_start_with_depends, *ret[1:])
+ return ret[0]
+
+ 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)
+ return component.stop()
+
+ c1 = ComponentTesterUpdate('test_update_c1')
+ cnt = int(c1.counter)
+ d = component.start(['test_update_c1'])
+
+ d.addCallback(on_start, c1, cnt)
+ return d
+
+ 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)
+
+ def on_start(result, c1, counter):
+ self.assertTrue(c1._component_timer)
+ self.assertNotEqual(c1.counter, counter)
+ d = component.pause(['test_pause_c1'])
+ d.addCallback(on_pause, c1, counter)
+ return d
+
+ c1 = ComponentTesterUpdate('test_pause_c1')
+ cnt = int(c1.counter)
+ d = component.start(['test_pause_c1'])
+
+ d.addCallback(on_start, c1, cnt)
+ return d
+
+ @defer.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
+ )
+
+ @defer.inlineCallbacks
+ def test_start_paused_error(self):
+ ComponentTesterUpdate('test_pause_c1')
+ yield component.start(['test_pause_c1'])
+ yield component.pause(['test_pause_c1'])
+
+ # 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)
+
+ 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'),
+ '',
+ ),
+ )
+ ],
+ )
+
+ 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)
+
+ def on_start(result, c1):
+ d = component.shutdown()
+ d.addCallback(on_shutdown, c1)
+ return d
+
+ c1 = ComponentTesterShutdown('test_shutdown_c1')
+ d = component.start(['test_shutdown_c1'])
+ d.addCallback(on_start, c1)
+ return d