1+ import os
2+ import platform
3+
14import pymupdf
5+
26import 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