def test_max_dbs(self): self.assertRaises(OverflowError, lambda: testlib.temp_env(max_dbs=-1)) for val in 0, 10, 20: _, env = testlib.temp_env(max_dbs=val) dbs = [env.open_db(B('db%d' % i)) for i in range(val)] self.assertRaises(lmdb.DbsFullError, lambda: env.open_db(B('toomany')))
def test_integerdup(self): _, env = testlib.temp_env() db1 = env.open_db(B('db1'), dupsort=True, integerdup=True) txn = env.begin(write=True, db=db1) assert txn.put(UINT_0001, UINT_0002) assert txn.put(UINT_0001, UINT_0001) assert txn.get(UINT_0001) == UINT_0001
def test_dupsort(self): _, env = testlib.temp_env() db1 = env.open_db(B('db1'), dupsort=True) txn = env.begin(write=True, db=db1) assert txn.put(B('a'), B('a')) assert txn.put(B('a'), B('b')) assert txn.get(B('a')) == B('a')
def test_reader_check(self): path, env = testlib.temp_env(max_spare_txns=0) rc = env.reader_check() assert rc == 0 # We need to open a separate env since Transaction.abort() always calls # reset for a read-only txn, the actual abort doesn't happen until # __del__, when Transaction discovers there is no room for it on the # freelist. env1 = lmdb.open(path) txn1 = env1.begin() assert env.readers() != NO_READERS assert env.reader_check() == 0 # Start a child, open a txn, then crash the child. rc = os.spawnl(os.P_WAIT, sys.executable, sys.executable, __file__, 'test_reader_check_child', path) assert rc == 0 assert env.reader_check() == 1 assert env.reader_check() == 0 assert env.readers() != NO_READERS txn1.abort() env1.close() assert env.readers() == NO_READERS env.close() self.assertRaises(Exception, lambda: env.reader_check())
def test_big_reverse(self): path, env = testlib.temp_env() txn = env.begin(write=True) keys = [B('%05d' % i) for i in range(0xffff)] for k in keys: txn.put(k, k, append=True) assert list(txn.cursor().iterprev(values=False)) == list(reversed(keys))
def test_readonly(self): _, env = testlib.temp_env() txn = lmdb.Transaction(env) # Read txn can't write. self.assertRaises(lmdb.ReadonlyError, lambda: txn.put(B('a'), B(''))) txn.abort()
def test_subdir_false_ok(self): path = testlib.temp_file(create=False) _, env = testlib.temp_env(path, subdir=False) assert os.path.exists(path) assert os.path.isfile(path) assert os.path.isfile(path + '-lock') assert not env.flags()['subdir']
def test_begin_readonly(self): _, env = testlib.temp_env() txn = env.begin() # Read txn can't write. self.assertRaises(lmdb.ReadonlyError, lambda: txn.put(B('a'), B(''))) txn.abort()
def test_reader_check(self): path, env = testlib.temp_env() rc = env.reader_check() assert rc == 0 txn1 = env.begin() assert env.readers() != NO_READERS assert env.reader_check() == 0 # Start a child, open a txn, then crash the child. child_pid = os.fork() if not child_pid: env2 = lmdb.open(path) txn = env2.begin() os.kill(os.getpid(), signal.SIGKILL) assert os.waitpid(child_pid, 0) == (child_pid, signal.SIGKILL) assert env.reader_check() == 1 assert env.reader_check() == 0 assert env.readers() != NO_READERS txn1.abort() assert env.readers() == NO_READERS env.close() self.assertRaises(Exception, lambda: env.reader_check())
def test_readonly_false(self): path, env = testlib.temp_env(readonly=False) with env.begin(write=True) as txn: txn.put(B('a'), B('')) with env.begin() as txn: assert txn.get(B('a')) == B('') assert not env.flags()['readonly']
def test_one(self): _, env = testlib.temp_env(max_spare_txns=1) # 1 here, since CFFI uses a temporary reader during init. assert 1 >= reader_count(env) t1 = env.begin() assert 1 == reader_count(env) t2 = env.begin() assert 2 == reader_count(env) t1.abort() del t1 assert 2 == reader_count(env) # 1 live, 1 cached t2.abort() del t2 assert 1 == reader_count(env) # 1 cached t3 = env.begin() assert 1 == reader_count(env) # 1 live t3.abort() del t3 assert 1 == reader_count(env) # 1 cached
def test_ok(self): path, env = testlib.temp_env() with env as env_: assert env_ is env with env.begin() as txn: txn.get(B('foo')) self.assertRaises(Exception, lambda: env.begin())
def test_sync(self): _, env = testlib.temp_env() env.sync(False) env.sync(True) env.close() self.assertRaises(Exception, lambda: env.sync(False))
def test_abort_rw(self): _, env = testlib.temp_env() txn = env.begin(write=True) assert txn.put(B('a'), B('a')) txn.abort() txn = env.begin() assert txn.get(B('a')) is None
def test_stat(self): _, env = testlib.temp_env() db1 = env.open_db(B('db1')) db2 = env.open_db(B('db2')) txn = lmdb.Transaction(env) for db in db1, db2: stat = txn.stat(db) for k in 'psize', 'depth', 'branch_pages', 'overflow_pages',\ 'entries': assert isinstance(stat[k], INT_TYPES), k assert stat[k] >= 0 assert stat['entries'] == 0 txn = lmdb.Transaction(env, write=True) txn.put(B('a'), B('b'), db=db1) txn.commit() txn = lmdb.Transaction(env) stat = txn.stat(db1) assert stat['entries'] == 1 stat = txn.stat(db2) assert stat['entries'] == 0 txn.abort() self.assertRaises(Exception, lambda: env.stat(db1)) env.close() self.assertRaises(Exception, lambda: env.stat(db1))
def test_readonly_env_sub_eperm(self): # https://github.com/dw/py-lmdb/issues/109 path, env = testlib.temp_env() env.close() env = lmdb.open(path, max_dbs=10, readonly=True) self.assertRaises(lmdb.ReadonlyError, lambda: env.open_db(B('node_schedules'), create=True))
def test_sub_txn(self): _, env = testlib.temp_env() txn = env.begin(write=True) db1 = env.open_db(B('subdb1'), txn=txn) db2 = env.open_db(B('subdb2'), txn=txn) for db in db1, db2: assert db.flags(txn) == {'reverse_key': False, 'dupsort': False} txn.commit()
def test_integerkey(self): _, env = testlib.temp_env() db1 = env.open_db(B('db1'), integerkey=True) txn = env.begin(write=True, db=db1) assert txn.put(UINT_0001, B('a')) assert txn.put(UINT_0002, B('b')) assert txn.get(UINT_0001) == B('a') assert txn.get(UINT_0002) == B('b')
def test_path(self): path, env = testlib.temp_env() assert path == env.path() assert isinstance(env.path(), UnicodeType) env.close() self.assertRaises(Exception, lambda: env.path())
def setUp(self): self.path, self.env = testlib.temp_env() db = self.env.open_db(B("db1"), dupsort=True) self.txn = self.env.begin(db, write=True) for _ in range(2): putData(self.txn) self.c = self.txn.cursor() self.empty_entry = ("", "")
def test_max_readers(self): _, env = testlib.temp_env() mr = env.max_readers() assert isinstance(mr, INT_TYPES) assert mr > 0 and mr == env.info()['max_readers'] env.close() self.assertRaises(Exception, lambda: env.max_readers())
def test_readonly_env_sub(self): # https://github.com/dw/py-lmdb/issues/109 path, env = testlib.temp_env() assert env.open_db(B('node_schedules')) is not None env.close() env = lmdb.open(path, max_dbs=10, readonly=True) db = env.open_db(B('node_schedules'), create=False) assert db is not None
def test_max_key_size(self): _, env = testlib.temp_env() mks = env.max_key_size() assert isinstance(mks, INT_TYPES) assert mks > 0 env.close() self.assertRaises(Exception, lambda: env.max_key_size())
def test_readonly_true_exist(self): path, env = testlib.temp_env() env2 = lmdb.open(path, readonly=True) assert env2.path() == path # Attempting a write txn should fail. self.assertRaises(lmdb.ReadonlyError, lambda: env2.begin(write=True)) # Flag should be set. assert env2.flags()['readonly']
def test_flags(self): _, env = testlib.temp_env() info = env.flags() for k in 'subdir', 'readonly', 'metasync', 'sync', 'map_async',\ 'readahead', 'writemap': assert isinstance(info[k], bool) env.close() self.assertRaises(Exception, lambda: env.flags())
def test_abort_ro(self): _, env = testlib.temp_env() txn = env.begin() assert txn.get(B('a')) is None txn.abort() self.assertRaises(Exception, lambda: txn.get(B('a'))) env.close() self.assertRaises(Exception, lambda: txn.get(B('a')))
def test_crash(self): path, env = testlib.temp_env() try: with env as env_: assert env_ is env with env.begin() as txn: txn.get(123) except: pass self.assertRaises(Exception, lambda: env.begin())
def test_dupsort_noexist(self): _, env = testlib.temp_env() db = env.open_db(B('db1'), dupsort=True) txn = env.begin(write=True, db=db) assert None == txn.replace(B('a'), B('x')) assert B('x') == txn.replace(B('a'), B('y')) assert B('y') == txn.replace(B('a'), B('z')) cur = txn.cursor() assert cur.set_key(B('a')) assert [B('z')] == list(cur.iternext_dup())
def test_crash(self): path, env = testlib.temp_env() txn = env.begin(write=True) try: with txn.cursor() as curs: curs.put(123, 123) except: pass self.assertRaises(Exception, lambda: curs.get(B('foo')))
def test_python3_iternext_segfault(self): # https://github.com/dw/py-lmdb/issues/105 _, env = testlib.temp_env() txn = env.begin() cur = txn.cursor() ite = cur.iternext() nex = getattr(ite, 'next', getattr(ite, '__next__', None)) assert nex is not None self.assertRaises(StopIteration, nex)
def test_readers(self): _, env = testlib.temp_env(max_spare_txns=0) r = env.readers() assert isinstance(r, UnicodeType) assert r == NO_READERS rtxn = env.begin() r2 = env.readers() assert isinstance(env.readers(), UnicodeType) assert env.readers() != r env.close() self.assertRaises(Exception, lambda: env.readers())
def test_bind_db_methods(self): _, env = testlib.temp_env() maindb = env.open_db(None) db1 = env.open_db(B('d1')) txn = lmdb.Transaction(env, write=True, db=db1) assert txn.put(B('a'), B('d1')) assert txn.get(B('a'), db=db1) == B('d1') assert txn.get(B('a'), db=maindb) is None assert txn.replace(B('a'), B('d11')) == B('d1') assert txn.pop(B('a')) == B('d11') assert txn.put(B('a'), B('main'), db=maindb, overwrite=False) assert not txn.delete(B('a')) txn.abort()
def test_sub_txn(self): _, env = testlib.temp_env() txn = env.begin(write=True) db1 = env.open_db(B('subdb1'), txn=txn) db2 = env.open_db(B('subdb2'), txn=txn) for db in db1, db2: assert db.flags(txn) == { 'dupfixed': False, 'dupsort': False, 'integerdup': False, 'integerkey': False, 'reverse_key': False, } txn.commit()
def test_crash(self): path, env = testlib.temp_env() txn = env.begin(write=True) try: with txn as txn_: txn.put(B('foo'), B('123')) txn.put(123, 123) except: pass self.assertRaises(Exception, lambda: txn.get(B('foo'))) with env.begin() as txn: assert txn.get(B('foo')) is None
def test_copy_compact(self): _, env = testlib.temp_env() txn = env.begin(write=True) txn.put(B('a'), B('b')) txn.commit() dest_dir = testlib.temp_dir() env.copy(dest_dir, compact=True) assert os.path.exists(dest_dir + '/data.mdb') cenv = lmdb.open(dest_dir) ctxn = cenv.begin() assert ctxn.get(B('a')) == B('b') env.close() self.assertRaises(Exception, lambda: env.copy(testlib.temp_dir()))
def test_bind_db(self): _, env = testlib.temp_env() main = env.open_db(None) sub = env.open_db(B('db1')) txn = lmdb.Transaction(env, write=True, db=sub) assert txn.put(B('b'), B('')) # -> sub assert txn.put(B('a'), B(''), db=main) # -> main txn.commit() txn = lmdb.Transaction(env) assert txn.get(B('a')) == B('') assert txn.get(B('b')) is None assert txn.get(B('a'), db=sub) is None assert txn.get(B('b'), db=sub) == B('') txn.abort()
def test_buffers(self): _, env = testlib.temp_env() txn = env.begin(write=True, buffers=True) assert txn.put(B('a'), B('a')) b = txn.get(B('a')) assert b is not None assert len(b) == 1 assert not isinstance(b, type(B(''))) txn.commit() txn = env.begin(buffers=False) b = txn.get(B('a')) assert b is not None assert len(b) == 1 assert isinstance(b, type(B(''))) txn.abort()
def test_bind_db(self): _, env = testlib.temp_env() main = env.open_db(None) self.assertRaises(ValueError, lambda: env.open_db(None, dupsort=True)) sub = env.open_db(B('db1')) txn = env.begin(write=True, db=sub) assert txn.put(B('b'), B('')) # -> sub assert txn.put(B('a'), B(''), db=main) # -> main txn.commit() txn = env.begin() assert txn.get(B('a')) == B('') assert txn.get(B('b')) is None assert txn.get(B('a'), db=sub) is None assert txn.get(B('b'), db=sub) == B('') txn.abort()
def test_copyfd_compact(self): path, env = testlib.temp_env() txn = env.begin(write=True) txn.put(B('a'), B('b')) txn.commit() dst_path = testlib.temp_file(create=False) fp = open(dst_path, 'wb') env.copyfd(fp.fileno(), compact=True) dstenv = lmdb.open(dst_path, subdir=False) dtxn = dstenv.begin() assert dtxn.get(B('a')) == B('b') env.close() self.assertRaises(Exception, lambda: env.copyfd(fp.fileno())) fp.close()
def test_stat(self): _, env = testlib.temp_env() stat = env.stat() for k in 'psize', 'depth', 'branch_pages', 'overflow_pages',\ 'entries': assert isinstance(stat[k], INT_TYPES), k assert stat[k] >= 0 assert stat['entries'] == 0 txn = env.begin(write=True) txn.put(B('a'), B('b')) txn.commit() stat = env.stat() assert stat['entries'] == 1 env.close() self.assertRaises(Exception, lambda: env.stat())
def test_info(self): _, env = testlib.temp_env() info = env.info() for k in 'map_addr', 'map_size', 'last_pgno', 'last_txnid', \ 'max_readers', 'num_readers': assert isinstance(info[k], INT_TYPES), k assert info[k] >= 0 assert info['last_txnid'] == 0 txn = env.begin(write=True) txn.put(B('a'), B('')) txn.commit() info = env.info() assert info['last_txnid'] == 1 env.close() self.assertRaises(Exception, lambda: env.info())
def test_none(self): _, env = testlib.temp_env(max_spare_txns=0) assert 0 == reader_count(env) t1 = env.begin() assert 1 == reader_count(env) t2 = env.begin() assert 2 == reader_count(env) t1.abort() del t1 assert 1 == reader_count(env) t2.abort() del t2 assert 0 == reader_count(env)
def test_17bf75b12eb94d9903cd62329048b146d5313bad(self): """ me_txn0 previously cached MDB_TXN_ERROR permanently. Fixed by 17bf75b12eb94d9903cd62329048b146d5313bad. """ path, env = testlib.temp_env(map_size=4096 * 9, sync=False, max_spare_txns=0) for i in itertools.count(): try: with env.begin(write=True) as txn: txn.put(B(str(i)), B(str(i))) except lmdb.MapFullError: break # Should not crash with MDB_BAD_TXN: with env.begin(write=True) as txn: txn.delete(B('1'))
def test_opendb_resize(self): ''' Test that we correctly handle a MDB_MAP_RESIZED in env.open_db. Would seg fault in cffi implementation ''' mpctx = multiprocessing.get_context('spawn') path, env = testlib.temp_env(max_dbs=10, map_size=MINDBSIZE) env.close() env = lmdb.open(path, max_dbs=10, map_size=MINDBSIZE, readonly=True) proc = mpctx.Process(target=self.do_resize, args=(path, )) proc.start() proc.join(5) assert proc.exitcode is not None self.assertRaises(lmdb.MapResizedError, env.open_db, b'foo')
def test_cursor_open_failure(self): ''' Test the error path for when mdb_cursor_open fails Note: this only would crash if cpython is built with Py_TRACE_REFS ''' # https://github.com/jnwatson/py-lmdb/issues/216 path, env = testlib.temp_env() db = env.open_db(b'db', dupsort=True) env.close() del env env = lmdb.open(path, readonly=True, max_dbs=4) txn1 = env.begin(write=False) db = env.open_db(b'db', dupsort=True, txn=txn1) txn2 = env.begin(write=False) self.assertRaises(lmdb.InvalidParameterError, txn2.cursor, db=db)
def test_flags(self): path, env = testlib.temp_env() txn = env.begin(write=True) for flag, val in self.FLAG_SETS: key = B('%s-%s' % (flag, val)) db = env.open_db(key, txn=txn, **{flag: val}) assert db.flags(txn)[flag] == val txn.commit() # Test flag persistence. env.close() env = lmdb.open(path, max_dbs=10) txn = env.begin(write=True) for flag, val in self.FLAG_SETS: key = B('%s-%s' % (flag, val)) db = env.open_db(key, txn=txn) assert db.flags(txn)[flag] == val
def test_parent(self): _, env = testlib.temp_env() parent = env.begin(write=True) parent.put(B('a'), B('a')) child = env.begin(write=True, parent=parent) assert child.get(B('a')) == B('a') assert child.put(B('a'), B('b')) child.abort() # put() should have rolled back assert parent.get(B('a')) == B('a') child = env.begin(write=True, parent=parent) assert child.put(B('a'), B('b')) child.commit() # put() should be visible assert parent.get(B('a')) == B('b')
def test_copyfd_compact(self): path, env = testlib.temp_env() txn = env.begin(write=True) txn.put(B('a'), B('b')) txn.commit() dst_path = testlib.temp_file(create=False) fp = open(dst_path, 'wb') env.copyfd(fp.fileno()) dstenv = lmdb.open(dst_path, subdir=False) dtxn = dstenv.begin() assert dtxn.get(B('a')) == B('b') fp.close() # Test copy with transaction provided dst_path = testlib.temp_file(create=False) fp = open(dst_path, 'wb') with env.begin(write=True) as txn: copy_txn = env.begin() txn.put(B('b'), B('b')) assert dtxn.get(B('b')) is None if have_txn_patch: env.copyfd(fp.fileno(), compact=True, txn=copy_txn) dstenv = lmdb.open(dst_path, subdir=False) dtxn = dstenv.begin() assert dtxn.get(B('a')) == B('b') # Verify that the write that occurred outside the txn isn't seen in the # copy assert dtxn.get(B('b')) is None dstenv.close() else: self.assertRaises( Exception, lambda: env.copyfd(fp.fileno(), compact=True, txn=copy_txn)) env.close() self.assertRaises(Exception, lambda: env.copyfd(fp.fileno())) fp.close()
def test_db(self): _, env = testlib.temp_env() maindb = env.open_db(None) db1 = env.open_db(B('db1')) txn = env.begin() assert txn.get(B('a'), db=db1) is None txn.abort() txn = env.begin(write=True) txn.put(B('a'), B('a'), db=db1) txn.commit() txn = env.begin() assert txn.get(B('a')) is None txn.abort() txn = env.begin(db=db1) assert txn.get(B('a')) == B('a') assert txn.get(B('a'), db=maindb) is None
def test_double_delete(self): _, env = testlib.temp_env() db1 = env.open_db(B('db1')) txn = env.begin(write=True, db=db1) txn.put(B('a'), B('a'), db=db1) txn.drop(db1) self.assertRaises(lmdb.InvalidParameterError, lambda: txn.get(B('a'), db=db1)) self.assertRaises(lmdb.InvalidParameterError, lambda: txn.drop(db1)) txn.commit() db1 = env.open_db(B('db1')) txn = env.begin(write=True, db=db1) txn.put(B('a'), B('a'), db=db1) txn.drop(db1) self.assertRaises(lmdb.InvalidParameterError, lambda: txn.get(B('a'), db=db1)) self.assertRaises(lmdb.InvalidParameterError, lambda: txn.drop(db1)) txn.commit()
def test_multiput_segfault(self): # http://github.com/jnwatson/py-lmdb/issues/173 _, env = testlib.temp_env() db = env.open_db(b'foo', dupsort=True) txn = env.begin(db=db, write=True) txn.put(b'a', b'\x00\x00\x00\x00\x00\x00\x00\x00') txn.put(b'a', b'\x05') txn.put(b'a', b'\t') txn.put(b'a', b'\r') txn.put(b'a', b'\x11') txn.put(b'a', b'\x15') txn.put(b'a', b'\x19') txn.put(b'a', b'\x1d') txn.put(b'a', b'!') txn.put(b'a', b'%') txn.put(b'a', b')') txn.put(b'a', b'-') txn.put(b'a', b'1') txn.put(b'a', b'5') txn.commit()
def test_copy_compact(self): _, env = testlib.temp_env() txn = env.begin(write=True) txn.put(B('a'), B('b')) txn.commit() dest_dir = testlib.temp_dir() env.copy(dest_dir, compact=True) assert os.path.exists(dest_dir + '/data.mdb') cenv = lmdb.open(dest_dir) ctxn = cenv.begin() assert ctxn.get(B('a')) == B('b') # Test copy with transaction provided dest_dir = testlib.temp_dir() with env.begin(write=True) as txn: copy_txn = env.begin() txn.put(B('b'), B('b')) assert ctxn.get(B('b')) is None if have_txn_patch: env.copy(dest_dir, compact=True, txn=copy_txn) assert os.path.exists(dest_dir + '/data.mdb') cenv = lmdb.open(dest_dir) ctxn = cenv.begin() assert ctxn.get(B('a')) == B('b') # Verify that the write that occurred outside the txn isn't seen in the # copy assert ctxn.get(B('b')) is None else: self.assertRaises( Exception, lambda: env.copy(dest_dir, compact=True, txn=copy_txn)) env.close() self.assertRaises(Exception, lambda: env.copy(testlib.temp_dir()))
def test_close(self): _, env = testlib.temp_env() # Attempting things should be ok. txn = env.begin(write=True) txn.put(B('a'), B('')) cursor = txn.cursor() list(cursor) cursor.first() it = iter(cursor) env.close() # Repeated calls are ignored: env.close() # Attempting to use invalid objects should crash. self.assertRaises(Exception, lambda: txn.cursor()) self.assertRaises(Exception, lambda: txn.commit()) self.assertRaises(Exception, lambda: cursor.first()) self.assertRaises(Exception, lambda: list(it)) # Abort should be OK though. txn.abort() # Attempting to start new txn should crash. self.assertRaises(Exception, lambda: env.begin())
def setUp(self): self.path, self.env = testlib.temp_env() self.txn = self.env.begin(write=True) self.c = self.txn.cursor()
def test_ok(self): path, env = testlib.temp_env() txn = env.begin(write=True) with txn.cursor() as curs: curs.put(B('foo'), B('123')) self.assertRaises(Exception, lambda: curs.get(B('foo')))
def test_bad_size(self): self.assertRaises(OverflowError, lambda: testlib.temp_env(map_size=-123))
def test_readonly_env_main(self): path, env = testlib.temp_env() env.close() env = lmdb.open(path, readonly=True) db = env.open_db(None)
def test_reopen(self): path, env = testlib.temp_env() db1 = env.open_db(B('subdb1')) env.close() env = lmdb.open(path, max_dbs=10) db1 = env.open_db(B('subdb1'))
def test_ok_path(self): path, env = testlib.temp_env() assert os.path.exists(path) assert os.path.exists(os.path.join(path, 'data.mdb')) assert os.path.exists(os.path.join(path, 'lock.mdb')) assert env.path() == path
def test_sub_rotxn(self): _, env = testlib.temp_env() txn = env.begin(write=False) self.assertRaises(lmdb.ReadonlyError, lambda: env.open_db(B('subdb'), txn=txn))