Skip to content

Commit 2a8127c

Browse files
bpo-25130: Add calls of gc.collect() in tests to support PyPy (GH-28005)
1 parent 07d3d54 commit 2a8127c

36 files changed

+144
-14
lines changed

Lib/test/_test_multiprocessing.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ def test_lose_target_ref(self):
611611
del c
612612
p.start()
613613
p.join()
614+
gc.collect() # For PyPy or other GCs.
614615
self.assertIs(wr(), None)
615616
self.assertEqual(q.get(), 5)
616617
close_queue(q)
@@ -2667,6 +2668,7 @@ def test_release_task_refs(self):
26672668
self.pool.map(identity, objs)
26682669

26692670
del objs
2671+
gc.collect() # For PyPy or other GCs.
26702672
time.sleep(DELTA) # let threaded cleanup code run
26712673
self.assertEqual(set(wr() for wr in refs), {None})
26722674
# With a process pool, copies of the objects are returned, check
@@ -4198,6 +4200,7 @@ def setUp(self):
41984200
util._finalizer_registry.clear()
41994201

42004202
def tearDown(self):
4203+
gc.collect() # For PyPy or other GCs.
42014204
self.assertFalse(util._finalizer_registry)
42024205
util._finalizer_registry.update(self.registry_backup)
42034206

@@ -4209,12 +4212,14 @@ class Foo(object):
42094212
a = Foo()
42104213
util.Finalize(a, conn.send, args=('a',))
42114214
del a # triggers callback for a
4215+
gc.collect() # For PyPy or other GCs.
42124216

42134217
b = Foo()
42144218
close_b = util.Finalize(b, conn.send, args=('b',))
42154219
close_b() # triggers callback for b
42164220
close_b() # does nothing because callback has already been called
42174221
del b # does nothing because callback has already been called
4222+
gc.collect() # For PyPy or other GCs.
42184223

42194224
c = Foo()
42204225
util.Finalize(c, conn.send, args=('c',))

Lib/test/lock_tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import os
6+
import gc
67
import sys
78
import time
89
from _thread import start_new_thread, TIMEOUT_MAX
@@ -221,6 +222,7 @@ def test_weakref_deleted(self):
221222
lock = self.locktype()
222223
ref = weakref.ref(lock)
223224
del lock
225+
gc.collect() # For PyPy or other GCs.
224226
self.assertIsNone(ref())
225227

226228

Lib/test/test_array.py

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,7 @@ def test_weakref(self):
10971097
p = weakref.proxy(s)
10981098
self.assertEqual(p.tobytes(), s.tobytes())
10991099
s = None
1100+
support.gc_collect() # For PyPy or other GCs.
11001101
self.assertRaises(ReferenceError, len, p)
11011102

11021103
@unittest.skipUnless(hasattr(sys, 'getrefcount'),

Lib/test/test_asyncgen.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import unittest
44

55
from test.support.import_helper import import_module
6+
from test.support import gc_collect
67
asyncio = import_module("asyncio")
78

89

@@ -871,6 +872,7 @@ async def run():
871872
await g.__anext__()
872873
await g.__anext__()
873874
del g
875+
gc_collect() # For PyPy or other GCs.
874876

875877
await asyncio.sleep(0.1)
876878

Lib/test/test_asyncio/test_tasks.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,6 +2307,7 @@ async def coro():
23072307
self.new_task(self.loop, gen)
23082308
finally:
23092309
gen.close()
2310+
gc.collect() # For PyPy or other GCs.
23102311

23112312
self.assertTrue(m_log.error.called)
23122313
message = m_log.error.call_args[0][0]

Lib/test/test_code.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@
137137
except ImportError:
138138
ctypes = None
139139
from test.support import (run_doctest, run_unittest, cpython_only,
140-
check_impl_detail, requires_debug_ranges)
140+
check_impl_detail, requires_debug_ranges,
141+
gc_collect)
141142
from test.support.script_helper import assert_python_ok
142143

143144

