From 48467bb7469c72a74fb1fbb996c9c13f7ce7d781 Mon Sep 17 00:00:00 2001 From: GregBestland Date: Fri, 8 Apr 2016 15:09:07 -0500 Subject: [PATCH] PYTHON-535 Tests for cqlengine routing key generation --- tests/integration/cqlengine/__init__.py | 1 + .../cqlengine/model/test_model_io.py | 161 ++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/tests/integration/cqlengine/__init__.py b/tests/integration/cqlengine/__init__.py index 2950984f..c54dd95a 100644 --- a/tests/integration/cqlengine/__init__.py +++ b/tests/integration/cqlengine/__init__.py @@ -38,6 +38,7 @@ def is_prepend_reversed(): ver, _ = get_server_versions() return not (ver >= (2, 0, 13) or ver >= (2, 1, 3)) + def setup_connection(keyspace_name): connection.setup(['127.0.0.1'], consistency=ConsistencyLevel.ONE, diff --git a/tests/integration/cqlengine/model/test_model_io.py b/tests/integration/cqlengine/model/test_model_io.py index b05c8b7c..a2cc1739 100644 --- a/tests/integration/cqlengine/model/test_model_io.py +++ b/tests/integration/cqlengine/model/test_model_io.py @@ -27,10 +27,17 @@ from cassandra.cqlengine import CQLEngineException from cassandra.cqlengine.management import sync_table from cassandra.cqlengine.management import drop_table from cassandra.cqlengine.models import Model +from cassandra.query import SimpleStatement from cassandra.util import Date, Time +from cassandra.cqltypes import Int32Type +from cassandra.cqlengine.statements import SelectStatement, DeleteStatement, WhereClause +from cassandra.cqlengine.operators import EqualsOperator from tests.integration import PROTOCOL_VERSION from tests.integration.cqlengine.base import BaseCassEngTestCase +from tests.integration.cqlengine import DEFAULT_KEYSPACE + + class TestModel(Model): @@ -638,6 +645,160 @@ class TestQuerying(BaseCassEngTestCase): self.assertTrue(inst.date == day) +class BasicModel(Model): + __table_name__ = 'basic_model_routing' + k = columns.Integer(primary_key=True) + v = columns.Integer() + + +class BasicModelMulti(Model): + __table_name__ = 'basic_model_routing_multi' + k = columns.Integer(partition_key=True) + v = columns.Integer(partition_key=True) + + +class ComplexModelRouting(Model): + __table_name__ = 'complex_model_routing' + partition = columns.UUID(partition_key=True, default=uuid4) + cluster = columns.Integer(partition_key=True) + count = columns.Integer() + text = columns.Text(partition_key=True) + float = columns.Float(partition_key=True) + text_2 = columns.Text() + + +class TestModelRoutingKeys(BaseCassEngTestCase): + + @classmethod + def setUpClass(cls): + super(TestModelRoutingKeys, cls).setUpClass() + sync_table(BasicModel) + sync_table(BasicModelMulti) + sync_table(ComplexModelRouting) + + @classmethod + def tearDownClass(cls): + super(TestModelRoutingKeys, cls).tearDownClass() + drop_table(BasicModel) + drop_table(BasicModelMulti) + drop_table(ComplexModelRouting) + + def test_routing_key_generation_basic(self): + """ + Compares the routing key generated by simple partition key using the model with the one generated by the equivalent + bound statement + @since 3.2 + @jira_ticket PYTHON-535 + @expected_result they should match + + @test_category object_mapper + """ + + prepared = self.session.prepare( + """ + INSERT INTO {0}.basic_model_routing (k, v) VALUES (?, ?) + """.format(DEFAULT_KEYSPACE)) + bound = prepared.bind((1, 2)) + + mrk = BasicModel._routing_key_from_values([1], self.session.cluster.protocol_version) + simple = SimpleStatement("") + simple.routing_key = mrk + self.assertEqual(bound.routing_key, simple.routing_key) + + def test_routing_key_generation_multi(self): + """ + Compares the routing key generated by composite partition key using the model with the one generated by the equivalent + bound statement + @since 3.2 + @jira_ticket PYTHON-535 + @expected_result they should match + + @test_category object_mapper + """ + + prepared = self.session.prepare( + """ + INSERT INTO {0}.basic_model_routing_multi (k, v) VALUES (?, ?) + """.format(DEFAULT_KEYSPACE)) + bound = prepared.bind((1, 2)) + mrk = BasicModelMulti._routing_key_from_values([1, 2], self.session.cluster.protocol_version) + simple = SimpleStatement("") + simple.routing_key = mrk + self.assertEqual(bound.routing_key, simple.routing_key) + + def test_routing_key_generation_complex(self): + """ + Compares the routing key generated by complex composite partition key using the model with the one generated by the equivalent + bound statement + @since 3.2 + @jira_ticket PYTHON-535 + @expected_result they should match + + @test_category object_mapper + """ + prepared = self.session.prepare( + """ + INSERT INTO {0}.complex_model_routing (partition, cluster, count, text, float, text_2) VALUES (?, ?, ?, ?, ?, ?) + """.format(DEFAULT_KEYSPACE)) + partition = uuid4() + cluster = 1 + count = 2 + text = "text" + float = 1.2 + text_2 = "text_2" + bound = prepared.bind((partition, cluster, count, text, float, text_2)) + mrk = ComplexModelRouting._routing_key_from_values([partition, cluster, text, float], self.session.cluster.protocol_version) + simple = SimpleStatement("") + simple.routing_key = mrk + self.assertEqual(bound.routing_key, simple.routing_key) + + def test_partition_key_index(self): + """ + Test to ensure that statement partition key generation is in the correct order + @since 3.2 + @jira_ticket PYTHON-535 + @expected_result . + + @test_category object_mapper + """ + self._check_partition_value_generation(BasicModel, SelectStatement(BasicModel.__table_name__)) + self._check_partition_value_generation(BasicModel, DeleteStatement(BasicModel.__table_name__)) + self._check_partition_value_generation(BasicModelMulti, SelectStatement(BasicModelMulti.__table_name__)) + self._check_partition_value_generation(BasicModelMulti, DeleteStatement(BasicModelMulti.__table_name__)) + self._check_partition_value_generation(ComplexModelRouting, SelectStatement(ComplexModelRouting.__table_name__)) + self._check_partition_value_generation(ComplexModelRouting, DeleteStatement(ComplexModelRouting.__table_name__)) + self._check_partition_value_generation(BasicModel, SelectStatement(BasicModel.__table_name__), reverse=True) + self._check_partition_value_generation(BasicModel, DeleteStatement(BasicModel.__table_name__), reverse=True) + self._check_partition_value_generation(BasicModelMulti, SelectStatement(BasicModelMulti.__table_name__), reverse=True) + self._check_partition_value_generation(BasicModelMulti, DeleteStatement(BasicModelMulti.__table_name__), reverse=True) + self._check_partition_value_generation(ComplexModelRouting, SelectStatement(ComplexModelRouting.__table_name__), reverse=True) + self._check_partition_value_generation(ComplexModelRouting, DeleteStatement(ComplexModelRouting.__table_name__), reverse=True) + + def _check_partition_value_generation(self, model, state, reverse=False): + """ + This generates a some statements based on the partition_key_index of the model. + It then validates that order of the partition key values in the statement matches the index + specified in the models partition_key_index + """ + # Setup some unique values for statement generation + uuid = uuid4() + values = {'k': 5, 'v': 3, 'partition': uuid, 'cluster': 6, 'count': 42, 'text': 'text', 'float': 3.1415, 'text_2': 'text_2'} + res = dict((v, k) for k, v in values.items()) + items = model._partition_key_index.items() + if(reverse): + items.reverse() + # Add where clauses for each partition key + for partition_key, position in items: + wc = WhereClause(partition_key, EqualsOperator(), values.get(partition_key)) + state._add_where_clause(wc) + + # Iterate over the partition key values check to see that their index matches + # Those specified in the models partition field + for indx, value in enumerate(state.partition_key_values(model._partition_key_index)): + name = res.get(value) + self.assertEqual(indx, model._partition_key_index.get(name)) + + def test_none_filter_fails(): class NoneFilterModel(Model):