Skip to content

Commit 1f95032

Browse files
committed
PYTHON-614 PYTHON-619 Adding tests. Enabling protocol v5 detection and support to test harness.
1 parent e76a9d9 commit 1f95032

4 files changed

Lines changed: 94 additions & 38 deletions

File tree

test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ twisted
1212
gevent>=1.0
1313
eventlet
1414
cython>=0.21
15+
packaging

tests/integration/__init__.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import unittest2 as unittest
1717
except ImportError:
1818
import unittest # noqa
19-
19+
from packaging.version import Version
2020
import logging
2121
import os
2222
import socket
@@ -140,11 +140,11 @@ def _get_cass_version_from_dse(dse_version):
140140

141141
def get_default_protocol():
142142

143-
if CASSANDRA_VERSION >= '2.2':
143+
if Version(CASSANDRA_VERSION) >= Version('2.2'):
144144
return 4
145-
elif CASSANDRA_VERSION >= '2.1':
145+
elif Version(CASSANDRA_VERSION) >= Version('2.1'):
146146
return 3
147-
elif CASSANDRA_VERSION >= '2.0':
147+
elif Version(CASSANDRA_VERSION) >= Version('2.0'):
148148
return 2
149149
else:
150150
return 1
@@ -157,14 +157,17 @@ def get_supported_protocol_versions():
157157
2.1 -> 3, 2, 1
158158
2.2 -> 4, 3, 2, 1
159159
3.X -> 4, 3
160+
3.10 -> 5(beta),4,3
160161
` """
161-
if CASSANDRA_VERSION >= '3.0':
162+
if Version(CASSANDRA_VERSION) >= Version('3.10'):
163+
return (3, 4, 5)
164+
elif Version(CASSANDRA_VERSION) >= Version('3.0'):
162165
return (3, 4)
163-
elif CASSANDRA_VERSION >= '2.2':
166+
elif Version(CASSANDRA_VERSION) >= Version('2.2'):
164167
return (1, 2, 3, 4)
165-
elif CASSANDRA_VERSION >= '2.1':
168+
elif Version(CASSANDRA_VERSION) >= Version('2.1'):
166169
return (1, 2, 3)
167-
elif CASSANDRA_VERSION >= '2.0':
170+
elif Version(CASSANDRA_VERSION) >= Version('2.0'):
168171
return (1, 2)
169172
else:
170173
return (1)
@@ -176,7 +179,7 @@ def get_unsupported_lower_protocol():
176179
supported by the version of C* running
177180
"""
178181

179-
if CASSANDRA_VERSION >= '3.0':
182+
if Version(CASSANDRA_VERSION) >= Version('3.0'):
180183
return 2
181184
else:
182185
return None
@@ -188,11 +191,11 @@ def get_unsupported_upper_protocol():
188191
supported by the version of C* running
189192
"""
190193

191-
if CASSANDRA_VERSION >= '2.2':
194+
if Version(CASSANDRA_VERSION) >= Version('2.2'):
192195
return None
193-
if CASSANDRA_VERSION >= '2.1':
196+
if Version(CASSANDRA_VERSION) >= Version('2.1'):
194197
return 4
195-
elif CASSANDRA_VERSION >= '2.0':
198+
elif Version(CASSANDRA_VERSION) >= Version('2.0'):
196199
return 3
197200
else:
198201
return None
@@ -205,6 +208,7 @@ def get_unsupported_upper_protocol():
205208
notprotocolv1 = unittest.skipUnless(PROTOCOL_VERSION > 1, 'Protocol v1 not supported')
206209
lessthenprotocolv4 = unittest.skipUnless(PROTOCOL_VERSION < 4, 'Protocol versions 4 or greater not supported')
207210
greaterthanprotocolv3 = unittest.skipUnless(PROTOCOL_VERSION >= 4, 'Protocol versions less than 4 are not supported')
211+
protocolv5 = unittest.skipUnless(5 in get_supported_protocol_versions(), 'Protocol versions less than 5 are not supported')
208212

209213
greaterthancass20 = unittest.skipUnless(CASSANDRA_VERSION >= '2.1', 'Cassandra version 2.1 or greater required')
210214
greaterthancass21 = unittest.skipUnless(CASSANDRA_VERSION >= '2.2', 'Cassandra version 2.2 or greater required')

tests/integration/long/test_failure_types.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
from cassandra import ConsistencyLevel, OperationTimedOut, ReadTimeout, WriteTimeout, ReadFailure, WriteFailure,\
1818
FunctionFailure
19-
from cassandra.cluster import Cluster
19+
from cassandra.protocol import MAX_SUPPORTED_VERSION
20+
from cassandra.cluster import Cluster, NoHostAvailable
2021
from cassandra.concurrent import execute_concurrent_with_args
2122
from cassandra.query import SimpleStatement
2223
from tests.integration import use_singledc, PROTOCOL_VERSION, get_cluster, setup_keyspace, remove_cluster, get_node
@@ -63,14 +64,20 @@ def setUp(self):
6364
"""
6465
Test is skipped if run with native protocol version <4
6566
"""
66-
67+
self.support_v5 = True
6768
if PROTOCOL_VERSION < 4:
6869
raise unittest.SkipTest(
6970
"Native protocol 4,0+ is required for custom payloads, currently using %r"
7071
% (PROTOCOL_VERSION,))
72+
try:
73+
self.cluster = Cluster(protocol_version=MAX_SUPPORTED_VERSION, allow_beta_protocol_version=True)
74+
self.session = self.cluster.connect()
75+
except NoHostAvailable:
76+
log.info("Protocol Version 5 not supported,")
77+
self.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
78+
self.session = self.cluster.connect()
79+
self.support_v5 = False
7180

72-
self.cluster = Cluster(protocol_version=PROTOCOL_VERSION)
73-
self.session = self.cluster.connect()
7481
self.nodes_currently_failing = []
7582
self.node1, self.node2, self.node3 = get_cluster().nodes.values()
7683

@@ -132,21 +139,28 @@ def setFailingNodes(self, failing_nodes, keyspace):
132139
node.start(wait_for_binary_proto=True, wait_other_notice=True)
133140
self.nodes_currently_failing.remove(node)
134141

135-
def _perform_cql_statement(self, text, consistency_level, expected_exception):
142+
def _perform_cql_statement(self, text, consistency_level, expected_exception, session=None):
136143
"""
137144
Simple helper method to preform cql statements and check for expected exception
138145
@param text CQl statement to execute
139146
@param consistency_level Consistency level at which it is to be executed
140147
@param expected_exception Exception expected to be throw or none
141148
"""
149+
if session is None:
150+
session = self.session
142151
statement = SimpleStatement(text)
143152
statement.consistency_level = consistency_level
144153

145154
if expected_exception is None:
146-
self.execute_helper(self.session, statement)
155+
self.execute_helper(session, statement)
147156
else:
148-
with self.assertRaises(expected_exception):
149-
self.execute_helper(self.session, statement)
157+
with self.assertRaises(expected_exception) as cm:
158+
self.execute_helper(session, statement)
159+
if self.support_v5 and (isinstance(cm.exception, WriteFailure) or isinstance(cm.exception, ReadFailure)):
160+
if isinstance(cm.exception, ReadFailure):
161+
self.assertEqual(cm.exception.error_code_map.values()[0], 1)
162+
else:
163+
self.assertEqual(cm.exception.error_code_map.values()[0], 0)
150164

151165
def test_write_failures_from_coordinator(self):
152166
"""
@@ -157,8 +171,8 @@ def test_write_failures_from_coordinator(self):
157171
factor of the keyspace, and the consistency level, we will expect the coordinator to send WriteFailure, or not.
158172
159173
160-
@since 2.6.0
161-
@jira_ticket PYTHON-238
174+
@since 2.6.0, 3.7.0
175+
@jira_ticket PYTHON-238, PYTHON-619
162176
@expected_result Appropriate write failures from the coordinator
163177
164178
@test_category queries:basic
@@ -217,8 +231,8 @@ def test_tombstone_overflow_read_failure(self):
217231
from the coordinator.
218232
219233
220-
@since 2.6.0
221-
@jira_ticket PYTHON-238
234+
@since 2.6.0, 3.7.0
235+
@jira_ticket PYTHON-238, PYTHON-619
222236
@expected_result Appropriate write failures from the coordinator
223237
224238
@test_category queries:basic
@@ -379,11 +393,3 @@ def test_async_timeouts(self):
379393
self.assertAlmostEqual(expected_time, total_time, delta=.05)
380394
self.assertTrue(mock_errorback.called)
381395
self.assertFalse(mock_callback.called)
382-
383-
384-
385-
386-
387-
388-
389-

tests/integration/standard/test_cluster.py

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
from cassandra.protocol import MAX_SUPPORTED_VERSION
3434
from cassandra.query import SimpleStatement, TraceUnavailable, tuple_factory
3535

36-
from tests.integration import use_singledc, PROTOCOL_VERSION, get_server_versions, get_node, CASSANDRA_VERSION, execute_until_pass, execute_with_long_wait_retry, get_node,\
37-
MockLoggingHandler, get_unsupported_lower_protocol, get_unsupported_upper_protocol
36+
from tests.integration import use_singledc, PROTOCOL_VERSION, get_server_versions, CASSANDRA_VERSION, execute_until_pass, execute_with_long_wait_retry, get_node,\
37+
MockLoggingHandler, get_unsupported_lower_protocol, get_unsupported_upper_protocol, protocolv5
3838
from tests.integration.util import assert_quiescent_pool_state
3939

4040

@@ -460,7 +460,7 @@ def test_refresh_schema_no_wait(self):
460460
end_time = time.time()
461461
self.assertGreaterEqual(end_time - start_time, agreement_timeout)
462462
self.assertIs(original_meta, c.metadata.keyspaces)
463-
463+
464464
# refresh wait overrides cluster value
465465
original_meta = c.metadata.keyspaces
466466
start_time = time.time()
@@ -489,7 +489,7 @@ def test_refresh_schema_no_wait(self):
489489
self.assertLess(end_time - start_time, refresh_threshold)
490490
self.assertIsNot(original_meta, c.metadata.keyspaces)
491491
self.assertEqual(original_meta, c.metadata.keyspaces)
492-
492+
493493
# refresh wait overrides cluster value
494494
original_meta = c.metadata.keyspaces
495495
start_time = time.time()
@@ -587,7 +587,7 @@ def test_idle_heartbeat(self):
587587
cluster.set_core_connections_per_host(HostDistance.LOCAL, 1)
588588
session = cluster.connect(wait_for_all_pools=True)
589589

590-
# This test relies on impl details of connection req id management to see if heartbeats
590+
# This test relies on impl details of connection req id management to see if heartbeats
591591
# are being sent. May need update if impl is changed
592592
connection_request_ids = {}
593593
for h in cluster.get_connection_holders():
@@ -763,7 +763,7 @@ def test_profile_lb_swap(self):
763763
expected_hosts = set(cluster.metadata.all_hosts())
764764
rr1_queried_hosts = set()
765765
rr2_queried_hosts = set()
766-
766+
767767
rs = session.execute(query, execution_profile='rr1')
768768
rr1_queried_hosts.add(rs.response_future._current_host)
769769
rs = session.execute(query, execution_profile='rr2')
@@ -1054,3 +1054,48 @@ def test_duplicate(self):
10541054
self.assertEqual(len(warnings), 1)
10551055
self.assertTrue('multiple' in warnings[0])
10561056
logger.removeHandler(mock_handler)
1057+
1058+
1059+
@protocolv5
1060+
class BetaProtocolTest(unittest.TestCase):
1061+
1062+
@protocolv5
1063+
def test_invalid_protocol_version_beta_option(self):
1064+
"""
1065+
Test cluster connection with protocol v5 and beta flag not set
1066+
1067+
@since 3.7.0
1068+
@jira_ticket PYTHON-614
1069+
@expected_result client shouldn't connect with V5 and no beta flag set
1070+
1071+
@test_category connection
1072+
"""
1073+
1074+
cluster = Cluster(protocol_version=MAX_SUPPORTED_VERSION, allow_beta_protocol_version=False)
1075+
try:
1076+
with self.assertRaises(NoHostAvailable):
1077+
cluster.connect()
1078+
except Exception as e:
1079+
self.fail("Unexpected error encountered {0}".format(e.message))
1080+
cluster.shutdown()
1081+
1082+
@protocolv5
1083+
def test_valid_protocol_version_beta_options_connect(self):
1084+
"""
1085+
Test cluster connection with protocol version 5 and beta flag set
1086+
1087+
@since 3.7.0
1088+
@jira_ticket PYTHON-614
1089+
@expected_result client should connect with protocol v5 and beta flag set.
1090+
1091+
@test_category connection
1092+
"""
1093+
cluster = Cluster(protocol_version=MAX_SUPPORTED_VERSION, allow_beta_protocol_version=True)
1094+
session = cluster.connect()
1095+
self.assertEqual(cluster.protocol_version, MAX_SUPPORTED_VERSION)
1096+
self.assertTrue(session.execute("select release_version from system.local")[0])
1097+
1098+
1099+
1100+
1101+

0 commit comments

Comments
 (0)