@@ -510,6 +511,7 @@ def callback(code):
510511
coderef = weakref.ref(f.__code__, callback)
511512
self.assertTrue(bool(coderef()))
512513
del f
514+
gc_collect() # For PyPy or other GCs.
513515
self.assertFalse(bool(coderef()))
514516
self.assertTrue(self.called)
515517

Lib/test/test_concurrent_futures.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ def test_thread_names_assigned(self):
463463
executor.map(abs, range(-5, 5))
464464
threads = executor._threads
465465
del executor
466+
support.gc_collect() # For PyPy or other GCs.
466467

467468
for t in threads:
468469
self.assertRegex(t.name, r'^SpecialPool_[0-4]$')
@@ -473,6 +474,7 @@ def test_thread_names_default(self):
473474
executor.map(abs, range(-5, 5))
474475
threads = executor._threads
475476
del executor
477+
support.gc_collect() # For PyPy or other GCs.
476478

477479
for t in threads:
478480
# Ensure that our default name is reasonably sane and unique when
@@ -535,6 +537,7 @@ def test_del_shutdown(self):
535537
call_queue = executor._call_queue
536538
executor_manager_thread = executor._executor_manager_thread
537539
del executor
540+
support.gc_collect() # For PyPy or other GCs.
538541

539542
# Make sure that all the executor resources were properly cleaned by
540543
# the shutdown process
@@ -759,13 +762,15 @@ def test_free_reference_yielded_future(self):
759762
futures_list.remove(future)
760763
wr = weakref.ref(future)
761764
del future
765+
support.gc_collect() # For PyPy or other GCs.
762766
self.assertIsNone(wr())
763767

764768
futures_list[0].set_result("test")
765769
for future in futures.as_completed(futures_list):
766770
futures_list.remove(future)
767771
wr = weakref.ref(future)
768772
del future
773+
support.gc_collect() # For PyPy or other GCs.
769774
self.assertIsNone(wr())
770775
if futures_list:
771776
futures_list[0].set_result("test")
@@ -865,6 +870,7 @@ def test_free_reference(self):
865870
for obj in self.executor.map(make_dummy_object, range(10)):
866871
wr = weakref.ref(obj)
867872
del obj
873+
support.gc_collect() # For PyPy or other GCs.
868874
self.assertIsNone(wr())
869875

870876

Lib/test/test_copy.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from operator import le, lt, ge, gt, eq, ne
88

99
import unittest
10+
from test import support
1011

1112
order_comparisons = le, lt, ge, gt
1213
equality_comparisons = eq, ne
@@ -805,6 +806,7 @@ class C(object):
805806
self.assertEqual(v[c], d)
806807
self.assertEqual(len(v), 2)
807808
del c, d
809+
support.gc_collect() # For PyPy or other GCs.
808810
self.assertEqual(len(v), 1)
809811
x, y = C(), C()
810812
# The underlying containers are decoupled
@@ -834,6 +836,7 @@ def __init__(self, i):
834836
self.assertEqual(v[a].i, b.i)
835837
self.assertEqual(v[c].i, d.i)
836838
del c
839+
support.gc_collect() # For PyPy or other GCs.
837840
self.assertEqual(len(v), 1)
838841

839842
def test_deepcopy_weakvaluedict(self):
@@ -857,6 +860,7 @@ def __init__(self, i):
857860
self.assertIs(t, d)
858861
del x, y, z, t
859862
del d
863+
support.gc_collect() # For PyPy or other GCs.
860864
self.assertEqual(len(v), 1)
861865

862866
def test_deepcopy_bound_method(self):

Lib/test/test_deque.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ def test_weakref(self):
870870
p = weakref.proxy(d)
871871
self.assertEqual(str(p), str(d))
872872
d = None
873+
support.gc_collect() # For PyPy or other GCs.
873874
self.assertRaises(ReferenceError, str, p)
874875

875876
def test_strange_subclass(self):

Lib/test/test_enum.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,7 @@ def _missing_(cls, item):
20442044
raise Exception('Exception not raised.')
20452045

