blob: 70d2f1cf54b76294023c69331132d4bf5d951109 [file] [log] [blame]
Tim Petersc7b6bed2002-07-17 00:34:26 +00001import sys
Skip Montanaro599bd5e2004-11-04 04:31:30 +00002import unittest
Guido van Rossum34d19282007-08-09 01:03:29 +00003import io
Fred Drakec19425d2000-06-28 15:07:31 +00004import atexit
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Fred Drakec19425d2000-06-28 15:07:31 +00006
Collin Winter670e6922007-03-21 02:57:17 +00007### helpers
8def h1():
9 print("h1")
10
11def h2():
12 print("h2")
13
14def h3():
15 print("h3")
16
17def h4(*args, **kwargs):
18 print("h4", args, kwargs)
19
20def raise1():
21 raise TypeError
22
23def raise2():
24 raise SystemError
25
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020026
27class GeneralTest(unittest.TestCase):
28
Collin Winter670e6922007-03-21 02:57:17 +000029 def setUp(self):
Victor Stinner457ab062011-01-05 23:47:00 +000030 self.save_stdout = sys.stdout
31 self.save_stderr = sys.stderr
Guido van Rossum34d19282007-08-09 01:03:29 +000032 self.stream = io.StringIO()
Collin Winter670e6922007-03-21 02:57:17 +000033 sys.stdout = sys.stderr = self.stream
34 atexit._clear()
Guido van Rossumd8faa362007-04-27 19:54:29 +000035
Collin Winter670e6922007-03-21 02:57:17 +000036 def tearDown(self):
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000037 sys.stdout = self.save_stdout
38 sys.stderr = self.save_stderr
Collin Winter670e6922007-03-21 02:57:17 +000039 atexit._clear()
40
Skip Montanaro599bd5e2004-11-04 04:31:30 +000041 def test_args(self):
42 # be sure args are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000043 atexit.register(h1)
44 atexit.register(h4)
45 atexit.register(h4, 4, kw="abc")
46 atexit._run_exitfuncs()
47
48 self.assertEqual(self.stream.getvalue(),
49 "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000050
Benjamin Petersonb8401c72008-09-23 03:14:49 +000051 def test_badargs(self):
52 atexit.register(lambda: 1, 0, 0, (x for x in (1,2)), 0, 0)
53 self.assertRaises(TypeError, atexit._run_exitfuncs)
54
Skip Montanaro599bd5e2004-11-04 04:31:30 +000055 def test_order(self):
56 # be sure handlers are executed in reverse order
Collin Winter670e6922007-03-21 02:57:17 +000057 atexit.register(h1)
58 atexit.register(h2)
59 atexit.register(h3)
60 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +000061
Collin Winter670e6922007-03-21 02:57:17 +000062 self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000063
Skip Montanaro599bd5e2004-11-04 04:31:30 +000064 def test_raise(self):
65 # be sure raises are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000066 atexit.register(raise1)
67 atexit.register(raise2)
Guido van Rossumd8faa362007-04-27 19:54:29 +000068
Collin Winter670e6922007-03-21 02:57:17 +000069 self.assertRaises(TypeError, atexit._run_exitfuncs)
Guido van Rossumd8faa362007-04-27 19:54:29 +000070
Victor Stinner358e11d2011-01-05 03:54:25 +000071 def test_raise_unnormalized(self):
72 # Issue #10756: Make sure that an unnormalized exception is
73 # handled properly
74 atexit.register(lambda: 1 / 0)
75
76 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
77 self.assertIn("ZeroDivisionError", self.stream.getvalue())
78
Antoine Pitrou24201d42013-10-13 21:53:13 +020079 def test_print_tracebacks(self):
80 # Issue #18776: the tracebacks should be printed when errors occur.
81 def f():
82 1/0 # one
83 def g():
84 1/0 # two
85 def h():
86 1/0 # three
87 atexit.register(f)
88 atexit.register(g)
89 atexit.register(h)
90
91 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
92 stderr = self.stream.getvalue()
93 self.assertEqual(stderr.count("ZeroDivisionError"), 3)
94 self.assertIn("# one", stderr)
95 self.assertIn("# two", stderr)
96 self.assertIn("# three", stderr)
97
Collin Winter670e6922007-03-21 02:57:17 +000098 def test_stress(self):
99 a = [0]
100 def inc():
101 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000102
Collin Winter670e6922007-03-21 02:57:17 +0000103 for i in range(128):
104 atexit.register(inc)
105 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000106
Collin Winter670e6922007-03-21 02:57:17 +0000107 self.assertEqual(a[0], 128)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000108
Collin Winter670e6922007-03-21 02:57:17 +0000109 def test_clear(self):
110 a = [0]
111 def inc():
112 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000113
Collin Winter670e6922007-03-21 02:57:17 +0000114 atexit.register(inc)
115 atexit._clear()
116 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000117
Collin Winter670e6922007-03-21 02:57:17 +0000118 self.assertEqual(a[0], 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000119
Collin Winter670e6922007-03-21 02:57:17 +0000120 def test_unregister(self):
121 a = [0]
122 def inc():
123 a[0] += 1
124 def dec():
125 a[0] -= 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000126
127 for i in range(4):
Collin Winter670e6922007-03-21 02:57:17 +0000128 atexit.register(inc)
129 atexit.register(dec)
130 atexit.unregister(inc)
131 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000132
Collin Winter670e6922007-03-21 02:57:17 +0000133 self.assertEqual(a[0], -1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000134
Collin Winter670e6922007-03-21 02:57:17 +0000135 def test_bound_methods(self):
136 l = []
137 atexit.register(l.append, 5)
138 atexit._run_exitfuncs()
139 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140
Collin Winter670e6922007-03-21 02:57:17 +0000141 atexit.unregister(l.append)
142 atexit._run_exitfuncs()
143 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144
Tim Peters012b69c2002-07-16 19:30:59 +0000145
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200146class SubinterpreterTest(unittest.TestCase):
147
148 def test_callbacks_leak(self):
149 # This test shows a leak in refleak mode if atexit doesn't
150 # take care to free callbacks in its per-subinterpreter module
151 # state.
152 n = atexit._ncallbacks()
153 code = r"""if 1:
154 import atexit
155 def f():
156 pass
157 atexit.register(f)
158 del atexit
159 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100160 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200161 self.assertEqual(ret, 0)
162 self.assertEqual(atexit._ncallbacks(), n)
163
164 def test_callbacks_leak_refcycle(self):
165 # Similar to the above, but with a refcycle through the atexit
166 # module.
167 n = atexit._ncallbacks()
168 code = r"""if 1:
169 import atexit
170 def f():
171 pass
172 atexit.register(f)
173 atexit.__atexit = atexit
174 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100175 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200176 self.assertEqual(ret, 0)
177 self.assertEqual(atexit._ncallbacks(), n)
178
179
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000180def test_main():
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200181 support.run_unittest(__name__)
182
Tim Peters012b69c2002-07-16 19:30:59 +0000183
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000184if __name__ == "__main__":
185 test_main()