1"""Test script for the dbm.open function based on testdumbdbm.py""" 2 3import unittest 4import glob 5import test.support 6 7# Skip tests if dbm module doesn't exist. 8dbm = test.support.import_module('dbm') 9 10try: 11 from dbm import ndbm 12except ImportError: 13 ndbm = None 14 15_fname = test.support.TESTFN 16 17# 18# Iterates over every database module supported by dbm currently available, 19# setting dbm to use each in turn, and yielding that module 20# 21def dbm_iterator(): 22 for name in dbm._names: 23 try: 24 mod = __import__(name, fromlist=['open']) 25 except ImportError: 26 continue 27 dbm._modules[name] = mod 28 yield mod 29 30# 31# Clean up all scratch databases we might have created during testing 32# 33def delete_files(): 34 # we don't know the precise name the underlying database uses 35 # so we use glob to locate all names 36 for f in glob.glob(glob.escape(_fname) + "*"): 37 test.support.unlink(f) 38 39 40class AnyDBMTestCase: 41 _dict = {'a': b'Python:', 42 'b': b'Programming', 43 'c': b'the', 44 'd': b'way', 45 'f': b'Guido', 46 'g': b'intended', 47 } 48 49 def init_db(self): 50 f = dbm.open(_fname, 'n') 51 for k in self._dict: 52 f[k.encode("ascii")] = self._dict[k] 53 f.close() 54 55 def keys_helper(self, f): 56 keys = sorted(k.decode("ascii") for k in f.keys()) 57 dkeys = sorted(self._dict.keys()) 58 self.assertEqual(keys, dkeys) 59 return keys 60 61 def test_error(self): 62 self.assertTrue(issubclass(self.module.error, OSError)) 63 64 def test_anydbm_not_existing(self): 65 self.assertRaises(dbm.error, dbm.open, _fname) 66 67 def test_anydbm_creation(self): 68 f = dbm.open(_fname, 'c') 69 self.assertEqual(list(f.keys()), []) 70 for key in self._dict: 71 f[key.encode("ascii")] = self._dict[key] 72 self.read_helper(f) 73 f.close() 74 75 def test_anydbm_creation_n_file_exists_with_invalid_contents(self): 76 # create an empty file 77 test.support.create_empty_file(_fname) 78 with dbm.open(_fname, 'n') as f: 79 self.assertEqual(len(f), 0) 80 81 def test_anydbm_modification(self): 82 self.init_db() 83 f = dbm.open(_fname, 'c') 84 self._dict['g'] = f[b'g'] = b"indented" 85 self.read_helper(f) 86 # setdefault() works as in the dict interface 87 self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo') 88 self.assertEqual(f[b'xxx'], b'foo') 89 f.close() 90 91 def test_anydbm_read(self): 92 self.init_db() 93 f = dbm.open(_fname, 'r') 94 self.read_helper(f) 95 # get() works as in the dict interface 96 self.assertEqual(f.get(b'a'), self._dict['a']) 97 self.assertEqual(f.get(b'xxx', b'foo'), b'foo') 98 self.assertIsNone(f.get(b'xxx')) 99 with self.assertRaises(KeyError): 100 f[b'xxx'] 101 f.close() 102 103 def test_anydbm_keys(self): 104 self.init_db() 105 f = dbm.open(_fname, 'r') 106 keys = self.keys_helper(f) 107 f.close() 108 109 def test_empty_value(self): 110 if getattr(dbm._defaultmod, 'library', None) == 'Berkeley DB': 111 self.skipTest("Berkeley DB doesn't distinguish the empty value " 112 "from the absent one") 113 f = dbm.open(_fname, 'c') 114 self.assertEqual(f.keys(), []) 115 f[b'empty'] = b'' 116 self.assertEqual(f.keys(), [b'empty']) 117 self.assertIn(b'empty', f) 118 self.assertEqual(f[b'empty'], b'') 119 self.assertEqual(f.get(b'empty'), b'') 120 self.assertEqual(f.setdefault(b'empty'), b'') 121 f.close() 122 123 def test_anydbm_access(self): 124 self.init_db() 125 f = dbm.open(_fname, 'r') 126 key = "a".encode("ascii") 127 self.assertIn(key, f) 128 assert(f[key] == b"Python:") 129 f.close() 130 131 def read_helper(self, f): 132 keys = self.keys_helper(f) 133 for key in self._dict: 134 self.assertEqual(self._dict[key], f[key.encode("ascii")]) 135 136 def tearDown(self): 137 delete_files() 138 139 def setUp(self): 140 dbm._defaultmod = self.module 141 delete_files() 142 143 144class WhichDBTestCase(unittest.TestCase): 145 def test_whichdb(self): 146 for module in dbm_iterator(): 147 # Check whether whichdb correctly guesses module name 148 # for databases opened with "module" module. 149 # Try with empty files first 150 name = module.__name__ 151 if name == 'dbm.dumb': 152 continue # whichdb can't support dbm.dumb 153 delete_files() 154 f = module.open(_fname, 'c') 155 f.close() 156 self.assertEqual(name, self.dbm.whichdb(_fname)) 157 # Now add a key 158 f = module.open(_fname, 'w') 159 f[b"1"] = b"1" 160 # and test that we can find it 161 self.assertIn(b"1", f) 162 # and read it 163 self.assertEqual(f[b"1"], b"1") 164 f.close() 165 self.assertEqual(name, self.dbm.whichdb(_fname)) 166 167 @unittest.skipUnless(ndbm, reason='Test requires ndbm') 168 def test_whichdb_ndbm(self): 169 # Issue 17198: check that ndbm which is referenced in whichdb is defined 170 db_file = '{}_ndbm.db'.format(_fname) 171 with open(db_file, 'w'): 172 self.addCleanup(test.support.unlink, db_file) 173 self.assertIsNone(self.dbm.whichdb(db_file[:-3])) 174 175 def tearDown(self): 176 delete_files() 177 178 def setUp(self): 179 delete_files() 180 self.filename = test.support.TESTFN 181 self.d = dbm.open(self.filename, 'c') 182 self.d.close() 183 self.dbm = test.support.import_fresh_module('dbm') 184 185 def test_keys(self): 186 self.d = dbm.open(self.filename, 'c') 187 self.assertEqual(self.d.keys(), []) 188 a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')] 189 for k, v in a: 190 self.d[k] = v 191 self.assertEqual(sorted(self.d.keys()), sorted(k for (k, v) in a)) 192 for k, v in a: 193 self.assertIn(k, self.d) 194 self.assertEqual(self.d[k], v) 195 self.assertNotIn(b'xxx', self.d) 196 self.assertRaises(KeyError, lambda: self.d[b'xxx']) 197 self.d.close() 198 199 200def load_tests(loader, tests, pattern): 201 classes = [] 202 for mod in dbm_iterator(): 203 classes.append(type("TestCase-" + mod.__name__, 204 (AnyDBMTestCase, unittest.TestCase), 205 {'module': mod})) 206 suites = [unittest.makeSuite(c) for c in classes] 207 208 tests.addTests(suites) 209 return tests 210 211if __name__ == "__main__": 212 unittest.main() 213