PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Lib/test/test_atexit.py

https://gitlab.com/unofficial-mirrors/cpython
Python | 181 lines | 136 code | 35 blank | 10 comment | 3 complexity | c7cb05a1d20e652dbb8c0c044ed22729 MD5 | raw file
  1. import sys
  2. import unittest
  3. import io
  4. import atexit
  5. from test import support
  6. ### helpers
  7. def h1():
  8. print("h1")
  9. def h2():
  10. print("h2")
  11. def h3():
  12. print("h3")
  13. def h4(*args, **kwargs):
  14. print("h4", args, kwargs)
  15. def raise1():
  16. raise TypeError
  17. def raise2():
  18. raise SystemError
  19. class GeneralTest(unittest.TestCase):
  20. def setUp(self):
  21. self.save_stdout = sys.stdout
  22. self.save_stderr = sys.stderr
  23. self.stream = io.StringIO()
  24. sys.stdout = sys.stderr = self.stream
  25. atexit._clear()
  26. def tearDown(self):
  27. sys.stdout = self.save_stdout
  28. sys.stderr = self.save_stderr
  29. atexit._clear()
  30. def test_args(self):
  31. # be sure args are handled properly
  32. atexit.register(h1)
  33. atexit.register(h4)
  34. atexit.register(h4, 4, kw="abc")
  35. atexit._run_exitfuncs()
  36. self.assertEqual(self.stream.getvalue(),
  37. "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
  38. def test_badargs(self):
  39. atexit.register(lambda: 1, 0, 0, (x for x in (1,2)), 0, 0)
  40. self.assertRaises(TypeError, atexit._run_exitfuncs)
  41. def test_order(self):
  42. # be sure handlers are executed in reverse order
  43. atexit.register(h1)
  44. atexit.register(h2)
  45. atexit.register(h3)
  46. atexit._run_exitfuncs()
  47. self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
  48. def test_raise(self):
  49. # be sure raises are handled properly
  50. atexit.register(raise1)
  51. atexit.register(raise2)
  52. self.assertRaises(TypeError, atexit._run_exitfuncs)
  53. def test_raise_unnormalized(self):
  54. # Issue #10756: Make sure that an unnormalized exception is
  55. # handled properly
  56. atexit.register(lambda: 1 / 0)
  57. self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
  58. self.assertIn("ZeroDivisionError", self.stream.getvalue())
  59. def test_print_tracebacks(self):
  60. # Issue #18776: the tracebacks should be printed when errors occur.
  61. def f():
  62. 1/0 # one
  63. def g():
  64. 1/0 # two
  65. def h():
  66. 1/0 # three
  67. atexit.register(f)
  68. atexit.register(g)
  69. atexit.register(h)
  70. self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
  71. stderr = self.stream.getvalue()
  72. self.assertEqual(stderr.count("ZeroDivisionError"), 3)
  73. self.assertIn("# one", stderr)
  74. self.assertIn("# two", stderr)
  75. self.assertIn("# three", stderr)
  76. def test_stress(self):
  77. a = [0]
  78. def inc():
  79. a[0] += 1
  80. for i in range(128):
  81. atexit.register(inc)
  82. atexit._run_exitfuncs()
  83. self.assertEqual(a[0], 128)
  84. def test_clear(self):
  85. a = [0]
  86. def inc():
  87. a[0] += 1
  88. atexit.register(inc)
  89. atexit._clear()
  90. atexit._run_exitfuncs()
  91. self.assertEqual(a[0], 0)
  92. def test_unregister(self):
  93. a = [0]
  94. def inc():
  95. a[0] += 1
  96. def dec():
  97. a[0] -= 1
  98. for i in range(4):
  99. atexit.register(inc)
  100. atexit.register(dec)
  101. atexit.unregister(inc)
  102. atexit._run_exitfuncs()
  103. self.assertEqual(a[0], -1)
  104. def test_bound_methods(self):
  105. l = []
  106. atexit.register(l.append, 5)
  107. atexit._run_exitfuncs()
  108. self.assertEqual(l, [5])
  109. atexit.unregister(l.append)
  110. atexit._run_exitfuncs()
  111. self.assertEqual(l, [5])
  112. class SubinterpreterTest(unittest.TestCase):
  113. def test_callbacks_leak(self):
  114. # This test shows a leak in refleak mode if atexit doesn't
  115. # take care to free callbacks in its per-subinterpreter module
  116. # state.
  117. n = atexit._ncallbacks()
  118. code = r"""if 1:
  119. import atexit
  120. def f():
  121. pass
  122. atexit.register(f)
  123. del atexit
  124. """
  125. ret = support.run_in_subinterp(code)
  126. self.assertEqual(ret, 0)
  127. self.assertEqual(atexit._ncallbacks(), n)
  128. def test_callbacks_leak_refcycle(self):
  129. # Similar to the above, but with a refcycle through the atexit
  130. # module.
  131. n = atexit._ncallbacks()
  132. code = r"""if 1:
  133. import atexit
  134. def f():
  135. pass
  136. atexit.register(f)
  137. atexit.__atexit = atexit
  138. """
  139. ret = support.run_in_subinterp(code)
  140. self.assertEqual(ret, 0)
  141. self.assertEqual(atexit._ncallbacks(), n)
  142. if __name__ == "__main__":
  143. unittest.main()