1"""Test script for the dbm.open function based on testdumbdbm.py""" 2 3import unittest 4import dbm 5import os 6from test.support import import_helper 7from test.support import os_helper 8 9try: 10 from dbm import ndbm 11except ImportError: 12 ndbm = None 13 14dirname = os_helper.TESTFN 15_fname = os.path.join(dirname, os_helper.TESTFN) 16 17# 18# Iterates over every database module supported by dbm currently available. 19# 20def dbm_iterator(): 21 for name in dbm._names: 22 try: 23 mod = __import__(name, fromlist=['open']) 24 except ImportError: 25 continue 26 dbm._modules[name] = mod 27 yield mod 28 29# 30# Clean up all scratch databases we might have created during testing 31# 32def cleaunup_test_dir(): 33 os_helper.rmtree(dirname) 34 35def setup_test_dir(): 36 cleaunup_test_dir() 37 os.mkdir(dirname) 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 os_helper.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 test_keys(self): 137 with dbm.open(_fname, 'c') as d: 138 self.assertEqual(d.keys(), []) 139 a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')] 140 for k, v in a: 141 d[k] = v 142 self.assertEqual(sorted(d.keys()), sorted(k for (k, v) in a)) 143 for k, v in a: 144 self.assertIn(k, d) 145 self.assertEqual(d[k], v) 146 self.assertNotIn(b'xxx', d) 147 self.assertRaises(KeyError, lambda: d[b'xxx']) 148 149 def setUp(self): 150 self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod) 151 dbm._defaultmod = self.module 152 self.addCleanup(cleaunup_test_dir) 153 setup_test_dir() 154 155 156class WhichDBTestCase(unittest.TestCase): 157 def test_whichdb(self): 158 self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod) 159 for module in dbm_iterator(): 160 # Check whether whichdb correctly guesses module name 161 # for databases opened with "module" module. 162 name = module.__name__ 163 setup_test_dir() 164 dbm._defaultmod = module 165 # Try with empty files first 166 with module.open(_fname, 'c'): pass 167 self.assertEqual(name, self.dbm.whichdb(_fname)) 168 # Now add a key 169 with module.open(_fname, 'w') as f: 170 f[b"1"] = b"1" 171 # and test that we can find it 172 self.assertIn(b"1", f) 173 # and read it 174 self.assertEqual(f[b"1"], b"1") 175 self.assertEqual(name, self.dbm.whichdb(_fname)) 176 177 @unittest.skipUnless(ndbm, reason='Test requires ndbm') 178 def test_whichdb_ndbm(self): 179 # Issue 17198: check that ndbm which is referenced in whichdb is defined 180 with open(_fname + '.db', 'wb'): pass 181 self.assertIsNone(self.dbm.whichdb(_fname)) 182 183 def setUp(self): 184 self.addCleanup(cleaunup_test_dir) 185 setup_test_dir() 186 self.dbm = import_helper.import_fresh_module('dbm') 187 188 189for mod in dbm_iterator(): 190 assert mod.__name__.startswith('dbm.') 191 suffix = mod.__name__[4:] 192 testname = f'TestCase_{suffix}' 193 globals()[testname] = type(testname, 194 (AnyDBMTestCase, unittest.TestCase), 195 {'module': mod}) 196 197 198if __name__ == "__main__": 199 unittest.main() 200