class CassandraClientTest(unittest.TestCase): @defer.inlineCallbacks def setUp(self): self.cmanager = ManagedCassandraClientFactory(keyspace='system') self.client = CassandraClient(self.cmanager) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) yield self.cmanager.deferred remote_ver = yield self.client.describe_version() self.version = getAPIVersion(remote_ver) self.my_keyspace = KsDef( name=KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={'replication_factor': '1'}, cf_defs=[ CfDef( keyspace=KEYSPACE, name=CF, column_type='Standard' ), CfDef( keyspace=KEYSPACE, name=SCF, column_type='Super' ), CfDef( keyspace=KEYSPACE, name=IDX_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.UTF8Type', column_metadata=[ ColumnDef( name='col1', validation_class='org.apache.cassandra.db.marshal.UTF8Type', index_type=IndexType.KEYS, index_name='idxCol1') ], default_validation_class='org.apache.cassandra.db.marshal.BytesType' ), ] ) if self.version == CASSANDRA_08_VERSION: self.my_keyspace.cf_defs.extend([ CfDef( keyspace=KEYSPACE, name=COUNTER_CF, column_type='Standard', default_validation_class='org.apache.cassandra.db.marshal.CounterColumnType' ), CfDef( keyspace=KEYSPACE, name=SUPERCOUNTER_CF, column_type='Super', default_validation_class='org.apache.cassandra.db.marshal.CounterColumnType' ), ]) yield self.client.system_add_keyspace(self.my_keyspace) yield self.client.set_keyspace(KEYSPACE) @defer.inlineCallbacks def tearDown(self): yield self.client.system_drop_keyspace(self.my_keyspace.name) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', SCF, 'superval', column=COLUMN, super_column=SCOLUMN) yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, {COLUMN: 'test', COLUMN2: 'test2'}) yield self.client.batch_insert('test', SCF, {SCOLUMN: {COLUMN: 'test', COLUMN2: 'test2'}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_count('test', CF) self.assertEqual(res, 2) @defer.inlineCallbacks def test_batch_mutate_and_remove(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } }, 'test2': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } } }) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_remove({CF: ['test', 'test2']}, names=['test', 'test2']) yield self.client.batch_remove({SCF: ['test', 'test2']}, names=['test', 'test2'], supercolumn=SCOLUMN) @defer.inlineCallbacks def test_batch_mutate_with_deletion(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_mutate({'test': {CF: {COLUMN: None, COLUMN2: 'test3'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(len(res), 1) self.assertEqual(res[0].column.value, 'test3') @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test'][1].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(len(res['test']), 0) self.assertEqual(len(res['test2']), 0) @defer.inlineCallbacks def test_range_slices(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) ks = yield self.client.get_range_slices(CF, start='', finish='') keys = [k.key for k in ks] for key in ['test', 'test2']: self.assertIn(key, keys) @defer.inlineCallbacks def test_indexed_slices(self): yield self.client.insert('test1', IDX_CF, 'one', column='col1') yield self.client.insert('test2', IDX_CF, 'two', column='col1') yield self.client.insert('test3', IDX_CF, 'three', column='col1') expressions = [IndexExpression('col1', IndexOperator.EQ, 'two')] res = yield self.client.get_indexed_slices(IDX_CF, expressions, start_key='') self.assertEquals(res[0].columns[0].column.value,'two') @defer.inlineCallbacks def test_counter_add(self): if self.version != CASSANDRA_08_VERSION: raise unittest.SkipTest('Counters are not supported in 0.7') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 2) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 2) @defer.inlineCallbacks def test_counter_remove(self): if self.version != CASSANDRA_08_VERSION: raise unittest.SkipTest('Counters are not supported in 0.7') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', COUNTER_CF, column='col') yield self.assertFailure(self.client.get('test', COUNTER_CF, column='col'), NotFoundException) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', SUPERCOUNTER_CF, column='col', super_column='scol') yield self.assertFailure(self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol'), NotFoundException) @defer.inlineCallbacks def test_cql(self): if self.version != CASSANDRA_08_VERSION: raise unittest.SkipTest('CQL is not supported in 0.7') yield self.client.insert('test', CF, 'testval', column='col1') res = yield self.client.get('test', CF, column='col1') self.assertEquals(res.column.value, 'testval') query = 'SELECT * from %s where KEY = %s' % (CF, 'test'.encode('hex')) uncompressed_result = yield self.client.execute_cql_query(query, Compression.NONE) self.assertEquals(uncompressed_result.rows[0].columns[0].name, 'col1') self.assertEquals(uncompressed_result.rows[0].columns[0].value, 'testval') compressed_query = zlib.compress(query) compressed_result = yield self.client.execute_cql_query(compressed_query, Compression.GZIP) self.assertEquals(uncompressed_result, compressed_result) def sleep(self, secs): d = defer.Deferred() reactor.callLater(secs, d.callback, None) return d @defer.inlineCallbacks def test_ttls(self): yield self.client.insert('test_ttls', CF, 'testval', column=COLUMN, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_insert('test_ttls', CF, {COLUMN:'testval'}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_mutate({'test_ttls': {CF: {COLUMN: 'testval'}}}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) def compare_keyspaces(self, ks1, ks2): self.assertEqual(ks1.name, ks2.name) self.assertEqual(ks1.strategy_class, ks2.strategy_class) self.assertEqual(ks1.cf_defs, ks2.cf_defs) def get_rf(ksdef): rf = ksdef.replication_factor if ksdef.strategy_options and \ 'replication_factor' in ksdef.strategy_options: rf = int(ksdef.strategy_options['replication_factor']) return rf def strat_opts_no_rf(ksdef): if not ksdef.strategy_options: return {} opts = ksdef.strategy_options.copy() if 'replication_factor' in ksdef.strategy_options: del opts['replication_factor'] return opts self.assertEqual(get_rf(ks1), get_rf(ks2)) self.assertEqual(strat_opts_no_rf(ks1), strat_opts_no_rf(ks2)) @defer.inlineCallbacks def test_keyspace_manipulation(self): try: yield self.client.system_drop_keyspace(T_KEYSPACE) except InvalidRequestException: pass ksdef = KsDef(name=T_KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={'replication_factor': '1'}, cf_defs=[]) yield self.client.system_add_keyspace(ksdef) ks2 = yield self.client.describe_keyspace(T_KEYSPACE) self.compare_keyspaces(ksdef, ks2) if DO_SYSTEM_RENAMING: newname = T_KEYSPACE + '2' yield self.client.system_rename_keyspace(T_KEYSPACE, newname) ks2 = yield self.client.describe_keyspace(newname) ksdef.name = newname self.compare_keyspaces(ksdef, ks2) yield self.client.system_drop_keyspace(ksdef.name) yield self.assertFailure(self.client.describe_keyspace(T_KEYSPACE), NotFoundException) if DO_SYSTEM_RENAMING: yield self.assertFailure(self.client.describe_keyspace(ksdef.name), NotFoundException) @defer.inlineCallbacks def test_column_family_manipulation(self): cfdef = CfDef(KEYSPACE, T_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.BytesType', comment='foo', row_cache_size=0.0, key_cache_size=200000.0, read_repair_chance=1.0, column_metadata=[], gc_grace_seconds=86400, default_validation_class='org.apache.cassandra.db.marshal.BytesType', key_validation_class='org.apache.cassandra.db.marshal.BytesType', min_compaction_threshold=5, max_compaction_threshold=31, row_cache_save_period_in_seconds=0, key_cache_save_period_in_seconds=3600, memtable_flush_after_mins=60, memtable_throughput_in_mb=249, memtable_operations_in_millions=1.1671875, replicate_on_write=False, merge_shards_chance=0.10000000000000001, row_cache_provider=None, key_alias=None, ) post_07_fields = ['replicate_on_write', 'merge_shards_chance', 'key_validation_class', 'row_cache_provider', 'key_alias'] yield self.client.system_add_column_family(cfdef) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == T_CF][0] for field in post_07_fields: # Most of these are ignored in 0.7, so we can't reliably compare them setattr(cfdef, field, None) setattr(cfdef2, field, None) # we don't know the id ahead of time. copy the new one so the equality # comparison won't fail cfdef.id = cfdef2.id self.assertEqual(cfdef, cfdef2) if DO_SYSTEM_RENAMING: newname = T_CF + '2' yield self.client.system_rename_column_family(T_CF, newname) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == newname][0] self.assertNotIn(T_CF, [c.name for c in ksdef.cf_defs]) cfdef.name = newname self.assertEqual(cfdef, cfdef2) yield self.client.system_drop_column_family(cfdef.name) ksdef = yield self.client.describe_keyspace(KEYSPACE) self.assertNotIn(cfdef.name, [c.name for c in ksdef.cf_defs]) @defer.inlineCallbacks def test_describes(self): name = yield self.client.describe_cluster_name() self.assertIsInstance(name, str) self.assertNotEqual(name, '') partitioner = yield self.client.describe_partitioner() self.assert_(partitioner.startswith('org.apache.cassandra.'), msg='partitioner is %r' % partitioner) snitch = yield self.client.describe_snitch() self.assert_(snitch.startswith('org.apache.cassandra.'), msg='snitch is %r' % snitch) version = yield self.client.describe_version() self.assertIsInstance(version, str) self.assertIn('.', version) schemavers = yield self.client.describe_schema_versions() self.assertIsInstance(schemavers, dict) self.assertNotEqual(schemavers, {}) ring = yield self.client.describe_ring(KEYSPACE) self.assertIsInstance(ring, list) self.assertNotEqual(ring, []) for r in ring: self.assertIsInstance(r.start_token, str) self.assertIsInstance(r.end_token, str) self.assertIsInstance(r.endpoints, list) self.assertNotEqual(r.endpoints, []) for ep in r.endpoints: self.assertIsInstance(ep, str) @defer.inlineCallbacks def test_errback(self): yield self.client.remove('poiqwe', CF) try: yield self.client.get('poiqwe', CF, column='foo') except Exception, e: pass
class CassandraClientTest(unittest.TestCase): @defer.inlineCallbacks def setUp(self): self.cmanager = ManagedCassandraClientFactory(keyspace='system') self.client = CassandraClient(self.cmanager) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) yield self.cmanager.deferred remote_ver = yield self.client.describe_version() self.version = thrift_api_ver_to_cassandra_ver(remote_ver) self.my_keyspace = KsDef( name=KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={'replication_factor': '1'}, cf_defs=[ CfDef(keyspace=KEYSPACE, name=CF, column_type='Standard'), CfDef(keyspace=KEYSPACE, name=SCF, column_type='Super'), CfDef( keyspace=KEYSPACE, name=IDX_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.UTF8Type', column_metadata=[ ColumnDef(name='col1', validation_class= 'org.apache.cassandra.db.marshal.UTF8Type', index_type=IndexType.KEYS, index_name='idxCol1') ], default_validation_class= 'org.apache.cassandra.db.marshal.BytesType'), ]) if self.version == CASSANDRA_08_VERSION: self.my_keyspace.cf_defs.extend([ CfDef(keyspace=KEYSPACE, name=COUNTER_CF, column_type='Standard', default_validation_class= 'org.apache.cassandra.db.marshal.CounterColumnType'), CfDef(keyspace=KEYSPACE, name=SUPERCOUNTER_CF, column_type='Super', default_validation_class= 'org.apache.cassandra.db.marshal.CounterColumnType'), ]) yield self.client.system_add_keyspace(self.my_keyspace) yield self.client.set_keyspace(KEYSPACE) @defer.inlineCallbacks def tearDown(self): yield self.client.system_drop_keyspace(self.my_keyspace.name) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', SCF, 'superval', column=COLUMN, super_column=SCOLUMN) yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, { COLUMN: 'test', COLUMN2: 'test2' }) yield self.client.batch_insert( 'test', SCF, {SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2' }}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_count('test', CF) self.assertEqual(res, 2) @defer.inlineCallbacks def test_batch_mutate_and_remove(self): yield self.client.batch_mutate({ 'test': { CF: { COLUMN: 'test', COLUMN2: 'test2' }, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2' } } }, 'test2': { CF: { COLUMN: 'test', COLUMN2: 'test2' }, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2' } } } }) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_remove({CF: ['test', 'test2']}, names=['test', 'test2']) yield self.client.batch_remove({SCF: ['test', 'test2']}, names=['test', 'test2'], supercolumn=SCOLUMN) @defer.inlineCallbacks def test_batch_mutate_with_deletion(self): yield self.client.batch_mutate( {'test': { CF: { COLUMN: 'test', COLUMN2: 'test2' } }}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_mutate( {'test': { CF: { COLUMN: None, COLUMN2: 'test3' } }}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(len(res), 1) self.assertEqual(res[0].column.value, 'test3') @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test'][1].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(len(res['test']), 0) self.assertEqual(len(res['test2']), 0) @defer.inlineCallbacks def test_range_slices(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) ks = yield self.client.get_range_slices(CF, start='', finish='') keys = [k.key for k in ks] for key in ['test', 'test2']: self.assertIn(key, keys) @defer.inlineCallbacks def test_indexed_slices(self): yield self.client.insert('test1', IDX_CF, 'one', column='col1') yield self.client.insert('test2', IDX_CF, 'two', column='col1') yield self.client.insert('test3', IDX_CF, 'three', column='col1') expressions = [IndexExpression('col1', IndexOperator.EQ, 'two')] res = yield self.client.get_indexed_slices(IDX_CF, expressions, start_key='') self.assertEquals(res[0].columns[0].column.value, 'two') @defer.inlineCallbacks def test_counter_add(self): if self.version != CASSANDRA_08_VERSION: raise unittest.SkipTest('Counters are not supported in 0.7') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 2) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 2) @defer.inlineCallbacks def test_counter_remove(self): if self.version != CASSANDRA_08_VERSION: raise unittest.SkipTest('Counters are not supported in 0.7') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', COUNTER_CF, column='col') yield self.assertFailure( self.client.get('test', COUNTER_CF, column='col'), NotFoundException) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', SUPERCOUNTER_CF, column='col', super_column='scol') yield self.assertFailure( self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol'), NotFoundException) def sleep(self, secs): d = defer.Deferred() reactor.callLater(secs, d.callback, None) return d @defer.inlineCallbacks def test_ttls(self): yield self.client.insert('test_ttls', CF, 'testval', column=COLUMN, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure( self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_insert('test_ttls', CF, {COLUMN: 'testval'}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure( self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_mutate( {'test_ttls': { CF: { COLUMN: 'testval' } }}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure( self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) def compare_keyspaces(self, ks1, ks2): self.assertEqual(ks1.name, ks2.name) self.assertEqual(ks1.strategy_class, ks2.strategy_class) self.assertEqual(ks1.cf_defs, ks2.cf_defs) def get_rf(ksdef): rf = ksdef.replication_factor if ksdef.strategy_options and \ 'replication_factor' in ksdef.strategy_options: rf = int(ksdef.strategy_options['replication_factor']) return rf def strat_opts_no_rf(ksdef): if not ksdef.strategy_options: return {} opts = ksdef.strategy_options.copy() if 'replication_factor' in ksdef.strategy_options: del opts['replication_factor'] return opts self.assertEqual(get_rf(ks1), get_rf(ks2)) self.assertEqual(strat_opts_no_rf(ks1), strat_opts_no_rf(ks2)) @defer.inlineCallbacks def test_keyspace_manipulation(self): try: yield self.client.system_drop_keyspace(T_KEYSPACE) except InvalidRequestException: pass ksdef = KsDef( name=T_KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={'replication_factor': '1'}, cf_defs=[]) yield self.client.system_add_keyspace(ksdef) ks2 = yield self.client.describe_keyspace(T_KEYSPACE) self.compare_keyspaces(ksdef, ks2) if DO_SYSTEM_RENAMING: newname = T_KEYSPACE + '2' yield self.client.system_rename_keyspace(T_KEYSPACE, newname) ks2 = yield self.client.describe_keyspace(newname) ksdef.name = newname self.compare_keyspaces(ksdef, ks2) yield self.client.system_drop_keyspace(ksdef.name) yield self.assertFailure(self.client.describe_keyspace(T_KEYSPACE), NotFoundException) if DO_SYSTEM_RENAMING: yield self.assertFailure(self.client.describe_keyspace(ksdef.name), NotFoundException) @defer.inlineCallbacks def test_column_family_manipulation(self): cfdef = CfDef( KEYSPACE, T_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.BytesType', comment='foo', row_cache_size=0.0, key_cache_size=200000.0, read_repair_chance=1.0, column_metadata=[], gc_grace_seconds=86400, default_validation_class= 'org.apache.cassandra.db.marshal.BytesType', key_validation_class='org.apache.cassandra.db.marshal.BytesType', min_compaction_threshold=5, max_compaction_threshold=31, row_cache_save_period_in_seconds=0, key_cache_save_period_in_seconds=3600, memtable_flush_after_mins=60, memtable_throughput_in_mb=249, memtable_operations_in_millions=1.1671875, replicate_on_write=False, merge_shards_chance=0.10000000000000001, row_cache_provider=None, key_alias=None, ) post_07_fields = [ 'replicate_on_write', 'merge_shards_chance', 'key_validation_class', 'row_cache_provider', 'key_alias' ] post_08_fields = [ 'memtable_throughput_in_mb', 'memtable_flush_after_mins', 'memtable_operations_in_millions' ] yield self.client.system_add_column_family(cfdef) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == T_CF][0] for field in post_07_fields: # Most of these are ignored in 0.7, so we can't reliably compare them setattr(cfdef, field, None) setattr(cfdef2, field, None) for field in post_08_fields: # These fields change from 0.8 to 1.0 setattr(cfdef, field, None) setattr(cfdef2, field, None) # we don't know the id ahead of time. copy the new one so the equality # comparison won't fail cfdef.id = cfdef2.id self.assertEqual(cfdef, cfdef2) if DO_SYSTEM_RENAMING: newname = T_CF + '2' yield self.client.system_rename_column_family(T_CF, newname) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == newname][0] self.assertNotIn(T_CF, [c.name for c in ksdef.cf_defs]) cfdef.name = newname self.assertEqual(cfdef, cfdef2) yield self.client.system_drop_column_family(cfdef.name) ksdef = yield self.client.describe_keyspace(KEYSPACE) self.assertNotIn(cfdef.name, [c.name for c in ksdef.cf_defs]) @defer.inlineCallbacks def test_describes(self): name = yield self.client.describe_cluster_name() self.assertIsInstance(name, str) self.assertNotEqual(name, '') partitioner = yield self.client.describe_partitioner() self.assert_(partitioner.startswith('org.apache.cassandra.'), msg='partitioner is %r' % partitioner) snitch = yield self.client.describe_snitch() self.assert_(snitch.startswith('org.apache.cassandra.'), msg='snitch is %r' % snitch) version = yield self.client.describe_version() self.assertIsInstance(version, str) self.assertIn('.', version) schemavers = yield self.client.describe_schema_versions() self.assertIsInstance(schemavers, dict) self.assertNotEqual(schemavers, {}) ring = yield self.client.describe_ring(KEYSPACE) self.assertIsInstance(ring, list) self.assertNotEqual(ring, []) for r in ring: self.assertIsInstance(r.start_token, str) self.assertIsInstance(r.end_token, str) self.assertIsInstance(r.endpoints, list) self.assertNotEqual(r.endpoints, []) for ep in r.endpoints: self.assertIsInstance(ep, str) @defer.inlineCallbacks def test_errback(self): yield self.client.remove('poiqwe', CF) try: yield self.client.get('poiqwe', CF, column='foo') except Exception, e: pass
class PassthroughHandler(BaseHandler): """ The passthrough handler simply takes what has been sent in from the router and reads/writes/deletes without any validation. Handlers should subclass this handler in order to do parameter validation. After validation, the handlers should call through the passthrough handler to write to the database """ cass_factories = {} @classmethod def add_cass_factory(cls, factory_name, factory): cls.cass_factories[factory_name] = factory def initialize(self, factory_name, table, column): """ The factory_name, table and column are set as part of the Application router, see api/__init__.py The table corresponds to the cassandra table, while the column specifies the cassandra column to operate on The row to operate on is passed to each function, while the value is in the request body, if relevant """ self.table = table self.column = column self.cass = CassandraClient(self.cass_factories[factory_name]) @defer.inlineCallbacks def get(self, row): try: result = yield self.ha_get(column_family=self.table, key=row, column=self.column) self.finish(result.column.value) except NotFoundException: raise HTTPError(404) # POST is difficult to generalize as it resource-specific - so force subclasses to implement def post(self, *args): raise HTTPError(405) @defer.inlineCallbacks def put(self, row): yield self.cass.insert(column_family=self.table, key=row, column=self.column, value=self.request.body) self.finish({}) @defer.inlineCallbacks def delete(self, row): yield self.cass.remove(column_family=self.table, key=row, column=self.column) self.set_status(httplib.NO_CONTENT) self.finish() # After growing a cluster, Cassandra does not pro-actively populate the # new nodes with their data (the nodes are expected to use `nodetool # repair` if they need to get their data). # @defer.inlineCallbacks def ha_get(self, *args, **kwargs): kwargs['consistency'] = ConsistencyLevel.LOCAL_QUORUM try: result = yield self.cass.get(*args, **kwargs) defer.returnValue(result) except UnavailableException as e: try: kwargs['consistency'] = ConsistencyLevel.ONE result = yield self.cass.get(*args, **kwargs) defer.returnValue(result) except (NotFoundException, UnavailableException) as e: raise e @defer.inlineCallbacks def ha_get_slice(self, *args, **kwargs): kwargs['consistency'] = ConsistencyLevel.LOCAL_QUORUM try: result = yield self.cass.get_slice(*args, **kwargs) defer.returnValue(result) except UnavailableException as e: try: kwargs['consistency'] = ConsistencyLevel.ONE result = yield self.cass.get_slice(*args, **kwargs) defer.returnValue(result) except (NotFoundException, UnavailableException) as e: raise e
class CassandraClientTest(unittest.TestCase): def setUp(self): self.cmanager = ManagedCassandraClientFactory() self.client = CassandraClient(self.cmanager, KEYSPACE) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) return self.cmanager.deferred @defer.inlineCallbacks def tearDown(self): yield self.client.remove('test', CF) yield self.client.remove('test2', CF) yield self.client.remove('test', SCF) yield self.client.remove('test2', SCF) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', ColumnPath(CF, None, COLUMN), 'testval') yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', ColumnPath(SCF, SCOLUMN, COLUMN), 'superval') yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assert_(res.column.value == 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assert_(res.column.value == 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assert_(res.column.value == 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assert_(res.column.value == 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, {COLUMN: 'test', COLUMN2: 'test2'}) yield self.client.batch_insert('test', SCF, {SCOLUMN: {COLUMN: 'test', COLUMN2: 'test2'}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_count('test', CF) self.assert_(res == 2) @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assert_(res['test'].column.value == 'testval') self.assert_(res['test2'].column.value == 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assert_(res['test'][0].column.value == 'testval') self.assert_(res['test'][1].column.value == 'testval') self.assert_(res['test2'][0].column.value == 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assert_(res['test'].column == None) self.assert_(res['test2'].column == None)
class PassthroughHandler(BaseHandler): """ The passthrough handler simply takes what has been sent in from the router and reads/writes/deletes without any validation. Handlers should subclass this handler in order to do parameter validation. After validation, the handlers should call through the passthrough handler to write to the database """ cass_factories = {} @classmethod def add_cass_factory(cls, factory_name, factory): cls.cass_factories[factory_name] = factory def initialize(self, factory_name, table, column): """ The factory_name, table and column are set as part of the Application router, see api/__init__.py The table corresponds to the cassandra table, while the column specifies the cassandra column to operate on The row to operate on is passed to each function, while the value is in the request body, if relevant """ self.table = table self.column = column self.cass = CassandraClient(self.cass_factories[factory_name]) @defer.inlineCallbacks def get(self, row): try: result = yield self.ha_get(column_family=self.table, key=row, column=self.column) self.finish(result.column.value) except NotFoundException: raise HTTPError(404) # POST is difficult to generalize as it resource-specific - so force subclasses to implement def post(self, *args): raise HTTPError(405) @defer.inlineCallbacks def put(self, row): yield self.cass.insert(column_family=self.table, key=row, column=self.column, value=self.request.body) self.finish({}) @defer.inlineCallbacks def delete(self, row): yield self.cass.remove(column_family=self.table, key=row, column=self.column) self.set_status(httplib.NO_CONTENT) self.finish() # After growing a cluster, Cassandra does not pro-actively populate the # new nodes with their data (the nodes are expected to use `nodetool # repair` if they need to get their data). Combining this with # the fact that we generally use consistency ONE when reading data, the # behaviour on new nodes is to return NotFoundException or empty result # sets to queries, even though the other nodes have a copy of the data. # # To resolve this issue, these two functions can be used as drop-in # replacements for `CassandraClient#get` and `CassandraClient#get_slice` # and will attempt a QUORUM read in the event that a ONE read returns # no data. If the QUORUM read fails due to unreachable nodes, the # original result will be returned (i.e. an empty set or NotFound). @defer.inlineCallbacks def ha_get(self, *args, **kwargs): try: result = yield self.cass.get(*args, **kwargs) defer.returnValue(result) except NotFoundException as e: kwargs['consistency'] = ConsistencyLevel.QUORUM try: result = yield self.cass.get(*args, **kwargs) defer.returnValue(result) except (NotFoundException, UnavailableException): raise e @defer.inlineCallbacks def ha_get_slice(self, *args, **kwargs): result = yield self.cass.get_slice(*args, **kwargs) if len(result) == 0: kwargs['consistency'] = ConsistencyLevel.QUORUM try: qresult = yield self.cass.get_slice(*args, **kwargs) result = qresult except UnavailableException: pass defer.returnValue(result)
class CassandraClientTest(unittest.TestCase): @defer.inlineCallbacks def setUp(self): self.cmanager = ManagedCassandraClientFactory(keyspace='system') self.client = CassandraClient(self.cmanager) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) yield self.cmanager.deferred self.my_keyspace = KsDef( name=KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', replication_factor=1, cf_defs=[ CfDef( keyspace=KEYSPACE, name=CF, column_type='Standard' ), CfDef( keyspace=KEYSPACE, name=SCF, column_type='Super' ), CfDef( keyspace=KEYSPACE, name=IDX_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.UTF8Type', column_metadata=[ ColumnDef( name='col1', validation_class='org.apache.cassandra.db.marshal.UTF8Type', index_type=IndexType.KEYS, index_name='idxCol1') ], default_validation_class='org.apache.cassandra.db.marshal.BytesType') ] ) yield self.client.system_add_keyspace(self.my_keyspace) yield self.client.set_keyspace(KEYSPACE) @defer.inlineCallbacks def tearDown(self): yield self.client.system_drop_keyspace(self.my_keyspace.name) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', SCF, 'superval', column=COLUMN, super_column=SCOLUMN) yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, {COLUMN: 'test', COLUMN2: 'test2'}) yield self.client.batch_insert('test', SCF, {SCOLUMN: {COLUMN: 'test', COLUMN2: 'test2'}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_count('test', CF) self.assertEqual(res, 2) @defer.inlineCallbacks def test_batch_mutate_and_remove(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } }, 'test2': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } } }) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_remove({CF: ['test', 'test2']}, names=['test', 'test2']) yield self.client.batch_remove({SCF: ['test', 'test2']}, names=['test', 'test2'], supercolumn=SCOLUMN) @defer.inlineCallbacks def test_batch_mutate_with_deletion(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_mutate({'test': {CF: {COLUMN: None, COLUMN2: 'test3'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(len(res), 1) self.assertEqual(res[0].column.value, 'test3') @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test'][1].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(len(res['test']), 0) self.assertEqual(len(res['test2']), 0) @defer.inlineCallbacks def test_range_slices(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) ks = yield self.client.get_range_slices(CF, start='', finish='') keys = [k.key for k in ks] for key in ['test', 'test2']: self.assertIn(key, keys) @defer.inlineCallbacks def test_indexed_slices(self): yield self.client.insert('test1', IDX_CF, 'one', column='col1') yield self.client.insert('test2', IDX_CF, 'two', column='col1') yield self.client.insert('test3', IDX_CF, 'three', column='col1') expressions = [IndexExpression('col1', IndexOperator.EQ, 'two')] res = yield self.client.get_indexed_slices(IDX_CF, expressions, start_key='') self.assertEquals(res[0].columns[0].column.value,'two') def sleep(self, secs): d = defer.Deferred() reactor.callLater(secs, d.callback, None) return d @defer.inlineCallbacks def test_ttls(self): yield self.client.insert('test_ttls', CF, 'testval', column=COLUMN, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_insert('test_ttls', CF, {COLUMN:'testval'}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) yield self.client.batch_mutate({'test_ttls': {CF: {COLUMN: 'testval'}}}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), NotFoundException) @defer.inlineCallbacks def test_keyspace_manipulation(self): ksdef = KsDef(name=T_KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', replication_factor=1, cf_defs=[]) yield self.client.system_add_keyspace(ksdef) ks2 = yield self.client.describe_keyspace(T_KEYSPACE) self.assertEqual(ksdef, ks2) if DO_SYSTEM_RENAMING: newname = T_KEYSPACE + '2' yield self.client.system_rename_keyspace(T_KEYSPACE, newname) ks2 = yield self.client.describe_keyspace(newname) ksdef.name = newname self.assertEqual(ksdef, ks2) yield self.client.system_drop_keyspace(ksdef.name) yield self.assertFailure(self.client.describe_keyspace(T_KEYSPACE), NotFoundException) if DO_SYSTEM_RENAMING: yield self.assertFailure(self.client.describe_keyspace(ksdef.name), NotFoundException) @defer.inlineCallbacks def test_column_family_manipulation(self): cfdef = CfDef(KEYSPACE, T_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.BytesType', comment='foo', row_cache_size=0.0, key_cache_size=200000.0, read_repair_chance=1.0, column_metadata=[], gc_grace_seconds=86400, default_validation_class='org.apache.cassandra.db.marshal.BytesType', min_compaction_threshold=5, max_compaction_threshold=31, row_cache_save_period_in_seconds=0, key_cache_save_period_in_seconds=3600, memtable_flush_after_mins=60, memtable_throughput_in_mb=249, memtable_operations_in_millions=1.1671875, ) yield self.client.system_add_column_family(cfdef) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == T_CF][0] # we don't know the id ahead of time. copy the new one so the equality # comparison won't fail cfdef.id = cfdef2.id self.assertEqual(cfdef, cfdef2) if DO_SYSTEM_RENAMING: newname = T_CF + '2' yield self.client.system_rename_column_family(T_CF, newname) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == newname][0] self.assertNotIn(T_CF, [c.name for c in ksdef.cf_defs]) cfdef.name = newname self.assertEqual(cfdef, cfdef2) yield self.client.system_drop_column_family(cfdef.name) ksdef = yield self.client.describe_keyspace(KEYSPACE) self.assertNotIn(cfdef.name, [c.name for c in ksdef.cf_defs]) @defer.inlineCallbacks def test_describes(self): name = yield self.client.describe_cluster_name() self.assertIsInstance(name, str) self.assertNotEqual(name, '') partitioner = yield self.client.describe_partitioner() self.assert_(partitioner.startswith('org.apache.cassandra.'), msg='partitioner is %r' % partitioner) snitch = yield self.client.describe_snitch() self.assert_(snitch.startswith('org.apache.cassandra.'), msg='snitch is %r' % snitch) version = yield self.client.describe_version() self.assertIsInstance(version, str) self.assertIn('.', version) schemavers = yield self.client.describe_schema_versions() self.assertIsInstance(schemavers, dict) self.assertNotEqual(schemavers, {}) ring = yield self.client.describe_ring(KEYSPACE) self.assertIsInstance(ring, list) self.assertNotEqual(ring, []) for r in ring: self.assertIsInstance(r.start_token, str) self.assertIsInstance(r.end_token, str) self.assertIsInstance(r.endpoints, list) self.assertNotEqual(r.endpoints, []) for ep in r.endpoints: self.assertIsInstance(ep, str) @defer.inlineCallbacks def test_errback(self): yield self.client.remove('poiqwe', CF) try: yield self.client.get('poiqwe', CF, column='foo') except Exception, e: pass
class CassandraClientTest(unittest.TestCase): @defer.inlineCallbacks def setUp(self): self.cmanager = ManagedCassandraClientFactory(keyspace='system') self.client = CassandraClient(self.cmanager) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) yield self.cmanager.deferred remote_ver = yield self.client.describe_version() self.version = tuple(map(int, remote_ver.split('.'))) self.my_keyspace = ttypes.KsDef( name=KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={}, cf_defs=[ ttypes.CfDef( keyspace=KEYSPACE, name=CF, column_type='Standard' ), ttypes.CfDef( keyspace=KEYSPACE, name=SCF, column_type='Super' ), ttypes.CfDef( keyspace=KEYSPACE, name=IDX_CF, column_type='Standard', comparator_type='org.apache.cassandra.db.marshal.UTF8Type', column_metadata=[ ttypes.ColumnDef( name='col1', validation_class='org.apache.cassandra.db.marshal.UTF8Type', index_type=ttypes.IndexType.KEYS, index_name='idxCol1') ], default_validation_class='org.apache.cassandra.db.marshal.BytesType' ), ] ) if self.version <= KS_RF_ATTRIBUTE: self.my_keyspace.replication_factor = 1 else: self.my_keyspace.strategy_options['replication_factor'] = '1' if self.version >= COUNTERS_SUPPORTED_API: self.my_keyspace.cf_defs.extend([ ttypes.CfDef( keyspace=KEYSPACE, name=COUNTER_CF, column_type='Standard', default_validation_class='org.apache.cassandra.db.marshal.CounterColumnType' ), ttypes.CfDef( keyspace=KEYSPACE, name=SUPERCOUNTER_CF, column_type='Super', default_validation_class='org.apache.cassandra.db.marshal.CounterColumnType' ), ]) yield self.client.system_add_keyspace(self.my_keyspace) yield self.client.set_keyspace(KEYSPACE) @defer.inlineCallbacks def tearDown(self): yield self.client.system_drop_keyspace(self.my_keyspace.name) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', SCF, 'superval', column=COLUMN, super_column=SCOLUMN) yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assertEqual(res.column.value, 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, {COLUMN: 'test', COLUMN2: 'test2'}) yield self.client.batch_insert('test', SCF, {SCOLUMN: {COLUMN: 'test', COLUMN2: 'test2'}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_count('test', CF) self.assertEqual(res, 2) @defer.inlineCallbacks def test_batch_mutate_and_remove(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } }, 'test2': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } } }) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') res = yield self.client.get_slice('test2', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_remove({CF: ['test', 'test2']}, names=['test', 'test2']) yield self.client.batch_remove({SCF: ['test', 'test2']}, names=['test', 'test2'], supercolumn=SCOLUMN) @defer.inlineCallbacks def test_batch_mutate_with_deletion(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(res[0].column.value, 'test') self.assertEqual(res[1].column.value, 'test2') yield self.client.batch_mutate({'test': {CF: {COLUMN: None, COLUMN2: 'test3'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assertEqual(len(res), 1) self.assertEqual(res[0].column.value, 'test3') @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assertEqual(res['test'][0].column.value, 'testval') self.assertEqual(res['test'][1].column.value, 'testval') self.assertEqual(res['test2'][0].column.value, 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assertEqual(len(res['test']), 0) self.assertEqual(len(res['test2']), 0) @defer.inlineCallbacks def test_range_slices(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) ks = yield self.client.get_range_slices(CF, start='', finish='') keys = [k.key for k in ks] for key in ['test', 'test2']: self.assertIn(key, keys) @defer.inlineCallbacks def test_indexed_slices(self): yield self.client.insert('test1', IDX_CF, 'one', column='col1') yield self.client.insert('test2', IDX_CF, 'two', column='col1') yield self.client.insert('test3', IDX_CF, 'three', column='col1') expressions = [ttypes.IndexExpression('col1', ttypes.IndexOperator.EQ, 'two')] res = yield self.client.get_indexed_slices(IDX_CF, expressions, start_key='') self.assertEquals(res[0].columns[0].column.value,'two') @defer.inlineCallbacks def test_counter_add(self): if self.version < COUNTERS_SUPPORTED_API: raise unittest.SkipTest('Counters are not supported before 0.8') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 2) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 2) @defer.inlineCallbacks def test_counter_remove(self): if self.version < COUNTERS_SUPPORTED_API: raise unittest.SkipTest('Counters are not supported before 0.8') # test standard column counter yield self.client.add('test', COUNTER_CF, 1, column='col') res = yield self.client.get('test', COUNTER_CF, column='col') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', COUNTER_CF, column='col') yield self.assertFailure(self.client.get('test', COUNTER_CF, column='col'), ttypes.NotFoundException) # test super column counters yield self.client.add('test', SUPERCOUNTER_CF, 1, column='col', super_column='scol') res = yield self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol') self.assertEquals(res.counter_column.value, 1) yield self.client.remove_counter('test', SUPERCOUNTER_CF, column='col', super_column='scol') yield self.assertFailure(self.client.get('test', SUPERCOUNTER_CF, column='col', super_column='scol'), ttypes.NotFoundException) def sleep(self, secs): d = defer.Deferred() reactor.callLater(secs, d.callback, None) return d @defer.inlineCallbacks def test_ttls(self): yield self.client.insert('test_ttls', CF, 'testval', column=COLUMN, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), ttypes.NotFoundException) yield self.client.batch_insert('test_ttls', CF, {COLUMN:'testval'}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), ttypes.NotFoundException) yield self.client.batch_mutate({'test_ttls': {CF: {COLUMN: 'testval'}}}, ttl=1) res = yield self.client.get('test_ttls', CF, column=COLUMN) self.assertEqual(res.column.value, 'testval') yield self.sleep(2) yield self.assertFailure(self.client.get('test_ttls', CF, column=COLUMN), ttypes.NotFoundException) def compare_keyspaces(self, ks1, ks2): self.assertEqual(ks1.name, ks2.name) self.assertEqual(ks1.strategy_class, ks2.strategy_class) self.assertEqual(ks1.cf_defs, ks2.cf_defs) def get_rf(ksdef): rf = ksdef.replication_factor if ksdef.strategy_options and \ 'replication_factor' in ksdef.strategy_options: rf = int(ksdef.strategy_options['replication_factor']) return rf def strat_opts_no_rf(ksdef): if not ksdef.strategy_options: return {} opts = ksdef.strategy_options.copy() if 'replication_factor' in ksdef.strategy_options: del opts['replication_factor'] return opts self.assertEqual(get_rf(ks1), get_rf(ks2)) self.assertEqual(strat_opts_no_rf(ks1), strat_opts_no_rf(ks2)) @defer.inlineCallbacks def test_keyspace_manipulation(self): try: yield self.client.system_drop_keyspace(T_KEYSPACE) except ttypes.InvalidRequestException: pass ksdef = ttypes.KsDef(name=T_KEYSPACE, strategy_class='org.apache.cassandra.locator.SimpleStrategy', strategy_options={}, cf_defs=[]) if self.version <= KS_RF_ATTRIBUTE: ksdef.replication_factor = 1 else: ksdef.strategy_options['replication_factor'] = '1' yield self.client.system_add_keyspace(ksdef) ks2 = yield self.client.describe_keyspace(T_KEYSPACE) self.compare_keyspaces(ksdef, ks2) if DO_SYSTEM_RENAMING: newname = T_KEYSPACE + '2' yield self.client.system_rename_keyspace(T_KEYSPACE, newname) ks2 = yield self.client.describe_keyspace(newname) ksdef.name = newname self.compare_keyspaces(ksdef, ks2) yield self.client.system_drop_keyspace(ksdef.name) yield self.assertFailure(self.client.describe_keyspace(T_KEYSPACE), ttypes.NotFoundException) if DO_SYSTEM_RENAMING: yield self.assertFailure(self.client.describe_keyspace(ksdef.name), ttypes.NotFoundException) @defer.inlineCallbacks def test_column_family_manipulation(self): # CfDef attributes present in all supported c*/thrift-api versions common_attrs = ( ('column_type', 'Standard'), ('comparator_type', 'org.apache.cassandra.db.marshal.BytesType'), ('comment', 'foo'), ('read_repair_chance', 1.0), ('column_metadata', []), ('gc_grace_seconds', 86400), ('default_validation_class', 'org.apache.cassandra.db.marshal.BytesType'), ('min_compaction_threshold', 5), ('max_compaction_threshold', 31), ) cfdef = ttypes.CfDef(KEYSPACE, T_CF) for attr, val in common_attrs: setattr(cfdef, attr, val) yield self.client.system_add_column_family(cfdef) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdefs = [c for c in ksdef.cf_defs if c.name == T_CF] self.assertEqual(len(cfdefs), 1) cfdef2 = cfdefs[0] for attr, val in common_attrs: val1 = getattr(cfdef, attr) val2 = getattr(cfdef2, attr) self.assertEqual(val1, val2, 'attribute %s mismatch: %r != %r' % (attr, val1, val2)) if DO_SYSTEM_RENAMING: newname = T_CF + '2' yield self.client.system_rename_column_family(T_CF, newname) ksdef = yield self.client.describe_keyspace(KEYSPACE) cfdef2 = [c for c in ksdef.cf_defs if c.name == newname][0] self.assertNotIn(T_CF, [c.name for c in ksdef.cf_defs]) cfdef.name = newname self.assertEqual(cfdef, cfdef2) yield self.client.system_drop_column_family(cfdef.name) ksdef = yield self.client.describe_keyspace(KEYSPACE) self.assertNotIn(cfdef.name, [c.name for c in ksdef.cf_defs]) @defer.inlineCallbacks def test_describes(self): name = yield self.client.describe_cluster_name() self.assertIsInstance(name, str) self.assertNotEqual(name, '') partitioner = yield self.client.describe_partitioner() self.assert_(partitioner.startswith('org.apache.cassandra.'), msg='partitioner is %r' % partitioner) snitch = yield self.client.describe_snitch() self.assert_(snitch.startswith('org.apache.cassandra.'), msg='snitch is %r' % snitch) version = yield self.client.describe_version() self.assertIsInstance(version, str) self.assertIn('.', version) schemavers = yield self.client.describe_schema_versions() self.assertIsInstance(schemavers, dict) self.assertNotEqual(schemavers, {}) ring = yield self.client.describe_ring(KEYSPACE) self.assertIsInstance(ring, list) self.assertNotEqual(ring, []) for r in ring: self.assertIsInstance(r.start_token, str) self.assertIsInstance(r.end_token, str) self.assertIsInstance(r.endpoints, list) self.assertNotEqual(r.endpoints, []) for ep in r.endpoints: self.assertIsInstance(ep, str) @defer.inlineCallbacks def test_errback(self): yield self.client.remove('poiqwe', CF) try: yield self.client.get('poiqwe', CF, column='foo') except Exception, e: pass
class CassandraClientTest(unittest.TestCase): def setUp(self): self.cmanager = ManagedCassandraClientFactory() self.client = CassandraClient(self.cmanager, KEYSPACE) for i in xrange(CONNS): reactor.connectTCP(HOST, PORT, self.cmanager) return self.cmanager.deferred @defer.inlineCallbacks def tearDown(self): yield self.client.remove('test', CF) yield self.client.remove('test2', CF) yield self.client.remove('test', SCF) yield self.client.remove('test2', SCF) self.cmanager.shutdown() for c in reactor.getDelayedCalls(): c.cancel() reactor.removeAll() @defer.inlineCallbacks def test_insert_get(self): yield self.client.insert('test', ColumnPath(CF, None, COLUMN), 'testval') yield self.client.insert('test2', CF, 'testval2', column=COLUMN) yield self.client.insert('test', ColumnPath(SCF, SCOLUMN, COLUMN), 'superval') yield self.client.insert('test2', SCF, 'superval2', column=COLUMN, super_column=SCOLUMN) res = yield self.client.get('test', CF, column=COLUMN) self.assert_(res.column.value == 'testval') res = yield self.client.get('test2', CF, column=COLUMN) self.assert_(res.column.value == 'testval2') res = yield self.client.get('test', SCF, column=COLUMN, super_column=SCOLUMN) self.assert_(res.column.value == 'superval') res = yield self.client.get('test2', SCF, column=COLUMN, super_column=SCOLUMN) self.assert_(res.column.value == 'superval2') @defer.inlineCallbacks def test_batch_insert_get_slice_and_count(self): yield self.client.batch_insert('test', CF, {COLUMN: 'test', COLUMN2: 'test2'}) yield self.client.batch_insert('test', SCF, {SCOLUMN: {COLUMN: 'test', COLUMN2: 'test2'}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_count('test', CF) self.assert_(res == 2) @defer.inlineCallbacks def test_batch_mutate_and_remove(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } }, 'test2': {CF: {COLUMN: 'test', COLUMN2: 'test2'}, SCF: { SCOLUMN: { COLUMN: 'test', COLUMN2: 'test2'} } } }) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_slice('test2', CF, names=(COLUMN, COLUMN2)) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_slice('test', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') res = yield self.client.get_slice('test2', SCF, names=(COLUMN, COLUMN2), super_column=SCOLUMN) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') yield self.client.batch_remove({CF: ['test', 'test2']}, names=['test', 'test2']) yield self.client.batch_remove({SCF: ['test', 'test2']}, names=['test', 'test2'], supercolumn=SCOLUMN) @defer.inlineCallbacks def test_batch_mutate_with_deletion(self): yield self.client.batch_mutate({'test': {CF: {COLUMN: 'test', COLUMN2: 'test2'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assert_(res[0].column.value == 'test') self.assert_(res[1].column.value == 'test2') yield self.client.batch_mutate({'test': {CF: {COLUMN: None, COLUMN2: 'test3'}}}) res = yield self.client.get_slice('test', CF, names=(COLUMN, COLUMN2)) self.assert_(len(res) == 1) self.assert_(res[0].column.value == 'test3') @defer.inlineCallbacks def test_multiget_slice_remove(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assert_(res['test'].column.value == 'testval') self.assert_(res['test2'].column.value == 'testval2') res = yield self.client.multiget_slice(['test', 'test2'], CF) self.assert_(res['test'][0].column.value == 'testval') self.assert_(res['test'][1].column.value == 'testval') self.assert_(res['test2'][0].column.value == 'testval2') yield self.client.remove('test', CF, column=COLUMN) yield self.client.remove('test2', CF, column=COLUMN) res = yield self.client.multiget(['test', 'test2'], CF, column=COLUMN) self.assert_(res['test'].column == None) self.assert_(res['test2'].column == None) @defer.inlineCallbacks def test_range_slices(self): yield self.client.insert('test', CF, 'testval', column=COLUMN) yield self.client.insert('test', CF, 'testval', column=COLUMN2) yield self.client.insert('test2', CF, 'testval2', column=COLUMN) ks = yield self.client.get_range_slices(CF, start='', finish='') keys = [k.key for k in ks] for key in ['test', 'test2']: self.assert_(key in keys) @defer.inlineCallbacks def test_errback(self): yield self.client.remove('poiqwe', CF) try: yield self.client.get('poiqwe', CF, column='foo') except Exception, e: pass