1import unittest 2import os, glob 3 4from test_all import db, test_support, get_new_environment_path, \ 5 get_new_database_path 6 7#---------------------------------------------------------------------- 8 9class DBEnv(unittest.TestCase): 10 def setUp(self): 11 self.homeDir = get_new_environment_path() 12 self.env = db.DBEnv() 13 14 def tearDown(self): 15 self.env.close() 16 del self.env 17 test_support.rmtree(self.homeDir) 18 19class DBEnv_general(DBEnv) : 20 def test_get_open_flags(self) : 21 flags = db.DB_CREATE | db.DB_INIT_MPOOL 22 self.env.open(self.homeDir, flags) 23 self.assertEqual(flags, self.env.get_open_flags()) 24 25 def test_get_open_flags2(self) : 26 flags = db.DB_CREATE | db.DB_INIT_MPOOL | \ 27 db.DB_INIT_LOCK | db.DB_THREAD 28 self.env.open(self.homeDir, flags) 29 self.assertEqual(flags, self.env.get_open_flags()) 30 31 if db.version() >= (4, 7) : 32 def test_lk_partitions(self) : 33 for i in [10, 20, 40] : 34 self.env.set_lk_partitions(i) 35 self.assertEqual(i, self.env.get_lk_partitions()) 36 37 def test_getset_intermediate_dir_mode(self) : 38 self.assertEqual(None, self.env.get_intermediate_dir_mode()) 39 for mode in ["rwx------", "rw-rw-rw-", "rw-r--r--"] : 40 self.env.set_intermediate_dir_mode(mode) 41 self.assertEqual(mode, self.env.get_intermediate_dir_mode()) 42 self.assertRaises(db.DBInvalidArgError, 43 self.env.set_intermediate_dir_mode, "abcde") 44 45 if db.version() >= (4, 6) : 46 def test_thread(self) : 47 for i in [16, 100, 1000] : 48 self.env.set_thread_count(i) 49 self.assertEqual(i, self.env.get_thread_count()) 50 51 def test_cache_max(self) : 52 for size in [64, 128] : 53 size = size*1024*1024 # Megabytes 54 self.env.set_cache_max(0, size) 55 size2 = self.env.get_cache_max() 56 self.assertEqual(0, size2[0]) 57 self.assertLessEqual(size, size2[1]) 58 self.assertGreater(2*size, size2[1]) 59 60 if db.version() >= (4, 4) : 61 def test_mutex_stat(self) : 62 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | 63 db.DB_INIT_LOCK) 64 stat = self.env.mutex_stat() 65 self.assertIn("mutex_inuse_max", stat) 66 67 def test_lg_filemode(self) : 68 for i in [0600, 0660, 0666] : 69 self.env.set_lg_filemode(i) 70 self.assertEqual(i, self.env.get_lg_filemode()) 71 72 def test_mp_max_openfd(self) : 73 for i in [17, 31, 42] : 74 self.env.set_mp_max_openfd(i) 75 self.assertEqual(i, self.env.get_mp_max_openfd()) 76 77 def test_mp_max_write(self) : 78 for i in [100, 200, 300] : 79 for j in [1, 2, 3] : 80 j *= 1000000 81 self.env.set_mp_max_write(i, j) 82 v=self.env.get_mp_max_write() 83 self.assertEqual((i, j), v) 84 85 def test_invalid_txn(self) : 86 # This environment doesn't support transactions 87 self.assertRaises(db.DBInvalidArgError, self.env.txn_begin) 88 89 def test_mp_mmapsize(self) : 90 for i in [16, 32, 64] : 91 i *= 1024*1024 92 self.env.set_mp_mmapsize(i) 93 self.assertEqual(i, self.env.get_mp_mmapsize()) 94 95 def test_tmp_dir(self) : 96 for i in ["a", "bb", "ccc"] : 97 self.env.set_tmp_dir(i) 98 self.assertEqual(i, self.env.get_tmp_dir()) 99 100 def test_flags(self) : 101 self.env.set_flags(db.DB_AUTO_COMMIT, 1) 102 self.assertEqual(db.DB_AUTO_COMMIT, self.env.get_flags()) 103 self.env.set_flags(db.DB_TXN_NOSYNC, 1) 104 self.assertEqual(db.DB_AUTO_COMMIT | db.DB_TXN_NOSYNC, 105 self.env.get_flags()) 106 self.env.set_flags(db.DB_AUTO_COMMIT, 0) 107 self.assertEqual(db.DB_TXN_NOSYNC, self.env.get_flags()) 108 self.env.set_flags(db.DB_TXN_NOSYNC, 0) 109 self.assertEqual(0, self.env.get_flags()) 110 111 def test_lk_max_objects(self) : 112 for i in [1000, 2000, 3000] : 113 self.env.set_lk_max_objects(i) 114 self.assertEqual(i, self.env.get_lk_max_objects()) 115 116 def test_lk_max_locks(self) : 117 for i in [1000, 2000, 3000] : 118 self.env.set_lk_max_locks(i) 119 self.assertEqual(i, self.env.get_lk_max_locks()) 120 121 def test_lk_max_lockers(self) : 122 for i in [1000, 2000, 3000] : 123 self.env.set_lk_max_lockers(i) 124 self.assertEqual(i, self.env.get_lk_max_lockers()) 125 126 def test_lg_regionmax(self) : 127 for i in [128, 256, 1000] : 128 i = i*1024*1024 129 self.env.set_lg_regionmax(i) 130 j = self.env.get_lg_regionmax() 131 self.assertLessEqual(i, j) 132 self.assertGreater(2*i, j) 133 134 def test_lk_detect(self) : 135 flags= [db.DB_LOCK_DEFAULT, db.DB_LOCK_EXPIRE, db.DB_LOCK_MAXLOCKS, 136 db.DB_LOCK_MINLOCKS, db.DB_LOCK_MINWRITE, 137 db.DB_LOCK_OLDEST, db.DB_LOCK_RANDOM, db.DB_LOCK_YOUNGEST] 138 139 flags.append(db.DB_LOCK_MAXWRITE) 140 141 for i in flags : 142 self.env.set_lk_detect(i) 143 self.assertEqual(i, self.env.get_lk_detect()) 144 145 def test_lg_dir(self) : 146 for i in ["a", "bb", "ccc", "dddd"] : 147 self.env.set_lg_dir(i) 148 self.assertEqual(i, self.env.get_lg_dir()) 149 150 def test_lg_bsize(self) : 151 log_size = 70*1024 152 self.env.set_lg_bsize(log_size) 153 self.assertGreaterEqual(self.env.get_lg_bsize(), log_size) 154 self.assertLess(self.env.get_lg_bsize(), 4*log_size) 155 self.env.set_lg_bsize(4*log_size) 156 self.assertGreaterEqual(self.env.get_lg_bsize(), 4*log_size) 157 158 def test_setget_data_dirs(self) : 159 dirs = ("a", "b", "c", "d") 160 for i in dirs : 161 self.env.set_data_dir(i) 162 self.assertEqual(dirs, self.env.get_data_dirs()) 163 164 def test_setget_cachesize(self) : 165 cachesize = (0, 512*1024*1024, 3) 166 self.env.set_cachesize(*cachesize) 167 self.assertEqual(cachesize, self.env.get_cachesize()) 168 169 cachesize = (0, 1*1024*1024, 5) 170 self.env.set_cachesize(*cachesize) 171 cachesize2 = self.env.get_cachesize() 172 self.assertEqual(cachesize[0], cachesize2[0]) 173 self.assertEqual(cachesize[2], cachesize2[2]) 174 # Berkeley DB expands the cache 25% accounting overhead, 175 # if the cache is small. 176 self.assertEqual(125, int(100.0*cachesize2[1]/cachesize[1])) 177 178 # You can not change configuration after opening 179 # the environment. 180 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) 181 cachesize = (0, 2*1024*1024, 1) 182 self.assertRaises(db.DBInvalidArgError, 183 self.env.set_cachesize, *cachesize) 184 cachesize3 = self.env.get_cachesize() 185 self.assertEqual(cachesize2[0], cachesize3[0]) 186 self.assertEqual(cachesize2[2], cachesize3[2]) 187 # In Berkeley DB 5.1, the cachesize can change when opening the Env 188 self.assertLessEqual(cachesize2[1], cachesize3[1]) 189 190 def test_set_cachesize_dbenv_db(self) : 191 # You can not configure the cachesize using 192 # the database handle, if you are using an environment. 193 d = db.DB(self.env) 194 self.assertRaises(db.DBInvalidArgError, 195 d.set_cachesize, 0, 1024*1024, 1) 196 197 def test_setget_shm_key(self) : 198 shm_key=137 199 self.env.set_shm_key(shm_key) 200 self.assertEqual(shm_key, self.env.get_shm_key()) 201 self.env.set_shm_key(shm_key+1) 202 self.assertEqual(shm_key+1, self.env.get_shm_key()) 203 204 # You can not change configuration after opening 205 # the environment. 206 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) 207 # If we try to reconfigure cache after opening the 208 # environment, core dump. 209 self.assertRaises(db.DBInvalidArgError, 210 self.env.set_shm_key, shm_key) 211 self.assertEqual(shm_key+1, self.env.get_shm_key()) 212 213 if db.version() >= (4, 4) : 214 def test_mutex_setget_max(self) : 215 v = self.env.mutex_get_max() 216 v2 = v*2+1 217 218 self.env.mutex_set_max(v2) 219 self.assertEqual(v2, self.env.mutex_get_max()) 220 221 self.env.mutex_set_max(v) 222 self.assertEqual(v, self.env.mutex_get_max()) 223 224 # You can not change configuration after opening 225 # the environment. 226 self.env.open(self.homeDir, db.DB_CREATE) 227 self.assertRaises(db.DBInvalidArgError, 228 self.env.mutex_set_max, v2) 229 230 def test_mutex_setget_increment(self) : 231 v = self.env.mutex_get_increment() 232 v2 = 127 233 234 self.env.mutex_set_increment(v2) 235 self.assertEqual(v2, self.env.mutex_get_increment()) 236 237 self.env.mutex_set_increment(v) 238 self.assertEqual(v, self.env.mutex_get_increment()) 239 240 # You can not change configuration after opening 241 # the environment. 242 self.env.open(self.homeDir, db.DB_CREATE) 243 self.assertRaises(db.DBInvalidArgError, 244 self.env.mutex_set_increment, v2) 245 246 def test_mutex_setget_tas_spins(self) : 247 self.env.mutex_set_tas_spins(0) # Default = BDB decides 248 v = self.env.mutex_get_tas_spins() 249 v2 = v*2+1 250 251 self.env.mutex_set_tas_spins(v2) 252 self.assertEqual(v2, self.env.mutex_get_tas_spins()) 253 254 self.env.mutex_set_tas_spins(v) 255 self.assertEqual(v, self.env.mutex_get_tas_spins()) 256 257 # In this case, you can change configuration 258 # after opening the environment. 259 self.env.open(self.homeDir, db.DB_CREATE) 260 self.env.mutex_set_tas_spins(v2) 261 262 def test_mutex_setget_align(self) : 263 v = self.env.mutex_get_align() 264 v2 = 64 265 if v == 64 : 266 v2 = 128 267 268 self.env.mutex_set_align(v2) 269 self.assertEqual(v2, self.env.mutex_get_align()) 270 271 # Requires a nonzero power of two 272 self.assertRaises(db.DBInvalidArgError, 273 self.env.mutex_set_align, 0) 274 self.assertRaises(db.DBInvalidArgError, 275 self.env.mutex_set_align, 17) 276 277 self.env.mutex_set_align(2*v2) 278 self.assertEqual(2*v2, self.env.mutex_get_align()) 279 280 # You can not change configuration after opening 281 # the environment. 282 self.env.open(self.homeDir, db.DB_CREATE) 283 self.assertRaises(db.DBInvalidArgError, 284 self.env.mutex_set_align, v2) 285 286 287class DBEnv_log(DBEnv) : 288 def setUp(self): 289 DBEnv.setUp(self) 290 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_LOG) 291 292 def test_log_file(self) : 293 log_file = self.env.log_file((1, 1)) 294 self.assertEqual("log.0000000001", log_file[-14:]) 295 296 if db.version() >= (4, 4) : 297 # The version with transactions is checked in other test object 298 def test_log_printf(self) : 299 msg = "This is a test..." 300 self.env.log_printf(msg) 301 logc = self.env.log_cursor() 302 self.assertIn(msg, logc.last()[1]) 303 304 if db.version() >= (4, 7) : 305 def test_log_config(self) : 306 self.env.log_set_config(db.DB_LOG_DSYNC | db.DB_LOG_ZERO, 1) 307 self.assertTrue(self.env.log_get_config(db.DB_LOG_DSYNC)) 308 self.assertTrue(self.env.log_get_config(db.DB_LOG_ZERO)) 309 self.env.log_set_config(db.DB_LOG_ZERO, 0) 310 self.assertTrue(self.env.log_get_config(db.DB_LOG_DSYNC)) 311 self.assertFalse(self.env.log_get_config(db.DB_LOG_ZERO)) 312 313 314class DBEnv_log_txn(DBEnv) : 315 def setUp(self): 316 DBEnv.setUp(self) 317 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | 318 db.DB_INIT_LOG | db.DB_INIT_TXN) 319 320 if (db.version() >= (4, 5)) and (db.version() < (5, 2)) : 321 def test_tx_max(self) : 322 txns=[] 323 def tx() : 324 for i in xrange(self.env.get_tx_max()) : 325 txns.append(self.env.txn_begin()) 326 327 tx() 328 self.assertRaises(MemoryError, tx) 329 330 # Abort the transactions before garbage collection, 331 # to avoid "warnings". 332 for i in txns : 333 i.abort() 334 335 if db.version() >= (4, 4) : 336 # The version without transactions is checked in other test object 337 def test_log_printf(self) : 338 msg = "This is a test..." 339 txn = self.env.txn_begin() 340 self.env.log_printf(msg, txn=txn) 341 txn.commit() 342 logc = self.env.log_cursor() 343 logc.last() # Skip the commit 344 self.assertIn(msg, logc.prev()[1]) 345 346 msg = "This is another test..." 347 txn = self.env.txn_begin() 348 self.env.log_printf(msg, txn=txn) 349 txn.abort() # Do not store the new message 350 logc.last() # Skip the abort 351 self.assertNotIn(msg, logc.prev()[1]) 352 353 msg = "This is a third test..." 354 txn = self.env.txn_begin() 355 self.env.log_printf(msg, txn=txn) 356 txn.commit() # Do not store the new message 357 logc.last() # Skip the commit 358 self.assertIn(msg, logc.prev()[1]) 359 360 361class DBEnv_memp(DBEnv): 362 def setUp(self): 363 DBEnv.setUp(self) 364 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_LOG) 365 self.db = db.DB(self.env) 366 self.db.open("test", db.DB_HASH, db.DB_CREATE, 0660) 367 368 def tearDown(self): 369 self.db.close() 370 del self.db 371 DBEnv.tearDown(self) 372 373 def test_memp_1_trickle(self) : 374 self.db.put("hi", "bye") 375 self.assertGreater(self.env.memp_trickle(100), 0) 376 377# Preserve the order, do "memp_trickle" test first 378 def test_memp_2_sync(self) : 379 self.db.put("hi", "bye") 380 self.env.memp_sync() # Full flush 381 # Nothing to do... 382 self.assertEqual(self.env.memp_trickle(100), 0) 383 384 self.db.put("hi", "bye2") 385 self.env.memp_sync((1, 0)) # NOP, probably 386 # Something to do... or not 387 self.assertGreaterEqual(self.env.memp_trickle(100), 0) 388 389 self.db.put("hi", "bye3") 390 self.env.memp_sync((123, 99)) # Full flush 391 # Nothing to do... 392 self.assertEqual(self.env.memp_trickle(100), 0) 393 394 def test_memp_stat_1(self) : 395 stats = self.env.memp_stat() # No param 396 self.assertEqual(len(stats), 2) 397 self.assertIn("cache_miss", stats[0]) 398 stats = self.env.memp_stat(db.DB_STAT_CLEAR) # Positional param 399 self.assertIn("cache_miss", stats[0]) 400 stats = self.env.memp_stat(flags=0) # Keyword param 401 self.assertIn("cache_miss", stats[0]) 402 403 def test_memp_stat_2(self) : 404 stats=self.env.memp_stat()[1] 405 self.assertEqual(len(stats), 1) 406 self.assertIn("test", stats) 407 self.assertIn("page_in", stats["test"]) 408 409class DBEnv_logcursor(DBEnv): 410 def setUp(self): 411 DBEnv.setUp(self) 412 self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | 413 db.DB_INIT_LOG | db.DB_INIT_TXN) 414 txn = self.env.txn_begin() 415 self.db = db.DB(self.env) 416 self.db.open("test", db.DB_HASH, db.DB_CREATE, 0660, txn=txn) 417 txn.commit() 418 for i in ["2", "8", "20"] : 419 txn = self.env.txn_begin() 420 self.db.put(key = i, data = i*int(i), txn=txn) 421 txn.commit() 422 423 def tearDown(self): 424 self.db.close() 425 del self.db 426 DBEnv.tearDown(self) 427 428 def _check_return(self, value) : 429 self.assertIsInstance(value, tuple) 430 self.assertEqual(len(value), 2) 431 self.assertIsInstance(value[0], tuple) 432 self.assertEqual(len(value[0]), 2) 433 self.assertIsInstance(value[0][0], int) 434 self.assertIsInstance(value[0][1], int) 435 self.assertIsInstance(value[1], str) 436 437 # Preserve test order 438 def test_1_first(self) : 439 logc = self.env.log_cursor() 440 v = logc.first() 441 self._check_return(v) 442 self.assertLess((1, 1), v[0]) 443 self.assertGreater(len(v[1]), 0) 444 445 def test_2_last(self) : 446 logc = self.env.log_cursor() 447 lsn_first = logc.first()[0] 448 v = logc.last() 449 self._check_return(v) 450 self.assertLess(lsn_first, v[0]) 451 452 def test_3_next(self) : 453 logc = self.env.log_cursor() 454 lsn_last = logc.last()[0] 455 self.assertEqual(logc.next(), None) 456 lsn_first = logc.first()[0] 457 v = logc.next() 458 self._check_return(v) 459 self.assertLess(lsn_first, v[0]) 460 self.assertGreater(lsn_last, v[0]) 461 462 v2 = logc.next() 463 self.assertGreater(v2[0], v[0]) 464 self.assertGreater(lsn_last, v2[0]) 465 466 v3 = logc.next() 467 self.assertGreater(v3[0], v2[0]) 468 self.assertGreater(lsn_last, v3[0]) 469 470 def test_4_prev(self) : 471 logc = self.env.log_cursor() 472 lsn_first = logc.first()[0] 473 self.assertEqual(logc.prev(), None) 474 lsn_last = logc.last()[0] 475 v = logc.prev() 476 self._check_return(v) 477 self.assertLess(lsn_first, v[0]) 478 self.assertGreater(lsn_last, v[0]) 479 480 v2 = logc.prev() 481 self.assertLess(v2[0], v[0]) 482 self.assertLess(lsn_first, v2[0]) 483 484 v3 = logc.prev() 485 self.assertLess(v3[0], v2[0]) 486 self.assertLess(lsn_first, v3[0]) 487 488 def test_5_current(self) : 489 logc = self.env.log_cursor() 490 logc.first() 491 v = logc.next() 492 self.assertEqual(v, logc.current()) 493 494 def test_6_set(self) : 495 logc = self.env.log_cursor() 496 logc.first() 497 v = logc.next() 498 self.assertNotEqual(v, logc.next()) 499 self.assertNotEqual(v, logc.next()) 500 self.assertEqual(v, logc.set(v[0])) 501 502 def test_explicit_close(self) : 503 logc = self.env.log_cursor() 504 logc.close() 505 self.assertRaises(db.DBCursorClosedError, logc.next) 506 507 def test_implicit_close(self) : 508 logc = [self.env.log_cursor() for i in xrange(10)] 509 self.env.close() # This close should close too all its tree 510 for i in logc : 511 self.assertRaises(db.DBCursorClosedError, i.next) 512 513def test_suite(): 514 suite = unittest.TestSuite() 515 516 suite.addTest(unittest.makeSuite(DBEnv_general)) 517 suite.addTest(unittest.makeSuite(DBEnv_memp)) 518 suite.addTest(unittest.makeSuite(DBEnv_logcursor)) 519 suite.addTest(unittest.makeSuite(DBEnv_log)) 520 suite.addTest(unittest.makeSuite(DBEnv_log_txn)) 521 522 return suite 523 524if __name__ == '__main__': 525 unittest.main(defaultTest='test_suite') 526