1#! /usr/bin/env python
2"""Test script for the dumbdbm module
3   Original by Roger E. Masse
4"""
5
6import os
7import unittest
8import dumbdbm
9from test import test_support
10
11_fname = test_support.TESTFN
12
13def _delete_files():
14    for ext in [".dir", ".dat", ".bak"]:
15        try:
16            os.unlink(_fname + ext)
17        except OSError:
18            pass
19
20class 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    def test_dumbdbm_creation_mode(self):
42        # On platforms without chmod, don't do anything.
43        if not (hasattr(os, 'chmod') and hasattr(os, 'umask')):
44            return
45
46        try:
47            old_umask = os.umask(0002)
48            f = dumbdbm.open(_fname, 'c', 0637)
49            f.close()
50        finally:
51            os.umask(old_umask)
52
53        expected_mode = 0635
54        if os.name != 'posix':
55            # Windows only supports setting the read-only attribute.
56            # This shouldn't fail, but doesn't work like Unix either.
57            expected_mode = 0666
58
59        import stat
60        st = os.stat(_fname + '.dat')
61        self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
62        st = os.stat(_fname + '.dir')
63        self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
64
65    def test_close_twice(self):
66        f = dumbdbm.open(_fname)
67        f['a'] = 'b'
68        self.assertEqual(f['a'], 'b')
69        f.close()
70        f.close()
71
72    def test_dumbdbm_modification(self):
73        self.init_db()
74        f = dumbdbm.open(_fname, 'w')
75        self._dict['g'] = f['g'] = "indented"
76        self.read_helper(f)
77        f.close()
78
79    def test_dumbdbm_read(self):
80        self.init_db()
81        f = dumbdbm.open(_fname, 'r')
82        self.read_helper(f)
83        f.close()
84
85    def test_dumbdbm_keys(self):
86        self.init_db()
87        f = dumbdbm.open(_fname)
88        keys = self.keys_helper(f)
89        f.close()
90
91    def test_write_write_read(self):
92        # test for bug #482460
93        f = dumbdbm.open(_fname)
94        f['1'] = 'hello'
95        f['1'] = 'hello2'
96        f.close()
97        f = dumbdbm.open(_fname)
98        self.assertEqual(f['1'], 'hello2')
99        f.close()
100
101    def test_line_endings(self):
102        # test for bug #1172763: dumbdbm would die if the line endings
103        # weren't what was expected.
104        f = dumbdbm.open(_fname)
105        f['1'] = 'hello'
106        f['2'] = 'hello2'
107        f.close()
108
109        # Mangle the file by adding \r before each newline
110        data = open(_fname + '.dir').read()
111        data = data.replace('\n', '\r\n')
112        open(_fname + '.dir', 'wb').write(data)
113
114        f = dumbdbm.open(_fname)
115        self.assertEqual(f['1'], 'hello')
116        self.assertEqual(f['2'], 'hello2')
117
118
119    def read_helper(self, f):
120        keys = self.keys_helper(f)
121        for key in self._dict:
122            self.assertEqual(self._dict[key], f[key])
123
124    def init_db(self):
125        f = dumbdbm.open(_fname, 'w')
126        for k in self._dict:
127            f[k] = self._dict[k]
128        f.close()
129
130    def keys_helper(self, f):
131        keys = f.keys()
132        keys.sort()
133        dkeys = self._dict.keys()
134        dkeys.sort()
135        self.assertEqual(keys, dkeys)
136        return keys
137
138    # Perform randomized operations.  This doesn't make assumptions about
139    # what *might* fail.
140    def test_random(self):
141        import random
142        d = {}  # mirror the database
143        for dummy in range(5):
144            f = dumbdbm.open(_fname)
145            for dummy in range(100):
146                k = random.choice('abcdefghijklm')
147                if random.random() < 0.2:
148                    if k in d:
149                        del d[k]
150                        del f[k]
151                else:
152                    v = random.choice('abc') * random.randrange(10000)
153                    d[k] = v
154                    f[k] = v
155                    self.assertEqual(f[k], v)
156            f.close()
157
158            f = dumbdbm.open(_fname)
159            expected = d.items()
160            expected.sort()
161            got = f.items()
162            got.sort()
163            self.assertEqual(expected, got)
164            f.close()
165
166    def tearDown(self):
167        _delete_files()
168
169    def setUp(self):
170        _delete_files()
171
172def test_main():
173    try:
174        test_support.run_unittest(DumbDBMTestCase)
175    finally:
176        _delete_files()
177
178if __name__ == "__main__":
179    test_main()
180