
- Fixed failing unit tests after Session.__init__ change - Added integration test for PYTHON-665
355 lines
18 KiB
Python
355 lines
18 KiB
Python
# Copyright 2013-2016 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.
|
|
try:
|
|
import unittest2 as unittest
|
|
except ImportError:
|
|
import unittest # noqa
|
|
|
|
from mock import patch
|
|
|
|
from cassandra import ConsistencyLevel, DriverException, Timeout, Unavailable, RequestExecutionException, ReadTimeout, WriteTimeout, CoordinationFailure, ReadFailure, WriteFailure, FunctionFailure, AlreadyExists,\
|
|
InvalidRequest, Unauthorized, AuthenticationFailed, OperationTimedOut, UnsupportedOperation, RequestValidationException, ConfigurationException
|
|
from cassandra.cluster import _Scheduler, Session, Cluster, _NOT_SET, default_lbp_factory, \
|
|
ExecutionProfile, _ConfigMode, EXEC_PROFILE_DEFAULT, NoHostAvailable
|
|
from cassandra.policies import HostDistance, RetryPolicy, RoundRobinPolicy, \
|
|
DowngradingConsistencyRetryPolicy, SimpleConvictionPolicy
|
|
from cassandra.query import SimpleStatement, named_tuple_factory, tuple_factory
|
|
from cassandra.pool import Host
|
|
from tests.unit.utils import mock_session_pools
|
|
|
|
class ExceptionTypeTest(unittest.TestCase):
|
|
|
|
def test_exception_types(self):
|
|
"""
|
|
PYTHON-443
|
|
Sanity check to ensure we don't unintentionally change class hierarchy of exception types
|
|
"""
|
|
self.assertTrue(issubclass(Unavailable, DriverException))
|
|
self.assertTrue(issubclass(Unavailable, RequestExecutionException))
|
|
|
|
self.assertTrue(issubclass(ReadTimeout, DriverException))
|
|
self.assertTrue(issubclass(ReadTimeout, RequestExecutionException))
|
|
self.assertTrue(issubclass(ReadTimeout, Timeout))
|
|
|
|
self.assertTrue(issubclass(WriteTimeout, DriverException))
|
|
self.assertTrue(issubclass(WriteTimeout, RequestExecutionException))
|
|
self.assertTrue(issubclass(WriteTimeout, Timeout))
|
|
|
|
self.assertTrue(issubclass(CoordinationFailure, DriverException))
|
|
self.assertTrue(issubclass(CoordinationFailure, RequestExecutionException))
|
|
|
|
self.assertTrue(issubclass(ReadFailure, DriverException))
|
|
self.assertTrue(issubclass(ReadFailure, RequestExecutionException))
|
|
self.assertTrue(issubclass(ReadFailure, CoordinationFailure))
|
|
|
|
self.assertTrue(issubclass(WriteFailure, DriverException))
|
|
self.assertTrue(issubclass(WriteFailure, RequestExecutionException))
|
|
self.assertTrue(issubclass(WriteFailure, CoordinationFailure))
|
|
|
|
self.assertTrue(issubclass(FunctionFailure, DriverException))
|
|
self.assertTrue(issubclass(FunctionFailure, RequestExecutionException))
|
|
|
|
self.assertTrue(issubclass(RequestValidationException, DriverException))
|
|
|
|
self.assertTrue(issubclass(ConfigurationException, DriverException))
|
|
self.assertTrue(issubclass(ConfigurationException, RequestValidationException))
|
|
|
|
self.assertTrue(issubclass(AlreadyExists, DriverException))
|
|
self.assertTrue(issubclass(AlreadyExists, RequestValidationException))
|
|
self.assertTrue(issubclass(AlreadyExists, ConfigurationException))
|
|
|
|
self.assertTrue(issubclass(InvalidRequest, DriverException))
|
|
self.assertTrue(issubclass(InvalidRequest, RequestValidationException))
|
|
|
|
self.assertTrue(issubclass(Unauthorized, DriverException))
|
|
self.assertTrue(issubclass(Unauthorized, RequestValidationException))
|
|
|
|
self.assertTrue(issubclass(AuthenticationFailed, DriverException))
|
|
|
|
self.assertTrue(issubclass(OperationTimedOut, DriverException))
|
|
|
|
self.assertTrue(issubclass(UnsupportedOperation, DriverException))
|
|
|
|
|
|
class ClusterTest(unittest.TestCase):
|
|
|
|
def test_invalid_contact_point_types(self):
|
|
with self.assertRaises(ValueError):
|
|
Cluster(contact_points=[None], protocol_version=4, connect_timeout=1)
|
|
with self.assertRaises(TypeError):
|
|
Cluster(contact_points="not a sequence", protocol_version=4, connect_timeout=1)
|
|
|
|
def test_requests_in_flight_threshold(self):
|
|
d = HostDistance.LOCAL
|
|
mn = 3
|
|
mx = 5
|
|
c = Cluster(protocol_version=2)
|
|
c.set_min_requests_per_connection(d, mn)
|
|
c.set_max_requests_per_connection(d, mx)
|
|
# min underflow, max, overflow
|
|
for n in (-1, mx, 127):
|
|
self.assertRaises(ValueError, c.set_min_requests_per_connection, d, n)
|
|
# max underflow, under min, overflow
|
|
for n in (0, mn, 128):
|
|
self.assertRaises(ValueError, c.set_max_requests_per_connection, d, n)
|
|
|
|
|
|
class SchedulerTest(unittest.TestCase):
|
|
# TODO: this suite could be expanded; for now just adding a test covering a ticket
|
|
|
|
@patch('time.time', return_value=3) # always queue at same time
|
|
@patch('cassandra.cluster._Scheduler.run') # don't actually run the thread
|
|
def test_event_delay_timing(self, *_):
|
|
"""
|
|
Schedule something with a time collision to make sure the heap comparison works
|
|
|
|
PYTHON-473
|
|
"""
|
|
sched = _Scheduler(None)
|
|
sched.schedule(0, lambda: None)
|
|
sched.schedule(0, lambda: None) # pre-473: "TypeError: unorderable types: function() < function()"t
|
|
|
|
|
|
class SessionTest(unittest.TestCase):
|
|
# TODO: this suite could be expanded; for now just adding a test covering a PR
|
|
@mock_session_pools
|
|
def test_default_serial_consistency_level(self, *_):
|
|
"""
|
|
Make sure default_serial_consistency_level passes through to a query message.
|
|
Also make sure Statement.serial_consistency_level overrides the default.
|
|
|
|
PR #510
|
|
"""
|
|
s = Session(Cluster(protocol_version=4), [Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
|
|
# default is None
|
|
self.assertIsNone(s.default_serial_consistency_level)
|
|
|
|
sentinel = 1001
|
|
for cl in (None, ConsistencyLevel.LOCAL_SERIAL, ConsistencyLevel.SERIAL, sentinel):
|
|
s.default_serial_consistency_level = cl
|
|
|
|
# default is passed through
|
|
f = s.execute_async(query='')
|
|
self.assertEqual(f.message.serial_consistency_level, cl)
|
|
|
|
# any non-None statement setting takes precedence
|
|
for cl_override in (ConsistencyLevel.LOCAL_SERIAL, ConsistencyLevel.SERIAL):
|
|
f = s.execute_async(SimpleStatement(query_string='', serial_consistency_level=cl_override))
|
|
self.assertEqual(s.default_serial_consistency_level, cl)
|
|
self.assertEqual(f.message.serial_consistency_level, cl_override)
|
|
|
|
|
|
class ExecutionProfileTest(unittest.TestCase):
|
|
|
|
def _verify_response_future_profile(self, rf, prof):
|
|
self.assertEqual(rf._load_balancer, prof.load_balancing_policy)
|
|
self.assertEqual(rf._retry_policy, prof.retry_policy)
|
|
self.assertEqual(rf.message.consistency_level, prof.consistency_level)
|
|
self.assertEqual(rf.message.serial_consistency_level, prof.serial_consistency_level)
|
|
self.assertEqual(rf.timeout, prof.request_timeout)
|
|
self.assertEqual(rf.row_factory, prof.row_factory)
|
|
|
|
@mock_session_pools
|
|
def test_default_exec_parameters(self):
|
|
cluster = Cluster()
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.UNCOMMITTED)
|
|
self.assertEqual(cluster.load_balancing_policy.__class__, default_lbp_factory().__class__)
|
|
self.assertEqual(cluster.default_retry_policy.__class__, RetryPolicy)
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
self.assertEqual(session.default_timeout, 10.0)
|
|
self.assertEqual(session.default_consistency_level, ConsistencyLevel.LOCAL_ONE)
|
|
self.assertEqual(session.default_serial_consistency_level, None)
|
|
self.assertEqual(session.row_factory, named_tuple_factory)
|
|
|
|
@mock_session_pools
|
|
def test_default_legacy(self):
|
|
cluster = Cluster(load_balancing_policy=RoundRobinPolicy(), default_retry_policy=DowngradingConsistencyRetryPolicy())
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.LEGACY)
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
session.default_timeout = 3.7
|
|
session.default_consistency_level = ConsistencyLevel.ALL
|
|
session.default_serial_consistency_level = ConsistencyLevel.SERIAL
|
|
rf = session.execute_async("query")
|
|
expected_profile = ExecutionProfile(cluster.load_balancing_policy, cluster.default_retry_policy,
|
|
session.default_consistency_level, session.default_serial_consistency_level,
|
|
session.default_timeout, session.row_factory)
|
|
self._verify_response_future_profile(rf, expected_profile)
|
|
|
|
@mock_session_pools
|
|
def test_default_profile(self):
|
|
non_default_profile = ExecutionProfile(RoundRobinPolicy(), *[object() for _ in range(3)])
|
|
cluster = Cluster(execution_profiles={'non-default': non_default_profile})
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.PROFILES)
|
|
|
|
default_profile = cluster.profile_manager.profiles[EXEC_PROFILE_DEFAULT]
|
|
rf = session.execute_async("query")
|
|
self._verify_response_future_profile(rf, default_profile)
|
|
|
|
rf = session.execute_async("query", execution_profile='non-default')
|
|
self._verify_response_future_profile(rf, non_default_profile)
|
|
|
|
@mock_session_pools
|
|
def test_statement_params_override_legacy(self):
|
|
cluster = Cluster(load_balancing_policy=RoundRobinPolicy(), default_retry_policy=DowngradingConsistencyRetryPolicy())
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.LEGACY)
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
|
|
ss = SimpleStatement("query", retry_policy=DowngradingConsistencyRetryPolicy(),
|
|
consistency_level=ConsistencyLevel.ALL, serial_consistency_level=ConsistencyLevel.SERIAL)
|
|
my_timeout = 1.1234
|
|
|
|
self.assertNotEqual(ss.retry_policy.__class__, cluster.default_retry_policy)
|
|
self.assertNotEqual(ss.consistency_level, session.default_consistency_level)
|
|
self.assertNotEqual(ss._serial_consistency_level, session.default_serial_consistency_level)
|
|
self.assertNotEqual(my_timeout, session.default_timeout)
|
|
|
|
rf = session.execute_async(ss, timeout=my_timeout)
|
|
expected_profile = ExecutionProfile(load_balancing_policy=cluster.load_balancing_policy, retry_policy=ss.retry_policy,
|
|
request_timeout=my_timeout, consistency_level=ss.consistency_level,
|
|
serial_consistency_level=ss._serial_consistency_level)
|
|
self._verify_response_future_profile(rf, expected_profile)
|
|
|
|
@mock_session_pools
|
|
def test_statement_params_override_profile(self):
|
|
non_default_profile = ExecutionProfile(RoundRobinPolicy(), *[object() for _ in range(3)])
|
|
cluster = Cluster(execution_profiles={'non-default': non_default_profile})
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.PROFILES)
|
|
|
|
rf = session.execute_async("query", execution_profile='non-default')
|
|
|
|
ss = SimpleStatement("query", retry_policy=DowngradingConsistencyRetryPolicy(),
|
|
consistency_level=ConsistencyLevel.ALL, serial_consistency_level=ConsistencyLevel.SERIAL)
|
|
my_timeout = 1.1234
|
|
|
|
self.assertNotEqual(ss.retry_policy.__class__, rf._load_balancer.__class__)
|
|
self.assertNotEqual(ss.consistency_level, rf.message.consistency_level)
|
|
self.assertNotEqual(ss._serial_consistency_level, rf.message.serial_consistency_level)
|
|
self.assertNotEqual(my_timeout, rf.timeout)
|
|
|
|
rf = session.execute_async(ss, timeout=my_timeout, execution_profile='non-default')
|
|
expected_profile = ExecutionProfile(non_default_profile.load_balancing_policy, ss.retry_policy,
|
|
ss.consistency_level, ss._serial_consistency_level, my_timeout, non_default_profile.row_factory)
|
|
self._verify_response_future_profile(rf, expected_profile)
|
|
|
|
@mock_session_pools
|
|
def test_no_profile_with_legacy(self):
|
|
# don't construct with both
|
|
self.assertRaises(ValueError, Cluster, load_balancing_policy=RoundRobinPolicy(), execution_profiles={'a': ExecutionProfile()})
|
|
self.assertRaises(ValueError, Cluster, default_retry_policy=DowngradingConsistencyRetryPolicy(), execution_profiles={'a': ExecutionProfile()})
|
|
self.assertRaises(ValueError, Cluster, load_balancing_policy=RoundRobinPolicy(),
|
|
default_retry_policy=DowngradingConsistencyRetryPolicy(), execution_profiles={'a': ExecutionProfile()})
|
|
|
|
# can't add after
|
|
cluster = Cluster(load_balancing_policy=RoundRobinPolicy())
|
|
self.assertRaises(ValueError, cluster.add_execution_profile, 'name', ExecutionProfile())
|
|
|
|
# session settings lock out profiles
|
|
cluster = Cluster()
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
for attr, value in (('default_timeout', 1),
|
|
('default_consistency_level', ConsistencyLevel.ANY),
|
|
('default_serial_consistency_level', ConsistencyLevel.SERIAL),
|
|
('row_factory', tuple_factory)):
|
|
cluster._config_mode = _ConfigMode.UNCOMMITTED
|
|
setattr(session, attr, value)
|
|
self.assertRaises(ValueError, cluster.add_execution_profile, 'name' + attr, ExecutionProfile())
|
|
|
|
# don't accept profile
|
|
self.assertRaises(ValueError, session.execute_async, "query", execution_profile='some name here')
|
|
|
|
@mock_session_pools
|
|
def test_no_legacy_with_profile(self):
|
|
cluster_init = Cluster(execution_profiles={'name': ExecutionProfile()})
|
|
cluster_add = Cluster()
|
|
cluster_add.add_execution_profile('name', ExecutionProfile())
|
|
# for clusters with profiles added either way...
|
|
for cluster in (cluster_init, cluster_init):
|
|
# don't allow legacy parameters set
|
|
for attr, value in (('default_retry_policy', RetryPolicy()),
|
|
('load_balancing_policy', default_lbp_factory())):
|
|
self.assertRaises(ValueError, setattr, cluster, attr, value)
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
for attr, value in (('default_timeout', 1),
|
|
('default_consistency_level', ConsistencyLevel.ANY),
|
|
('default_serial_consistency_level', ConsistencyLevel.SERIAL),
|
|
('row_factory', tuple_factory)):
|
|
self.assertRaises(ValueError, setattr, session, attr, value)
|
|
|
|
@mock_session_pools
|
|
def test_profile_name_value(self):
|
|
|
|
internalized_profile = ExecutionProfile(RoundRobinPolicy(), *[object() for _ in range(3)])
|
|
cluster = Cluster(execution_profiles={'by-name': internalized_profile})
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
self.assertEqual(cluster._config_mode, _ConfigMode.PROFILES)
|
|
|
|
rf = session.execute_async("query", execution_profile='by-name')
|
|
self._verify_response_future_profile(rf, internalized_profile)
|
|
|
|
by_value = ExecutionProfile(RoundRobinPolicy(), *[object() for _ in range(3)])
|
|
rf = session.execute_async("query", execution_profile=by_value)
|
|
self._verify_response_future_profile(rf, by_value)
|
|
|
|
@mock_session_pools
|
|
def test_exec_profile_clone(self):
|
|
|
|
cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(), 'one': ExecutionProfile()})
|
|
session = Session(cluster, hosts=[Host("127.0.0.1", SimpleConvictionPolicy)])
|
|
|
|
profile_attrs = {'request_timeout': 1,
|
|
'consistency_level': ConsistencyLevel.ANY,
|
|
'serial_consistency_level': ConsistencyLevel.SERIAL,
|
|
'row_factory': tuple_factory,
|
|
'retry_policy': RetryPolicy(),
|
|
'load_balancing_policy': default_lbp_factory()}
|
|
reference_attributes = ('retry_policy', 'load_balancing_policy')
|
|
|
|
# default and one named
|
|
for profile in (EXEC_PROFILE_DEFAULT, 'one'):
|
|
active = cluster.profile_manager.profiles[profile]
|
|
clone = session.execution_profile_clone_update(profile)
|
|
self.assertIsNot(clone, active)
|
|
|
|
all_updated = session.execution_profile_clone_update(clone, **profile_attrs)
|
|
self.assertIsNot(all_updated, clone)
|
|
for attr, value in profile_attrs.items():
|
|
self.assertEqual(getattr(clone, attr), getattr(active, attr))
|
|
if attr in reference_attributes:
|
|
self.assertIs(getattr(clone, attr), getattr(active, attr))
|
|
self.assertNotEqual(getattr(all_updated, attr), getattr(active, attr))
|
|
|
|
# cannot clone nonexistent profile
|
|
self.assertRaises(ValueError, session.execution_profile_clone_update, 'DOES NOT EXIST', **profile_attrs)
|
|
|
|
def test_no_profiles_same_name(self):
|
|
# can override default in init
|
|
cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(), 'one': ExecutionProfile()})
|
|
|
|
# cannot update default
|
|
self.assertRaises(ValueError, cluster.add_execution_profile, EXEC_PROFILE_DEFAULT, ExecutionProfile())
|
|
|
|
# cannot update named init
|
|
self.assertRaises(ValueError, cluster.add_execution_profile, 'one', ExecutionProfile())
|
|
|
|
# can add new name
|
|
cluster.add_execution_profile('two', ExecutionProfile())
|
|
|
|
# cannot add a profile added dynamically
|
|
self.assertRaises(ValueError, cluster.add_execution_profile, 'two', ExecutionProfile())
|