blob: aa56388ef608817ca6b283bf32ca912a5f645f36 [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
Antoine Pitroufc5db952017-12-13 02:29:07 +01006from test.support import script_helper
Fred Drakec19425d2000-06-28 15:07:31 +00007
Collin Winter670e6922007-03-21 02:57:17 +00008### helpers
9def h1():
10 print("h1")
11
12def h2():
13 print("h2")
14
15def h3():
16 print("h3")
17
18def h4(*args, **kwargs):
19 print("h4", args, kwargs)
20
21def raise1():
22 raise TypeError
23
24def raise2():
25 raise SystemError
26
Serhiy Storchaka3fd54d42017-06-12 08:25:04 +030027def exit():
28 raise SystemExit
29
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020030
31class GeneralTest(unittest.TestCase):
32
Collin Winter670e6922007-03-21 02:57:17 +000033 def setUp(self):
Victor Stinner457ab062011-01-05 23:47:00 +000034 self.save_stdout = sys.stdout
35 self.save_stderr = sys.stderr
Guido van Rossum34d19282007-08-09 01:03:29 +000036 self.stream = io.StringIO()
Collin Winter670e6922007-03-21 02:57:17 +000037 sys.stdout = sys.stderr = self.stream
38 atexit._clear()
Guido van Rossumd8faa362007-04-27 19:54:29 +000039
Collin Winter670e6922007-03-21 02:57:17 +000040 def tearDown(self):
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000041 sys.stdout = self.save_stdout
42 sys.stderr = self.save_stderr
Collin Winter670e6922007-03-21 02:57:17 +000043 atexit._clear()
44
Skip Montanaro599bd5e2004-11-04 04:31:30 +000045 def test_args(self):
46 # be sure args are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000047 atexit.register(h1)
48 atexit.register(h4)
49 atexit.register(h4, 4, kw="abc")
50 atexit._run_exitfuncs()
51
52 self.assertEqual(self.stream.getvalue(),
53 "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000054
Benjamin Petersonb8401c72008-09-23 03:14:49 +000055 def test_badargs(self):
56 atexit.register(lambda: 1, 0, 0, (x for x in (1,2)), 0, 0)
57 self.assertRaises(TypeError, atexit._run_exitfuncs)
58
Skip Montanaro599bd5e2004-11-04 04:31:30 +000059 def test_order(self):
60 # be sure handlers are executed in reverse order
Collin Winter670e6922007-03-21 02:57:17 +000061 atexit.register(h1)
62 atexit.register(h2)
63 atexit.register(h3)
64 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +000065
Collin Winter670e6922007-03-21 02:57:17 +000066 self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000067
Skip Montanaro599bd5e2004-11-04 04:31:30 +000068 def test_raise(self):
69 # be sure raises are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000070 atexit.register(raise1)
71 atexit.register(raise2)
Guido van Rossumd8faa362007-04-27 19:54:29 +000072
Collin Winter670e6922007-03-21 02:57:17 +000073 self.assertRaises(TypeError, atexit._run_exitfuncs)
Guido van Rossumd8faa362007-04-27 19:54:29 +000074
Victor Stinner358e11d2011-01-05 03:54:25 +000075 def test_raise_unnormalized(self):
76 # Issue #10756: Make sure that an unnormalized exception is
77 # handled properly
78 atexit.register(lambda: 1 / 0)
79
80 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
81 self.assertIn("ZeroDivisionError", self.stream.getvalue())
82
Serhiy Storchaka3fd54d42017-06-12 08:25:04 +030083 def test_exit(self):
84 # be sure a SystemExit is handled properly
85 atexit.register(exit)
86
87 self.assertRaises(SystemExit, atexit._run_exitfuncs)
88 self.assertEqual(self.stream.getvalue(), '')
89
Antoine Pitrou24201d42013-10-13 21:53:13 +020090 def test_print_tracebacks(self):
91 # Issue #18776: the tracebacks should be printed when errors occur.
92 def f():
93 1/0 # one
94 def g():
95 1/0 # two
96 def h():
97 1/0 # three
98 atexit.register(f)
99 atexit.register(g)
100 atexit.register(h)
101
102 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
103 stderr = self.stream.getvalue()
104 self.assertEqual(stderr.count("ZeroDivisionError"), 3)
105 self.assertIn("# one", stderr)
106 self.assertIn("# two", stderr)
107 self.assertIn("# three", stderr)
108
Collin Winter670e6922007-03-21 02:57:17 +0000109 def test_stress(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 for i in range(128):
115 atexit.register(inc)
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], 128)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000119
Collin Winter670e6922007-03-21 02:57:17 +0000120 def test_clear(self):
121 a = [0]
122 def inc():
123 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000124
Collin Winter670e6922007-03-21 02:57:17 +0000125 atexit.register(inc)
126 atexit._clear()
127 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000128
Collin Winter670e6922007-03-21 02:57:17 +0000129 self.assertEqual(a[0], 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000130
Collin Winter670e6922007-03-21 02:57:17 +0000131 def test_unregister(self):
132 a = [0]
133 def inc():
134 a[0] += 1
135 def dec():
136 a[0] -= 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137
138 for i in range(4):
Collin Winter670e6922007-03-21 02:57:17 +0000139 atexit.register(inc)
140 atexit.register(dec)
141 atexit.unregister(inc)
142 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000143
Collin Winter670e6922007-03-21 02:57:17 +0000144 self.assertEqual(a[0], -1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145
Collin Winter670e6922007-03-21 02:57:17 +0000146 def test_bound_methods(self):
147 l = []
148 atexit.register(l.append, 5)
149 atexit._run_exitfuncs()
150 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000151
Collin Winter670e6922007-03-21 02:57:17 +0000152 atexit.unregister(l.append)
153 atexit._run_exitfuncs()
154 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000155
Antoine Pitroufc5db952017-12-13 02:29:07 +0100156 def test_shutdown(self):
157 # Actually test the shutdown mechanism in a subprocess
158 code = """if 1:
159 import atexit
160
161 def f(msg):
162 print(msg)
163
164 atexit.register(f, "one")
165 atexit.register(f, "two")
166 """
167 res = script_helper.assert_python_ok("-c", code)
168 self.assertEqual(res.out.decode().splitlines(), ["two", "one"])
169 self.assertFalse(res.err)
170
Tim Peters012b69c2002-07-16 19:30:59 +0000171
Serhiy Storchaka24c738a2017-03-19 20:20:10 +0200172@support.cpython_only
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200173class SubinterpreterTest(unittest.TestCase):
174
175 def test_callbacks_leak(self):
176 # This test shows a leak in refleak mode if atexit doesn't
177 # take care to free callbacks in its per-subinterpreter module
178 # state.
179 n = atexit._ncallbacks()
180 code = r"""if 1:
181 import atexit
182 def f():
183 pass
184 atexit.register(f)
185 del atexit
186 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100187 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200188 self.assertEqual(ret, 0)
189 self.assertEqual(atexit._ncallbacks(), n)
190
191 def test_callbacks_leak_refcycle(self):
192 # Similar to the above, but with a refcycle through the atexit
193 # module.
194 n = atexit._ncallbacks()
195 code = r"""if 1:
196 import atexit
197 def f():
198 pass
199 atexit.register(f)
200 atexit.__atexit = atexit
201 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100202 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200203 self.assertEqual(ret, 0)
204 self.assertEqual(atexit._ncallbacks(), n)
205
206
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000207if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500208 unittest.main()