Files
deb-python-cassandra-driver/tests/integration/cqlengine/test_ifnotexists.py
2017-04-24 17:20:57 -04:00

206 lines
6.8 KiB
Python

# Copyright 2013-2017 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
import mock
from uuid import uuid4
from cassandra.cqlengine import columns
from cassandra.cqlengine.management import sync_table, drop_table
from cassandra.cqlengine.models import Model
from cassandra.cqlengine.query import BatchQuery, LWTException, IfNotExistsWithCounterColumn
from tests.integration.cqlengine.base import BaseCassEngTestCase
from tests.integration import PROTOCOL_VERSION
class TestIfNotExistsModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
count = columns.Integer()
text = columns.Text(required=False)
class TestIfNotExistsWithCounterModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
likes = columns.Counter()
class BaseIfNotExistsTest(BaseCassEngTestCase):
@classmethod
def setUpClass(cls):
super(BaseIfNotExistsTest, cls).setUpClass()
"""
when receiving an insert statement with 'if not exist', cassandra would
perform a read with QUORUM level. Unittest would be failed if replica_factor
is 3 and one node only. Therefore I have create a new keyspace with
replica_factor:1.
"""
sync_table(TestIfNotExistsModel)
@classmethod
def tearDownClass(cls):
super(BaseIfNotExistsTest, cls).tearDownClass()
drop_table(TestIfNotExistsModel)
class BaseIfNotExistsWithCounterTest(BaseCassEngTestCase):
@classmethod
def setUpClass(cls):
super(BaseIfNotExistsWithCounterTest, cls).setUpClass()
sync_table(TestIfNotExistsWithCounterModel)
@classmethod
def tearDownClass(cls):
super(BaseIfNotExistsWithCounterTest, cls).tearDownClass()
drop_table(TestIfNotExistsWithCounterModel)
class IfNotExistsInsertTests(BaseIfNotExistsTest):
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
def test_insert_if_not_exists(self):
""" tests that insertion with if_not_exists work as expected """
id = uuid4()
TestIfNotExistsModel.create(id=id, count=8, text='123456789')
with self.assertRaises(LWTException) as assertion:
TestIfNotExistsModel.if_not_exists().create(id=id, count=9, text='111111111111')
with self.assertRaises(LWTException) as assertion:
TestIfNotExistsModel.objects(count=9, text='111111111111').if_not_exists().create(id=id)
self.assertEqual(assertion.exception.existing, {
'count': 8,
'id': id,
'text': '123456789',
'[applied]': False,
})
q = TestIfNotExistsModel.objects(id=id)
self.assertEqual(len(q), 1)
tm = q.first()
self.assertEqual(tm.count, 8)
self.assertEqual(tm.text, '123456789')
@unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0")
def test_batch_insert_if_not_exists(self):
""" tests that batch insertion with if_not_exists work as expected """
id = uuid4()
with BatchQuery() as b:
TestIfNotExistsModel.batch(b).if_not_exists().create(id=id, count=8, text='123456789')
b = BatchQuery()
TestIfNotExistsModel.batch(b).if_not_exists().create(id=id, count=9, text='111111111111')
with self.assertRaises(LWTException) as assertion:
b.execute()
self.assertEqual(assertion.exception.existing, {
'count': 8,
'id': id,
'text': '123456789',
'[applied]': False,
})
q = TestIfNotExistsModel.objects(id=id)
self.assertEqual(len(q), 1)
tm = q.first()
self.assertEqual(tm.count, 8)
self.assertEqual(tm.text, '123456789')
class IfNotExistsModelTest(BaseIfNotExistsTest):
def test_if_not_exists_included_on_create(self):
""" tests that if_not_exists on models works as expected """
with mock.patch.object(self.session, 'execute') as m:
TestIfNotExistsModel.if_not_exists().create(count=8)
query = m.call_args[0][0].query_string
self.assertIn("IF NOT EXISTS", query)
def test_if_not_exists_included_on_save(self):
""" tests if we correctly put 'IF NOT EXISTS' for insert statement """
with mock.patch.object(self.session, 'execute') as m:
tm = TestIfNotExistsModel(count=8)
tm.if_not_exists().save()
query = m.call_args[0][0].query_string
self.assertIn("IF NOT EXISTS", query)
def test_queryset_is_returned_on_class(self):
""" ensure we get a queryset description back """
qs = TestIfNotExistsModel.if_not_exists()
self.assertTrue(isinstance(qs, TestIfNotExistsModel.__queryset__), type(qs))
def test_batch_if_not_exists(self):
""" ensure 'IF NOT EXISTS' exists in statement when in batch """
with mock.patch.object(self.session, 'execute') as m:
with BatchQuery() as b:
TestIfNotExistsModel.batch(b).if_not_exists().create(count=8)
self.assertIn("IF NOT EXISTS", m.call_args[0][0].query_string)
class IfNotExistsInstanceTest(BaseIfNotExistsTest):
def test_instance_is_returned(self):
"""
ensures that we properly handle the instance.if_not_exists().save()
scenario
"""
o = TestIfNotExistsModel.create(text="whatever")
o.text = "new stuff"
o = o.if_not_exists()
self.assertEqual(True, o._if_not_exists)
def test_if_not_exists_is_not_include_with_query_on_update(self):
"""
make sure we don't put 'IF NOT EXIST' in update statements
"""
o = TestIfNotExistsModel.create(text="whatever")
o.text = "new stuff"
o = o.if_not_exists()
with mock.patch.object(self.session, 'execute') as m:
o.save()
query = m.call_args[0][0].query_string
self.assertNotIn("IF NOT EXIST", query)
class IfNotExistWithCounterTest(BaseIfNotExistsWithCounterTest):
def test_instance_raise_exception(self):
""" make sure exception is raised when calling
if_not_exists on table with counter column
"""
id = uuid4()
with self.assertRaises(IfNotExistsWithCounterColumn):
TestIfNotExistsWithCounterModel.if_not_exists()