blob: e0feef7c653606c68e49d7e1bf780ddaaff0f57a [file] [log] [blame]
Fred Drakec19425d2000-06-28 15:07:31 +00001import atexit
Marcel Plch776407f2017-12-20 11:17:58 +01002import os
Victor Stinner83d52042020-12-14 22:40:40 +01003import sys
4import textwrap
5import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Antoine Pitroufc5db952017-12-13 02:29:07 +01007from test.support import script_helper
Fred Drakec19425d2000-06-28 15:07:31 +00008
Antoine Pitrou2d350fd2013-08-01 20:56:12 +02009
10class GeneralTest(unittest.TestCase):
Victor Stinner3ca2b8f2020-12-15 17:12:02 +010011 def test_general(self):
12 # Run _test_atexit.py in a subprocess since it calls atexit._clear()
13 script = support.findfile("_test_atexit.py")
14 script_helper.run_test_script(script)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020015
Victor Stinner3ca2b8f2020-12-15 17:12:02 +010016class FunctionalTest(unittest.TestCase):
Antoine Pitroufc5db952017-12-13 02:29:07 +010017 def test_shutdown(self):
18 # Actually test the shutdown mechanism in a subprocess
Victor Stinner83d52042020-12-14 22:40:40 +010019 code = textwrap.dedent("""
Antoine Pitroufc5db952017-12-13 02:29:07 +010020 import atexit
21
22 def f(msg):
23 print(msg)
24
25 atexit.register(f, "one")
26 atexit.register(f, "two")
Victor Stinner83d52042020-12-14 22:40:40 +010027 """)
Antoine Pitroufc5db952017-12-13 02:29:07 +010028 res = script_helper.assert_python_ok("-c", code)
29 self.assertEqual(res.out.decode().splitlines(), ["two", "one"])
30 self.assertFalse(res.err)
31
Victor Stinnerb8fa1352020-12-15 14:34:19 +010032 def test_atexit_instances(self):
33 # bpo-42639: It is safe to have more than one atexit instance.
34 code = textwrap.dedent("""
35 import sys
36 import atexit as atexit1
37 del sys.modules['atexit']
38 import atexit as atexit2
39 del sys.modules['atexit']
40
41 assert atexit2 is not atexit1
42
43 atexit1.register(print, "atexit1")
44 atexit2.register(print, "atexit2")
45 """)
46 res = script_helper.assert_python_ok("-c", code)
47 self.assertEqual(res.out.decode().splitlines(), ["atexit2", "atexit1"])
48 self.assertFalse(res.err)
49
Tim Peters012b69c2002-07-16 19:30:59 +000050
Serhiy Storchaka24c738a2017-03-19 20:20:10 +020051@support.cpython_only
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020052class SubinterpreterTest(unittest.TestCase):
53
54 def test_callbacks_leak(self):
55 # This test shows a leak in refleak mode if atexit doesn't
56 # take care to free callbacks in its per-subinterpreter module
57 # state.
58 n = atexit._ncallbacks()
Victor Stinner83d52042020-12-14 22:40:40 +010059 code = textwrap.dedent(r"""
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020060 import atexit
61 def f():
62 pass
63 atexit.register(f)
64 del atexit
Victor Stinner83d52042020-12-14 22:40:40 +010065 """)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010066 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020067 self.assertEqual(ret, 0)
68 self.assertEqual(atexit._ncallbacks(), n)
69
70 def test_callbacks_leak_refcycle(self):
71 # Similar to the above, but with a refcycle through the atexit
72 # module.
73 n = atexit._ncallbacks()
Victor Stinner83d52042020-12-14 22:40:40 +010074 code = textwrap.dedent(r"""
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020075 import atexit
76 def f():
77 pass
78 atexit.register(f)
79 atexit.__atexit = atexit
Victor Stinner83d52042020-12-14 22:40:40 +010080 """)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010081 ret = support.run_in_subinterp(code)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020082 self.assertEqual(ret, 0)
83 self.assertEqual(atexit._ncallbacks(), n)
84
Marcel Plch776407f2017-12-20 11:17:58 +010085 def test_callback_on_subinterpreter_teardown(self):
86 # This tests if a callback is called on
87 # subinterpreter teardown.
88 expected = b"The test has passed!"
89 r, w = os.pipe()
90
Victor Stinner83d52042020-12-14 22:40:40 +010091 code = textwrap.dedent(r"""
Marcel Plch776407f2017-12-20 11:17:58 +010092 import os
93 import atexit
94 def callback():
95 os.write({:d}, b"The test has passed!")
96 atexit.register(callback)
Victor Stinner83d52042020-12-14 22:40:40 +010097 """.format(w))
Marcel Plch776407f2017-12-20 11:17:58 +010098 ret = support.run_in_subinterp(code)
99 os.close(w)
100 self.assertEqual(os.read(r, len(expected)), expected)
101 os.close(r)
102
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200103
Skip Montanaro599bd5e2004-11-04 04:31:30 +0000104if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500105 unittest.main()