blob: b641015b70629499c8cc969f3ffdfd28a43d934f [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
Antoine Pitrou2d350fd2013-08-01 20:56:12 +02005import _testcapi
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
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
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020027
28class GeneralTest(unittest.TestCase):
29
Collin Winter670e6922007-03-21 02:57:17 +000030 def setUp(self):
Victor Stinner457ab062011-01-05 23:47:00 +000031 self.save_stdout = sys.stdout
32 self.save_stderr = sys.stderr
Guido van Rossum34d19282007-08-09 01:03:29 +000033 self.stream = io.StringIO()
Collin Winter670e6922007-03-21 02:57:17 +000034 sys.stdout = sys.stderr = self.stream
35 atexit._clear()
Guido van Rossumd8faa362007-04-27 19:54:29 +000036
Collin Winter670e6922007-03-21 02:57:17 +000037 def tearDown(self):
Benjamin Petersonf10a79a2008-10-11 00:49:57 +000038 sys.stdout = self.save_stdout
39 sys.stderr = self.save_stderr
Collin Winter670e6922007-03-21 02:57:17 +000040 atexit._clear()
41
Skip Montanaro599bd5e2004-11-04 04:31:30 +000042 def test_args(self):
43 # be sure args are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000044 atexit.register(h1)
45 atexit.register(h4)
46 atexit.register(h4, 4, kw="abc")
47 atexit._run_exitfuncs()
48
49 self.assertEqual(self.stream.getvalue(),
50 "h4 (4,) {'kw': 'abc'}\nh4 () {}\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000051
Benjamin Petersonb8401c72008-09-23 03:14:49 +000052 def test_badargs(self):
53 atexit.register(lambda: 1, 0, 0, (x for x in (1,2)), 0, 0)
54 self.assertRaises(TypeError, atexit._run_exitfuncs)
55
Skip Montanaro599bd5e2004-11-04 04:31:30 +000056 def test_order(self):
57 # be sure handlers are executed in reverse order
Collin Winter670e6922007-03-21 02:57:17 +000058 atexit.register(h1)
59 atexit.register(h2)
60 atexit.register(h3)
61 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +000062
Collin Winter670e6922007-03-21 02:57:17 +000063 self.assertEqual(self.stream.getvalue(), "h3\nh2\nh1\n")
Fred Drakec19425d2000-06-28 15:07:31 +000064
Skip Montanaro599bd5e2004-11-04 04:31:30 +000065 def test_raise(self):
66 # be sure raises are handled properly
Collin Winter670e6922007-03-21 02:57:17 +000067 atexit.register(raise1)
68 atexit.register(raise2)
Guido van Rossumd8faa362007-04-27 19:54:29 +000069
Collin Winter670e6922007-03-21 02:57:17 +000070 self.assertRaises(TypeError, atexit._run_exitfuncs)
Guido van Rossumd8faa362007-04-27 19:54:29 +000071
Victor Stinner358e11d2011-01-05 03:54:25 +000072 def test_raise_unnormalized(self):
73 # Issue #10756: Make sure that an unnormalized exception is
74 # handled properly
75 atexit.register(lambda: 1 / 0)
76
77 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
78 self.assertIn("ZeroDivisionError", self.stream.getvalue())
79
Antoine Pitrou24201d42013-10-13 21:53:13 +020080 def test_print_tracebacks(self):
81 # Issue #18776: the tracebacks should be printed when errors occur.
82 def f():
83 1/0 # one
84 def g():
85 1/0 # two
86 def h():
87 1/0 # three
88 atexit.register(f)
89 atexit.register(g)
90 atexit.register(h)
91
92 self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
93 stderr = self.stream.getvalue()
94 self.assertEqual(stderr.count("ZeroDivisionError"), 3)
95 self.assertIn("# one", stderr)
96 self.assertIn("# two", stderr)
97 self.assertIn("# three", stderr)
98
Collin Winter670e6922007-03-21 02:57:17 +000099 def test_stress(self):
100 a = [0]
101 def inc():
102 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000103
Collin Winter670e6922007-03-21 02:57:17 +0000104 for i in range(128):
105 atexit.register(inc)
106 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000107
Collin Winter670e6922007-03-21 02:57:17 +0000108 self.assertEqual(a[0], 128)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000109
Collin Winter670e6922007-03-21 02:57:17 +0000110 def test_clear(self):
111 a = [0]
112 def inc():
113 a[0] += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000114
Collin Winter670e6922007-03-21 02:57:17 +0000115 atexit.register(inc)
116 atexit._clear()
117 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000118
Collin Winter670e6922007-03-21 02:57:17 +0000119 self.assertEqual(a[0], 0)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000120
Collin Winter670e6922007-03-21 02:57:17 +0000121 def test_unregister(self):
122 a = [0]
123 def inc():
124 a[0] += 1
125 def dec():
126 a[0] -= 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000127
128 for i in range(4):
Collin Winter670e6922007-03-21 02:57:17 +0000129 atexit.register(inc)
130 atexit.register(dec)
131 atexit.unregister(inc)
132 atexit._run_exitfuncs()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000133
Collin Winter670e6922007-03-21 02:57:17 +0000134 self.assertEqual(a[0], -1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000135
Collin Winter670e6922007-03-21 02:57:17 +0000136 def test_bound_methods(self):
137 l = []
138 atexit.register(l.append, 5)
139 atexit._run_exitfuncs()
140 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000141
Collin Winter670e6922007-03-21 02:57:17 +0000142 atexit.unregister(l.append)
143 atexit._run_exitfuncs()
144 self.assertEqual(l, [5])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145
Tim Peters012b69c2002-07-16 19:30:59 +0000146
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200147class SubinterpreterTest(unittest.TestCase):
148
149 def test_callbacks_leak(self):
150 # This test shows a leak in refleak mode if atexit doesn't
151 # take care to free callbacks in its per-subinterpreter module
152 # state.
153 n = atexit._ncallbacks()
154 code = r"""if 1:
155 import atexit
156 def f():
157 pass
158 atexit.register(f)
159 del atexit
160 """
161 ret = _testcapi.run_in_subinterp(code)
162 self.assertEqual(ret, 0)
163 self.assertEqual(atexit._ncallbacks(), n)
164
165 def test_callbacks_leak_refcycle(self):
166 # Similar to the above, but with a refcycle through the atexit
167 # module.
168 n = atexit._ncallbacks()
169 code = r"""if 1:
170 import atexit
171 def f():
172 pass
173 atexit.register(f)
174 atexit.__atexit = atexit
175 """
176 ret = _testcapi.run_in_subinterp(code)
177 self.assertEqual(ret, 0)
178 self.assertEqual(atexit._ncallbacks(), n)
179
180
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000181def test_main():
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200182 support.run_unittest(__name__)
183
Tim Peters012b69c2002-07-16 19:30:59 +0000184
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000185if __name__ == "__main__":
186 test_main()