|
1 | 1 | import unittest
|
2 |
| -from test.support import verbose, run_unittest |
| 2 | +from test.support import verbose, run_unittest, strip_python_stderr |
3 | 3 | import sys
|
4 | 4 | import gc
|
5 | 5 | import weakref
|
@@ -466,6 +466,42 @@ def callback(ignored):
|
466 | 466 | # would be damaged, with an empty __dict__.
|
467 | 467 | self.assertEqual(x, None)
|
468 | 468 |
|
| 469 | + def test_garbage_at_shutdown(self): |
| 470 | + import subprocess |
| 471 | + code = """if 1: |
| 472 | + import gc |
| 473 | + class X: |
| 474 | + def __init__(self, name): |
| 475 | + self.name = name |
| 476 | + def __repr__(self): |
| 477 | + return "<X %%r>" %% self.name |
| 478 | + def __del__(self): |
| 479 | + pass |
| 480 | +
|
| 481 | + x = X('first') |
| 482 | + x.x = x |
| 483 | + x.y = X('second') |
| 484 | + del x |
| 485 | + if %d: |
| 486 | + gc.set_debug(gc.DEBUG_UNCOLLECTABLE) |
| 487 | + """ |
| 488 | + def run_command(code): |
| 489 | + p = subprocess.Popen([sys.executable, "-c", code], |
| 490 | + stdout=subprocess.PIPE, |
| 491 | + stderr=subprocess.PIPE) |
| 492 | + stdout, stderr = p.communicate() |
| 493 | + self.assertEqual(p.returncode, 0) |
| 494 | + self.assertEqual(stdout.strip(), b"") |
| 495 | + return strip_python_stderr(stderr) |
| 496 | + |
| 497 | + stderr = run_command(code % 0) |
| 498 | + self.assertIn(b"gc: 2 uncollectable objects at shutdown", stderr) |
| 499 | + self.assertNotIn(b"[<X 'first'>, <X 'second'>]", stderr) |
| 500 | + # With DEBUG_UNCOLLECTABLE, the garbage list gets printed |
| 501 | + stderr = run_command(code % 1) |
| 502 | + self.assertIn(b"gc: 2 uncollectable objects at shutdown", stderr) |
| 503 | + self.assertIn(b"[<X 'first'>, <X 'second'>]", stderr) |
| 504 | + |
469 | 505 | class GCTogglingTests(unittest.TestCase):
|
470 | 506 | def setUp(self):
|
471 | 507 | gc.enable()
|
|
0 commit comments