blob: ff63c88c0bc5c81342c961568b1ed82f315140ff [file] [log] [blame]
Guido van Rossum2f1064c2001-01-18 16:46:52 +00001"""Test script for the dumbdbm module
2 Original by Roger E. Masse
3"""
4
Guido van Rossum6252e102007-05-23 20:51:02 +00005import io
Benjamin Petersone3083d32014-04-26 16:56:52 -04006import operator
Guido van Rossum2f1064c2001-01-18 16:46:52 +00007import os
Barry Warsaw3ca656f2001-11-13 20:16:52 +00008import unittest
Georg Brandl0a7ac7d2008-05-26 10:29:35 +00009import dbm.dumb as dumbdbm
Benjamin Petersonee8712c2008-05-20 21:35:26 +000010from test import support
Benjamin Petersone3083d32014-04-26 16:56:52 -040011from functools import partial
Guido van Rossum2f1064c2001-01-18 16:46:52 +000012
Benjamin Petersonee8712c2008-05-20 21:35:26 +000013_fname = support.TESTFN
Tim Petersd9fbf352002-01-30 07:32:53 +000014
15def _delete_files():
16 for ext in [".dir", ".dat", ".bak"]:
17 try:
18 os.unlink(_fname + ext)
19 except OSError:
20 pass
21
Barry Warsaw3ca656f2001-11-13 20:16:52 +000022class DumbDBMTestCase(unittest.TestCase):
Brett Cannon58425d32008-11-21 00:17:53 +000023 _dict = {b'0': b'',
24 b'a': b'Python:',
25 b'b': b'Programming',
26 b'c': b'the',
27 b'd': b'way',
28 b'f': b'Guido',
29 b'g': b'intended',
30 '\u00fc'.encode('utf-8') : b'!',
Barry Warsaw3ca656f2001-11-13 20:16:52 +000031 }
32
Barry Warsaw3ca656f2001-11-13 20:16:52 +000033 def test_dumbdbm_creation(self):
Tim Petersd9fbf352002-01-30 07:32:53 +000034 f = dumbdbm.open(_fname, 'c')
Brett Cannonc1b22a02007-02-22 05:04:32 +000035 self.assertEqual(list(f.keys()), [])
Barry Warsaw3ca656f2001-11-13 20:16:52 +000036 for key in self._dict:
Brett Cannon58425d32008-11-21 00:17:53 +000037 f[key] = self._dict[key]
Barry Warsaw3ca656f2001-11-13 20:16:52 +000038 self.read_helper(f)
39 f.close()
40
Serhiy Storchaka43767632013-11-03 21:31:38 +020041 @unittest.skipUnless(hasattr(os, 'umask'), 'test needs os.umask()')
42 @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()')
Thomas Wouters902d6eb2007-01-09 23:18:33 +000043 def test_dumbdbm_creation_mode(self):
Thomas Wouters902d6eb2007-01-09 23:18:33 +000044 try:
Guido van Rossumcd16bf62007-06-13 18:07:49 +000045 old_umask = os.umask(0o002)
46 f = dumbdbm.open(_fname, 'c', 0o637)
Thomas Wouters902d6eb2007-01-09 23:18:33 +000047 f.close()
48 finally:
49 os.umask(old_umask)
Thomas Wouters9fe394c2007-02-05 01:24:16 +000050
Guido van Rossumcd16bf62007-06-13 18:07:49 +000051 expected_mode = 0o635
Thomas Woutersb2137042007-02-01 18:02:27 +000052 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.
Guido van Rossumcd16bf62007-06-13 18:07:49 +000055 expected_mode = 0o666
Thomas Woutersb2137042007-02-01 18:02:27 +000056
Thomas Wouters902d6eb2007-01-09 23:18:33 +000057 import stat
58 st = os.stat(_fname + '.dat')
Thomas Woutersb2137042007-02-01 18:02:27 +000059 self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
Thomas Wouters902d6eb2007-01-09 23:18:33 +000060 st = os.stat(_fname + '.dir')
Thomas Woutersb2137042007-02-01 18:02:27 +000061 self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
Thomas Wouters9fe394c2007-02-05 01:24:16 +000062
Tim Peters7a6c7332003-07-13 17:21:10 +000063 def test_close_twice(self):
64 f = dumbdbm.open(_fname)
Martin v. Löwise6568692007-08-07 05:37:39 +000065 f[b'a'] = b'b'
66 self.assertEqual(f[b'a'], b'b')
Tim Peters7a6c7332003-07-13 17:21:10 +000067 f.close()
68 f.close()
69
Barry Warsaw3ca656f2001-11-13 20:16:52 +000070 def test_dumbdbm_modification(self):
Skip Montanaroc08fe822002-03-17 23:03:42 +000071 self.init_db()
Tim Petersd9fbf352002-01-30 07:32:53 +000072 f = dumbdbm.open(_fname, 'w')
Brett Cannon58425d32008-11-21 00:17:53 +000073 self._dict[b'g'] = f[b'g'] = b"indented"
Barry Warsaw3ca656f2001-11-13 20:16:52 +000074 self.read_helper(f)
75 f.close()
76
77 def test_dumbdbm_read(self):
Skip Montanaroc08fe822002-03-17 23:03:42 +000078 self.init_db()
Tim Petersd9fbf352002-01-30 07:32:53 +000079 f = dumbdbm.open(_fname, 'r')
Barry Warsaw3ca656f2001-11-13 20:16:52 +000080 self.read_helper(f)
81 f.close()
82
83 def test_dumbdbm_keys(self):
Skip Montanaroc08fe822002-03-17 23:03:42 +000084 self.init_db()
Tim Petersd9fbf352002-01-30 07:32:53 +000085 f = dumbdbm.open(_fname)
Barry Warsaw3ca656f2001-11-13 20:16:52 +000086 keys = self.keys_helper(f)
87 f.close()
88
Gregory P. Smith178fefb2007-08-24 21:59:45 +000089 def test_write_contains(self):
90 f = dumbdbm.open(_fname)
91 f[b'1'] = b'hello'
Benjamin Peterson577473f2010-01-19 00:09:57 +000092 self.assertIn(b'1', f)
Gregory P. Smith178fefb2007-08-24 21:59:45 +000093 f.close()
94
Skip Montanaroc08fe822002-03-17 23:03:42 +000095 def test_write_write_read(self):
96 # test for bug #482460
97 f = dumbdbm.open(_fname)
Martin v. Löwise6568692007-08-07 05:37:39 +000098 f[b'1'] = b'hello'
99 f[b'1'] = b'hello2'
Skip Montanaroc08fe822002-03-17 23:03:42 +0000100 f.close()
101 f = dumbdbm.open(_fname)
Guido van Rossum7b4beea2007-08-28 00:09:54 +0000102 self.assertEqual(f[b'1'], b'hello2')
Skip Montanaroc08fe822002-03-17 23:03:42 +0000103 f.close()
104
Brett Cannon58425d32008-11-21 00:17:53 +0000105 def test_str_read(self):
106 self.init_db()
107 f = dumbdbm.open(_fname, 'r')
108 self.assertEqual(f['\u00fc'], self._dict['\u00fc'.encode('utf-8')])
109
110 def test_str_write_contains(self):
111 self.init_db()
112 f = dumbdbm.open(_fname)
113 f['\u00fc'] = b'!'
Brett Cannon7317c1e2008-11-25 19:19:17 +0000114 f['1'] = 'a'
Brett Cannon58425d32008-11-21 00:17:53 +0000115 f.close()
116 f = dumbdbm.open(_fname, 'r')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000117 self.assertIn('\u00fc', f)
Brett Cannon58425d32008-11-21 00:17:53 +0000118 self.assertEqual(f['\u00fc'.encode('utf-8')],
119 self._dict['\u00fc'.encode('utf-8')])
Brett Cannon7317c1e2008-11-25 19:19:17 +0000120 self.assertEqual(f[b'1'], b'a')
Brett Cannon58425d32008-11-21 00:17:53 +0000121
Andrew M. Kuchlingecdad852005-06-07 19:36:10 +0000122 def test_line_endings(self):
123 # test for bug #1172763: dumbdbm would die if the line endings
124 # weren't what was expected.
125 f = dumbdbm.open(_fname)
Martin v. Löwise6568692007-08-07 05:37:39 +0000126 f[b'1'] = b'hello'
127 f[b'2'] = b'hello2'
Andrew M. Kuchlingecdad852005-06-07 19:36:10 +0000128 f.close()
129
Christian Heimes9289bfc2007-10-31 19:40:17 +0000130 # Mangle the file by changing the line separator to Windows or Unix
Brett Cannonc0eee312010-10-29 22:49:14 +0000131 with io.open(_fname + '.dir', 'rb') as file:
132 data = file.read()
Guido van Rossum98297ee2007-11-06 21:34:58 +0000133 if os.linesep == '\n':
Christian Heimes9289bfc2007-10-31 19:40:17 +0000134 data = data.replace(b'\n', b'\r\n')
135 else:
136 data = data.replace(b'\r\n', b'\n')
Brett Cannonc0eee312010-10-29 22:49:14 +0000137 with io.open(_fname + '.dir', 'wb') as file:
138 file.write(data)
Anthony Baxter95a2a4e2005-06-08 04:35:50 +0000139
Andrew M. Kuchlingecdad852005-06-07 19:36:10 +0000140 f = dumbdbm.open(_fname)
Martin v. Löwise6568692007-08-07 05:37:39 +0000141 self.assertEqual(f[b'1'], b'hello')
142 self.assertEqual(f[b'2'], b'hello2')
Anthony Baxter95a2a4e2005-06-08 04:35:50 +0000143
144
Barry Warsaw3ca656f2001-11-13 20:16:52 +0000145 def read_helper(self, f):
146 keys = self.keys_helper(f)
147 for key in self._dict:
Brett Cannon58425d32008-11-21 00:17:53 +0000148 self.assertEqual(self._dict[key], f[key])
Tim Peters88768482001-11-13 21:51:26 +0000149
Skip Montanaroc08fe822002-03-17 23:03:42 +0000150 def init_db(self):
151 f = dumbdbm.open(_fname, 'w')
152 for k in self._dict:
Brett Cannon58425d32008-11-21 00:17:53 +0000153 f[k] = self._dict[k]
Skip Montanaroc08fe822002-03-17 23:03:42 +0000154 f.close()
155
Barry Warsaw3ca656f2001-11-13 20:16:52 +0000156 def keys_helper(self, f):
Brett Cannon58425d32008-11-21 00:17:53 +0000157 keys = sorted(f.keys())
Brett Cannonc1b22a02007-02-22 05:04:32 +0000158 dkeys = sorted(self._dict.keys())
Skip Montanaroc08fe822002-03-17 23:03:42 +0000159 self.assertEqual(keys, dkeys)
Barry Warsaw3ca656f2001-11-13 20:16:52 +0000160 return keys
161
Tim Peters663d1b62003-07-11 04:09:09 +0000162 # Perform randomized operations. This doesn't make assumptions about
163 # what *might* fail.
164 def test_random(self):
165 import random
166 d = {} # mirror the database
167 for dummy in range(5):
168 f = dumbdbm.open(_fname)
169 for dummy in range(100):
170 k = random.choice('abcdefghijklm')
171 if random.random() < 0.2:
172 if k in d:
173 del d[k]
Brett Cannon58425d32008-11-21 00:17:53 +0000174 del f[k]
Tim Peters663d1b62003-07-11 04:09:09 +0000175 else:
Guido van Rossum6252e102007-05-23 20:51:02 +0000176 v = random.choice((b'a', b'b', b'c')) * random.randrange(10000)
Tim Peters663d1b62003-07-11 04:09:09 +0000177 d[k] = v
Brett Cannon58425d32008-11-21 00:17:53 +0000178 f[k] = v
179 self.assertEqual(f[k], v)
Tim Peters663d1b62003-07-11 04:09:09 +0000180 f.close()
181
182 f = dumbdbm.open(_fname)
Guido van Rossum7b4beea2007-08-28 00:09:54 +0000183 expected = sorted((k.encode("latin-1"), v) for k, v in d.items())
Brett Cannonc1b22a02007-02-22 05:04:32 +0000184 got = sorted(f.items())
Tim Peters663d1b62003-07-11 04:09:09 +0000185 self.assertEqual(expected, got)
186 f.close()
187
Nick Coghlanc610aba2013-11-17 15:59:51 +1000188 def test_context_manager(self):
189 with dumbdbm.open(_fname, 'c') as db:
190 db["dumbdbm context manager"] = "context manager"
191
192 with dumbdbm.open(_fname, 'r') as db:
193 self.assertEqual(list(db.keys()), [b"dumbdbm context manager"])
194
Benjamin Petersone3083d32014-04-26 16:56:52 -0400195 with self.assertRaises(dumbdbm.error):
Nick Coghlanc610aba2013-11-17 15:59:51 +1000196 db.keys()
197
Benjamin Petersone3083d32014-04-26 16:56:52 -0400198 def test_check_closed(self):
199 f = dumbdbm.open(_fname, 'c')
200 f.close()
201
202 for meth in (partial(operator.delitem, f),
203 partial(operator.setitem, f, 'b'),
204 partial(operator.getitem, f),
205 partial(operator.contains, f)):
206 with self.assertRaises(dumbdbm.error) as cm:
207 meth('test')
208 self.assertEqual(str(cm.exception),
209 "DBM object has already been closed")
210
211 for meth in (operator.methodcaller('keys'),
212 operator.methodcaller('iterkeys'),
213 operator.methodcaller('items'),
214 len):
215 with self.assertRaises(dumbdbm.error) as cm:
216 meth(f)
217 self.assertEqual(str(cm.exception),
218 "DBM object has already been closed")
219
Serhiy Storchakab398d332014-06-10 21:16:00 +0300220 def test_create_new(self):
221 with dumbdbm.open(_fname, 'n') as f:
222 for k in self._dict:
223 f[k] = self._dict[k]
224
225 with dumbdbm.open(_fname, 'n') as f:
226 self.assertEqual(f.keys(), [])
227
Serhiy Storchaka74eb8b22015-02-16 00:30:43 +0200228 def test_eval(self):
229 with open(_fname + '.dir', 'w') as stream:
230 stream.write("str(print('Hacked!')), 0\n")
231 with support.captured_stdout() as stdout:
232 with self.assertRaises(ValueError):
233 with dumbdbm.open(_fname) as f:
234 pass
235 self.assertEqual(stdout.getvalue(), '')
236
Skip Montanaroc08fe822002-03-17 23:03:42 +0000237 def tearDown(self):
238 _delete_files()
239
240 def setUp(self):
241 _delete_files()
242
Barry Warsaw3ca656f2001-11-13 20:16:52 +0000243
244if __name__ == "__main__":
Ezio Melottif79493b2013-03-01 11:23:28 +0200245 unittest.main()