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
« 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
4"""Tests of coverage/debug.py"""
6from __future__ import annotations 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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
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
17import pytest 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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
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
42class InfoFormatterTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
43 """Tests of debug.info_formatter."""
45 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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
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
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
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
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
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
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
142class DebugTraceTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
143 """Tests of debug output."""
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
154 for i in range(5):
155 f1(i)
156 """,
157 )
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
165 return debug_out.getvalue() 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIq2r4CstD
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
170 # We should have no output at all.
171 assert not out_text 1EaJbuKcdYvLeZf0wMgNhxOiVjykPlUzmWnAXoQp1Bq2r4CstD
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
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
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
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
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
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
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
204 last_line = out_text.splitlines()[-1] 1EaJb3uKcFdYvLef0wMgNhRxOiVjSyGkPlUzHmWnTAXoQp1BIqrCstD
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
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
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
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
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
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
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
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
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
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!(#$)
284class DebugOutputTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
285 """Tests that we can direct debug output where we want."""
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
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
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
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
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
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
327class DebugControlTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
328 """Tests of DebugControl (via DebugControlString)."""
330 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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
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
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."""
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
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
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
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 ]
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
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
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
392class ShortStackTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
393 """Tests of coverage.debug.short_stack."""
395 run_in_temp_dir = False 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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
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
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
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
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
448class ShortFilenameTest(CoverageTest): 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
449 """Tests of debug.py:short_filename."""
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
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
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
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."""
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
507 __repr__ = auto_repr 1EaJb3uKcFdYvLeZf0wMgNhRxOiVjSyGk5Pl6Uz%Hm7Wn8TA'Xo9Qp!1B(Iq#2r$4C)stD
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