blob: 78c32c4c93d35c377d4fe85ac686a74a86724f5f [file] [log] [blame]
Georg Brandl7f986ac2008-05-26 10:30:20 +00001"""Test script for the dbm.open function based on testdumbdbm.py"""
2
Georg Brandl7f986ac2008-05-26 10:30:20 +00003import unittest
Georg Brandl7f986ac2008-05-26 10:30:20 +00004import glob
5import test.support
6
R. David Murraya21e4ca2009-03-31 23:16:50 +00007# Skip tests if dbm module doesn't exist.
8dbm = test.support.import_module('dbm')
9
Ezio Melottib08495b2013-07-07 13:15:08 +020010try:
11 from dbm import ndbm
12except ImportError:
13 ndbm = None
14
Georg Brandl7f986ac2008-05-26 10:30:20 +000015_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():
Georg Brandlb17acad2008-05-28 08:43:17 +000022 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
Georg Brandl7f986ac2008-05-26 10:30:20 +000029
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(_fname + "*"):
37 test.support.unlink(f)
38
39
Ezio Melottif79493b2013-03-01 11:23:28 +020040class AnyDBMTestCase:
Miss Islington (bot)e57d3e32018-04-29 06:37:21 -070041 _dict = {'a': b'Python:',
Georg Brandl7f986ac2008-05-26 10:30:20 +000042 'b': b'Programming',
43 'c': b'the',
44 'd': b'way',
45 'f': b'Guido',
46 'g': b'intended',
47 }
48
Georg Brandlb17acad2008-05-28 08:43:17 +000049 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):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020062 self.assertTrue(issubclass(self.module.error, OSError))
Georg Brandl7f986ac2008-05-26 10:30:20 +000063
Amaury Forgeot d'Arcb5cf3012008-09-25 22:27:43 +000064 def test_anydbm_not_existing(self):
65 self.assertRaises(dbm.error, dbm.open, _fname)
66
Georg Brandl7f986ac2008-05-26 10:30:20 +000067 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
briancurtin525c25d2011-03-14 16:03:54 -040075 def test_anydbm_creation_n_file_exists_with_invalid_contents(self):
Victor Stinnerbf816222011-06-30 23:25:47 +020076 # create an empty file
77 test.support.create_empty_file(_fname)
briancurtin525c25d2011-03-14 16:03:54 -040078
79 f = dbm.open(_fname, 'n')
80 self.addCleanup(f.close)
81 self.assertEqual(len(f), 0)
82
Georg Brandl7f986ac2008-05-26 10:30:20 +000083 def test_anydbm_modification(self):
84 self.init_db()
85 f = dbm.open(_fname, 'c')
86 self._dict['g'] = f[b'g'] = b"indented"
87 self.read_helper(f)
Miss Islington (bot)ee95feb2018-04-29 04:50:26 -070088 # setdefault() works as in the dict interface
89 self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
90 self.assertEqual(f[b'xxx'], b'foo')
Georg Brandl7f986ac2008-05-26 10:30:20 +000091 f.close()
92
93 def test_anydbm_read(self):
94 self.init_db()
95 f = dbm.open(_fname, 'r')
96 self.read_helper(f)
Miss Islington (bot)ee95feb2018-04-29 04:50:26 -070097 # get() works as in the dict interface
98 self.assertEqual(f.get(b'a'), self._dict['a'])
99 self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
100 self.assertIsNone(f.get(b'xxx'))
101 with self.assertRaises(KeyError):
102 f[b'xxx']
Georg Brandl7f986ac2008-05-26 10:30:20 +0000103 f.close()
104
105 def test_anydbm_keys(self):
106 self.init_db()
107 f = dbm.open(_fname, 'r')
108 keys = self.keys_helper(f)
109 f.close()
110
Miss Islington (bot)e57d3e32018-04-29 06:37:21 -0700111 def test_empty_value(self):
112 if getattr(dbm._defaultmod, 'library', None) == 'Berkeley DB':
113 self.skipTest("Berkeley DB doesn't distinguish the empty value "
114 "from the absent one")
115 f = dbm.open(_fname, 'c')
116 self.assertEqual(f.keys(), [])
117 f[b'empty'] = b''
118 self.assertEqual(f.keys(), [b'empty'])
119 self.assertIn(b'empty', f)
120 self.assertEqual(f[b'empty'], b'')
121 self.assertEqual(f.get(b'empty'), b'')
122 self.assertEqual(f.setdefault(b'empty'), b'')
123 f.close()
124
Georg Brandl7f986ac2008-05-26 10:30:20 +0000125 def test_anydbm_access(self):
126 self.init_db()
127 f = dbm.open(_fname, 'r')
128 key = "a".encode("ascii")
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000129 self.assertIn(key, f)
Georg Brandl7f986ac2008-05-26 10:30:20 +0000130 assert(f[key] == b"Python:")
131 f.close()
132
133 def read_helper(self, f):
134 keys = self.keys_helper(f)
135 for key in self._dict:
136 self.assertEqual(self._dict[key], f[key.encode("ascii")])
137
Georg Brandl7f986ac2008-05-26 10:30:20 +0000138 def tearDown(self):
139 delete_files()
140
141 def setUp(self):
Georg Brandlb17acad2008-05-28 08:43:17 +0000142 dbm._defaultmod = self.module
Georg Brandl7f986ac2008-05-26 10:30:20 +0000143 delete_files()
144
145
146class WhichDBTestCase(unittest.TestCase):
Georg Brandl7f986ac2008-05-26 10:30:20 +0000147 def test_whichdb(self):
148 for module in dbm_iterator():
149 # Check whether whichdb correctly guesses module name
150 # for databases opened with "module" module.
151 # Try with empty files first
152 name = module.__name__
153 if name == 'dbm.dumb':
154 continue # whichdb can't support dbm.dumb
Senthil Kumaran725c2b92011-02-26 07:11:27 +0000155 delete_files()
Georg Brandl7f986ac2008-05-26 10:30:20 +0000156 f = module.open(_fname, 'c')
157 f.close()
Ezio Melottib08495b2013-07-07 13:15:08 +0200158 self.assertEqual(name, self.dbm.whichdb(_fname))
Georg Brandl7f986ac2008-05-26 10:30:20 +0000159 # Now add a key
160 f = module.open(_fname, 'w')
161 f[b"1"] = b"1"
162 # and test that we can find it
Benjamin Peterson577473f2010-01-19 00:09:57 +0000163 self.assertIn(b"1", f)
Georg Brandl7f986ac2008-05-26 10:30:20 +0000164 # and read it
165 self.assertTrue(f[b"1"] == b"1")
166 f.close()
Ezio Melottib08495b2013-07-07 13:15:08 +0200167 self.assertEqual(name, self.dbm.whichdb(_fname))
168
169 @unittest.skipUnless(ndbm, reason='Test requires ndbm')
170 def test_whichdb_ndbm(self):
171 # Issue 17198: check that ndbm which is referenced in whichdb is defined
172 db_file = '{}_ndbm.db'.format(_fname)
173 with open(db_file, 'w'):
174 self.addCleanup(test.support.unlink, db_file)
175 self.assertIsNone(self.dbm.whichdb(db_file[:-3]))
Georg Brandl7f986ac2008-05-26 10:30:20 +0000176
177 def tearDown(self):
178 delete_files()
179
180 def setUp(self):
181 delete_files()
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000182 self.filename = test.support.TESTFN
183 self.d = dbm.open(self.filename, 'c')
184 self.d.close()
Ezio Melottib08495b2013-07-07 13:15:08 +0200185 self.dbm = test.support.import_fresh_module('dbm')
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000186
187 def test_keys(self):
188 self.d = dbm.open(self.filename, 'c')
189 self.assertEqual(self.d.keys(), [])
190 a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')]
191 for k, v in a:
192 self.d[k] = v
193 self.assertEqual(sorted(self.d.keys()), sorted(k for (k, v) in a))
194 for k, v in a:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000195 self.assertIn(k, self.d)
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000196 self.assertEqual(self.d[k], v)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000197 self.assertNotIn(b'xxx', self.d)
Benjamin Peterson1bc15c22008-10-11 02:19:18 +0000198 self.assertRaises(KeyError, lambda: self.d[b'xxx'])
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000199 self.d.close()
Georg Brandl7f986ac2008-05-26 10:30:20 +0000200
201
Ezio Melottif79493b2013-03-01 11:23:28 +0200202def load_tests(loader, tests, pattern):
203 classes = []
Georg Brandlb17acad2008-05-28 08:43:17 +0000204 for mod in dbm_iterator():
Ezio Melottif79493b2013-03-01 11:23:28 +0200205 classes.append(type("TestCase-" + mod.__name__,
206 (AnyDBMTestCase, unittest.TestCase),
Georg Brandlb17acad2008-05-28 08:43:17 +0000207 {'module': mod}))
Ezio Melottif79493b2013-03-01 11:23:28 +0200208 suites = [unittest.makeSuite(c) for c in classes]
209
210 tests.addTests(suites)
211 return tests
Georg Brandl7f986ac2008-05-26 10:30:20 +0000212
213if __name__ == "__main__":
Ezio Melottif79493b2013-03-01 11:23:28 +0200214 unittest.main()