Home | History | Annotate | Download | only in test
      1 """Test script for the dumbdbm module
      2    Original by Roger E. Masse
      3 """
      4 
      5 import os
      6 import stat
      7 import unittest
      8 import dumbdbm
      9 from test import test_support
     10 
     11 _fname = test_support.TESTFN
     12 
     13 def _delete_files():
     14     for ext in [".dir", ".dat", ".bak"]:
     15         try:
     16             os.unlink(_fname + ext)
     17         except OSError:
     18             pass
     19 
     20 class 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 
    198 def test_main():
    199     try:
    200         test_support.run_unittest(DumbDBMTestCase)
    201     finally:
    202         _delete_files()
    203 
    204 if __name__ == "__main__":
    205     test_main()
    206