Merge pull request #731 from datastax/python-update-unit-tests
Python update unit tests
This commit is contained in:
commit
4ca22b2e8e
@ -12,24 +12,13 @@ python -c "import platform; print(platform.architecture())"
|
||||
|
||||
$wc = New-Object 'System.Net.WebClient'
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=unit_results.xml .\tests\unit
|
||||
|
||||
$env:MONKEY_PATCH_LOOP=1
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=unit_results.xml .\tests\unit\io\test_geventreactor.py
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=unit_results.xml .\tests\unit\io\test_eventletreactor.py
|
||||
Remove-Item $env:MONKEY_PATCH_LOOP
|
||||
|
||||
echo "uploading unit results"
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\unit_results.xml))
|
||||
|
||||
if($env:ci_type -eq 'standard' -Or $env:ci_type -eq 'long'){
|
||||
echo "Running CQLEngine integration tests"
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=cqlengine_results.xml .\tests\integration\cqlengine
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\cqlengine_results.xml))
|
||||
echo "uploading CQLEngine test results"
|
||||
|
||||
echo "Running standard integration tests"
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=standard_results.xml .\tests\integration\standard
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\standard_results.xml))
|
||||
echo "uploading standard integration test results"
|
||||
}
|
||||
|
||||
if($env:ci_type -eq 'long'){
|
||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=cqlengine_results.xml .\tests\integration\cqlengine
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\cqlengine_results.xml))
|
||||
echo "uploading standard integration test results"
|
||||
}
|
||||
exit 0
|
||||
|
@ -20,6 +20,7 @@ import logging
|
||||
import sys
|
||||
import socket
|
||||
import platform
|
||||
import os
|
||||
|
||||
log = logging.getLogger()
|
||||
log.setLevel('DEBUG')
|
||||
@ -44,7 +45,22 @@ def is_gevent_monkey_patched():
|
||||
return socket.socket is gevent.socket.socket
|
||||
|
||||
|
||||
def is_gevent_time_monkey_patched():
|
||||
import gevent.monkey
|
||||
return "time" in gevent.monkey.saved
|
||||
|
||||
|
||||
def is_eventlet_time_monkey_patched():
|
||||
import eventlet
|
||||
return eventlet.patcher.is_monkey_patched('time')
|
||||
|
||||
|
||||
def is_monkey_patched():
|
||||
return is_gevent_monkey_patched() or is_eventlet_monkey_patched()
|
||||
|
||||
|
||||
MONKEY_PATCH_LOOP = bool(os.getenv('MONKEY_PATCH_LOOP', False))
|
||||
|
||||
notwindows = unittest.skipUnless(not "Windows" in platform.system(), "This test is not adequate for windows")
|
||||
notpypy = unittest.skipUnless(not platform.python_implementation() == 'PyPy', "This tests is not suitable for pypy")
|
||||
notmonkeypatch = unittest.skipUnless(MONKEY_PATCH_LOOP, "Skpping this test because monkey patching is required")
|
@ -16,13 +16,21 @@
|
||||
import os
|
||||
import select
|
||||
import socket
|
||||
import thread
|
||||
import Queue
|
||||
try:
|
||||
import thread
|
||||
import Queue
|
||||
import __builtin__
|
||||
#For python3 compatibility
|
||||
except ImportError:
|
||||
import _thread as thread
|
||||
import queue as Queue
|
||||
import builtins as __builtin__
|
||||
|
||||
import threading
|
||||
import __builtin__
|
||||
import ssl
|
||||
import time
|
||||
|
||||
import eventlet
|
||||
from imp import reload
|
||||
|
||||
def eventlet_un_patch_all():
|
||||
"""
|
||||
@ -34,4 +42,7 @@ def eventlet_un_patch_all():
|
||||
for to_unpatch in modules_to_unpatch:
|
||||
reload(to_unpatch)
|
||||
|
||||
def restore_saved_module(module):
|
||||
reload(module)
|
||||
del eventlet.patcher.already_patched[module.__name__]
|
||||
|
||||
|
@ -18,50 +18,30 @@ try:
|
||||
except ImportError:
|
||||
import unittest # noqa
|
||||
|
||||
from tests.unit.io.utils import submit_and_wait_for_completion, TimerCallback
|
||||
from tests import is_eventlet_monkey_patched
|
||||
import time
|
||||
from tests.unit.io.utils import TimerConnectionTests
|
||||
from tests import notpypy, MONKEY_PATCH_LOOP, notmonkeypatch
|
||||
|
||||
from eventlet import monkey_patch
|
||||
|
||||
try:
|
||||
from cassandra.io.eventletreactor import EventletConnection
|
||||
except ImportError:
|
||||
EventletConnection = None # noqa
|
||||
|
||||
|
||||
class EventletTimerTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
if EventletConnection is None:
|
||||
raise unittest.SkipTest("Eventlet libraries not available")
|
||||
if not is_eventlet_monkey_patched():
|
||||
raise unittest.SkipTest("Can't test eventlet without monkey patching")
|
||||
# There are some issues with some versions of pypy and eventlet
|
||||
@notpypy
|
||||
@unittest.skipIf(EventletConnection is None, "Skpping the eventlet tests because it's not installed")
|
||||
@notmonkeypatch
|
||||
class EventletTimerTest(unittest.TestCase, TimerConnectionTests):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# This is run even though the class is skipped, so we need
|
||||
# to make sure no monkey patching is happening
|
||||
if not MONKEY_PATCH_LOOP:
|
||||
return
|
||||
monkey_patch()
|
||||
cls.connection_class = EventletConnection
|
||||
EventletConnection.initialize_reactor()
|
||||
|
||||
def test_multi_timer_validation(self, *args):
|
||||
"""
|
||||
Verify that timer timeouts are honored appropriately
|
||||
"""
|
||||
# Tests timers submitted in order at various timeouts
|
||||
submit_and_wait_for_completion(self, EventletConnection, 0, 100, 1, 100)
|
||||
# Tests timers submitted in reverse order at various timeouts
|
||||
submit_and_wait_for_completion(self, EventletConnection, 100, 0, -1, 100)
|
||||
# Tests timers submitted in varying order at various timeouts
|
||||
submit_and_wait_for_completion(self, EventletConnection, 0, 100, 1, 100, True)
|
||||
|
||||
def test_timer_cancellation(self):
|
||||
"""
|
||||
Verify that timer cancellation is honored
|
||||
"""
|
||||
|
||||
# Various lists for tracking callback stage
|
||||
timeout = .1
|
||||
callback = TimerCallback(timeout)
|
||||
timer = EventletConnection.create_timer(timeout, callback.invoke)
|
||||
timer.cancel()
|
||||
# Release context allow for timer thread to run.
|
||||
time.sleep(.2)
|
||||
timer_manager = EventletConnection._timers
|
||||
# Assert that the cancellation was honored
|
||||
self.assertFalse(timer_manager._queue)
|
||||
self.assertFalse(timer_manager._new_timers)
|
||||
self.assertFalse(callback.was_invoked())
|
||||
# There is no unpatching because there is not a clear way
|
||||
# of doing it reliably
|
||||
|
@ -17,67 +17,28 @@ try:
|
||||
except ImportError:
|
||||
import unittest # noqa
|
||||
|
||||
import time
|
||||
from tests.unit.io.utils import submit_and_wait_for_completion, TimerCallback
|
||||
from tests import is_gevent_monkey_patched, is_eventlet_monkey_patched
|
||||
|
||||
from tests.unit.io.utils import TimerConnectionTests
|
||||
from tests import MONKEY_PATCH_LOOP, notmonkeypatch
|
||||
try:
|
||||
from cassandra.io.geventreactor import GeventConnection
|
||||
import gevent.monkey
|
||||
from gevent_utils import gevent_un_patch_all
|
||||
except ImportError:
|
||||
GeventConnection = None # noqa
|
||||
|
||||
|
||||
class GeventTimerTest(unittest.TestCase):
|
||||
|
||||
need_unpatch = False
|
||||
|
||||
@unittest.skipIf(GeventConnection is None, "Skpping the gevent tests because it's not installed")
|
||||
@notmonkeypatch
|
||||
class GeventTimerTest(unittest.TestCase, TimerConnectionTests):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if is_eventlet_monkey_patched():
|
||||
return # no dynamic patching if we have eventlet applied
|
||||
if GeventConnection is not None:
|
||||
if not is_gevent_monkey_patched():
|
||||
cls.need_unpatch = True
|
||||
gevent.monkey.patch_all()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.need_unpatch:
|
||||
gevent_un_patch_all()
|
||||
|
||||
def setUp(self):
|
||||
if not is_gevent_monkey_patched():
|
||||
raise unittest.SkipTest("Can't test gevent without monkey patching")
|
||||
# This is run even though the class is skipped, so we need
|
||||
# to make sure no monkey patching is happening
|
||||
if not MONKEY_PATCH_LOOP:
|
||||
return
|
||||
gevent.monkey.patch_all()
|
||||
cls.connection_class = GeventConnection
|
||||
GeventConnection.initialize_reactor()
|
||||
|
||||
def test_multi_timer_validation(self):
|
||||
"""
|
||||
Verify that timer timeouts are honored appropriately
|
||||
"""
|
||||
|
||||
# Tests timers submitted in order at various timeouts
|
||||
submit_and_wait_for_completion(self, GeventConnection, 0, 100, 1, 100)
|
||||
# Tests timers submitted in reverse order at various timeouts
|
||||
submit_and_wait_for_completion(self, GeventConnection, 100, 0, -1, 100)
|
||||
# Tests timers submitted in varying order at various timeouts
|
||||
submit_and_wait_for_completion(self, GeventConnection, 0, 100, 1, 100, True),
|
||||
|
||||
def test_timer_cancellation(self):
|
||||
"""
|
||||
Verify that timer cancellation is honored
|
||||
"""
|
||||
|
||||
# Various lists for tracking callback stage
|
||||
timeout = .1
|
||||
callback = TimerCallback(timeout)
|
||||
timer = GeventConnection.create_timer(timeout, callback.invoke)
|
||||
timer.cancel()
|
||||
# Release context allow for timer thread to run.
|
||||
time.sleep(.2)
|
||||
timer_manager = GeventConnection._timers
|
||||
# Assert that the cancellation was honored
|
||||
self.assertFalse(timer_manager._queue)
|
||||
self.assertFalse(timer_manager._new_timers)
|
||||
self.assertFalse(callback.was_invoked())
|
||||
# There is no unpatching because there is not a clear way
|
||||
# of doing it reliably
|
||||
|
@ -22,6 +22,7 @@ from mock import patch, Mock
|
||||
import time
|
||||
|
||||
from tests.unit.io.utils import submit_and_wait_for_completion, TimerCallback
|
||||
from tests.unit.io.utils import TimerConnectionTests
|
||||
from tests import is_monkey_patched
|
||||
|
||||
|
||||
|
@ -12,6 +12,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
try:
|
||||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest # noqa
|
||||
|
||||
import time
|
||||
|
||||
|
||||
@ -103,3 +108,34 @@ def submit_and_wait_for_completion(unit_test, connection, start, end, increment,
|
||||
# ensure they are all called back in a timely fashion
|
||||
for callback in completed_callbacks:
|
||||
unit_test.assertAlmostEqual(callback.expected_wait, callback.get_wait_time(), delta=.15)
|
||||
|
||||
|
||||
class TimerConnectionTests(object):
|
||||
def test_multi_timer_validation(self):
|
||||
"""
|
||||
Verify that timer timeouts are honored appropriately
|
||||
"""
|
||||
# Tests timers submitted in order at various timeouts
|
||||
submit_and_wait_for_completion(self, self.connection_class, 0, 100, 1, 100)
|
||||
# Tests timers submitted in reverse order at various timeouts
|
||||
submit_and_wait_for_completion(self, self.connection_class, 100, 0, -1, 100)
|
||||
# Tests timers submitted in varying order at various timeouts
|
||||
submit_and_wait_for_completion(self, self.connection_class, 0, 100, 1, 100, True),
|
||||
|
||||
def test_timer_cancellation(self):
|
||||
"""
|
||||
Verify that timer cancellation is honored
|
||||
"""
|
||||
|
||||
# Various lists for tracking callback stage
|
||||
timeout = .1
|
||||
callback = TimerCallback(timeout)
|
||||
timer = self.connection_class.create_timer(timeout, callback.invoke)
|
||||
timer.cancel()
|
||||
# Release context allow for timer thread to run.
|
||||
time.sleep(.2)
|
||||
timer_manager = self.connection_class._timers
|
||||
# Assert that the cancellation was honored
|
||||
self.assertFalse(timer_manager._queue)
|
||||
self.assertFalse(timer_manager._new_timers)
|
||||
self.assertFalse(callback.was_invoked())
|
||||
|
33
tox.ini
33
tox.ini
@ -7,13 +7,40 @@ deps = nose
|
||||
PyYAML
|
||||
six
|
||||
packaging
|
||||
cython
|
||||
eventlet
|
||||
twisted <15.5.0
|
||||
|
||||
[testenv]
|
||||
deps = {[base]deps}
|
||||
cython
|
||||
py{27}: gevent
|
||||
twisted <15.5.0
|
||||
|
||||
setenv = LIBEV_EMBED=0
|
||||
CARES_EMBED=0
|
||||
changedir = {envtmpdir}
|
||||
commands = nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/
|
||||
|
||||
|
||||
[testenv:py27]
|
||||
deps = {[base]deps}
|
||||
gevent
|
||||
|
||||
setenv = LIBEV_EMBED=0
|
||||
CARES_EMBED=0
|
||||
MONKEY_PATCH_LOOP=1
|
||||
changedir = {envtmpdir}
|
||||
commands =
|
||||
nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/io/test_eventletreactor.py
|
||||
nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/io/test_geventreactor.py
|
||||
|
||||
|
||||
[testenv:py34]
|
||||
deps = {[base]deps}
|
||||
gevent
|
||||
|
||||
setenv = LIBEV_EMBED=0
|
||||
CARES_EMBED=0
|
||||
MONKEY_PATCH_LOOP=1
|
||||
changedir = {envtmpdir}
|
||||
commands =
|
||||
nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/io/test_eventletreactor.py
|
||||
nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/io/test_geventreactor.py
|
||||
|
Loading…
Reference in New Issue
Block a user