class test_empty(wttest.WiredTigerTestCase): name = 'test_empty' scenarios = check_scenarios([('file-r', dict(type='file:', fmt='r')), ('file-S', dict(type='file:', fmt='S')), ('table-r', dict(type='table:', fmt='r')), ('table-S', dict(type='table:', fmt='S'))]) # Creating an object and then closing it shouldn't write any blocks. def test_empty_create(self): uri = self.type + self.name self.session.create(uri, 'key_format=' + self.fmt) self.session.close() name = self.name if self.type == "table:": name = name + '.wt' self.assertEquals(os.stat(name).st_size, 4 * 1024) # Open a new sesssion, add a few rows to an object and then remove them, # then close the object. We open/close the object so it's flushed from # the underlying cache each time. def empty(self): uri = self.type + self.name self.session = self.conn.open_session() self.session.create(uri, 'key_format=' + self.fmt) # Add a few records to the object and remove them. cursor = self.session.open_cursor(uri, None, None) for i in range(1, 5): cursor.set_key(key_populate(cursor, i)) cursor.set_value("XXX") cursor.insert() cursor.remove() # Perform a checkpoint (we shouldn't write any underlying pages because # of a checkpoint, either). self.session.checkpoint("name=ckpt") # Open and close a checkpoint cursor. cursor = self.session.open_cursor(uri, None, "checkpoint=ckpt") cursor.close() self.session.close() # The file should not have grown. name = self.name if self.type == "table:": name = name + '.wt' self.assertEquals(os.stat(name).st_size, 4 * 1024) # Creating an object, inserting and removing records (that is, building an # empty, dirty tree), shouldn't write any blocks. This doesn't work for # column-store objects, though, because deleting an object modifies the name # space, which requires a write. def test_empty(self): if self.fmt == 'r': return for i in range(1, 5): self.empty()
class test_upgrade(wttest.WiredTigerTestCase): name = 'test_upgrade' scenarios = check_scenarios([ ('file', dict(uri='file:')), ('table', dict(uri='table:')) ]) # Populate an object, then upgrade it. def upgrade(self, populate, with_cursor): uri = self.uri + self.name populate(self, uri, 'key_format=S', 10) # Open cursors should cause failure. if with_cursor: cursor = self.session.open_cursor(uri, None, None) self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.drop(uri, None)) cursor.close() self.session.upgrade(uri, None) self.session.drop(uri) # Test upgrade of an object. def test_upgrade(self): # Simple file or table object. self.upgrade(simple_populate, False) self.upgrade(simple_populate, True) # A complex, multi-file table object. if self.uri == "table:": self.upgrade(complex_populate, False) self.upgrade(complex_populate, True)
class test_bulk_load_not_empty(wttest.WiredTigerTestCase): name = 'test_bulk' scenarios = check_scenarios([ ('file', dict(type='file:')), ('table', dict(type='table:')) ]) def test_bulk_load_not_empty(self): uri = self.type + self.name self.session.create(uri, 'key_format=S,value_format=S') cursor = self.session.open_cursor(uri, None) cursor.set_key(key_populate(cursor, 1)) cursor.set_value(value_populate(cursor, 1)) cursor.insert() # Close the insert cursor, else we'll get EBUSY. cursor.close() msg = '/bulk-load is only supported on newly created objects/' self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.session.open_cursor(uri, None, "bulk"), msg) def test_bulk_load_busy(self): uri = self.type + self.name self.session.create(uri, 'key_format=S,value_format=S') cursor = self.session.open_cursor(uri, None) cursor.set_key(key_populate(cursor, 1)) cursor.set_value(value_populate(cursor, 1)) cursor.insert() # Don't close the insert cursor, we want EBUSY. self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.open_cursor(uri, None, "bulk"))
class test_rename(wttest.WiredTigerTestCase): name1 = 'test_rename1' name2 = 'test_rename2' scenarios = check_scenarios([ ('file', dict(uri='file:')), ('table', dict(uri='table:')) ]) # Populate and object, and rename it a couple of times, confirming the # old name doesn't exist and the new name has the right contents. def rename(self, populate, check, with_cursor): uri1 = self.uri + self.name1 uri2 = self.uri + self.name2 populate(self, uri1, 'key_format=S', 10) # Open cursors should cause failure. if with_cursor: cursor = self.session.open_cursor(uri1, None, None) self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.rename(uri1, uri2, None)) cursor.close() self.session.rename(uri1, uri2, None) confirm_does_not_exist(self, uri1) check(self, uri2, 10) self.session.rename(uri2, uri1, None) confirm_does_not_exist(self, uri2) check(self, uri1, 10) self.session.drop(uri1) # Test rename of an object. def test_rename(self): # Simple, one-file file or table object. self.rename(simple_populate, simple_populate_check, False) self.rename(simple_populate, simple_populate_check, True) # A complex, multi-file table object. if self.uri == "table:": self.rename(complex_populate, complex_populate_check, False) self.rename(complex_populate, complex_populate_check, True) def test_rename_dne(self): uri1 = self.uri + self.name1 uri2 = self.uri + self.name2 confirm_does_not_exist(self, uri1) self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.rename(uri1, uri2, None)) def test_rename_bad_uri(self): uri1 = self.uri + self.name1 if self.uri == "file:": uri2 = "table:" + self.name2 else: uri2 = "file:" + self.name2 self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.session.rename(uri1, uri2, None), '/type must match URI/')
class test_cursor09(wttest.WiredTigerTestCase): scenarios = check_scenarios([ ('file-r', dict(type='file:', config='key_format=r', complex=0)), ('file-S', dict(type='file:', config='key_format=S', complex=0)), ('lsm-S', dict(type='lsm:', config='key_format=S', complex=0)), ('table-r', dict(type='table:', config='key_format=r', complex=0)), ('table-S', dict(type='table:', config='key_format=S', complex=0)), ('table-r-complex', dict(type='table:', config='key_format=r', complex=1)), ('table-S-complex', dict(type='table:', config='key_format=S', complex=1)), ('table-S-complex-lsm', dict(type='table:', config='key_format=S,type=lsm', complex=1)), ]) # WT_CURSOR.insert doesn't leave the cursor positioned, verify any # subsequent cursor operation fails with a "key not set" message. def test_cursor09(self): uri = self.type + 'cursor09' if self.complex: complex_populate(self, uri, self.config, 100) else: simple_populate(self, uri, self.config, 100) cursor = self.session.open_cursor(uri, None, None) cursor[key_populate(cursor, 10)] = \ tuple(complex_value_populate(cursor, 10)) if self.complex \ else value_populate(cursor, 10) msg = '/requires key be set/' self.assertRaisesWithMessage(wiredtiger.WiredTigerError, cursor.search, msg)
class test_bulk_load_row_order(wttest.WiredTigerTestCase): name = 'test_bulk' scenarios = check_scenarios([('file', dict(type='file:')), ('table', dict(type='table:'))]) def test_bulk_load_row_order_check(self): uri = self.type + self.name self.session.create(uri, 'key_format=S,value_format=S') cursor = self.session.open_cursor(uri, None, "bulk") cursor[key_populate(cursor, 10)] = value_populate(cursor, 10) cursor.set_key(key_populate(cursor, 1)) cursor.set_value(value_populate(cursor, 1)) msg = '/compares smaller than previously inserted key/' self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: cursor.insert(), msg) def test_bulk_load_row_order_nocheck(self): uri = self.type + self.name self.session.create(uri, 'key_format=S,value_format=S') cursor = self.session.open_cursor(uri, None, "bulk,skip_sort_check") cursor[key_populate(cursor, 10)] = value_populate(cursor, 10) cursor[key_populate(cursor, 1)] = value_populate(cursor, 1) if not wiredtiger.diagnostic_build(): self.skipTest('requires a diagnostic build') # Close explicitly, there's going to be a fallure. msg = '/are incorrectly sorted/' self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda: self.conn.close(), msg)
class test_checkpoint_last(wttest.WiredTigerTestCase): scenarios = check_scenarios([('file', dict(uri='file:checkpoint', fmt='S')), ('table', dict(uri='table:checkpoint', fmt='S'))]) def test_checkpoint_last(self): # Create an object, change one record to an easily recognizable string, # then checkpoint it and open a cursor, confirming we see the correct # value. Repeat this action, we want to be sure the engine gets the # latest checkpoint information each time. uri = self.uri simple_populate(self, uri, 'key_format=' + self.fmt, 100) for value in ('FIRST', 'SECOND', 'THIRD', 'FOURTH', 'FIFTH'): # Update the object. cursor = self.session.open_cursor(uri, None, "overwrite") cursor[key_populate(cursor, 10)] = value cursor.close() # Checkpoint the object. self.session.checkpoint() # Verify the "last" checkpoint sees the correct value. cursor = self.session.open_cursor( uri, None, "checkpoint=WiredTigerCheckpoint") self.assertEquals(cursor[key_populate(cursor, 10)], value)
class test_perf001(wttest.WiredTigerTestCase): table_name = 'test_perf001' scenarios = check_scenarios([ #('file-file', dict(tabletype='file',indextype='file')), ('file-lsm', dict(tabletype='file',indextype='lsm')), #('lsm-file', dict(tabletype='lsm',indextype='file')), #('lsm-lsm', dict(tabletype='lsm',indextype='lsm')), ]) def setUpConnectionOpen(self, dir): wtopen_args = 'create,cache_size=512M' conn = wiredtiger.wiredtiger_open(dir, wtopen_args) self.pr(`conn`) return conn def test_performance_of_indices(self): uri = 'table:' + self.table_name create_args = 'key_format=i,value_format=ii,columns=(a,c,d),type=' + self.tabletype self.session.create(uri, create_args) self.session.create('index:' + self.table_name + ':ia', 'columns=(d,c),type=' + self.indextype) c = self.session.open_cursor('table:' + self.table_name, None, None) start_time = clock() for i in xrange(750000): # 100 operations should never take 5 seconds, sometimes they take # 2 seconds when a page is being force-evicted. if i % 100 == 0 and i != 0: end_time = clock() self.assertTrue(end_time - start_time < 5) start_time = end_time c[i] = (int(time()), random.randint(1,5)) c.close()
class test_cursor06(wttest.WiredTigerTestCase): name = 'reconfigure' scenarios = check_scenarios([ ('file-r', dict(type='file:', keyfmt='r', complex=0)), ('file-S', dict(type='file:', keyfmt='S', complex=0)), ('lsm-S', dict(type='lsm:', keyfmt='S', complex=0)), ('table-r', dict(type='table:', keyfmt='r', complex=0)), ('table-S', dict(type='table:', keyfmt='S', complex=0)), ('table-r-complex', dict(type='table:', keyfmt='r', complex=1)), ('table-S-complex', dict(type='table:', keyfmt='S', complex=1)), ]) def pop(self, uri): if self.complex == 1: complex_populate(self, uri, 'key_format=' + self.keyfmt, 100) else: simple_populate(self, uri, 'key_format=' + self.keyfmt, 100) def set_kv(self, cursor): cursor.set_key(key_populate(cursor, 10)) if self.complex == 1: v = complex_value_populate(cursor, 10) cursor.set_value(v[0], v[1], v[2], v[3]) else: cursor.set_value(value_populate(cursor, 10)) def test_reconfigure_overwrite(self): uri = self.type + self.name for open_config in (None, "overwrite=0", "overwrite=1"): self.session.drop(uri, "force") self.pop(uri) cursor = self.session.open_cursor(uri, None, open_config) if open_config != "overwrite=0": self.set_kv(cursor) cursor.insert() for i in range(0, 10): cursor.reconfigure("overwrite=0") self.set_kv(cursor) self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.insert()) cursor.reconfigure("overwrite=1") self.set_kv(cursor) cursor.insert() cursor.close() def test_reconfigure_readonly(self): uri = self.type + self.name for open_config in (None, "readonly=0", "readonly=1"): self.session.drop(uri, "force") self.pop(uri) cursor = self.session.open_cursor(uri, None, open_config) if open_config == "readonly=1": self.set_kv(cursor) self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.update()) else: self.set_kv(cursor) cursor.update() cursor.close()
class test_intpack(wttest.WiredTigerTestCase): name = 'test_intpack' scenarios = check_scenarios([ ('b', dict(formatcode='b', low=-128, high=127, nbits=8)), ('B', dict(formatcode='B', low=0, high=255, nbits=8)), ('8t', dict(formatcode='8t', low=0, high=255, nbits=8)), ('5t', dict(formatcode='5t', low=0, high=31, nbits=5)), ('h', dict(formatcode='h', low=-32768, high=32767, nbits=16)), ('H', dict(formatcode='H', low=0, high=65535, nbits=16)), ('i', dict(formatcode='i', low=-2147483648, high=2147483647, nbits=32)), ('I', dict(formatcode='I', low=0, high=4294967295, nbits=32)), ('l', dict(formatcode='l', low=-2147483648, high=2147483647, nbits=32)), ('L', dict(formatcode='L', low=0, high=4294967295, nbits=32)), ('q', dict(formatcode='q', low=-9223372036854775808, high=9223372036854775807, nbits=64)), ('Q', dict(formatcode='Q', low=0, high=18446744073709551615, nbits=64)), ]) scenarios = check_scenarios(number_scenarios(scenarios)) def test_packing(self): pt = PackTester(self.formatcode, self.low, self.high, self.assertEquals) self.assertEquals(2**self.nbits, self.high - self.low + 1) pt.initialize(self.session) pt.check_range(-66000, 66000) if self.nbits >= 32: e32 = 2**32 pt.check_range(e32 - 1000, e32 + 1000) pt.check_range(-e32 - 1000, -e32 + 1000) if self.nbits >= 64: e64 = 2**64 pt.check_range(e64 - 1000, e64 + 1000) pt.check_range(-e64 - 1000, -e64 + 1000) pt.truncate() i = 8 while i < 1 << 60: pt.check_range(-i - 1, -i + 1) pt.check_range(i - 1, i + 1) i <<= 1
class test_txn03(wttest.WiredTigerTestCase): tablename = 'test_txn03' uri1 = 'table:' + tablename + "_1" uri2 = 'table:' + tablename + "_2" key_str = "TEST_KEY1" data_str1 = "VAL" data_str2 = "TEST_VAL1" nentries = 1000 scenarios = check_scenarios([ ('var', dict(create_params="key_format=S,value_format=S")), ]) def test_ops(self): self.session.create(self.uri1, self.create_params) self.session.create(self.uri2, self.create_params) # Set up the table with entries for 1 and 10 # We use the overwrite config so insert can update as needed. c = self.session.open_cursor(self.uri1, None, 'overwrite') c[self.key_str] = self.data_str1 c.close() c = self.session.open_cursor(self.uri2, None, 'overwrite') c[self.key_str] = self.data_str1 c.close() # Update the first table - this update should be visible in the # new session. self.session.begin_transaction() c = self.session.open_cursor(self.uri1, None, 'overwrite') c[self.key_str] = self.data_str2 self.session.commit_transaction() c.close() # Open another session and some transactional cursors. self.session2 = self.conn.open_session() self.session2.begin_transaction("isolation=snapshot") t1c = self.session2.open_cursor(self.uri1, None, 'overwrite') t2c = self.session2.open_cursor(self.uri2, None, 'overwrite') # Make an update in the first session. self.session.begin_transaction() c = self.session.open_cursor(self.uri2, None, 'overwrite') c[self.key_str] = self.data_str2 self.session.commit_transaction() c.close() t1c.set_key(self.key_str) t1c.search() t2c.set_key(self.key_str) t2c.search() self.assertEqual(t1c.get_value(), self.data_str2) self.assertEqual(t2c.get_value(), self.data_str1) # Clean up t1c.close() t2c.close() self.session2.rollback_transaction()
class test_checkpoint02(wttest.WiredTigerTestCase): scenarios = check_scenarios([('table-100', dict(uri='table:test', fmt='L', dsize=100, nops=50000, nthreads=10)), ('table-10', dict(uri='table:test', fmt='L', dsize=10, nops=50000, nthreads=30))]) def test_checkpoint02(self): done = threading.Event() self.session.create(self.uri, "key_format=" + self.fmt + ",value_format=S") ckpt = checkpoint_thread(self.conn, done) ckpt.start() uris = list() uris.append(self.uri) queue = Queue.Queue() my_data = 'a' * self.dsize for i in xrange(self.nops): if i % 191 == 0 and i != 0: queue.put_nowait(('b', i, my_data)) queue.put_nowait(('i', i, my_data)) opthreads = [] for i in xrange(self.nthreads): t = op_thread(self.conn, uris, self.fmt, queue, done) opthreads.append(t) t.start() queue.join() done.set() for t in opthreads: t.join() ckpt.join() # Create a cursor - ensure all items have been put. cursor = self.session.open_cursor(self.uri, None, None) i = 0 while True: nextret = cursor.next() if nextret != 0: break key = cursor.get_key() value = cursor.get_value() self.assertEqual(key, i) self.assertEqual(value, my_data) i += 1 self.assertEqual(i, self.nops)
class test_cursor_random_column(wttest.WiredTigerTestCase): scenarios = check_scenarios([('file', dict(uri='file:random')), ('table', dict(uri='table:random'))]) def test_cursor_random_column(self): self.session.create(self.uri, 'key_format=r,value_format=S') msg = '/Operation not supported/' self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.open_cursor( self.uri, None, "next_random=true"), msg)
class test_txn13(wttest.WiredTigerTestCase, suite_subprocess): logmax = "100K" tablename = 'test_txn13' uri = 'table:' + tablename nops = 1024 create_params = 'key_format=i,value_format=S' scenarios = check_scenarios([ ('1gb', dict(expect_err=False, valuesize=1048576)), ('2gb', dict(expect_err=False, valuesize=2097152)), ('4gb', dict(expect_err=True, valuesize=4194304)) ]) # Overrides WiredTigerTestCase def setUpConnectionOpen(self, dir): self.home = dir conn_params = \ 'log=(archive=false,enabled,file_max=%s)' % self.logmax + \ ',create,cache_size=8G,error_prefix="%s: ",' % self.shortid() # print "Creating conn at '%s' with config '%s'" % (dir, conn_params) try: conn = wiredtiger_open(dir, conn_params) except wiredtiger.WiredTigerError as e: print "Failed conn at '%s' with config '%s'" % (dir, conn_params) self.pr( ` conn `) return conn @wttest.longtest('txn tests with huge values') def test_large_values(self): # print "Creating %s with config '%s'" % (self.uri, self.create_params) # print "Running with %d" % (self.valuesize) self.session.create(self.uri, self.create_params) c = self.session.open_cursor(self.uri, None) # We want to test very large values. Generate 'nops' records within # a single transaction. valuepfx = self.valuesize * 'X' gotException = False self.session.begin_transaction() for k in range(self.nops): value = valuepfx + str(k) c[k] = value if self.expect_err: # EFBIG is expected: File too large msg = '/exceeds the maximum/' self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.commit_transaction(), msg) gotException = True else: self.session.commit_transaction() self.assertTrue(gotException == self.expect_err)
class test_create_excl(wttest.WiredTigerTestCase): scenarios = check_scenarios([('file', dict(type='file:')), ('table', dict(type='table:'))]) # Create the object with "exclusive", then assert that creation with # "exclusive" fails. def test_create_excl(self): uri = self.type + 'create_excl' self.session.create(uri, "exclusive") self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.create(uri, "exclusive"))
class test_cursor_random_column(wttest.WiredTigerTestCase): scenarios = check_scenarios([ ('file', dict(uri='file:random', fmt='r')), ('table', dict(uri='table:random', fmt='r')), ]) def test_cursor_random_column(self): self.session.create(self.uri, 'key_format=' + self.fmt + ',value_format=S') cursor = self.session.open_cursor(self.uri, None, "next_random=true") self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.next()) cursor.close()
class test_cursor07(wttest.WiredTigerTestCase, suite_subprocess): logmax = "100K" tablename = 'test_cursor07' uri = 'table:' + tablename # A large number of keys will force a log file change which will # test that scenario for log cursors. nkeys = 7000 scenarios = check_scenarios([('regular', dict(reopen=False)), ('reopen', dict(reopen=True))]) # Enable logging for this test. def conn_config(self, dir): return 'log=(archive=false,enabled,file_max=%s),' % self.logmax + \ 'transaction_sync="(method=dsync,enabled)"' def test_log_cursor(self): # print "Creating %s with config '%s'" % (self.uri, self.create_params) create_params = 'key_format=i,value_format=S' self.session.create(self.uri, create_params) c = self.session.open_cursor(self.uri, None) # A binary value. value = u'\u0001\u0002abcd\u0003\u0004' self.session.begin_transaction() for k in range(self.nkeys): c[k] = value self.session.commit_transaction() c.close() if self.reopen: self.reopen_conn() # Check for these values via a log cursor c = self.session.open_cursor("log:", None) count = 0 while c.next() == 0: # lsn.file, lsn.offset, opcount keys = c.get_key() # txnid, rectype, optype, fileid, logrec_key, logrec_value values = c.get_value() try: if value in str(values[5]): # logrec_value count += 1 except: pass c.close() self.assertEqual(count, self.nkeys)
class test_backup02(wttest.WiredTigerTestCase): scenarios = check_scenarios([ ('table', dict(uri='table:test',fmt='L',dsize=100,nops=200,nthreads=1,time=30)), ]) def test_backup02(self): done = threading.Event() uris = list() uris.append(self.uri + str(1)) uris.append(self.uri + str(2)) uris.append(self.uri + str(3)) for this_uri in uris: self.session.create(this_uri, "key_format=" + self.fmt + ",value_format=S") # TODO: Ideally we'd like a checkpoint thread, separate to the backup # thread. Need a way to stop checkpoints while doing backups. # ckpt = checkpoint_thread(self.conn, done) # ckpt.start() bkp = backup_thread(self.conn, 'backup.dir', done) bkp.start() queue = Queue.Queue() my_data = 'a' * self.dsize for i in xrange(self.nops): queue.put_nowait(('gi', i, my_data)) opthreads = [] for i in xrange(self.nthreads): t = op_thread(self.conn, uris, self.fmt, queue, done) opthreads.append(t) t.start() # Add 200 update entries into the queue every .1 seconds. more_time = self.time while more_time > 0: time.sleep(0.1) my_data = str(more_time) + 'a' * (self.dsize - len(str(more_time))) more_time = more_time - 0.1 for i in xrange(self.nops): queue.put_nowait(('gu', i, my_data)) queue.join() done.set() # # Wait for checkpoint thread to notice status change. # ckpt.join() for t in opthreads: t.join() bkp.join()
class test_checkpoint_target(wttest.WiredTigerTestCase): scenarios = check_scenarios([ ('file', dict(uri='file:checkpoint',fmt='S')), ('table', dict(uri='table:checkpoint',fmt='S')) ]) def update(self, uri, value): cursor = self.session.open_cursor(uri, None, "overwrite") cursor.set_key(key_populate(cursor, 10)) cursor.set_value(value) cursor.insert() cursor.close() def check(self, uri, value): cursor = self.session.open_cursor(uri, None, "checkpoint=checkpoint-1") self.assertEquals(cursor[key_populate(cursor, 10)], value) cursor.close() def test_checkpoint_target(self): # Create 3 objects, change one record to an easily recognizable string. uri = self.uri + '1' simple_populate(self, uri, 'key_format=' + self.fmt, 100) self.update(uri, 'ORIGINAL') uri = self.uri + '2' simple_populate(self, uri, 'key_format=' + self.fmt, 100) self.update(uri, 'ORIGINAL') uri = self.uri + '3' simple_populate(self, uri, 'key_format=' + self.fmt, 100) self.update(uri, 'ORIGINAL') # Checkpoint all three objects. self.session.checkpoint("name=checkpoint-1") # Update all 3 objects, then checkpoint two of the objects with the # same checkpoint name. self.update(self.uri + '1', 'UPDATE') self.update(self.uri + '2', 'UPDATE') self.update(self.uri + '3', 'UPDATE') target = 'target=("' + self.uri + '1"' + ',"' + self.uri + '2")' self.session.checkpoint("name=checkpoint-1," + target) # Confirm the checkpoint has the old value in objects that weren't # checkpointed, and the new value in objects that were checkpointed. self.check(self.uri + '1', 'UPDATE') self.check(self.uri + '2', 'UPDATE') self.check(self.uri + '3', 'ORIGINAL')
class test_duplicate_cursor(wttest.WiredTigerTestCase): name = 'test_dupc' nentries = 1000 config = 'key_format=' scenarios = check_scenarios([ ('file-r', dict(uri='file:', fmt='r')), ('file-S', dict(uri='file:', fmt='S')), ('table-r', dict(uri='table:', fmt='r')), ('table-S', dict(uri='table:', fmt='S')) ]) # Iterate through an object, duplicate the cursor and checking that it # matches the original and is set to the same record. def iterate(self, uri): cursor = self.session.open_cursor(uri, None, None) next = 0 while True: nextret = cursor.next() if nextret != 0: break next += 1 self.assertEqual(cursor.get_key(), key_populate(cursor, next)) dupc = self.session.open_cursor(None, cursor, None) self.assertEqual(cursor.compare(dupc), 0) self.assertEqual(dupc.get_key(), key_populate(dupc, next)) cursor.close() cursor = dupc self.assertEqual(next, self.nentries) self.assertEqual(nextret, wiredtiger.WT_NOTFOUND) cursor.close() def test_duplicate_cursor(self): uri = self.uri + self.name # A simple, one-file file or table object. simple_populate(self, uri, self.config + self.fmt, self.nentries) self.iterate(uri) self.session.drop(uri, None) # A complex, multi-file table object. if self.uri == "table:": complex_populate(self, uri, self.config + self.fmt, self.nentries) self.iterate(uri) self.session.drop(uri, None)
class test_checkpoint_cursor_update(wttest.WiredTigerTestCase): scenarios = check_scenarios([ ('file-r', dict(uri='file:checkpoint',fmt='r')), ('file-S', dict(uri='file:checkpoint',fmt='S')), ('table-r', dict(uri='table:checkpoint',fmt='r')), ('table-S', dict(uri='table:checkpoint',fmt='S')) ]) def test_checkpoint_cursor_update(self): simple_populate(self, self.uri, 'key_format=' + self.fmt, 100) self.session.checkpoint("name=ckpt") cursor = self.session.open_cursor(self.uri, None, "checkpoint=ckpt") cursor.set_key(key_populate(cursor, 10)) cursor.set_value("XXX") self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.insert()) self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.remove()) self.assertRaises(wiredtiger.WiredTigerError, lambda: cursor.update()) cursor.close()
class test_bug006(wttest.WiredTigerTestCase): name = 'test_bug006' scenarios = check_scenarios([ ('file', dict(uri='file:')), ('table', dict(uri='table:')), ]) def test_bug006(self): uri = self.uri + self.name self.session.create(uri, 'value_format=S,key_format=S') cursor = self.session.open_cursor(uri, None) for i in range(1, 1000): cursor.set_key(key_populate(cursor, i)) cursor.set_value(value_populate(cursor, i)) cursor.insert() # Table operations should fail, the cursor is open. self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.drop(uri, None)) self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.rename(uri, self.uri + "new", None)) self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.salvage(uri, None)) self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.truncate(uri, None, None, None)) self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.upgrade(uri, None)) self.assertRaises( wiredtiger.WiredTigerError, lambda: self.session.verify(uri, None)) cursor.close() # Table operations should succeed, the cursor is closed. self.session.rename(uri, self.uri + "new", None) self.session.rename(self.uri + "new", uri, None) self.session.salvage(uri, None) self.session.truncate(uri, None, None, None) self.session.upgrade(uri, None) self.session.verify(uri, None) self.session.drop(uri, None)
class test_truncate_uri(wttest.WiredTigerTestCase): name = 'test_truncate' scenarios = check_scenarios([('file', dict(type='file:')), ('table', dict(type='table:'))]) # Populate an object, truncate it by URI, and confirm it's empty. def test_truncate_uri(self): uri = self.type + self.name # A simple, one-file file or table object. simple_populate(self, uri, 'key_format=S', 100) self.session.truncate(uri, None, None, None) confirm_empty(self, uri) self.session.drop(uri, None) if self.type == "table:": complex_populate(self, uri, 'key_format=S', 100) self.session.truncate(uri, None, None, None) confirm_empty(self, uri) self.session.drop(uri, None)
class test_truncate_arguments(wttest.WiredTigerTestCase): name = 'test_truncate' scenarios = check_scenarios([('file', dict(type='file:')), ('table', dict(type='table:'))]) # Test truncation without URI or cursors specified, or with a URI and # either cursor specified, expect errors. def test_truncate_bad_args(self): uri = self.type + self.name simple_populate(self, uri, 'key_format=S', 100) msg = '/either a URI or start/stop cursors/' self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.truncate(None, None, None, None), msg) cursor = self.session.open_cursor(uri, None) self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.truncate(uri, cursor, None, None), msg) self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.truncate(uri, None, cursor, None), msg) # Test truncation of cursors where no key is set, expect errors. def test_truncate_cursor_notset(self): uri = self.type + self.name msg = '/requires key be set/' simple_populate(self, uri, 'key_format=S', 100) c1 = self.session.open_cursor(uri, None) c2 = self.session.open_cursor(uri, None) c2.set_key(key_populate(c2, 10)) self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.truncate(None, c1, c2, None), msg) self.assertRaisesWithMessage( wiredtiger.WiredTigerError, lambda: self.session.truncate(None, c2, c1, None), msg) c1.close() c2.close()
class test_rebalance(wttest.WiredTigerTestCase): name = 'test_rebalance' # Use small pages so we generate some internal layout # Setup LSM so multiple chunks are present config = 'key_format=S,allocation_size=512,internal_page_max=512' + \ ',leaf_page_max=1k,lsm=(chunk_size=512k,merge_min=10)' scenarios = check_scenarios([('file', dict(uri='file:')), ('table', dict(uri='table:')), ('lsm', dict(uri='lsm:'))]) # Populate an object, then rebalance it. def rebalance(self, populate, with_cursor): uri = self.uri + self.name populate(self, uri, self.config, 10000) # Force to disk, we don't rebalance in-memory objects. self.reopen_conn() # Open cursors should cause failure. if with_cursor: cursor = self.session.open_cursor(uri, None, None) self.assertRaises(wiredtiger.WiredTigerError, lambda: self.session.drop(uri, None)) cursor.close() self.session.rebalance(uri, None) self.session.drop(uri) # Test rebalance of an object. def test_rebalance(self): # Simple file or table object. self.rebalance(simple_populate, False) self.rebalance(simple_populate, True) # A complex, multi-file table object. if self.uri == "table:": self.rebalance(complex_populate, False) self.rebalance(complex_populate, True)
class test_util03(wttest.WiredTigerTestCase, suite_subprocess): tablename = 'test_util03.a' nentries = 1000 scenarios = check_scenarios([ ('none', dict(key_format=None, value_format=None)), ('SS', dict(key_format='S', value_format='S')), ('rS', dict(key_format='r', value_format='S')), ('ri', dict(key_format='r', value_format='i')), ]) def test_create_process(self): """ Test create in a 'wt' process """ args = ["create"] if self.key_format != None or self.value_format != None: args.append('-c') config = '' if self.key_format != None: config += 'key_format=' + self.key_format + ',' if self.value_format != None: config += 'value_format=' + self.value_format args.append(config) args.append('table:' + self.tablename) self.runWt(args) cursor = self.session.open_cursor('table:' + self.tablename, None, None) if self.key_format != None: self.assertEqual(cursor.key_format, self.key_format) if self.value_format != None: self.assertEqual(cursor.value_format, self.value_format) for key, val in cursor: self.fail('table should be empty') cursor.close()
class test_backup_target(wttest.WiredTigerTestCase, suite_subprocess): dir='backup.dir' # Backup directory name logmax="100K" # This test is written to test incremental backups. We want to add # enough data to generate more than one log file each time we add data. # First we populate and take a full backup. Then we loop, checkpointing # running an incremental backup with a targeted cursor and then calling # truncate to archive the logs. # # At the same time, we take a full backup during each loop. # We run recovery and verify the full backup with the incremental # backup after each loop. We compare two backups instead of the original # because running 'wt' causes all of our original handles to be closed # and that is not what we want here. # pfx = 'test_backup' scenarios = check_scenarios([ ('table', dict(uri='table:test',dsize=100,nops=2000,nthreads=1,time=30)), ]) # Create a large cache, otherwise this test runs quite slowly. def setUpConnectionOpen(self, dir): wtopen_args = \ 'create,cache_size=1G,log=(archive=false,enabled,file_max=%s)' % \ self.logmax conn = wiredtiger.wiredtiger_open(dir, wtopen_args) self.pr(`conn`) return conn def populate(self, uri, dsize, rows): self.pr('populate: ' + uri + ' with ' + str(rows) + ' rows') cursor = self.session.open_cursor(uri, None) for i in range(1, rows + 1): cursor[key_populate(cursor, i)] = str(i) + ':' + 'a' * dsize cursor.close() def update(self, uri, dsize, upd, rows): self.pr('update: ' + uri + ' with ' + str(rows) + ' rows') cursor = self.session.open_cursor(uri, None) for i in range(1, rows + 1): cursor[key_populate(cursor, i)] = str(i) + ':' + upd * dsize cursor.close() # Compare the original and backed-up files using the wt dump command. def compare(self, uri, dir_full, dir_incr): # print "Compare: full URI: " + uri + " with incremental URI " if dir_full == None: full_name='original' else: full_name='backup_full' incr_name='backup_incr' if os.path.exists(full_name): os.remove(full_name) if os.path.exists(incr_name): os.remove(incr_name) # # We have been copying the logs only, so we need to force 'wt' to # run recovery in order to apply all the logs and check the data. # if dir_full == None: self.runWt(['-R', 'dump', uri], outfilename=full_name) else: self.runWt(['-R', '-h', dir_full, 'dump', uri], outfilename=full_name) self.runWt(['-R', '-h', dir_incr, 'dump', uri], outfilename=incr_name) self.assertEqual(True, compare_files(self, full_name, incr_name)) def take_full_backup(self, dir): # Open up the backup cursor, and copy the files. Do a full backup. cursor = self.session.open_cursor('backup:', None, None) self.pr('Full backup to ' + dir + ': ') os.mkdir(dir) while True: ret = cursor.next() if ret != 0: break newfile = cursor.get_key() sz = os.path.getsize(newfile) self.pr('Copy from: ' + newfile + ' (' + str(sz) + ') to ' + dir) shutil.copy(newfile, dir) self.assertEqual(ret, wiredtiger.WT_NOTFOUND) cursor.close() # Take an incremental backup and then truncate/archive the logs. def take_incr_backup(self, dir): config = 'target=("log:")' cursor = self.session.open_cursor('backup:', None, config) while True: ret = cursor.next() if ret != 0: break newfile = cursor.get_key() sz = os.path.getsize(newfile) self.pr('Copy from: ' + newfile + ' (' + str(sz) + ') to ' + dir) shutil.copy(newfile, dir) self.assertEqual(ret, wiredtiger.WT_NOTFOUND) self.session.truncate('log:', cursor, None, None) cursor.close() # Run background inserts while running checkpoints and incremental backups # repeatedly. def test_incremental_backup(self): import sys # Create the backup directory. self.session.create(self.uri, "key_format=S,value_format=S") self.populate(self.uri, self.dsize, self.nops) # We need to start the directory for the incremental backup with # a full backup. The full backup function creates the directory. dir = self.dir self.take_full_backup(dir) self.session.checkpoint(None) # # Incremental backups perform a loop: # Do more work # Checkpoint # Copy log files returned by log targeted backup cursor # Truncate (archive) the log files # Close the backup cursor updstr="bcdefghi" for increment in range(0, 5): full_dir = self.dir + str(increment) # Add more work to move the logs forward. self.update(self.uri, self.dsize, updstr[increment], self.nops) self.session.checkpoint(None) self.pr('Iteration: ' + str(increment)) self.take_incr_backup(self.dir) # After running, take a full backup. Compare the incremental # backup to the original database and the full backup database. self.take_full_backup(full_dir) self.compare(self.uri, full_dir, self.dir) self.compare(self.uri, None, self.dir)
class test_async01(wttest.WiredTigerTestCase, suite_subprocess): """ Test basic operations """ table_name1 = 'test_async01' nentries = 100 async_ops = nentries / 2 async_threads = 3 current = {} scenarios = check_scenarios([ ('file-col', dict(tablekind='col', uri='file')), ('file-fix', dict(tablekind='fix', uri='file')), ('file-row', dict(tablekind='row', uri='file')), ('lsm-row', dict(tablekind='row', uri='lsm')), ('table-col', dict(tablekind='col', uri='table')), ('table-fix', dict(tablekind='fix', uri='table')), ('table-row', dict(tablekind='row', uri='table')), ]) # Overrides WiredTigerTestCase so that we can configure # async operations. def setUpConnectionOpen(self, dir): self.home = dir conn_params = \ 'create,error_prefix="%s: ",' % self.shortid() + \ 'async=(enabled=true,ops_max=%s,' % self.async_ops + \ 'threads=%s)' % self.async_threads sys.stdout.flush() conn = wiredtiger_open(dir, conn_params) self.pr( ` conn `) return conn def genkey(self, i): if self.tablekind == 'row': return 'key' + str(i) else: return long(i + 1) def genvalue(self, i): if self.tablekind == 'fix': return int(i & 0xff) else: return 'value' + str(i) # Create and populate the object. def create_session(self, tablearg): if self.tablekind == 'row': keyformat = 'key_format=S' else: keyformat = 'key_format=r' # record format if self.tablekind == 'fix': valformat = 'value_format=8t' else: valformat = 'value_format=S' create_args = keyformat + ',' + valformat self.pr('creating session: ' + create_args) self.session.create(tablearg, create_args) def test_ops(self): tablearg = self.uri + ':' + self.table_name1 ncompact = 0 self.create_session(tablearg) # Populate our reference table first, so we don't need to # use locks to reference it. self.current = {} for i in range(0, self.nentries): k = self.genkey(i) v = self.genvalue(i) self.current[k] = v # Populate table with async inserts, callback checks # to ensure key/value is correct. callback = Callback(self.current) for i in range(0, self.nentries): self.pr('creating async op') op = self.conn.async_new_op(tablearg, None, callback) k = self.genkey(i) v = self.genvalue(i) op.set_key(k) op.set_value(v) op.insert() # Compact after insert. # Wait for all outstanding async ops to finish. op = self.conn.async_new_op(tablearg, 'timeout=0', callback) op.compact() ncompact += 1 self.conn.async_flush() self.pr('flushed') # Now test async search and check key/value in the callback. for i in range(0, self.nentries): op = self.conn.async_new_op(tablearg, None, callback) k = self.genkey(i) op.set_key(k) op.search() # Wait for all outstanding async ops to finish. self.conn.async_flush() self.pr('flushed') # Reset the reference table for the update. for i in range(0, self.nentries): k = self.genkey(i) v = self.genvalue(i + 10) self.current[k] = v for i in range(0, self.nentries): self.pr('creating async op') op = self.conn.async_new_op(tablearg, None, callback) k = self.genkey(i) v = self.genvalue(i + 10) op.set_key(k) op.set_value(v) op.update() # Compact after update. # Wait for all outstanding async ops to finish. op = self.conn.async_new_op(tablearg, None, callback) op.compact() ncompact += 1 self.conn.async_flush() self.pr('flushed') # Now test async search and check key/value in the callback. for i in range(0, self.nentries): op = self.conn.async_new_op(tablearg, None, callback) k = self.genkey(i) op.set_key(k) op.search() # Wait for all outstanding async ops to finish. self.conn.async_flush() self.pr('flushed') for i in range(0, self.nentries): self.pr('creating async op') op = self.conn.async_new_op(tablearg, None, callback) k = self.genkey(i) op.set_key(k) op.remove() # Wait for all outstanding async ops to finish. self.conn.async_flush() self.pr('flushed') # Make sure all callbacks went according to plan. self.assertTrue(callback.ncompact == ncompact) self.assertTrue(callback.ninsert == self.nentries) self.assertTrue(callback.nremove == self.nentries) self.assertTrue(callback.nsearch == self.nentries * 2) self.assertTrue(callback.nupdate == self.nentries) self.assertTrue(callback.nerror == 0)
class test_cursor_pin(wttest.WiredTigerTestCase): uri = 'file:cursor_pin' nentries = 10000 config = 'allocation_size=512,leaf_page_max=512,value_format=S,key_format=' scenarios = check_scenarios([ ('recno', dict(keyfmt='r')), ('string', dict(keyfmt='S')), ]) # Create a multi-page file, confirm that a simple search to the local # page works, followed by a search to a different page. def test_smoke(self): simple_populate(self, self.uri, self.config + self.keyfmt, self.nentries) self.reopen_conn() c = self.session.open_cursor(self.uri, None) c.set_key(key_populate(c, 100)) self.assertEqual(c.search(), 0) self.assertEqual(c.get_value(), value_populate(c, 100)) c.set_key(key_populate(c, 101)) self.assertEqual(c.search(), 0) self.assertEqual(c.get_value(), value_populate(c, 101)) c.set_key(key_populate(c, 9999)) self.assertEqual(c.search(), 0) self.assertEqual(c.get_value(), value_populate(c, 9999)) # Forward check. def forward(self, c, max, notfound): for i in range(1, max + 1): c.set_key(key_populate(c, i)) if i in notfound: self.assertEqual(c.search(), wiredtiger.WT_NOTFOUND) else: self.assertEqual(c.search(), 0) self.assertEqual(c.get_value(), value_populate(c, i)) # Backward check. def backward(self, c, max, notfound): for i in range(max, 0, -1): c.set_key(key_populate(c, i)) if i in notfound: self.assertEqual(c.search(), wiredtiger.WT_NOTFOUND) else: self.assertEqual(c.search(), 0) self.assertEqual(c.get_value(), value_populate(c, i)) # Create a multi-page file, search backward, forward to check page # boundaries. def test_basic(self): simple_populate(self, self.uri, self.config + self.keyfmt, self.nentries) self.reopen_conn() c = self.session.open_cursor(self.uri, None) self.forward(c, self.nentries, []) self.backward(c, self.nentries, []) # Create a multi-page file with a big chunk of missing space in the # middle (to exercise column-store searches). def test_missing(self): simple_populate(self, self.uri, self.config + self.keyfmt, self.nentries) c = self.session.open_cursor(self.uri, None) for i in range(self.nentries + 3000, self.nentries + 5001): c[key_populate(c, i)] = value_populate(c, i) self.reopen_conn() c = self.session.open_cursor(self.uri, None) self.forward(c, self.nentries + 5000, list(range(self.nentries + 1, self.nentries + 3000))) self.backward(c, self.nentries + 5000, list(range(self.nentries + 1, self.nentries + 3000))) # Insert into the empty space so we test searching inserted items. for i in range(self.nentries + 1000, self.nentries + 2001): c[key_populate(c, i)] = value_populate(c, i) self.forward(c, self.nentries + 5000, list(range(self.nentries + 1, self.nentries + 1000) +\ range(self.nentries + 2001, self.nentries + 3000))) self.backward(c, self.nentries + 5000, list(range(self.nentries + 1, self.nentries + 1000) +\ range(self.nentries + 2001, self.nentries + 3000)))
class test_schema02(wttest.WiredTigerTestCase): """ Test basic operations """ nentries = 1000 scenarios = check_scenarios([ ('normal', { 'idx_config' : '' }), ('lsm', { 'idx_config' : ',type=lsm' }), ]) def expect_failure_colgroup(self, name, configstr, match): self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda:self.session.create("colgroup:" + name, configstr), match) def test_colgroup_after_failure(self): # bogus formats self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda:self.session.create("table:main", "key_format=Z,value_format=S"), "/Invalid type 'Z' found in format 'Z'/") self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda:self.session.create("table:main", "key_format=S,value_format=Z"), "/Invalid type 'Z' found in format 'Z'/") # These should succeed self.session.create("table:main", "key_format=iS,value_format=SiSi," "columns=(ikey,Skey,S1,i2,S3,i4),colgroups=(c1,c2)") self.session.create("colgroup:main:c1", "columns=(S1,i2)") def test_colgroup_failures(self): # too many columns self.assertRaisesWithMessage(wiredtiger.WiredTigerError, lambda:self.session.create("table:main", "key_format=S," "value_format=,columns=(a,b)"), "/Number of columns in '\(a,b\)' does not match " "key format 'S' plus value format ''/") # Note: too few columns is allowed # expect this to work self.session.create("table:main", "key_format=iS,value_format=SiSi," "columns=(ikey,Skey,S1,i2,S3,i4)," "colgroups=(c1,c2)") # bad table name self.expect_failure_colgroup("nomatch:c", "columns=(S1,i2)", "/Can't create 'colgroup:nomatch:c'" " for non-existent table 'nomatch'/") # colgroup not declared in initial create self.expect_failure_colgroup("main:nomatch", "columns=(S1,i2)", "/Column group 'nomatch' not found" " in table 'main'/") # bad column self.expect_failure_colgroup("main:c1", "columns=(S1,i2,bad)", "/Column 'bad' not found/") # TODO: no columns allowed, or not? #self.session.create("colgroup:main:c0", "columns=()") # key in a column group self.expect_failure_colgroup("main:c1", "columns=(ikey,S1,i2)", "/A column group cannot store key column" " 'ikey' in its value/") # expect this to work self.session.create("colgroup:main:c1", "columns=(S1,i2)") # colgroup not declared in initial create self.expect_failure_colgroup("main:c3", "columns=(S3,i4)", "/Column group 'c3' not found in" " table 'main'/") # this is the last column group, but there are missing columns self.expect_failure_colgroup("main:c2", "columns=(S1,i4)", "/Column 'S3' in 'table:main' does not" " appear in a column group/") # TODO: is repartitioning column groups allowed? # this does not raise an error # self.expect_failure_colgroup("main:c2", "columns=(S1,S3,i4)" # expect this to work self.session.create("colgroup:main:c2", "columns=(S3,i4)") # expect these to work - each table name is a separate namespace self.session.create("table:main2", "key_format=iS,value_format=SiSi," "columns=(ikey,Skey,S1,i2,S3,i4),colgroups=(c1,c2)") self.session.create("colgroup:main2:c1", "columns=(S1,i2)") self.session.create("colgroup:main2:c2", "columns=(S3,i4)") def test_index(self): self.session.create("table:main", "key_format=iS,value_format=SiSi," "columns=(ikey,Skey,S1,i2,S3,i4),colgroups=(c1,c2)") # should be able to create colgroups before indices self.session.create("colgroup:main:c2", "columns=(S3,i4)") # should be able to create indices on all key combinations self.session.create( "index:main:ikey", "columns=(ikey)" + self.idx_config) self.session.create( "index:main:Skey", "columns=(Skey)" + self.idx_config) self.session.create( "index:main:ikeySkey", "columns=(ikey,Skey)" + self.idx_config) self.session.create( "index:main:Skeyikey", "columns=(Skey,ikey)" + self.idx_config) # should be able to create indices on all value combinations self.session.create( "index:main:S1", "columns=(S1)" + self.idx_config) self.session.create( "index:main:i2", "columns=(i2)" + self.idx_config) self.session.create( "index:main:i2S1", "columns=(i2,S1)" + self.idx_config) self.session.create( "index:main:S1i4", "columns=(S1,i4)" + self.idx_config) # somewhat nonsensical to repeat columns within an index, but allowed self.session.create( "index:main:i4S3i4S1", "columns=(i4,S3,i4,S1)" + self.idx_config) # should be able to create colgroups after indices self.session.create("colgroup:main:c1", "columns=(S1,i2)") self.populate() # should be able to create indices after populating self.session.create( "index:main:i2S1i4", "columns=(i2,S1,i4)" + self.idx_config) self.check_entries() def populate(self): cursor = self.session.open_cursor('table:main', None, None) for i in range(0, self.nentries): cursor.set_key(i, 'key' + str(i)) square = i * i cube = square * i cursor.set_value('val' + str(square), square, 'val' + str(cube), cube) cursor.insert() cursor.close() def check_entries(self): cursor = self.session.open_cursor('table:main', None, None) # spot check via search n = self.nentries for i in (n / 5, 0, n - 1, n - 2, 1): cursor.set_key(i, 'key' + str(i)) square = i * i cube = square * i cursor.search() (s1, i2, s3, i4) = cursor.get_values() self.assertEqual(s1, 'val' + str(square)) self.assertEqual(i2, square) self.assertEqual(s3, 'val' + str(cube)) self.assertEqual(i4, cube) i = 0 # then check all via cursor cursor.reset() for ikey, skey, s1, i2, s3, i4 in cursor: square = i * i cube = square * i self.assertEqual(ikey, i) self.assertEqual(skey, 'key' + str(i)) self.assertEqual(s1, 'val' + str(square)) self.assertEqual(i2, square) self.assertEqual(s3, 'val' + str(cube)) self.assertEqual(i4, cube) i += 1 cursor.close() self.assertEqual(i, n) def test_colgroups(self): self.session.create("table:main", "key_format=iS,value_format=SiSi," "columns=(ikey,Skey,S1,i2,S3,i4),colgroups=(c1,c2)") self.session.create("colgroup:main:c1", "columns=(S1,i2)") self.session.create("colgroup:main:c2", "columns=(S3,i4)") self.populate() self.check_entries()