_test_atexit.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. """
  2. Tests run by test_atexit in a subprocess since it clears atexit callbacks.
  3. """
  4. import atexit
  5. import sys
  6. import unittest
  7. from test import support
  8. class GeneralTest(unittest.TestCase):
  9. def setUp(self):
  10. atexit._clear()
  11. def tearDown(self):
  12. atexit._clear()
  13. def assert_raises_unraisable(self, exc_type, func, *args):
  14. with support.catch_unraisable_exception() as cm:
  15. atexit.register(func, *args)
  16. atexit._run_exitfuncs()
  17. self.assertEqual(cm.unraisable.object, func)
  18. self.assertEqual(cm.unraisable.exc_type, exc_type)
  19. self.assertEqual(type(cm.unraisable.exc_value), exc_type)
  20. def test_order(self):
  21. # Check that callbacks are called in reverse order with the expected
  22. # positional and keyword arguments.
  23. calls = []
  24. def func1(*args, **kwargs):
  25. calls.append(('func1', args, kwargs))
  26. def func2(*args, **kwargs):
  27. calls.append(('func2', args, kwargs))
  28. # be sure args are handled properly
  29. atexit.register(func1, 1, 2)
  30. atexit.register(func2)
  31. atexit.register(func2, 3, key="value")
  32. atexit._run_exitfuncs()
  33. self.assertEqual(calls,
  34. [('func2', (3,), {'key': 'value'}),
  35. ('func2', (), {}),
  36. ('func1', (1, 2), {})])
  37. def test_badargs(self):
  38. def func():
  39. pass
  40. # func() has no parameter, but it's called with 2 parameters
  41. self.assert_raises_unraisable(TypeError, func, 1 ,2)
  42. def test_raise(self):
  43. def raise_type_error():
  44. raise TypeError
  45. self.assert_raises_unraisable(TypeError, raise_type_error)
  46. def test_raise_unnormalized(self):
  47. # bpo-10756: Make sure that an unnormalized exception is handled
  48. # properly.
  49. def div_zero():
  50. 1 / 0
  51. self.assert_raises_unraisable(ZeroDivisionError, div_zero)
  52. def test_exit(self):
  53. self.assert_raises_unraisable(SystemExit, sys.exit)
  54. def test_stress(self):
  55. a = [0]
  56. def inc():
  57. a[0] += 1
  58. for i in range(128):
  59. atexit.register(inc)
  60. atexit._run_exitfuncs()
  61. self.assertEqual(a[0], 128)
  62. def test_clear(self):
  63. a = [0]
  64. def inc():
  65. a[0] += 1
  66. atexit.register(inc)
  67. atexit._clear()
  68. atexit._run_exitfuncs()
  69. self.assertEqual(a[0], 0)
  70. def test_unregister(self):
  71. a = [0]
  72. def inc():
  73. a[0] += 1
  74. def dec():
  75. a[0] -= 1
  76. for i in range(4):
  77. atexit.register(inc)
  78. atexit.register(dec)
  79. atexit.unregister(inc)
  80. atexit._run_exitfuncs()
  81. self.assertEqual(a[0], -1)
  82. def test_bound_methods(self):
  83. l = []
  84. atexit.register(l.append, 5)
  85. atexit._run_exitfuncs()
  86. self.assertEqual(l, [5])
  87. atexit.unregister(l.append)
  88. atexit._run_exitfuncs()
  89. self.assertEqual(l, [5])
  90. def test_atexit_with_unregistered_function(self):
  91. # See bpo-46025 for more info
  92. def func():
  93. atexit.unregister(func)
  94. 1/0
  95. atexit.register(func)
  96. try:
  97. with support.catch_unraisable_exception() as cm:
  98. atexit._run_exitfuncs()
  99. self.assertEqual(cm.unraisable.object, func)
  100. self.assertEqual(cm.unraisable.exc_type, ZeroDivisionError)
  101. self.assertEqual(type(cm.unraisable.exc_value), ZeroDivisionError)
  102. finally:
  103. atexit.unregister(func)
  104. if __name__ == "__main__":
  105. unittest.main()