Coverage for tests / test_debug.py: 100.000%

262 statements  

« prev     ^ index     » next       coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000

1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 

2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt 

3 

4"""Tests of coverage/debug.py""" 

5 

6from __future__ import annotations 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

7 

8import ast 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

9import io 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

10import os 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

11import re 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

12import sys 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

13 

14from typing import Any, Callable 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

15from collections.abc import Iterable 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

16 

17import pytest 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

18 

19import coverage 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

20from coverage import env 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

21from coverage.debug import ( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

22 DebugControl, 

23 DebugOutputFile, 

24 auto_repr, 

25 clipped_repr, 

26 exc_one_line, 

27 filter_text, 

28 info_formatter, 

29 info_header, 

30 relevant_environment_display, 

31 short_id, 

32 short_filename, 

33 short_stack, 

34) 

35from coverage.exceptions import DataError 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

36 

37from tests import testenv 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

38from tests.coveragetest import CoverageTest 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

39from tests.helpers import DebugControlString, re_line, re_lines, re_lines_text 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

40 

41 

42class InfoFormatterTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

43 """Tests of debug.info_formatter.""" 

44 

45 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

46 

47 def test_info_formatter(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

48 lines = list( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

49 info_formatter( 

50 [ 

51 ("x", "hello there"), 

52 ("very long label", ["one element"]), 

53 ("fits on 1", (17, 23, 42, 76, 99)), 

54 ("regular", ["abc", "def", "ghi", "jkl"]), 

55 ("nothing", []), 

56 ] 

57 ) 

58 ) 

59 expected = [ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

60 " x: hello there", 

61 " very long label: one element", 

62 " fits on 1: (17, 23, 42, 76, 99)", 

63 " regular: abc", 

64 " def", 

65 " ghi", 

66 " jkl", 

67 " nothing: -none-", 

68 ] 

69 assert expected == lines 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

70 

71 def test_info_formatter_with_generator(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

72 lines = list(info_formatter(("info%d" % i, i) for i in range(3))) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

73 expected = [ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

74 " info0: 0", 

75 " info1: 1", 

76 " info2: 2", 

77 ] 

78 assert expected == lines 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

79 

80 def test_too_long_label(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

81 with pytest.raises(AssertionError): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

82 list(info_formatter([("this label is way too long and will not fit", 23)])) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

83 

84 

85@pytest.mark.parametrize( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

86 "label, header", 

87 [ 

88 ("x", "-- x ---------------------------------------------------------"), 

89 ("hello there", "-- hello there -----------------------------------------------"), 

90 ], 

91) 

92def test_info_header(label: str, header: str) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

93 assert header == info_header(label) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

94 

95 

96@pytest.mark.parametrize( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

97 "id64, id16", 

98 [ 

99 (0x1234, 0x1234), 

100 (0x12340000, 0x1234), 

101 (0xA5A55A5A, 0xFFFF), 

102 (0x1234CBA956780FED, 0x8008), 

103 ], 

104) 

105def test_short_id(id64: int, id16: int) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

106 assert id16 == short_id(id64) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

107 

108 

109@pytest.mark.parametrize( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

110 "text, numchars, result", 

111 [ 

112 ("hello", 10, "'hello'"), 

113 ("0123456789abcdefghijklmnopqrstuvwxyz", 15, "'01234...vwxyz'"), 

114 ], 

115) 

116def test_clipped_repr(text: str, numchars: int, result: str) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

117 assert result == clipped_repr(text, numchars) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

118 

119 

120@pytest.mark.parametrize( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

121 "text, filters, result", 

122 [ 

123 ("hello", [], "hello"), 

124 ("hello\n", [], "hello\n"), 

125 ("hello\nhello\n", [], "hello\nhello\n"), 

126 ("hello\nbye\n", [lambda x: "=" + x], "=hello\n=bye\n"), 

127 ( 

128 "hello\nbye\n", 

129 [lambda x: "=" + x, lambda x: x + "\ndone\n"], 

130 "=hello\ndone\n=bye\ndone\n", 

131 ), 

132 ], 

133) 

134def test_filter_text( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

135 text: str, 

136 filters: Iterable[Callable[[str], str]], 

137 result: str, 

138) -> None: 

139 assert result == filter_text(text, filters) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

140 

141 

142class DebugTraceTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

143 """Tests of debug output.""" 

144 

145 def f1_debug_output(self, debug: Iterable[str]) -> str: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

146 """Runs some code with `debug` option, returns the debug output.""" 

147 # Make code to run. 

148 self.make_file( 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

149 "f1.py", 

150 """\ 

151 def f1(x): 

152 return x+1 

153 

154 for i in range(5): 

155 f1(i) 

156 """, 

157 ) 

158 

159 debug_out = io.StringIO() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

160 cov = coverage.Coverage(debug=debug) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

161 cov._debug_file = debug_out 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

162 self.start_import_stop(cov, "f1") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

163 cov.save() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

164 

165 return debug_out.getvalue() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

166 

167 def test_debug_no_trace(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

168 out_text = self.f1_debug_output([]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

169 

170 # We should have no output at all. 

171 assert not out_text 1EaJbuKcdYvLeZf0wMgNhxOiVjykPlUzmWnAXoQp1Bq2r4CstD

172 

173 def test_debug_trace(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

174 out_text = self.f1_debug_output(["trace"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

175 

176 # We should have a line like "Tracing 'f1.py'", perhaps with an 

177 # absolute path. 

178 assert re.search(r"Tracing '.*f1.py'", out_text) 1Eab3ucFdYveZf0wghRxiVjSyGklzHmWnTAXop1BIq2r4CstD

179 

180 # We should have lines like "Not tracing 'collector.py'..." 

181 assert re_lines(r"^Not tracing .*: is part of coverage.py$", out_text) 1Eab3ucFdYveZf0wghRxiVjSyGklzHmWnTAXop1BIq2r4CstD

182 

183 def test_debug_trace_pid(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

184 out_text = self.f1_debug_output(["trace", "pid"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

185 

186 # Now our lines are always prefixed with the process id. 

187 pid_prefix = r"^%5d\.[0-9a-f]{4}: " % os.getpid() 1EaJbuKcFdvLeZfwMgNhRxOijSyGkPlUzHmnTAoQpBIq2r4CstD

188 pid_lines = re_lines_text(pid_prefix, out_text) 1EaJbuKcFdvLeZfwMgNhRxOijSyGkPlUzHmnTAoQpBIq2r4CstD

189 assert pid_lines == out_text 1EaJbuKcFdvLeZfwMgNhRxOijSyGkPlUzHmnTAoQpBIq2r4CstD

190 

191 # We still have some tracing, and some not tracing. 

192 assert re_lines(pid_prefix + "Tracing ", out_text) 1EaJbuKcFdvLeZfwMgNhRxOijSyGkPlUzHmnTAoQpBIq2r4CstD

193 assert re_lines(pid_prefix + "Not tracing ", out_text) 1EaJbuKcFdvLeZfwMgNhRxOijSyGkPlUzHmnTAoQpBIq2r4CstD

194 

195 def test_debug_callers(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

196 out_text = self.f1_debug_output(["pid", "dataop", "dataio", "callers", "lock"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

197 # For every real message, there should be a stack trace with a line like 

198 # "f1_debug_output : /Users/ned/coverage/tests/test_debug.py:71" 

199 real_messages = re_lines(r"\.py:\d+$", out_text, match=False) 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

200 frame_pattern = r"\s+f1_debug_output : .*tests[/\\]test_debug.py:\d+$" 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

201 frames = re_lines(frame_pattern, out_text) 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

202 assert len(real_messages) == len(frames) 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

203 

204 last_line = out_text.splitlines()[-1] 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

205 

206 # The details of what to expect on the stack are empirical, and can change 

207 # as the code changes. This test is here to ensure that the debug code 

208 # continues working. It's ok to adjust these details over time. 

209 assert re_lines(r"^\s*\d+\.\w{4}: Writing \(no-op\) data file", real_messages[-1]) 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

210 assert re_lines(r"\s+_debug_dataio : .*coverage[/\\]sqldata.py:\d+$", last_line) 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD

211 

212 def test_debug_config(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

213 out_text = self.f1_debug_output(["config"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

214 

215 labels = """ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

216 branch config_file config_files_attempted config_files_read cover_pylib data_file 

217 debug exclude_list extra_css html_dir html_title ignore_errors 

218 run_include run_omit parallel partial_always_list partial_list paths 

219 precision show_missing source timid xml_output 

220 report_include report_omit 

221 """.split() 

222 for label in labels: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

223 label_pat = rf"^\s*{label}: " 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

224 msg = f"Incorrect lines for {label!r}" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

225 assert 1 == len(re_lines(label_pat, out_text)), msg 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

226 

227 def test_debug_sys(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

228 out_text = self.f1_debug_output(["sys"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

229 assert_good_debug_sys(out_text) 1aJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

230 

231 def test_debug_sys_ctracer(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

232 out_text = self.f1_debug_output(["sys"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

233 tracer_line = re_line(r"CTracer:", out_text).strip() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

234 if testenv.C_TRACER: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

235 assert tracer_line.startswith("CTracer: available from ") 1EJ3KFYLZ0MNROVSGPUHWTXQ1I24

236 else: 

237 assert tracer_line == "CTracer: unavailable" 1abucdvefwghxijyklzmnAopBqrCstD

238 

239 def test_debug_pybehave(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

240 out_text = self.f1_debug_output(["pybehave"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

241 out_lines = out_text.splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

242 assert 10 < len(out_lines) < 40 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

243 pyversion = re_line(r" PYVERSION:", out_text) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

244 vtuple = ast.literal_eval(pyversion.partition(":")[-1].strip()) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

245 assert vtuple[:5] == sys.version_info 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

246 

247 def test_debug_sqlite(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

248 out_text = self.f1_debug_output(["sqlite"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

249 assert "sqlite3_compile_options:" in out_text 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

250 # The rest of the output is tested in test_cmdline.py:test_debug_sqlite 

251 

252 def test_debug_process(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

253 out_text = self.f1_debug_output(["trace", "process"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

254 assert f"New process: pid={os.getpid()}, executable:" in out_text 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

255 

256 def test_debug_pytest(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

257 out_text = self.f1_debug_output(["trace", "pytest"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

258 ctx = "tests/test_debug.py::DebugTraceTest::test_debug_pytest (call)" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

259 assert f"Pytest context: {ctx}" in out_text 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

260 

261 

262def assert_good_debug_sys(out_text: str) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

263 """Assert that `str` is good output for debug=sys.""" 

264 labels = """ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

265 coverage_version coverage_module coverage_paths stdlib_paths third_party_paths 

266 core configs_attempted config_file configs_read data_file 

267 python platform implementation executable 

268 pid cwd path environment command_line cover_match pylib_match 

269 """.split() 

270 for label in labels: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

271 label_pat = rf"^\s*{label}: " 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

272 msg = f"Incorrect lines for {label!r}" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

273 assert 1 == len(re_lines(label_pat, out_text)), msg 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

274 tracer_line = re_line(" core:", out_text).strip() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

275 if testenv.C_TRACER: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

276 assert tracer_line == "core: CTracer" 1EJ3KFYLZ0MNROVSGPUHWTXQ1I24

277 elif testenv.PY_TRACER: 1abucdvefwghxijyk5l6z%m7n8A'o9p!B(q#r$C)stD

278 assert tracer_line == "core: PyTracer" 1abucdvefwghxijyklzmnAopBqrCstD

279 else: 

280 assert testenv.SYS_MON 156%78'9!(#$)

281 assert tracer_line == "core: SysMonitor" 156%78'9!(#$)

282 

283 

284class DebugOutputTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

285 """Tests that we can direct debug output where we want.""" 

286 

287 def setUp(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

288 super().setUp() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

289 # DebugOutputFile aggressively tries to start just one output file. We 

290 # need to manually force it to make a new one. 

291 DebugOutputFile._del_singleton_data() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

292 

293 def debug_sys(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

294 """Run just enough coverage to get full debug=sys output.""" 

295 cov = coverage.Coverage(debug=["sys"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

296 cov.start() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

297 cov.stop() 1abucdvefwghxijyklzmnAopBqrCstD

298 

299 def test_stderr_default(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

300 self.debug_sys() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

301 out, err = self.stdouterr() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

302 assert "" == out 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

303 assert_good_debug_sys(err) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

304 

305 def test_envvar(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

306 self.set_environ("COVERAGE_DEBUG_FILE", "debug.out") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

307 self.debug_sys() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

308 assert ("", "") == self.stdouterr() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

309 with open("debug.out", encoding="utf-8") as f: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

310 assert_good_debug_sys(f.read()) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

311 

312 def test_config_file(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

313 self.make_file(".coveragerc", "[run]\ndebug_file = lotsa_info.txt") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

314 self.debug_sys() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

315 assert ("", "") == self.stdouterr() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

316 with open("lotsa_info.txt", encoding="utf-8") as f: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

317 assert_good_debug_sys(f.read()) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

318 

319 def test_stdout_alias(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

320 self.set_environ("COVERAGE_DEBUG_FILE", "stdout") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

321 self.debug_sys() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

322 out, err = self.stdouterr() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

323 assert "" == err 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

324 assert_good_debug_sys(out) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD

325 

326 

327class DebugControlTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

328 """Tests of DebugControl (via DebugControlString).""" 

329 

330 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

331 

332 def test_debug_control(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

333 debug = DebugControlString(["yes"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

334 assert debug.should("yes") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

335 debug.write("YES") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

336 assert not debug.should("no") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

337 assert "YES\n" == debug.get_output() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

338 

339 def test_debug_write_exceptions(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

340 debug = DebugControlString(["yes"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

341 try: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

342 raise RuntimeError("Oops") # This is in the traceback 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

343 except Exception as exc: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

344 debug.write("Something happened", exc=exc) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

345 lines = debug.get_output().splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

346 assert "Something happened" == lines[0] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

347 assert "Traceback (most recent call last):" == lines[1] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

348 assert ' raise RuntimeError("Oops") # This is in the traceback' in lines 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

349 assert "RuntimeError: Oops" == lines[-1] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

350 

351 def test_debug_write_self(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

352 class DebugWritingClass: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

353 """A simple class to show 'self:' debug messages.""" 

354 

355 def __init__(self, debug: DebugControl) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

356 # This line will have "self:" reported. 

357 debug.write("Hello from me") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

358 

359 def __repr__(self) -> str: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

360 return "<<DebugWritingClass object!>>" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

361 

362 def run_some(debug: DebugControl) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

363 # This line will have no "self:" because there's no local self. 

364 debug.write("In run_some") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

365 DebugWritingClass(debug) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

366 

367 debug = DebugControlString(["self"]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

368 run_some(debug) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

369 lines = debug.get_output().splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

370 assert lines == [ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

371 "In run_some", 

372 "Hello from me", 

373 "self: <<DebugWritingClass object!>>", 

374 ] 

375 

376 

377def f_one(*args: Any, **kwargs: Any) -> str: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

378 """First of the chain of functions for testing `short_stack`.""" 

379 return f_two(*args, **kwargs) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

380 

381 

382def f_two(*args: Any, **kwargs: Any) -> str: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

383 """Second of the chain of functions for testing `short_stack`.""" 

384 return f_three(*args, **kwargs) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

385 

386 

387def f_three(*args: Any, **kwargs: Any) -> str: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

388 """Third of the chain of functions for testing `short_stack`.""" 

389 return short_stack(*args, **kwargs) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

390 

391 

392class ShortStackTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

393 """Tests of coverage.debug.short_stack.""" 

394 

395 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

396 

397 def test_short_stack(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

398 stack = f_one().splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

399 assert 4 == len(stack) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

400 assert "test_short_stack" in stack[0] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

401 assert "f_one" in stack[1] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

402 assert "f_two" in stack[2] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

403 assert "f_three" in stack[3] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

404 

405 def test_short_stack_skip(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

406 stack = f_one(skip=1).splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

407 assert 3 == len(stack) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

408 assert "test_short_stack" in stack[0] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

409 assert "f_one" in stack[1] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

410 assert "f_two" in stack[2] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

411 

412 def test_short_stack_full(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

413 stack_text = f_one(full=True) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

414 s = re.escape(os.sep) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

415 if env.WINDOWS: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

416 pylib = "[Ll]ib" 13uYv0wRxSyUz%TA'1B(4C)D

417 else: 

418 py = "pypy" if env.PYPY else "python" 1EaJbKcFdLeZfMgNhOiVjGk5Pl6Hm7Wn8Xo9Qp!Iq#2r$st

419 majv, minv = sys.version_info[:2] 1EaJbKcFdLeZfMgNhOiVjGk5Pl6Hm7Wn8Xo9Qp!Iq#2r$st

420 pylib = f"lib{s}{py}{majv}.{minv}{sys.abiflags}" 1EaJbKcFdLeZfMgNhOiVjGk5Pl6Hm7Wn8Xo9Qp!Iq#2r$st

421 assert len(re_lines(rf"{s}{pylib}{s}site-packages{s}_pytest", stack_text)) > 3 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

422 assert len(re_lines(rf"{s}{pylib}{s}site-packages{s}pluggy", stack_text)) > 3 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

423 assert not re_lines(r" 0x[0-9a-fA-F]+", stack_text) # No frame ids 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

424 stack = stack_text.splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

425 assert len(stack) > 25 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

426 assert "test_short_stack" in stack[-4] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

427 assert "f_one" in stack[-3] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

428 assert "f_two" in stack[-2] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

429 assert "f_three" in stack[-1] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

430 

431 def test_short_stack_short_filenames(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

432 stack_text = f_one(full=True, short_filenames=True) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

433 s = re.escape(os.sep) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

434 assert not re_lines(r"site-packages", stack_text) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

435 assert len(re_lines(rf"syspath:{s}_pytest", stack_text)) > 3 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

436 assert len(re_lines(rf"syspath:{s}pluggy", stack_text)) > 3 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

437 

438 def test_short_stack_frame_ids(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

439 stack = f_one(full=True, frame_ids=True).splitlines() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

440 assert len(stack) > 25 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

441 frame_ids = [m[0] for line in stack if (m := re.search(r" 0x[0-9a-fA-F]{6,}", line))] 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

442 # Every line has a frame id. 

443 assert len(frame_ids) == len(stack) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

444 # All the frame ids are different. 

445 assert len(set(frame_ids)) == len(frame_ids) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

446 

447 

448class ShortFilenameTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

449 """Tests of debug.py:short_filename.""" 

450 

451 def test_short_filename(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

452 s = os.sep 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

453 se = re.escape(s) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

454 assert short_filename(ast.__file__) == f"syspath:{s}ast.py" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

455 assert short_filename(pytest.__file__) == f"syspath:{s}pytest{s}__init__.py" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

456 assert short_filename(env.__file__) == f"cov:{s}env.py" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

457 self.make_file("hello.txt", "hi") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

458 short_hello = short_filename(os.path.abspath("hello.txt")) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

459 assert re.match(rf"tmp:{se}t\d+{se}hello.txt", short_hello) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

460 oddball = f"{s}xyzzy{s}plugh{s}foo.txt" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

461 assert short_filename(oddball) == oddball 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

462 assert short_filename(None) is None 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

463 

464 

465@pytest.mark.parametrize("long_len", [10, 100]) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

466def test_relevant_environment_display(long_len: int) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

467 env_vars = { 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

468 "HOME": "my home", 

469 "HOME_DIR": "other place", 

470 "XYZ_NEVER_MIND": "doesn't matter", 

471 "SOME_PYOTHER": "xyz123", 

472 "COVERAGE_THING": "abcd", 

473 "MY_PYPI_TOKEN": "secret.something", 

474 "TMP": "temporary", 

475 "COVERAGE_PROCESS_CONFIG": "abc" + "x" * (long_len - 3), 

476 } 

477 long_val = { 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

478 10: "abcxxxxxxx", 

479 100: "abc" + "x" * (60 - 3 - 3) + "...", 

480 }[long_len] 

481 expected = [ 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

482 ("COVERAGE_PROCESS_CONFIG", long_val), 

483 ("COVERAGE_THING", "abcd"), 

484 ("HOME", "my home"), 

485 ("MY_PYPI_TOKEN", "******.*********"), 

486 ("SOME_PYOTHER", "xyz123"), 

487 ("TMP", "temporary"), 

488 ] 

489 assert expected == relevant_environment_display(env_vars) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

490 

491 

492def test_exc_one_line() -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

493 try: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

494 raise DataError("wtf?") 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

495 except Exception as exc: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

496 assert "coverage.exceptions.DataError: wtf?" == exc_one_line(exc) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

497 

498 

499def test_auto_repr() -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

500 class MyStuff: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

501 """Random class to test auto_repr.""" 

502 

503 def __init__(self) -> None: 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

504 self.x = 17 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

505 self.y = "hello" 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

506 

507 __repr__ = auto_repr 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

508 

509 stuff = MyStuff() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

510 setattr(stuff, "$coverage.object_id", 123456) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD

511 assert re.match(r"<MyStuff @0x[a-f\d]+ x=17 y='hello'>", repr(stuff)) 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD