blob: 3ea6c669f38ccc4755ee870a45b5a1dc15db1bbf [file]
# Copyright DataStax, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
from unittest.mock import patch, Mock
import weakref
import socket
from tests import is_monkey_patched
from tests.unit.io.utils import ReactorTestMixin, TimerTestMixin, noop_if_monkey_patched
try:
from cassandra.io.libevreactor import _cleanup as libev__cleanup
from cassandra.io.libevreactor import LibevConnection
except ImportError:
LibevConnection = None # noqa
class LibevConnectionTest(ReactorTestMixin, unittest.TestCase):
connection_class = LibevConnection
socket_attr_name = '_socket'
null_handle_function_args = None, 0
def setUp(self):
if is_monkey_patched():
raise unittest.SkipTest("Can't test libev with monkey patching")
if LibevConnection is None:
raise unittest.SkipTest('libev does not appear to be installed correctly')
LibevConnection.initialize_reactor()
# we patch here rather than as a decorator so that the Mixin can avoid
# specifying patch args to test methods
patchers = [patch(obj) for obj in
('socket.socket',
'cassandra.io.libevwrapper.IO',
'cassandra.io.libevreactor.LibevLoop.maybe_start'
)]
for p in patchers:
self.addCleanup(p.stop)
for p in patchers:
p.start()
def test_watchers_are_finished(self):
"""
Test for asserting that watchers are closed in LibevConnection
This test simulates a process termination without calling cluster.shutdown(), which would trigger
_global_loop._cleanup. It will check the watchers have been closed
Finally it will restore the LibevConnection reactor so it doesn't affect
the rest of the tests
@since 3.10
@jira_ticket PYTHON-747
@expected_result the watchers are closed
@test_category connection
"""
from cassandra.io.libevreactor import _global_loop
with patch.object(_global_loop, "_thread"),\
patch.object(_global_loop, "notify"):
self.make_connection()
# We have to make a copy because the connections shouldn't
# be alive when we verify them
live_connections = set(_global_loop._live_conns)
# This simulates the process ending without cluster.shutdown()
# being called, then with atexit _cleanup for libevreactor would
# be called
libev__cleanup(_global_loop)
for conn in live_connections:
self.assertTrue(conn._write_watcher.stop.mock_calls)
self.assertTrue(conn._read_watcher.stop.mock_calls)
_global_loop._shutdown = False
class LibevTimerPatcher(unittest.TestCase):
@classmethod
@noop_if_monkey_patched
def setUpClass(cls):
if LibevConnection is None:
raise unittest.SkipTest('libev does not appear to be installed correctly')
cls.patchers = [
patch('socket.socket', spec=socket.socket),
patch('cassandra.io.libevwrapper.IO')
]
for p in cls.patchers:
p.start()
@classmethod
@noop_if_monkey_patched
def tearDownClass(cls):
for p in cls.patchers:
try:
p.stop()
except:
pass
class LibevTimerTest(TimerTestMixin, LibevTimerPatcher):
connection_class = LibevConnection
@property
def create_timer(self):
return self.connection.create_timer
@property
def _timers(self):
from cassandra.io.libevreactor import _global_loop
return _global_loop._timers
def make_connection(self):
c = LibevConnection('1.2.3.4', cql_version='3.0.1')
c._socket_impl = Mock()
c._socket.return_value.send.side_effect = lambda x: len(x)
return c
def setUp(self):
if is_monkey_patched():
raise unittest.SkipTest("Can't test libev with monkey patching.")
if LibevConnection is None:
raise unittest.SkipTest('libev does not appear to be installed correctly')
LibevConnection.initialize_reactor()
super(LibevTimerTest, self).setUp()