Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite566ce5

Browse files
authored
gh-93353: regrtest checks for leaked temporary files (#93776)
When running tests with -jN, create a temporary directory per processand mark a test as "environment changed" if a test leaks a temporaryfile or directory.
1 parentb083450 commite566ce5

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

‎Lib/test/libregrtest/runtest.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ class EnvChanged(Failed):
8080
def__str__(self)->str:
8181
returnf"{self.name} failed (env changed)"
8282

83+
# Convert Passed to EnvChanged
84+
@staticmethod
85+
deffrom_passed(other):
86+
returnEnvChanged(other.name,other.duration_sec,other.xml_data)
87+
8388

8489
classRefLeak(Failed):
8590
def__str__(self)->str:

‎Lib/test/libregrtest/runtest_mp.py‎

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
importfaulthandler
22
importjson
3-
importos
3+
importos.path
44
importqueue
55
importshlex
66
importsignal
@@ -17,7 +17,8 @@
1717
fromtest.libregrtest.cmdlineimportNamespace
1818
fromtest.libregrtest.mainimportRegrtest
1919
fromtest.libregrtest.runtestimport (
20-
runtest,is_failed,TestResult,Interrupted,Timeout,ChildError,PROGRESS_MIN_TIME)
20+
runtest,is_failed,TestResult,Interrupted,Timeout,ChildError,
21+
PROGRESS_MIN_TIME,Passed,EnvChanged)
2122
fromtest.libregrtest.setupimportsetup_tests
2223
fromtest.libregrtest.utilsimportformat_duration,print_warning
2324

@@ -52,7 +53,7 @@ def parse_worker_args(worker_args) -> tuple[Namespace, str]:
5253
return (ns,test_name)
5354

5455

55-
defrun_test_in_subprocess(testname:str,ns:Namespace)->subprocess.Popen:
56+
defrun_test_in_subprocess(testname:str,ns:Namespace,tmp_dir:str)->subprocess.Popen:
5657
ns_dict=vars(ns)
5758
worker_args= (ns_dict,testname)
5859
worker_args=json.dumps(worker_args)
@@ -66,10 +67,14 @@ def run_test_in_subprocess(testname: str, ns: Namespace) -> subprocess.Popen:
6667
'-m','test.regrtest',
6768
'--worker-args',worker_args]
6869

70+
env=dict(os.environ)
71+
env['TMPDIR']=tmp_dir
72+
env['TEMPDIR']=tmp_dir
73+
6974
# Running the child from the same working directory as regrtest's original
7075
# invocation ensures that TEMPDIR for the child is the same when
7176
# sysconfig.is_python_build() is true. See issue 15300.
72-
kw= {}
77+
kw= {'env':env}
7378
ifUSE_PROCESS_GROUP:
7479
kw['start_new_session']=True
7580
returnsubprocess.Popen(cmd,
@@ -206,12 +211,12 @@ def mp_result_error(
206211
test_result.duration_sec=time.monotonic()-self.start_time
207212
returnMultiprocessResult(test_result,stdout,err_msg)
208213

209-
def_run_process(self,test_name:str)->tuple[int,str,str]:
214+
def_run_process(self,test_name:str,tmp_dir:str)->tuple[int,str,str]:
210215
self.start_time=time.monotonic()
211216

212217
self.current_test_name=test_name
213218
try:
214-
popen=run_test_in_subprocess(test_name,self.ns)
219+
popen=run_test_in_subprocess(test_name,self.ns,tmp_dir)
215220

216221
self._killed=False
217222
self._popen=popen
@@ -266,7 +271,17 @@ def _run_process(self, test_name: str) -> tuple[int, str, str]:
266271
self.current_test_name=None
267272

268273
def_runtest(self,test_name:str)->MultiprocessResult:
269-
retcode,stdout=self._run_process(test_name)
274+
# gh-93353: Check for leaked temporary files in the parent process,
275+
# since the deletion of temporary files can happen late during
276+
# Python finalization: too late for libregrtest.
277+
tmp_dir=os.getcwd()+'_tmpdir'
278+
tmp_dir=os.path.abspath(tmp_dir)
279+
try:
280+
os.mkdir(tmp_dir)
281+
retcode,stdout=self._run_process(test_name,tmp_dir)
282+
finally:
283+
tmp_files=os.listdir(tmp_dir)
284+
os_helper.rmtree(tmp_dir)
270285

271286
ifretcodeisNone:
272287
returnself.mp_result_error(Timeout(test_name),stdout)
@@ -289,6 +304,14 @@ def _runtest(self, test_name: str) -> MultiprocessResult:
289304
iferr_msgisnotNone:
290305
returnself.mp_result_error(ChildError(test_name),stdout,err_msg)
291306

307+
iftmp_files:
308+
msg= (f'\n\n'
309+
f'Warning -- Test leaked temporary files ({len(tmp_files)}): '
310+
f'{", ".join(sorted(tmp_files))}')
311+
stdout+=msg
312+
ifisinstance(result,Passed):
313+
result=EnvChanged.from_passed(result)
314+
292315
returnMultiprocessResult(result,stdout,err_msg)
293316

294317
defrun(self)->None:

‎Lib/test/test_regrtest.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,26 @@ def test_cleanup(self):
13571357
fornameinnames:
13581358
self.assertFalse(os.path.exists(name),name)
13591359

1360+
deftest_leak_tmp_file(self):
1361+
code=textwrap.dedent(r"""
1362+
import os.path
1363+
import tempfile
1364+
import unittest
1365+
1366+
class FileTests(unittest.TestCase):
1367+
def test_leak_tmp_file(self):
1368+
filename = os.path.join(tempfile.gettempdir(), 'mytmpfile')
1369+
with open(filename, "wb") as fp:
1370+
fp.write(b'content')
1371+
""")
1372+
testname=self.create_test(code=code)
1373+
1374+
output=self.run_tests("--fail-env-changed","-v","-j1",testname,exitcode=3)
1375+
self.check_executed_tests(output, [testname],
1376+
env_changed=[testname],
1377+
fail_env_changed=True)
1378+
self.assertIn("Warning -- Test leaked temporary files (1): mytmpfile",output)
1379+
13601380

13611381
classTestUtils(unittest.TestCase):
13621382
deftest_format_duration(self):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp