1"""Test script for the dumbdbm module 2 Original by Roger E. Masse 3""" 4 5import os 6import stat 7import unittest 8import dumbdbm 9from test import test_support 10 11_fname = test_support.TESTFN 12 13def _delete_files(): 14 for ext in [".dir", ".dat", ".bak"]: 15 try: 16 os.unlink(_fname + ext) 17 except OSError: 18 pass 19 20class DumbDBMTestCase(unittest.TestCase): 21 _dict = {'0': '', 22 'a': 'Python:', 23 'b': 'Programming', 24 'c': 'the', 25 'd': 'way', 26 'f': 'Guido', 27 'g': 'intended' 28 } 29 30 def __init__(self, *args): 31 unittest.TestCase.__init__(self, *args) 32 33 def test_dumbdbm_creation(self): 34 f = dumbdbm.open(_fname, 'c') 35 self.assertEqual(f.keys(), []) 36 for key in self._dict: 37 f[key] = self._dict[key] 38 self.read_helper(f) 39 f.close() 40 41 @unittest.skipUnless(hasattr(os, 'chmod'), 'os.chmod not available') 42 @unittest.skipUnless(hasattr(os, 'umask'), 'os.umask not available') 43 def test_dumbdbm_creation_mode(self): 44 try: 45 old_umask = os.umask(0002) 46 f = dumbdbm.open(_fname, 'c', 0637) 47 f.close() 48 finally: 49 os.umask(old_umask) 50 51 expected_mode = 0635 52 if os.name != 'posix': 53 # Windows only supports setting the read-only attribute. 54 # This shouldn't fail, but doesn't work like Unix either. 55 expected_mode = 0666 56 57 import stat 58 st = os.stat(_fname + '.dat') 59 self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode) 60 st = os.stat(_fname + '.dir') 61 self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode) 62 63 def test_close_twice(self): 64 f = dumbdbm.open(_fname) 65 f['a'] = 'b' 66 self.assertEqual(f['a'], 'b') 67 f.close() 68 f.close() 69 70 def test_dumbdbm_modification(self): 71 self.init_db() 72 f = dumbdbm.open(_fname, 'w') 73 self._dict['g'] = f['g'] = "indented" 74 self.read_helper(f) 75 f.close() 76 77 def test_dumbdbm_read(self): 78 self.init_db() 79 f = dumbdbm.open(_fname, 'r') 80 self.read_helper(f) 81 f.close() 82 83 def test_dumbdbm_keys(self): 84 self.init_db() 85 f = dumbdbm.open(_fname) 86 keys = self.keys_helper(f) 87 f.close() 88 89 def test_write_write_read(self): 90 # test for bug #482460 91 f = dumbdbm.open(_fname) 92 f['1'] = 'hello' 93 f['1'] = 'hello2' 94 f.close() 95 f = dumbdbm.open(_fname) 96 self.assertEqual(f['1'], 'hello2') 97 f.close() 98 99 def test_line_endings(self): 100 # test for bug #1172763: dumbdbm would die if the line endings 101 # weren't what was expected. 102 f = dumbdbm.open(_fname) 103 f['1'] = 'hello' 104 f['2'] = 'hello2' 105 f.close() 106 107 # Mangle the file by adding \r before each newline 108 data = open(_fname + '.dir').read() 109 data = data.replace('\n', '\r\n') 110 open(_fname + '.dir', 'wb').write(data) 111 112 f = dumbdbm.open(_fname) 113 self.assertEqual(f['1'], 'hello') 114 self.assertEqual(f['2'], 'hello2') 115 116 117 def read_helper(self, f): 118 keys = self.keys_helper(f) 119 for key in self._dict: 120 self.assertEqual(self._dict[key], f[key]) 121 122 def init_db(self): 123 f = dumbdbm.open(_fname, 'w') 124 for k in self._dict: 125 f[k] = self._dict[k] 126 f.close() 127 128 def keys_helper(self, f): 129 keys = f.keys() 130 keys.sort() 131 dkeys = self._dict.keys() 132 dkeys.sort() 133 self.assertEqual(keys, dkeys) 134 return keys 135 136 # Perform randomized operations. This doesn't make assumptions about 137 # what *might* fail. 138 def test_random(self): 139 import random 140 d = {} # mirror the database 141 for dummy in range(5): 142 f = dumbdbm.open(_fname) 143 for dummy in range(100): 144 k = random.choice('abcdefghijklm') 145 if random.random() < 0.2: 146 if k in d: 147 del d[k] 148 del f[k] 149 else: 150 v = random.choice('abc') * random.randrange(10000) 151 d[k] = v 152 f[k] = v 153 self.assertEqual(f[k], v) 154 f.close() 155 156 f = dumbdbm.open(_fname) 157 expected = d.items() 158 expected.sort() 159 got = f.items() 160 got.sort() 161 self.assertEqual(expected, got) 162 f.close() 163 164 def test_eval(self): 165 with open(_fname + '.dir', 'w') as stream: 166 stream.write("str(__import__('sys').stdout.write('Hacked!')), 0\n") 167 with test_support.captured_stdout() as stdout: 168 with self.assertRaises(ValueError): 169 dumbdbm.open(_fname).close() 170 self.assertEqual(stdout.getvalue(), '') 171 172 @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()') 173 def test_readonly_files(self): 174 dir = _fname 175 os.mkdir(dir) 176 try: 177 fname = os.path.join(dir, 'db') 178 f = dumbdbm.open(fname, 'n') 179 self.assertEqual(list(f.keys()), []) 180 for key in self._dict: 181 f[key] = self._dict[key] 182 f.close() 183 os.chmod(fname + ".dir", stat.S_IRUSR) 184 os.chmod(fname + ".dat", stat.S_IRUSR) 185 os.chmod(dir, stat.S_IRUSR|stat.S_IXUSR) 186 f = dumbdbm.open(fname, 'r') 187 self.assertEqual(sorted(f.keys()), sorted(self._dict)) 188 f.close() # don't write 189 finally: 190 test_support.rmtree(dir) 191 192 def tearDown(self): 193 _delete_files() 194 195 def setUp(self): 196 _delete_files() 197 198def test_main(): 199 try: 200 test_support.run_unittest(DumbDBMTestCase) 201 finally: 202 _delete_files() 203 204if __name__ == "__main__": 205 test_main() 206