Skip to content

Commit 6de290e

Browse files
tests/conftest.py: add (disabled) checking for leaked fds in tests.
We don't actually fail if leaked fds are detected because several tests need fixing first. But we do output a diagnostic.
1 parent 5086534 commit 6de290e

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

tests/conftest.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import os
2+
import platform
3+
14
import pymupdf
5+
26
import pytest
37

48
@pytest.fixture(autouse=True)
@@ -7,10 +11,33 @@ def wrap(*args, **kwargs):
711
Check that tests return with empty MuPDF warnings buffer. For example this
812
detects failure to call fz_close_output() before fz_drop_output(), which
913
(as of 2024-4-12) generates a warning from MuPDF.
14+
15+
As of 2024-09-12 we also detect whether tests leave fds open; but for now
16+
do not fail tests, because many tests need fixing.
1017
'''
1118
wt = pymupdf.TOOLS.mupdf_warnings()
1219
assert not wt, f'{wt=}'
1320
assert not pymupdf.TOOLS.set_small_glyph_heights()
21+
next_fd_before = os.open(__file__, os.O_RDONLY)
22+
os.close(next_fd_before)
23+
24+
if platform.system() == 'Linux':
25+
# Gather detailed information about leaked fds.
26+
def get_fds():
27+
import subprocess
28+
path = 'PyMuPDF-linx-fds'
29+
path_l = 'PyMuPDF-linx-fds-l'
30+
command = f'ls /proc/{os.getpid()}/fd > {path}'
31+
command_l = f'ls -l /proc/{os.getpid()}/fd > {path_l}'
32+
subprocess.run(command, shell=1)
33+
subprocess.run(command_l, shell=1)
34+
with open(path) as f:
35+
ret = f.read()
36+
ret = ret.replace('\n', ' ')
37+
with open(path_l) as f:
38+
ret_l = f.read()
39+
return ret, ret_l
40+
open_fds_before, open_fds_before_l = get_fds()
1441

1542
pymupdf._log_items_clear()
1643
pymupdf._log_items_active(True)
@@ -29,3 +56,23 @@ def wrap(*args, **kwargs):
2956

3057
log_items = pymupdf._log_items()
3158
assert not log_items, f'log() was called; {len(log_items)=}.'
59+
60+
if platform.system() == 'Linux':
61+
# Show detailed information about leaked fds.
62+
open_fds_after, open_fds_after_l = get_fds()
63+
if open_fds_after != open_fds_before:
64+
import textwrap
65+
print(f'Test has changed process fds:')
66+
print(f' {open_fds_before=}')
67+
print(f' {open_fds_after=}')
68+
print(f'open_fds_before_l:')
69+
print(textwrap.indent(open_fds_before_l, ' '))
70+
print(f'open_fds_after_l:')
71+
print(textwrap.indent(open_fds_after_l, ' '))
72+
#assert 0
73+
74+
next_fd_after = os.open(__file__, os.O_RDONLY)
75+
os.close(next_fd_after)
76+
if next_fd_after != next_fd_before:
77+
print(f'Test has leaked fds, {next_fd_before=} {next_fd_after=}. {args=} {kwargs=}.')
78+
#assert 0, f'Test has leaked fds, {next_fd_before=} {next_fd_after=}. {args=} {kwargs=}.'

0 commit comments

Comments
 (0)