20462046
def test_missing_exceptions_reset(self):
2047+
import gc
20472048
import weakref
20482049
#
20492050
class TestEnum(enum.Enum):
@@ -2070,8 +2071,9 @@ def __init__(self):
20702071
class_2_ref = weakref.ref(Class2())
20712072
#
20722073
# The exception raised by Enum creates a reference loop and thus
2073-
# Class2 instances will stick around until the next gargage collection
2074+
# Class2 instances will stick around until the next garbage collection
20742075
# cycle, unlike Class1.
2076+
gc.collect() # For PyPy or other GCs.
20752077
self.assertIs(class_1_ref(), None)
20762078
self.assertIs(class_2_ref(), None)
20772079

Lib/test/test_exceptions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ def inner_raising_func():
656656
except MyException as e:
657657
pass
658658
obj = None
659+
gc_collect() # For PyPy or other GCs.
659660
obj = wr()
660661
self.assertIsNone(obj)
661662

@@ -667,6 +668,7 @@ def inner_raising_func():
667668
except MyException:
668669
pass
669670
obj = None
671+
gc_collect() # For PyPy or other GCs.
670672
obj = wr()
671673
self.assertIsNone(obj)
672674

@@ -678,6 +680,7 @@ def inner_raising_func():
678680
except:
679681
pass
680682
obj = None
683+
gc_collect() # For PyPy or other GCs.
681684
obj = wr()
682685
self.assertIsNone(obj)
683686

@@ -690,6 +693,7 @@ def inner_raising_func():
690693
except:
691694
break
692695
obj = None
696+
gc_collect() # For PyPy or other GCs.
693697
obj = wr()
694698
self.assertIsNone(obj)
695699

@@ -708,6 +712,7 @@ def inner_raising_func():
708712
# must clear the latter manually for our test to succeed.
709713
e.__context__ = None
710714
obj = None
715+
gc_collect() # For PyPy or other GCs.
711716
obj = wr()
712717
# guarantee no ref cycles on CPython (don't gc_collect)
713718
if check_impl_detail(cpython=False):
@@ -898,6 +903,7 @@ def raising_gen():
898903
next(g)
899904
testfunc(g)
900905
g = obj = None
906+
gc_collect() # For PyPy or other GCs.
901907
obj = wr()
902908
self.assertIsNone(obj)
903909

@@ -951,6 +957,7 @@ def __del__(self):
951957
raise Exception(MyObject())
952958
except:
953959
pass
960+
gc_collect() # For PyPy or other GCs.
954961
self.assertEqual(e, (None, None, None))
955962

956963
def test_raise_does_not_create_context_chain_cycle(self):
@@ -1413,6 +1420,7 @@ def inner():
14131420
self.assertNotEqual(wr(), None)
14141421
else:
14151422
self.fail("MemoryError not raised")
1423+
gc_collect() # For PyPy or other GCs.
14161424
self.assertEqual(wr(), None)
14171425

14181426
@no_tracing
@@ -1433,6 +1441,7 @@ def inner():
14331441
self.assertNotEqual(wr(), None)
14341442
else:
14351443
self.fail("RecursionError not raised")
1444+
gc_collect() # For PyPy or other GCs.
14361445
self.assertEqual(wr(), None)
14371446

14381447
def test_errno_ENOTDIR(self):
@@ -1453,6 +1462,7 @@ def __del__(self):
14531462
with support.catch_unraisable_exception() as cm:
14541463
del obj
14551464

1465+
gc_collect() # For PyPy or other GCs.
14561466
self.assertEqual(cm.unraisable.object, BrokenDel.__del__)
14571467
self.assertIsNotNone(cm.unraisable.exc_traceback)
14581468

Lib/test/test_file.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io
88
import _pyio as pyio
99

10+
from test.support import gc_collect
1011
from test.support.os_helper import TESTFN
1112
from test.support import os_helper
1213
from test.support import warnings_helper
@@ -30,6 +31,7 @@ def testWeakRefs(self):
3031
self.assertEqual(self.f.tell(), p.tell())
3132
self.f.close()
3233
self.f = None
34+
gc_collect() # For PyPy or other GCs.
3335
self.assertRaises(ReferenceError, getattr, p, 'tell')
3436

