(root)/
Python-3.11.7/
Lib/
test/
test_atexit.py
       1  import atexit
       2  import os
       3  import sys
       4  import textwrap
       5  import unittest
       6  from test import support
       7  from test.support import script_helper
       8  
       9  
      10  class ESC[4;38;5;81mGeneralTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      11      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)
      15  
      16  class ESC[4;38;5;81mFunctionalTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      17      def test_shutdown(self):
      18          # Actually test the shutdown mechanism in a subprocess
      19          code = textwrap.dedent("""
      20              import atexit
      21  
      22              def f(msg):
      23                  print(msg)
      24  
      25              atexit.register(f, "one")
      26              atexit.register(f, "two")
      27          """)
      28          res = script_helper.assert_python_ok("-c", code)
      29          self.assertEqual(res.out.decode().splitlines(), ["two", "one"])
      30          self.assertFalse(res.err)
      31  
      32      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  
      50  
      51  @support.cpython_only
      52  class ESC[4;38;5;81mSubinterpreterTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      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()
      59          code = textwrap.dedent(r"""
      60              import atexit
      61              def f():
      62                  pass
      63              atexit.register(f)
      64              del atexit
      65          """)
      66          ret = support.run_in_subinterp(code)
      67          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()
      74          code = textwrap.dedent(r"""
      75              import atexit
      76              def f():
      77                  pass
      78              atexit.register(f)
      79              atexit.__atexit = atexit
      80          """)
      81          ret = support.run_in_subinterp(code)
      82          self.assertEqual(ret, 0)
      83          self.assertEqual(atexit._ncallbacks(), n)
      84  
      85      @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
      86      def test_callback_on_subinterpreter_teardown(self):
      87          # This tests if a callback is called on
      88          # subinterpreter teardown.
      89          expected = b"The test has passed!"
      90          r, w = os.pipe()
      91  
      92          code = textwrap.dedent(r"""
      93              import os
      94              import atexit
      95              def callback():
      96                  os.write({:d}, b"The test has passed!")
      97              atexit.register(callback)
      98          """.format(w))
      99          ret = support.run_in_subinterp(code)
     100          os.close(w)
     101          self.assertEqual(os.read(r, len(expected)), expected)
     102          os.close(r)
     103  
     104  
     105  if __name__ == "__main__":
     106      unittest.main()