17db96d56Sopenharmony_ci"""Test script for the dbm.open function based on testdumbdbm.py"""
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciimport unittest
47db96d56Sopenharmony_ciimport dbm
57db96d56Sopenharmony_ciimport os
67db96d56Sopenharmony_cifrom test.support import import_helper
77db96d56Sopenharmony_cifrom test.support import os_helper
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_citry:
107db96d56Sopenharmony_ci    from dbm import ndbm
117db96d56Sopenharmony_ciexcept ImportError:
127db96d56Sopenharmony_ci    ndbm = None
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_cidirname = os_helper.TESTFN
157db96d56Sopenharmony_ci_fname = os.path.join(dirname, os_helper.TESTFN)
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci#
187db96d56Sopenharmony_ci# Iterates over every database module supported by dbm currently available.
197db96d56Sopenharmony_ci#
207db96d56Sopenharmony_cidef dbm_iterator():
217db96d56Sopenharmony_ci    for name in dbm._names:
227db96d56Sopenharmony_ci        try:
237db96d56Sopenharmony_ci            mod = __import__(name, fromlist=['open'])
247db96d56Sopenharmony_ci        except ImportError:
257db96d56Sopenharmony_ci            continue
267db96d56Sopenharmony_ci        dbm._modules[name] = mod
277db96d56Sopenharmony_ci        yield mod
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci#
307db96d56Sopenharmony_ci# Clean up all scratch databases we might have created during testing
317db96d56Sopenharmony_ci#
327db96d56Sopenharmony_cidef cleaunup_test_dir():
337db96d56Sopenharmony_ci    os_helper.rmtree(dirname)
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_cidef setup_test_dir():
367db96d56Sopenharmony_ci    cleaunup_test_dir()
377db96d56Sopenharmony_ci    os.mkdir(dirname)
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ciclass AnyDBMTestCase:
417db96d56Sopenharmony_ci    _dict = {'a': b'Python:',
427db96d56Sopenharmony_ci             'b': b'Programming',
437db96d56Sopenharmony_ci             'c': b'the',
447db96d56Sopenharmony_ci             'd': b'way',
457db96d56Sopenharmony_ci             'f': b'Guido',
467db96d56Sopenharmony_ci             'g': b'intended',
477db96d56Sopenharmony_ci             }
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci    def init_db(self):
507db96d56Sopenharmony_ci        f = dbm.open(_fname, 'n')
517db96d56Sopenharmony_ci        for k in self._dict:
527db96d56Sopenharmony_ci            f[k.encode("ascii")] = self._dict[k]
537db96d56Sopenharmony_ci        f.close()
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci    def keys_helper(self, f):
567db96d56Sopenharmony_ci        keys = sorted(k.decode("ascii") for k in f.keys())
577db96d56Sopenharmony_ci        dkeys = sorted(self._dict.keys())
587db96d56Sopenharmony_ci        self.assertEqual(keys, dkeys)
597db96d56Sopenharmony_ci        return keys
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci    def test_error(self):
627db96d56Sopenharmony_ci        self.assertTrue(issubclass(self.module.error, OSError))
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci    def test_anydbm_not_existing(self):
657db96d56Sopenharmony_ci        self.assertRaises(dbm.error, dbm.open, _fname)
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci    def test_anydbm_creation(self):
687db96d56Sopenharmony_ci        f = dbm.open(_fname, 'c')
697db96d56Sopenharmony_ci        self.assertEqual(list(f.keys()), [])
707db96d56Sopenharmony_ci        for key in self._dict:
717db96d56Sopenharmony_ci            f[key.encode("ascii")] = self._dict[key]
727db96d56Sopenharmony_ci        self.read_helper(f)
737db96d56Sopenharmony_ci        f.close()
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci    def test_anydbm_creation_n_file_exists_with_invalid_contents(self):
767db96d56Sopenharmony_ci        # create an empty file
777db96d56Sopenharmony_ci        os_helper.create_empty_file(_fname)
787db96d56Sopenharmony_ci        with dbm.open(_fname, 'n') as f:
797db96d56Sopenharmony_ci            self.assertEqual(len(f), 0)
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    def test_anydbm_modification(self):
827db96d56Sopenharmony_ci        self.init_db()
837db96d56Sopenharmony_ci        f = dbm.open(_fname, 'c')
847db96d56Sopenharmony_ci        self._dict['g'] = f[b'g'] = b"indented"
857db96d56Sopenharmony_ci        self.read_helper(f)
867db96d56Sopenharmony_ci        # setdefault() works as in the dict interface
877db96d56Sopenharmony_ci        self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
887db96d56Sopenharmony_ci        self.assertEqual(f[b'xxx'], b'foo')
897db96d56Sopenharmony_ci        f.close()
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci    def test_anydbm_read(self):
927db96d56Sopenharmony_ci        self.init_db()
937db96d56Sopenharmony_ci        f = dbm.open(_fname, 'r')
947db96d56Sopenharmony_ci        self.read_helper(f)
957db96d56Sopenharmony_ci        # get() works as in the dict interface
967db96d56Sopenharmony_ci        self.assertEqual(f.get(b'a'), self._dict['a'])
977db96d56Sopenharmony_ci        self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
987db96d56Sopenharmony_ci        self.assertIsNone(f.get(b'xxx'))
997db96d56Sopenharmony_ci        with self.assertRaises(KeyError):
1007db96d56Sopenharmony_ci            f[b'xxx']
1017db96d56Sopenharmony_ci        f.close()
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci    def test_anydbm_keys(self):
1047db96d56Sopenharmony_ci        self.init_db()
1057db96d56Sopenharmony_ci        f = dbm.open(_fname, 'r')
1067db96d56Sopenharmony_ci        keys = self.keys_helper(f)
1077db96d56Sopenharmony_ci        f.close()
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci    def test_empty_value(self):
1107db96d56Sopenharmony_ci        if getattr(dbm._defaultmod, 'library', None) == 'Berkeley DB':
1117db96d56Sopenharmony_ci            self.skipTest("Berkeley DB doesn't distinguish the empty value "
1127db96d56Sopenharmony_ci                          "from the absent one")
1137db96d56Sopenharmony_ci        f = dbm.open(_fname, 'c')
1147db96d56Sopenharmony_ci        self.assertEqual(f.keys(), [])
1157db96d56Sopenharmony_ci        f[b'empty'] = b''
1167db96d56Sopenharmony_ci        self.assertEqual(f.keys(), [b'empty'])
1177db96d56Sopenharmony_ci        self.assertIn(b'empty', f)
1187db96d56Sopenharmony_ci        self.assertEqual(f[b'empty'], b'')
1197db96d56Sopenharmony_ci        self.assertEqual(f.get(b'empty'), b'')
1207db96d56Sopenharmony_ci        self.assertEqual(f.setdefault(b'empty'), b'')
1217db96d56Sopenharmony_ci        f.close()
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    def test_anydbm_access(self):
1247db96d56Sopenharmony_ci        self.init_db()
1257db96d56Sopenharmony_ci        f = dbm.open(_fname, 'r')
1267db96d56Sopenharmony_ci        key = "a".encode("ascii")
1277db96d56Sopenharmony_ci        self.assertIn(key, f)
1287db96d56Sopenharmony_ci        assert(f[key] == b"Python:")
1297db96d56Sopenharmony_ci        f.close()
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci    def test_open_with_bytes(self):
1327db96d56Sopenharmony_ci        dbm.open(os.fsencode(_fname), "c").close()
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci    def test_open_with_pathlib_path(self):
1357db96d56Sopenharmony_ci        dbm.open(os_helper.FakePath(_fname), "c").close()
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci    def test_open_with_pathlib_path_bytes(self):
1387db96d56Sopenharmony_ci        dbm.open(os_helper.FakePath(os.fsencode(_fname)), "c").close()
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    def read_helper(self, f):
1417db96d56Sopenharmony_ci        keys = self.keys_helper(f)
1427db96d56Sopenharmony_ci        for key in self._dict:
1437db96d56Sopenharmony_ci            self.assertEqual(self._dict[key], f[key.encode("ascii")])
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci    def test_keys(self):
1467db96d56Sopenharmony_ci        with dbm.open(_fname, 'c') as d:
1477db96d56Sopenharmony_ci            self.assertEqual(d.keys(), [])
1487db96d56Sopenharmony_ci            a = [(b'a', b'b'), (b'12345678910', b'019237410982340912840198242')]
1497db96d56Sopenharmony_ci            for k, v in a:
1507db96d56Sopenharmony_ci                d[k] = v
1517db96d56Sopenharmony_ci            self.assertEqual(sorted(d.keys()), sorted(k for (k, v) in a))
1527db96d56Sopenharmony_ci            for k, v in a:
1537db96d56Sopenharmony_ci                self.assertIn(k, d)
1547db96d56Sopenharmony_ci                self.assertEqual(d[k], v)
1557db96d56Sopenharmony_ci            self.assertNotIn(b'xxx', d)
1567db96d56Sopenharmony_ci            self.assertRaises(KeyError, lambda: d[b'xxx'])
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ci    def setUp(self):
1597db96d56Sopenharmony_ci        self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod)
1607db96d56Sopenharmony_ci        dbm._defaultmod = self.module
1617db96d56Sopenharmony_ci        self.addCleanup(cleaunup_test_dir)
1627db96d56Sopenharmony_ci        setup_test_dir()
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ciclass WhichDBTestCase(unittest.TestCase):
1667db96d56Sopenharmony_ci    def test_whichdb(self):
1677db96d56Sopenharmony_ci        self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod)
1687db96d56Sopenharmony_ci        _bytes_fname = os.fsencode(_fname)
1697db96d56Sopenharmony_ci        fnames = [_fname, os_helper.FakePath(_fname),
1707db96d56Sopenharmony_ci                  _bytes_fname, os_helper.FakePath(_bytes_fname)]
1717db96d56Sopenharmony_ci        for module in dbm_iterator():
1727db96d56Sopenharmony_ci            # Check whether whichdb correctly guesses module name
1737db96d56Sopenharmony_ci            # for databases opened with "module" module.
1747db96d56Sopenharmony_ci            name = module.__name__
1757db96d56Sopenharmony_ci            setup_test_dir()
1767db96d56Sopenharmony_ci            dbm._defaultmod = module
1777db96d56Sopenharmony_ci            # Try with empty files first
1787db96d56Sopenharmony_ci            with module.open(_fname, 'c'): pass
1797db96d56Sopenharmony_ci            for path in fnames:
1807db96d56Sopenharmony_ci                self.assertEqual(name, self.dbm.whichdb(path))
1817db96d56Sopenharmony_ci            # Now add a key
1827db96d56Sopenharmony_ci            with module.open(_fname, 'w') as f:
1837db96d56Sopenharmony_ci                f[b"1"] = b"1"
1847db96d56Sopenharmony_ci                # and test that we can find it
1857db96d56Sopenharmony_ci                self.assertIn(b"1", f)
1867db96d56Sopenharmony_ci                # and read it
1877db96d56Sopenharmony_ci                self.assertEqual(f[b"1"], b"1")
1887db96d56Sopenharmony_ci            for path in fnames:
1897db96d56Sopenharmony_ci                self.assertEqual(name, self.dbm.whichdb(path))
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci    @unittest.skipUnless(ndbm, reason='Test requires ndbm')
1927db96d56Sopenharmony_ci    def test_whichdb_ndbm(self):
1937db96d56Sopenharmony_ci        # Issue 17198: check that ndbm which is referenced in whichdb is defined
1947db96d56Sopenharmony_ci        with open(_fname + '.db', 'wb'): pass
1957db96d56Sopenharmony_ci        _bytes_fname = os.fsencode(_fname)
1967db96d56Sopenharmony_ci        fnames = [_fname, os_helper.FakePath(_fname),
1977db96d56Sopenharmony_ci                  _bytes_fname, os_helper.FakePath(_bytes_fname)]
1987db96d56Sopenharmony_ci        for path in fnames:
1997db96d56Sopenharmony_ci            self.assertIsNone(self.dbm.whichdb(path))
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci    def setUp(self):
2027db96d56Sopenharmony_ci        self.addCleanup(cleaunup_test_dir)
2037db96d56Sopenharmony_ci        setup_test_dir()
2047db96d56Sopenharmony_ci        self.dbm = import_helper.import_fresh_module('dbm')
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_cifor mod in dbm_iterator():
2087db96d56Sopenharmony_ci    assert mod.__name__.startswith('dbm.')
2097db96d56Sopenharmony_ci    suffix = mod.__name__[4:]
2107db96d56Sopenharmony_ci    testname = f'TestCase_{suffix}'
2117db96d56Sopenharmony_ci    globals()[testname] = type(testname,
2127db96d56Sopenharmony_ci                               (AnyDBMTestCase, unittest.TestCase),
2137db96d56Sopenharmony_ci                               {'module': mod})
2147db96d56Sopenharmony_ci
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ciif __name__ == "__main__":
2177db96d56Sopenharmony_ci    unittest.main()
218