3537
def testAttributes(self):

Lib/test/test_fileio.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from weakref import proxy
1010
from functools import wraps
1111

12-
from test.support import (run_unittest, cpython_only, swap_attr)
12+
from test.support import run_unittest, cpython_only, swap_attr, gc_collect
1313
from test.support.os_helper import (TESTFN, TESTFN_UNICODE, make_bad_fd)
1414
from test.support.warnings_helper import check_warnings
1515
from collections import UserList
@@ -36,6 +36,7 @@ def testWeakRefs(self):
3636
self.assertEqual(self.f.tell(), p.tell())
3737
self.f.close()
3838
self.f = None
39+
gc_collect() # For PyPy or other GCs.
3940
self.assertRaises(ReferenceError, getattr, p, 'tell')
4041

4142
def testSeekTell(self):

Lib/test/test_functools.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ def test_weakref(self):
167167
p = proxy(f)
168168
self.assertEqual(f.func, p.func)
169169
f = None
170+
support.gc_collect() # For PyPy or other GCs.
170171
self.assertRaises(ReferenceError, getattr, p, 'func')
171172

172173
def test_with_bound_and_unbound_methods(self):

Lib/test/test_generators.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,8 @@ def printsolution(self, x):
19661966
"""
19671967

19681968
coroutine_tests = """\
1969+
>>> from test.support import gc_collect
1970+
19691971
Sending a value into a started generator:
19701972
19711973
>>> def f():
@@ -2189,7 +2191,7 @@ def printsolution(self, x):
21892191
21902192
>>> g = f()
21912193
>>> next(g)
2192-
>>> del g
2194+
>>> del g; gc_collect() # For PyPy or other GCs.
21932195
exiting
21942196
21952197
@@ -2204,7 +2206,7 @@ def printsolution(self, x):
22042206
22052207
>>> g = f()
22062208
>>> next(g)
2207-
>>> del g
2209+
>>> del g; gc_collect() # For PyPy or other GCs.
22082210
finally
22092211
22102212

Lib/test/test_io.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4372,6 +4372,31 @@ def check_interrupted_write(self, item, bytes, **fdopen_kwargs):
43724372
"""Check that a partial write, when it gets interrupted, properly
43734373
invokes the signal handler, and bubbles up the exception raised
43744374
in the latter."""
4375+
4376+
# XXX This test has three flaws that appear when objects are
4377+
# XXX not reference counted.
4378+
4379+
# - if wio.write() happens to trigger a garbage collection,
4380+
# the signal exception may be raised when some __del__
4381+
# method is running; it will not reach the assertRaises()
4382+
# call.
4383+
4384+
# - more subtle, if the wio object is not destroyed at once
4385+
# and survives this function, the next opened file is likely
4386+
# to have the same fileno (since the file descriptor was
4387+
# actively closed). When wio.__del__ is finally called, it
4388+
# will close the other's test file... To trigger this with
4389+
# CPython, try adding "global wio" in this function.
4390+
4391+
# - This happens only for streams created by the _pyio module,
4392+
# because a wio.close() that fails still consider that the
4393+
# file needs to be closed again. You can try adding an
4394+
# "assert wio.closed" at the end of the function.
4395+
4396+
# Fortunately, a little gc.collect() seems to be enough to
4397+
# work around all these issues.
4398+
support.gc_collect() # For PyPy or other GCs.
4399+
43754400
read_results = []
43764401
def _read():
43774402
s = os.read(r, 1)

Lib/test/test_itertools.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@ def test_tee(self):
14421442
p = weakref.proxy(a)
14431443
self.assertEqual(getattr(p, '__class__'), type(b))
14441444
del a
1445+
support.gc_collect() # For PyPy or other GCs.
14451446
self.assertRaises(ReferenceError, getattr, p, '__class__')
14461447

14471448
ans = list('abc')

0 commit comments

Comments
 (0)