@@ -986,6 +986,174 @@ def test_run_target():
986986 ])
987987 assert result .ret == 0
988988
989+
990+ @pytest .mark .skipif ('sys.platform == "win32"' ,
991+ reason = "fork not available on Windows" )
992+ def test_cleanup_on_sigterm (testdir ):
993+ script = testdir .makepyfile ('''
994+ import os, signal, subprocess, sys, time
995+
996+ def cleanup(num, frame):
997+ print("num == signal.SIGTERM => %s" % (num == signal.SIGTERM))
998+ raise Exception()
999+
1000+ def test_run():
1001+ proc = subprocess.Popen([sys.executable, __file__], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1002+ time.sleep(1)
1003+ proc.terminate()
1004+ stdout, stderr = proc.communicate()
1005+ assert not stderr
1006+ assert stdout == b"""num == signal.SIGTERM => True
1007+ captured Exception()
1008+ """
1009+ assert proc.returncode == 0
1010+
1011+ if __name__ == "__main__":
1012+ signal.signal(signal.SIGTERM, cleanup)
1013+
1014+ from pytest_cov.embed import cleanup_on_sigterm
1015+ cleanup_on_sigterm()
1016+
1017+ try:
1018+ time.sleep(10)
1019+ except BaseException as exc:
1020+ print("captured %r" % exc)
1021+ ''' )
1022+
1023+ result = testdir .runpytest ('-vv' ,
1024+ '--cov=%s' % script .dirpath (),
1025+ '--cov-report=term-missing' ,
1026+ script )
1027+
1028+ result .stdout .fnmatch_lines ([
1029+ '*- coverage: platform *, python * -*' ,
1030+ 'test_cleanup_on_sigterm* 26-27' ,
1031+ '*1 passed*'
1032+ ])
1033+ assert result .ret == 0
1034+
1035+
1036+ @pytest .mark .skipif ('sys.platform == "win32"' , reason = "fork not available on Windows" )
1037+ @pytest .mark .parametrize ('setup' , [
1038+ ('signal.signal(signal.SIGTERM, signal.SIG_DFL); cleanup_on_sigterm()' , '88% 18-19' ),
1039+ ('cleanup_on_sigterm()' , '88% 18-19' ),
1040+ ('cleanup()' , '75% 16-19' ),
1041+ ])
1042+ def test_cleanup_on_sigterm_sig_dfl (testdir , setup ):
1043+ script = testdir .makepyfile ('''
1044+ import os, signal, subprocess, sys, time
1045+
1046+ def test_run():
1047+ proc = subprocess.Popen([sys.executable, __file__], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1048+ time.sleep(1)
1049+ proc.terminate()
1050+ stdout, stderr = proc.communicate()
1051+ assert not stderr
1052+ assert stdout == b""
1053+ assert proc.returncode in [128 + signal.SIGTERM, -signal.SIGTERM]
1054+
1055+ if __name__ == "__main__":
1056+ from pytest_cov.embed import cleanup_on_sigterm, cleanup
1057+ {0}
1058+
1059+ try:
1060+ time.sleep(10)
1061+ except BaseException as exc:
1062+ print("captured %r" % exc)
1063+ ''' .format (setup [0 ]))
1064+
1065+ result = testdir .runpytest ('-vv' ,
1066+ '--cov=%s' % script .dirpath (),
1067+ '--cov-report=term-missing' ,
1068+ script )
1069+
1070+ result .stdout .fnmatch_lines ([
1071+ '*- coverage: platform *, python * -*' ,
1072+ 'test_cleanup_on_sigterm* %s' % setup [1 ],
1073+ '*1 passed*'
1074+ ])
1075+ assert result .ret == 0
1076+
1077+
1078+ @pytest .mark .skipif ('sys.platform == "win32"' , reason = "fork not available on Windows" )
1079+ def test_cleanup_on_sigterm_sig_dfl_sigint (testdir ):
1080+ script = testdir .makepyfile ('''
1081+ import os, signal, subprocess, sys, time
1082+
1083+ def test_run():
1084+ proc = subprocess.Popen([sys.executable, __file__], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1085+ time.sleep(1)
1086+ proc.send_signal(signal.SIGINT)
1087+ stdout, stderr = proc.communicate()
1088+ assert not stderr
1089+ assert stdout == b"""captured KeyboardInterrupt()
1090+ """
1091+ assert proc.returncode == 0
1092+
1093+ if __name__ == "__main__":
1094+ from pytest_cov.embed import cleanup_on_signal
1095+ cleanup_on_signal(signal.SIGINT)
1096+
1097+ try:
1098+ time.sleep(10)
1099+ except BaseException as exc:
1100+ print("captured %r" % exc)
1101+ ''' )
1102+
1103+ result = testdir .runpytest ('-vv' ,
1104+ '--cov=%s' % script .dirpath (),
1105+ '--cov-report=term-missing' ,
1106+ script )
1107+
1108+ result .stdout .fnmatch_lines ([
1109+ '*- coverage: platform *, python * -*' ,
1110+ 'test_cleanup_on_sigterm* 88% 19-20' ,
1111+ '*1 passed*'
1112+ ])
1113+ assert result .ret == 0
1114+
1115+ @pytest .mark .skipif ('sys.platform == "win32"' , reason = "fork not available on Windows" )
1116+ def test_cleanup_on_sigterm_sig_ign (testdir ):
1117+ script = testdir .makepyfile ('''
1118+ import os, signal, subprocess, sys, time
1119+
1120+ def test_run():
1121+ proc = subprocess.Popen([sys.executable, __file__], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1122+ time.sleep(1)
1123+ proc.send_signal(signal.SIGINT)
1124+ time.sleep(1)
1125+ proc.terminate()
1126+ stdout, stderr = proc.communicate()
1127+ assert not stderr
1128+ assert stdout == b""
1129+ # it appears signal handling is buggy on python 2?
1130+ if sys.version_info == 3: assert proc.returncode in [128 + signal.SIGTERM, -signal.SIGTERM]
1131+
1132+ if __name__ == "__main__":
1133+ signal.signal(signal.SIGINT, signal.SIG_IGN)
1134+
1135+ from pytest_cov.embed import cleanup_on_signal
1136+ cleanup_on_signal(signal.SIGINT)
1137+
1138+ try:
1139+ time.sleep(10)
1140+ except BaseException as exc:
1141+ print("captured %r" % exc)
1142+ ''' )
1143+
1144+ result = testdir .runpytest ('-vv' ,
1145+ '--cov=%s' % script .dirpath (),
1146+ '--cov-report=term-missing' ,
1147+ script )
1148+
1149+ result .stdout .fnmatch_lines ([
1150+ '*- coverage: platform *, python * -*' ,
1151+ 'test_cleanup_on_sigterm* 89% 23-24' ,
1152+ '*1 passed*'
1153+ ])
1154+ assert result .ret == 0
1155+
1156+
9891157MODULE = '''
9901158def func():
9911159 return 1
0 commit comments