Merge pull request #731 from datastax/python-update-unit-tests
Python update unit tests
This commit is contained in:
@@ -12,24 +12,13 @@ python -c "import platform; print(platform.architecture())"
|
|||||||
|
|
||||||
$wc = New-Object 'System.Net.WebClient'
|
$wc = New-Object 'System.Net.WebClient'
|
||||||
nosetests -s -v --with-ignore-docstrings --with-xunit --xunit-file=unit_results.xml .\tests\unit
|
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"
|
echo "uploading unit results"
|
||||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\unit_results.xml))
|
$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
|
exit 0
|
||||||
|
@@ -20,6 +20,7 @@ import logging
|
|||||||
import sys
|
import sys
|
||||||
import socket
|
import socket
|
||||||
import platform
|
import platform
|
||||||
|
import os
|
||||||
|
|
||||||
log = logging.getLogger()
|
log = logging.getLogger()
|
||||||
log.setLevel('DEBUG')
|
log.setLevel('DEBUG')
|
||||||
@@ -44,7 +45,22 @@ def is_gevent_monkey_patched():
|
|||||||
return socket.socket is gevent.socket.socket
|
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():
|
def is_monkey_patched():
|
||||||
return is_gevent_monkey_patched() or is_eventlet_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")
|
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 os
|
||||||
import select
|
import select
|
||||||
import socket
|
import socket
|
||||||
import thread
|
try:
|
||||||
import Queue
|
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 threading
|
||||||
import __builtin__
|
|
||||||
import ssl
|
import ssl
|
||||||
import time
|
import time
|
||||||
|
import eventlet
|
||||||
|
from imp import reload
|
||||||
|
|
||||||
def eventlet_un_patch_all():
|
def eventlet_un_patch_all():
|
||||||
"""
|
"""
|
||||||
@@ -34,4 +42,7 @@ def eventlet_un_patch_all():
|
|||||||
for to_unpatch in modules_to_unpatch:
|
for to_unpatch in modules_to_unpatch:
|
||||||
reload(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:
|
except ImportError:
|
||||||
import unittest # noqa
|
import unittest # noqa
|
||||||
|
|
||||||
from tests.unit.io.utils import submit_and_wait_for_completion, TimerCallback
|
from tests.unit.io.utils import TimerConnectionTests
|
||||||
from tests import is_eventlet_monkey_patched
|
from tests import notpypy, MONKEY_PATCH_LOOP, notmonkeypatch
|
||||||
import time
|
|
||||||
|
from eventlet import monkey_patch
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cassandra.io.eventletreactor import EventletConnection
|
from cassandra.io.eventletreactor import EventletConnection
|
||||||
except ImportError:
|
except ImportError:
|
||||||
EventletConnection = None # noqa
|
EventletConnection = None # noqa
|
||||||
|
|
||||||
|
# There are some issues with some versions of pypy and eventlet
|
||||||
class EventletTimerTest(unittest.TestCase):
|
@notpypy
|
||||||
|
@unittest.skipIf(EventletConnection is None, "Skpping the eventlet tests because it's not installed")
|
||||||
def setUp(self):
|
@notmonkeypatch
|
||||||
if EventletConnection is None:
|
class EventletTimerTest(unittest.TestCase, TimerConnectionTests):
|
||||||
raise unittest.SkipTest("Eventlet libraries not available")
|
@classmethod
|
||||||
if not is_eventlet_monkey_patched():
|
def setUpClass(cls):
|
||||||
raise unittest.SkipTest("Can't test eventlet 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
|
||||||
|
monkey_patch()
|
||||||
|
cls.connection_class = EventletConnection
|
||||||
EventletConnection.initialize_reactor()
|
EventletConnection.initialize_reactor()
|
||||||
|
|
||||||
def test_multi_timer_validation(self, *args):
|
# There is no unpatching because there is not a clear way
|
||||||
"""
|
# of doing it reliably
|
||||||
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())
|
|
||||||
|
@@ -17,67 +17,28 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import unittest # noqa
|
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:
|
try:
|
||||||
from cassandra.io.geventreactor import GeventConnection
|
from cassandra.io.geventreactor import GeventConnection
|
||||||
import gevent.monkey
|
import gevent.monkey
|
||||||
from gevent_utils import gevent_un_patch_all
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
GeventConnection = None # noqa
|
GeventConnection = None # noqa
|
||||||
|
|
||||||
|
|
||||||
class GeventTimerTest(unittest.TestCase):
|
@unittest.skipIf(GeventConnection is None, "Skpping the gevent tests because it's not installed")
|
||||||
|
@notmonkeypatch
|
||||||
need_unpatch = False
|
class GeventTimerTest(unittest.TestCase, TimerConnectionTests):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
if is_eventlet_monkey_patched():
|
# This is run even though the class is skipped, so we need
|
||||||
return # no dynamic patching if we have eventlet applied
|
# to make sure no monkey patching is happening
|
||||||
if GeventConnection is not None:
|
if not MONKEY_PATCH_LOOP:
|
||||||
if not is_gevent_monkey_patched():
|
return
|
||||||
cls.need_unpatch = True
|
|
||||||
gevent.monkey.patch_all()
|
gevent.monkey.patch_all()
|
||||||
|
cls.connection_class = GeventConnection
|
||||||
@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")
|
|
||||||
GeventConnection.initialize_reactor()
|
GeventConnection.initialize_reactor()
|
||||||
|
|
||||||
def test_multi_timer_validation(self):
|
# There is no unpatching because there is not a clear way
|
||||||
"""
|
# of doing it reliably
|
||||||
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())
|
|
||||||
|
@@ -22,6 +22,7 @@ from mock import patch, Mock
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from tests.unit.io.utils import submit_and_wait_for_completion, TimerCallback
|
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
|
from tests import is_monkey_patched
|
||||||
|
|
||||||
|
|
||||||
|
@@ -12,6 +12,11 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
try:
|
||||||
|
import unittest2 as unittest
|
||||||
|
except ImportError:
|
||||||
|
import unittest # noqa
|
||||||
|
|
||||||
import time
|
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
|
# ensure they are all called back in a timely fashion
|
||||||
for callback in completed_callbacks:
|
for callback in completed_callbacks:
|
||||||
unit_test.assertAlmostEqual(callback.expected_wait, callback.get_wait_time(), delta=.15)
|
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
|
PyYAML
|
||||||
six
|
six
|
||||||
packaging
|
packaging
|
||||||
|
cython
|
||||||
|
eventlet
|
||||||
|
twisted <15.5.0
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = {[base]deps}
|
deps = {[base]deps}
|
||||||
cython
|
|
||||||
py{27}: gevent
|
|
||||||
twisted <15.5.0
|
|
||||||
setenv = LIBEV_EMBED=0
|
setenv = LIBEV_EMBED=0
|
||||||
CARES_EMBED=0
|
CARES_EMBED=0
|
||||||
changedir = {envtmpdir}
|
changedir = {envtmpdir}
|
||||||
commands = nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/
|
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
|
||||||
|
Reference in New Issue
Block a user