blob: e02d1e16ae3da7c7bf33eac5b92f52fadde531b6 [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
Hai Shia089d212020-07-06 17:15:08 +08005from test.support import import_helper
6from test.support import os_helper
Georg Brandl7f986ac2008-05-26 10:30:20 +00007
R. David Murraya21e4ca2009-03-31 23:16:50 +00008# Skip tests if dbm module doesn't exist.
Hai Shia089d212020-07-06 17:15:08 +08009dbm = import_helper.import_module('dbm')
R. David Murraya21e4ca2009-03-31 23:16:50 +000010
Ezio Melottib08495b2013-07-07 13:15:08 +020011try:
12 from dbm import ndbm
13except ImportError:
14 ndbm = None
15
Hai Shia089d212020-07-06 17:15:08 +080016_fname = os_helper.TESTFN
Georg Brandl7f986ac2008-05-26 10:30:20 +000017
18#
19# Iterates over every database module supported by dbm currently available,
20# setting dbm to use each in turn, and yielding that module
21#
22def dbm_iterator():
Georg Brandlb17acad2008-05-28 08:43:17 +000023 for name in dbm._names:
24 try:
25 mod = __import__(name, fromlist=['open'])
26 except ImportError:
27 continue
28 dbm._modules[name] = mod
29 yield mod
Georg Brandl7f986ac2008-05-26 10:30:20 +000030
31#
32# Clean up all scratch databases we might have created during testing
33#
34def delete_files():
35 # we don't know the precise name the underlying database uses
36 # so we use glob to locate all names
Serhiy Storchaka93558682020-06-20 11:10:31 +030037 for f in glob.glob(glob.escape(_fname) + "*"):
Hai Shia089d212020-07-06 17:15:08 +080038 os_helper.unlink(f)
Georg Brandl7f986ac2008-05-26 10:30:20 +000039
40
Ezio Melottif79493b2013-03-01 11:23:28 +020041class AnyDBMTestCase:
Serhiy Storchaka70af06c2018-04-29 15:45:03 +030042 _dict = {'a': b'Python:',
Georg Brandl7f986ac2008-05-26 10:30:20 +000043 'b': b'Programming',
44 'c': b'the',
45 'd': b'way',
46 'f': b'Guido',
47 'g': b'intended',
48 }
49
Georg Brandlb17acad2008-05-28 08:43:17 +000050 def init_db(self):
51 f = dbm.open(_fname, 'n')
52 for k in self._dict:
53 f[k.encode("ascii")] = self._dict[k]
54 f.close()
55
56 def keys_helper(self, f):
57 keys = sorted(k.decode("ascii") for k in f.keys())
58 dkeys = sorted(self._dict.keys())
59 self.assertEqual(keys, dkeys)
60 return keys
61
62 def test_error(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020063 self.assertTrue(issubclass(self.module.error, OSError))
Georg Brandl7f986ac2008-05-26 10:30:20 +000064
Amaury Forgeot d'Arcb5cf3012008-09-25 22:27:43 +000065 def test_anydbm_not_existing(self):
66 self.assertRaises(dbm.error, dbm.open, _fname)
67
Georg Brandl7f986ac2008-05-26 10:30:20 +000068 def test_anydbm_creation(self):
69 f = dbm.open(_fname, 'c')
70 self.assertEqual(list(f.keys()), [])
71 for key in self._dict:
72 f[key.encode("ascii")] = self._dict[key]
73 self.read_helper(f)
74 f.close()
75
briancurtin525c25d2011-03-14 16:03:54 -040076 def test_anydbm_creation_n_file_exists_with_invalid_contents(self):
Victor Stinnerbf816222011-06-30 23:25:47 +020077 # create an empty file
Hai Shia089d212020-07-06 17:15:08 +080078 os_helper.create_empty_file(_fname)
Serhiy Storchaka6592d7f2018-06-05 16:03:00 +030079 with dbm.open(_fname, 'n') as f:
80 self.assertEqual(len(f), 0)
briancurtin525c25d2011-03-14 16:03:54 -040081
Georg Brandl7f986ac2008-05-26 10:30:20 +000082 def test_anydbm_modification(self):
83 self.init_db()
84 f = dbm.open(_fname, 'c')
85 self._dict['g'] = f[b'g'] = b"indented"
86 self.read_helper(f)
Serhiy Storchaka2e38cc32018-04-29 12:38:06 +030087 # setdefault() works as in the dict interface
88 self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
89 self.assertEqual(f[b'xxx'], b'foo')
Georg Brandl7f986ac2008-05-26 10:30:20 +000090 f.close()
91
92 def test_anydbm_read(self):
93 self.init_db()
94 f = dbm.open(_fname, 'r')
95 self.read_helper(f)
Serhiy Storchaka2e38cc32018-04-29 12:38:06 +030096 # get() works as in the dict interface
97 self.assertEqual(f.get(b'a'), self._dict['a'])
98 self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
99 self.assertIsNone(f.get(b'xxx'))
100 with self.assertRaises(KeyError):
101 f[b'xxx']
Georg Brandl7f986ac2008-05-26 10:30:20 +0000102 f.close()
103
104 def test_anydbm_keys(self):
105 self.init_db()
106 f = dbm.open(_fname, 'r')
107 keys = self.keys_helper(f)
108 f.close()
109
Serhiy Storchaka70af06c2018-04-29 15:45:03 +0300110 def test_empty_value(self):
111 if getattr(dbm._defaultmod, 'library', None) == 'Berkeley DB':
112 self.skipTest("Berkeley DB doesn't distinguish the empty value "
113 "from the absent one")
114 f = dbm.open(_fname, 'c')
115 self.assertEqual(f.keys(), [])
116 f[b'empty'] = b''
117 self.assertEqual(f.keys(), [b'empty'])
118 self.assertIn(b'empty', f)
119 self.assertEqual(f[b'empty'], b'')
120 self.assertEqual(f.get(b'empty'), b'')
121 self.assertEqual(f.setdefault(b'empty'), b'')
122 f.close()
123
Georg Brandl7f986ac2008-05-26 10:30:20 +0000124 def test_anydbm_access(self):
125 self.init_db()
126 f = dbm.open(_fname, 'r')
127 key = "a".encode("ascii")
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000128 self.assertIn(key, f)
Georg Brandl7f986ac2008-05-26 10:30:20 +0000129 assert(f[key] == b"Python:")
130 f.close()
131
132 def read_helper(self, f):
133 keys = self.keys_helper(f)
134 for key in self._dict:
135 self.assertEqual(self._dict[key], f[key.encode("ascii")])
136
Georg Brandl7f986ac2008-05-26 10:30:20 +0000137 def tearDown(self):
138 delete_files()
139
140 def setUp(self):
Georg Brandlb17acad2008-05-28 08:43:17 +0000141 dbm._defaultmod = self.module
Georg Brandl7f986ac2008-05-26 10:30:20 +0000142 delete_files()
143
144
145class WhichDBTestCase(unittest.TestCase):
Georg Brandl7f986ac2008-05-26 10:30:20 +0000146 def test_whichdb(self):
147 for module in dbm_iterator():
148 # Check whether whichdb correctly guesses module name
149 # for databases opened with "module" module.
150 # Try with empty files first
151 name = module.__name__
152 if name == 'dbm.dumb':
153 continue # whichdb can't support dbm.dumb
Senthil Kumaran725c2b92011-02-26 07:11:27 +0000154 delete_files()
Georg Brandl7f986ac2008-05-26 10:30:20 +0000155 f = module.open(_fname, 'c')
156 f.close()
Ezio Melottib08495b2013-07-07 13:15:08 +0200157 self.assertEqual(name, self.dbm.whichdb(_fname))
Georg Brandl7f986ac2008-05-26 10:30:20 +0000158 # Now add a key
159 f = module.open(_fname, 'w')
160 f[b"1"] = b"1"
161 # and test that we can find it
Benjamin Peterson577473f2010-01-19 00:09:57 +0000162 self.assertIn(b"1", f)
Georg Brandl7f986ac2008-05-26 10:30:20 +0000163 # and read it
Serhiy Storchaka22525de2018-06-19 13:31:48 +0300164 self.assertEqual(f[b"1"], b"1")
Georg Brandl7f986ac2008-05-26 10:30:20 +0000165 f.close()
Ezio Melottib08495b2013-07-07 13:15:08 +0200166 self.assertEqual(name, self.dbm.whichdb(_fname))
167
168 @unittest.skipUnless(ndbm, reason='Test requires ndbm')
169 def test_whichdb_ndbm(self):
170 # Issue 17198: check that ndbm which is referenced in whichdb is defined
171 db_file = '{}_ndbm.db'.format(_fname)
172 with open(db_file, 'w'):
Hai Shia089d212020-07-06 17:15:08 +0800173 self.addCleanup(os_helper.unlink, db_file)
Ezio Melottib08495b2013-07-07 13:15:08 +0200174 self.assertIsNone(self.dbm.whichdb(db_file[:-3]))
Georg Brandl7f986ac2008-05-26 10:30:20 +0000175
176 def tearDown(self):
177 delete_files()
178
179 def setUp(self):
180 delete_files()
Hai Shia089d212020-07-06 17:15:08 +0800181 self.filename = os_helper.TESTFN
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000182 self.d = dbm.open(self.filename, 'c')
183 self.d.close()
Hai Shia089d212020-07-06 17:15:08 +0800184 self.dbm = import_helper.import_fresh_module('dbm')
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000185
186 def test_keys(self):
187 self.d = dbm.open(self.filename, 'c')
188 self.assertEqual(self.d.keys(), [])
189 a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')]
190 for k, v in a:
191 self.d[k] = v
192 self.assertEqual(sorted(self.d.keys()), sorted(k for (k, v) in a))
193 for k, v in a:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000194 self.assertIn(k, self.d)
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000195 self.assertEqual(self.d[k], v)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000196 self.assertNotIn(b'xxx', self.d)
Benjamin Peterson1bc15c22008-10-11 02:19:18 +0000197 self.assertRaises(KeyError, lambda: self.d[b'xxx'])
Benjamin Petersonf10a79a2008-10-11 00:49:57 +0000198 self.d.close()
Georg Brandl7f986ac2008-05-26 10:30:20 +0000199
200
Ezio Melottif79493b2013-03-01 11:23:28 +0200201def load_tests(loader, tests, pattern):
202 classes = []
Georg Brandlb17acad2008-05-28 08:43:17 +0000203 for mod in dbm_iterator():
Ezio Melottif79493b2013-03-01 11:23:28 +0200204 classes.append(type("TestCase-" + mod.__name__,
205 (AnyDBMTestCase, unittest.TestCase),
Georg Brandlb17acad2008-05-28 08:43:17 +0000206 {'module': mod}))
Ezio Melottif79493b2013-03-01 11:23:28 +0200207 suites = [unittest.makeSuite(c) for c in classes]
208
209 tests.addTests(suites)
210 return tests
Georg Brandl7f986ac2008-05-26 10:30:20 +0000211
212if __name__ == "__main__":
Ezio Melottif79493b2013-03-01 11:23:28 +0200213 unittest.main()