| 
									
										
										
										
											2000-06-28 15:07:31 +00:00
										 |  |  | import atexit | 
					
						
							| 
									
										
										
										
											2017-12-20 11:17:58 +01:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  | import textwrap | 
					
						
							|  |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2008-05-20 21:35:26 +00:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2017-12-13 02:29:07 +01:00
										 |  |  | from test.support import script_helper | 
					
						
							| 
									
										
										
										
											2000-06-28 15:07:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class GeneralTest(unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2020-12-15 17:12:02 +01:00
										 |  |  |     def test_general(self): | 
					
						
							|  |  |  |         # Run _test_atexit.py in a subprocess since it calls atexit._clear() | 
					
						
							|  |  |  |         script = support.findfile("_test_atexit.py") | 
					
						
							|  |  |  |         script_helper.run_test_script(script) | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 17:12:02 +01:00
										 |  |  | class FunctionalTest(unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2017-12-13 02:29:07 +01:00
										 |  |  |     def test_shutdown(self): | 
					
						
							|  |  |  |         # Actually test the shutdown mechanism in a subprocess | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         code = textwrap.dedent("""
 | 
					
						
							| 
									
										
										
										
											2017-12-13 02:29:07 +01:00
										 |  |  |             import atexit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def f(msg): | 
					
						
							|  |  |  |                 print(msg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             atexit.register(f, "one") | 
					
						
							|  |  |  |             atexit.register(f, "two") | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         """)
 | 
					
						
							| 
									
										
										
										
											2017-12-13 02:29:07 +01:00
										 |  |  |         res = script_helper.assert_python_ok("-c", code) | 
					
						
							|  |  |  |         self.assertEqual(res.out.decode().splitlines(), ["two", "one"]) | 
					
						
							|  |  |  |         self.assertFalse(res.err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 14:34:19 +01:00
										 |  |  |     def test_atexit_instances(self): | 
					
						
							|  |  |  |         # bpo-42639: It is safe to have more than one atexit instance. | 
					
						
							|  |  |  |         code = textwrap.dedent("""
 | 
					
						
							|  |  |  |             import sys | 
					
						
							|  |  |  |             import atexit as atexit1 | 
					
						
							|  |  |  |             del sys.modules['atexit'] | 
					
						
							|  |  |  |             import atexit as atexit2 | 
					
						
							|  |  |  |             del sys.modules['atexit'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             assert atexit2 is not atexit1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             atexit1.register(print, "atexit1") | 
					
						
							|  |  |  |             atexit2.register(print, "atexit2") | 
					
						
							|  |  |  |         """)
 | 
					
						
							|  |  |  |         res = script_helper.assert_python_ok("-c", code) | 
					
						
							|  |  |  |         self.assertEqual(res.out.decode().splitlines(), ["atexit2", "atexit1"]) | 
					
						
							|  |  |  |         self.assertFalse(res.err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-16 19:30:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-19 20:20:10 +02:00
										 |  |  | @support.cpython_only | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  | class SubinterpreterTest(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_callbacks_leak(self): | 
					
						
							|  |  |  |         # This test shows a leak in refleak mode if atexit doesn't | 
					
						
							|  |  |  |         # take care to free callbacks in its per-subinterpreter module | 
					
						
							|  |  |  |         # state. | 
					
						
							|  |  |  |         n = atexit._ncallbacks() | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         code = textwrap.dedent(r"""
 | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  |             import atexit | 
					
						
							|  |  |  |             def f(): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             atexit.register(f) | 
					
						
							|  |  |  |             del atexit | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         """)
 | 
					
						
							| 
									
										
										
										
											2013-11-23 12:27:24 +01:00
										 |  |  |         ret = support.run_in_subinterp(code) | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  |         self.assertEqual(ret, 0) | 
					
						
							|  |  |  |         self.assertEqual(atexit._ncallbacks(), n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_callbacks_leak_refcycle(self): | 
					
						
							|  |  |  |         # Similar to the above, but with a refcycle through the atexit | 
					
						
							|  |  |  |         # module. | 
					
						
							|  |  |  |         n = atexit._ncallbacks() | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         code = textwrap.dedent(r"""
 | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  |             import atexit | 
					
						
							|  |  |  |             def f(): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             atexit.register(f) | 
					
						
							|  |  |  |             atexit.__atexit = atexit | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         """)
 | 
					
						
							| 
									
										
										
										
											2013-11-23 12:27:24 +01:00
										 |  |  |         ret = support.run_in_subinterp(code) | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  |         self.assertEqual(ret, 0) | 
					
						
							|  |  |  |         self.assertEqual(atexit._ncallbacks(), n) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-16 09:37:30 +02:00
										 |  |  |     @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") | 
					
						
							| 
									
										
										
										
											2017-12-20 11:17:58 +01:00
										 |  |  |     def test_callback_on_subinterpreter_teardown(self): | 
					
						
							|  |  |  |         # This tests if a callback is called on | 
					
						
							|  |  |  |         # subinterpreter teardown. | 
					
						
							|  |  |  |         expected = b"The test has passed!" | 
					
						
							|  |  |  |         r, w = os.pipe() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         code = textwrap.dedent(r"""
 | 
					
						
							| 
									
										
										
										
											2017-12-20 11:17:58 +01:00
										 |  |  |             import os | 
					
						
							|  |  |  |             import atexit | 
					
						
							|  |  |  |             def callback(): | 
					
						
							|  |  |  |                 os.write({:d}, b"The test has passed!") | 
					
						
							|  |  |  |             atexit.register(callback) | 
					
						
							| 
									
										
										
										
											2020-12-14 22:40:40 +01:00
										 |  |  |         """.format(w))
 | 
					
						
							| 
									
										
										
										
											2017-12-20 11:17:58 +01:00
										 |  |  |         ret = support.run_in_subinterp(code) | 
					
						
							|  |  |  |         os.close(w) | 
					
						
							|  |  |  |         self.assertEqual(os.read(r, len(expected)), expected) | 
					
						
							|  |  |  |         os.close(r) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-01 20:56:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-11-04 04:31:30 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2015-04-13 15:00:43 -05:00
										 |  |  |     unittest.main() |