blob: 1d0b018aafaf934349eafe57d652b5345e545cf9 [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
Serhiy Storchaka3fd54d42017-06-12 08:25:04 +030026def exit():
27 raise SystemExit
28
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020029
30class GeneralTest(unittest.TestCase):
31
Collin Winter670e6922007-03-21 02:57:17 +000032 def setUp(self):
Victor Stinner457ab062011-01-05 23:47:00 +000033 self.save_stdout = sys.stdout
34 self.save_stderr = sys.stderr
Guido van Rossum34d19282007-08-09 01:03:29 +000035 self.stream = io.StringIO()
Collin Winter670e6922007-03-21 02:57:17 +000036 sys.stdout = sys.stderr = self.stream
37 atexit._clear()
Guido van Rossumd8faa362007-04-27 19:54:29 +000038
Collin Winter670e6922007-03-21 02:57:17 +000039 def tearDown(self):
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000040 sys.stdout = self.save_stdout
41 sys.stderr = self.save_stderr
Collin Winter670e6922007-03-21 02:57:17 +000042 atexit._clear()
43
Skip Montanaro599bd5e2004-11-04 04:31:30 +000044 def test_args(self):
45 # be sure args are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000046 atexit.register(h1)
47 atexit.register(h4)
48 atexit.register(h4, 4, kw="abc")
49 atexit._run_exitfuncs()
50
51 self.assertEqual(self.stream.getvalue(),
52 "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000053
Benjamin Petersonb8401c72008-09-23 03:14:49 +000054 def test_badargs(self):
55 atexit.register(lambda: 1, 0, 0, (x for x in (1,2)), 0, 0)
56 self.assertRaises(TypeError, atexit._run_exitfuncs)
57
Skip Montanaro599bd5e2004-11-04 04:31:30 +000058 def test_order(self):
59 # be sure handlers are executed in reverse order
Collin Winter670e6922007-03-21 02:57:17 +000060 atexit.register(h1)
61 atexit.register(h2)
62 atexit.register(h3)
63 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +000064
Collin Winter670e6922007-03-21 02:57:17 +000065 self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000066
Skip Montanaro599bd5e2004-11-04 04:31:30 +000067 def test_raise(self):
68 # be sure raises are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000069 atexit.register(raise1)
70 atexit.register(raise2)
Guido van Rossumd8faa362007-04-27 19:54:29 +000071
Collin Winter670e6922007-03-21 02:57:17 +000072 self.assertRaises(TypeError, atexit._run_exitfuncs)
Guido van Rossumd8faa362007-04-27 19:54:29 +000073
Victor Stinner358e11d2011-01-05 03:54:25 +000074 def test_raise_unnormalized(self):
75 # Issue #10756: Make sure that an unnormalized exception is
76 # handled properly
77 atexit.register(lambda: 1 / 0)
78
79 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
80 self.assertIn("ZeroDivisionError", self.stream.getvalue())
81
Serhiy Storchaka3fd54d42017-06-12 08:25:04 +030082 def test_exit(self):
83 # be sure a SystemExit is handled properly
84 atexit.register(exit)
85
86 self.assertRaises(SystemExit, atexit._run_exitfuncs)
87 self.assertEqual(self.stream.getvalue(), '')
88
Antoine Pitrou24201d42013-10-13 21:53:13 +020089 def test_print_tracebacks(self):
90 # Issue #18776: the tracebacks should be printed when errors occur.
91 def f():
92 1/0 # one
93 def g():
94 1/0 # two
95 def h():
96 1/0 # three
97 atexit.register(f)
98 atexit.register(g)
99 atexit.register(h)
100
101 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
102 stderr = self.stream.getvalue()
103 self.assertEqual(stderr.count("ZeroDivisionError"), 3)
104 self.assertIn("# one", stderr)
105 self.assertIn("# two", stderr)
106 self.assertIn("# three", stderr)
107
Collin Winter670e6922007-03-21 02:57:17 +0000108 def test_stress(self):
109 a = [0]
110 def inc():
111 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000112
Collin Winter670e6922007-03-21 02:57:17 +0000113 for i in range(128):
114 atexit.register(inc)
115 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000116
Collin Winter670e6922007-03-21 02:57:17 +0000117 self.assertEqual(a[0], 128)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000118
Collin Winter670e6922007-03-21 02:57:17 +0000119 def test_clear(self):
120 a = [0]
121 def inc():
122 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000123
Collin Winter670e6922007-03-21 02:57:17 +0000124 atexit.register(inc)
125 atexit._clear()
126 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000127
Collin Winter670e6922007-03-21 02:57:17 +0000128 self.assertEqual(a[0], 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000129
Collin Winter670e6922007-03-21 02:57:17 +0000130 def test_unregister(self):
131 a = [0]
132 def inc():
133 a[0] += 1
134 def dec():
135 a[0] -= 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000136
137 for i in range(4):
Collin Winter670e6922007-03-21 02:57:17 +0000138 atexit.register(inc)
139 atexit.register(dec)
140 atexit.unregister(inc)
141 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000142
Collin Winter670e6922007-03-21 02:57:17 +0000143 self.assertEqual(a[0], -1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144
Collin Winter670e6922007-03-21 02:57:17 +0000145 def test_bound_methods(self):
146 l = []
147 atexit.register(l.append, 5)
148 atexit._run_exitfuncs()
149 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000150
Collin Winter670e6922007-03-21 02:57:17 +0000151 atexit.unregister(l.append)
152 atexit._run_exitfuncs()
153 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000154
Tim Peters012b69c2002-07-16 19:30:59 +0000155
Serhiy Storchaka24c738a2017-03-19 20:20:10 +0200156@support.cpython_only
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200157class SubinterpreterTest(unittest.TestCase):
158
159 def test_callbacks_leak(self):
160 # This test shows a leak in refleak mode if atexit doesn't
161 # take care to free callbacks in its per-subinterpreter module
162 # state.
163 n = atexit._ncallbacks()
164 code = r"""if 1:
165 import atexit
166 def f():
167 pass
168 atexit.register(f)
169 del atexit
170 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100171 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200172 self.assertEqual(ret, 0)
173 self.assertEqual(atexit._ncallbacks(), n)
174
175 def test_callbacks_leak_refcycle(self):
176 # Similar to the above, but with a refcycle through the atexit
177 # module.
178 n = atexit._ncallbacks()
179 code = r"""if 1:
180 import atexit
181 def f():
182 pass
183 atexit.register(f)
184 atexit.__atexit = atexit
185 """
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100186 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200187 self.assertEqual(ret, 0)
188 self.assertEqual(atexit._ncallbacks(), n)
189
190
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000191if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500192 unittest.main()