Skip to content

Commit

Permalink
Merge pull request #3491 from qstokkink/fix_test_reactor_conflict
Browse files Browse the repository at this point in the history
Fixed reactor conflict in tests
  • Loading branch information
devos50 authored Mar 4, 2018
2 parents 3bd251b + 93b496c commit 77fb0d1
Showing 1 changed file with 1 addition and 147 deletions.
148 changes: 1 addition & 147 deletions Tribler/Test/util/ipv8_util.py
Original file line number Diff line number Diff line change
@@ -1,152 +1,6 @@
import Queue
import sys

from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from twisted.python import log

_twisted_thread = None


class TimeExpired(AssertionError):
pass


def make_decorator(func):
"""
Wraps a test decorator so as to properly replicate metadata
of the decorated function, including nose's additional stuff
(namely, setup and teardown).
"""

def decorate(newfunc):
if hasattr(func, 'compat_func_name'):
name = func.compat_func_name
else:
name = func.__name__
newfunc.__dict__ = func.__dict__
newfunc.__doc__ = func.__doc__
newfunc.__module__ = func.__module__
if not hasattr(newfunc, 'compat_co_firstlineno'):
newfunc.compat_co_firstlineno = func.func_code.co_firstlineno
try:
newfunc.__name__ = name
except TypeError:
# can't set func name in 2.3
newfunc.compat_func_name = name
return newfunc

return decorate


def threaded_reactor():
"""
Start the Twisted reactor in a separate thread, if not already done.
Returns the reactor.
"""
global _twisted_thread
if not _twisted_thread:
from threading import Thread

_twisted_thread = Thread(target=lambda: reactor.run(installSignalHandlers=False), name="Twisted")
_twisted_thread.setDaemon(True)
_twisted_thread.start()

def hook_observer():
observer = log.PythonLoggingObserver()
observer.start()
import logging
log.msg("PythonLoggingObserver hooked up", logLevel=logging.DEBUG)

reactor.callFromThread(hook_observer)

return reactor, _twisted_thread


def deferred(timeout=None):
"""
By wrapping a test function with this decorator, you can return a
twisted Deferred and the test will wait for the deferred to be triggered.
The whole test function will run inside the Twisted event loop.
The optional timeout parameter specifies the maximum duration of the test.
The difference with timed() is that timed() will still wait for the test
to end, while deferred() will stop the test when its timeout has expired.
The latter is more desireable when dealing with network tests, because
the result may actually never arrive.
If the callback is triggered, the test has passed.
If the errback is triggered or the timeout expires, the test has failed.
Example::
@deferred(timeout=5.0)
def test_resolve():
return reactor.resolve("www.python.org")
Attention! If you combine this decorator with other decorators (like
"raises"), deferred() must be called *first*!
In other words, this is good::
@raises(DNSLookupError)
@deferred()
def test_error():
return reactor.resolve("xxxjhjhj.biz")
and this is bad::
@deferred()
@raises(DNSLookupError)
def test_error():
return reactor.resolve("xxxjhjhj.biz")
"""
reactor, reactor_thread = threaded_reactor()
if reactor is None:
raise ImportError("twisted is not available or could not be imported")
# Check for common syntax mistake
# (otherwise, tests can be silently ignored
# if one writes "@deferred" instead of "@deferred()")
try:
timeout is None or timeout + 0
except TypeError:
raise TypeError("'timeout' argument must be a number or None")

def decorate(func):
def wrapper(*args, **kargs):
q = Queue.Queue()

def callback(_):
q.put(None)

def errback(failure):
# Retrieve and save full exception info
try:
failure.raiseException()
except:
q.put(sys.exc_info())

def g():
try:
d = func(*args, **kargs)
try:
d.addCallbacks(callback, errback)
# Check for a common mistake and display a nice error
# message
except AttributeError:
raise TypeError("you must return a twisted Deferred "
"from your test case!")
# Catch exceptions raised in the test body (from the
# Twisted thread)
except:
q.put(sys.exc_info())

reactor.callFromThread(g)
try:
error = q.get(timeout=timeout)
except Queue.Empty:
raise TimeExpired("timeout expired before end of test (%f s.)"
% timeout)
# Re-raise all exceptions
if error is not None:
exc_type, exc_value, tb = error
raise exc_type, exc_value, tb

wrapper = make_decorator(func)(wrapper)
return wrapper

return decorate
from Tribler.Test.twisted_thread import deferred


def twisted_wrapper(arg):
Expand Down

0 comments on commit 77fb0d1

Please sign in to comment.