test_dumbdbm.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. """Test script for the dumbdbm module
  2. Original by Roger E. Masse
  3. """
  4. import os
  5. import unittest
  6. import dumbdbm
  7. from test import test_support
  8. _fname = test_support.TESTFN
  9. def _delete_files():
  10. for ext in [".dir", ".dat", ".bak"]:
  11. try:
  12. os.unlink(_fname + ext)
  13. except OSError:
  14. pass
  15. class DumbDBMTestCase(unittest.TestCase):
  16. _dict = {'0': '',
  17. 'a': 'Python:',
  18. 'b': 'Programming',
  19. 'c': 'the',
  20. 'd': 'way',
  21. 'f': 'Guido',
  22. 'g': 'intended'
  23. }
  24. def __init__(self, *args):
  25. unittest.TestCase.__init__(self, *args)
  26. def test_dumbdbm_creation(self):
  27. f = dumbdbm.open(_fname, 'c')
  28. self.assertEqual(f.keys(), [])
  29. for key in self._dict:
  30. f[key] = self._dict[key]
  31. self.read_helper(f)
  32. f.close()
  33. @unittest.skipUnless(hasattr(os, 'chmod'), 'os.chmod not available')
  34. @unittest.skipUnless(hasattr(os, 'umask'), 'os.umask not available')
  35. def test_dumbdbm_creation_mode(self):
  36. try:
  37. old_umask = os.umask(0002)
  38. f = dumbdbm.open(_fname, 'c', 0637)
  39. f.close()
  40. finally:
  41. os.umask(old_umask)
  42. expected_mode = 0635
  43. if os.name != 'posix':
  44. # Windows only supports setting the read-only attribute.
  45. # This shouldn't fail, but doesn't work like Unix either.
  46. expected_mode = 0666
  47. import stat
  48. st = os.stat(_fname + '.dat')
  49. self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
  50. st = os.stat(_fname + '.dir')
  51. self.assertEqual(stat.S_IMODE(st.st_mode), expected_mode)
  52. def test_close_twice(self):
  53. f = dumbdbm.open(_fname)
  54. f['a'] = 'b'
  55. self.assertEqual(f['a'], 'b')
  56. f.close()
  57. f.close()
  58. def test_dumbdbm_modification(self):
  59. self.init_db()
  60. f = dumbdbm.open(_fname, 'w')
  61. self._dict['g'] = f['g'] = "indented"
  62. self.read_helper(f)
  63. f.close()
  64. def test_dumbdbm_read(self):
  65. self.init_db()
  66. f = dumbdbm.open(_fname, 'r')
  67. self.read_helper(f)
  68. f.close()
  69. def test_dumbdbm_keys(self):
  70. self.init_db()
  71. f = dumbdbm.open(_fname)
  72. keys = self.keys_helper(f)
  73. f.close()
  74. def test_write_write_read(self):
  75. # test for bug #482460
  76. f = dumbdbm.open(_fname)
  77. f['1'] = 'hello'
  78. f['1'] = 'hello2'
  79. f.close()
  80. f = dumbdbm.open(_fname)
  81. self.assertEqual(f['1'], 'hello2')
  82. f.close()
  83. def test_line_endings(self):
  84. # test for bug #1172763: dumbdbm would die if the line endings
  85. # weren't what was expected.
  86. f = dumbdbm.open(_fname)
  87. f['1'] = 'hello'
  88. f['2'] = 'hello2'
  89. f.close()
  90. # Mangle the file by adding \r before each newline
  91. data = open(_fname + '.dir').read()
  92. data = data.replace('\n', '\r\n')
  93. open(_fname + '.dir', 'wb').write(data)
  94. f = dumbdbm.open(_fname)
  95. self.assertEqual(f['1'], 'hello')
  96. self.assertEqual(f['2'], 'hello2')
  97. def read_helper(self, f):
  98. keys = self.keys_helper(f)
  99. for key in self._dict:
  100. self.assertEqual(self._dict[key], f[key])
  101. def init_db(self):
  102. f = dumbdbm.open(_fname, 'w')
  103. for k in self._dict:
  104. f[k] = self._dict[k]
  105. f.close()
  106. def keys_helper(self, f):
  107. keys = f.keys()
  108. keys.sort()
  109. dkeys = self._dict.keys()
  110. dkeys.sort()
  111. self.assertEqual(keys, dkeys)
  112. return keys
  113. # Perform randomized operations. This doesn't make assumptions about
  114. # what *might* fail.
  115. def test_random(self):
  116. import random
  117. d = {} # mirror the database
  118. for dummy in range(5):
  119. f = dumbdbm.open(_fname)
  120. for dummy in range(100):
  121. k = random.choice('abcdefghijklm')
  122. if random.random() < 0.2:
  123. if k in d:
  124. del d[k]
  125. del f[k]
  126. else:
  127. v = random.choice('abc') * random.randrange(10000)
  128. d[k] = v
  129. f[k] = v
  130. self.assertEqual(f[k], v)
  131. f.close()
  132. f = dumbdbm.open(_fname)
  133. expected = d.items()
  134. expected.sort()
  135. got = f.items()
  136. got.sort()
  137. self.assertEqual(expected, got)
  138. f.close()
  139. def test_eval(self):
  140. with open(_fname + '.dir', 'w') as stream:
  141. stream.write("str(__import__('sys').stdout.write('Hacked!')), 0\n")
  142. with test_support.captured_stdout() as stdout:
  143. with self.assertRaises(ValueError):
  144. dumbdbm.open(_fname).close()
  145. self.assertEqual(stdout.getvalue(), '')
  146. def tearDown(self):
  147. _delete_files()
  148. def setUp(self):
  149. _delete_files()
  150. def test_main():
  151. try:
  152. test_support.run_unittest(DumbDBMTestCase)
  153. finally:
  154. _delete_files()
  155. if __name__ == "__main__":
  156. test_main()