Skip to content

Commit

Permalink
Merge pull request #22494 from charris/backport-22485
Browse files Browse the repository at this point in the history
TST: Make test_partial_iteration_cleanup robust but require leak checker
  • Loading branch information
charris committed Oct 28, 2022
2 parents e55d2d0 + e3eb14a commit e5c39c8
Showing 1 changed file with 9 additions and 13 deletions.
22 changes: 9 additions & 13 deletions numpy/core/tests/test_nditer.py
Expand Up @@ -3130,41 +3130,37 @@ def test_warn_noclose():

@pytest.mark.skipif(sys.version_info[:2] == (3, 9) and sys.platform == "win32",
reason="Errors with Python 3.9 on Windows")
@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
@pytest.mark.parametrize(["in_dtype", "buf_dtype"],
[("i", "O"), ("O", "i"), # most simple cases
("i,O", "O,O"), # structured partially only copying O
("O,i", "i,O"), # structured casting to and from O
])
@pytest.mark.parametrize("steps", [1, 2, 3])
def test_partial_iteration_cleanup(in_dtype, buf_dtype, steps):
value = 123 # relies on python cache (leak-check will still find it)
"""
Checks for reference counting leaks during cleanup. Using explicit
reference counts lead to occasional false positives (at least in parallel
test setups). This test now should still test leaks correctly when
run e.g. with pytest-valgrind or pytest-leaks
"""
value = 2**30 + 1 # just a random value that Python won't intern
arr = np.full(int(np.BUFSIZE * 2.5), value).astype(in_dtype)
count = sys.getrefcount(value)

it = np.nditer(arr, op_dtypes=[np.dtype(buf_dtype)],
flags=["buffered", "external_loop", "refs_ok"], casting="unsafe")
for step in range(steps):
# The iteration finishes in 3 steps, the first two are partial
next(it)

# Note that resetting does not free references
del it
break_cycles()
break_cycles()
assert count == sys.getrefcount(value)
del it # not necessary, but we test the cleanup

# Repeat the test with `iternext`
it = np.nditer(arr, op_dtypes=[np.dtype(buf_dtype)],
flags=["buffered", "external_loop", "refs_ok"], casting="unsafe")
for step in range(steps):
it.iternext()

del it # should ensure cleanup
break_cycles()
break_cycles()
assert count == sys.getrefcount(value)

del it # not necessary, but we test the cleanup

@pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
@pytest.mark.parametrize(["in_dtype", "buf_dtype"],
Expand Down

0 comments on commit e5c39c8

Please sign in to comment.