blob: a724f483d43865d3f2bc1bdb51b6a4d8c585d820 [file]
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
"""Tests for core selection of coverage.py."""
from __future__ import annotations
import pytest
import coverage
from coverage import env
from coverage.exceptions import ConfigError
from tests.coveragetest import CoverageTest
from tests.helpers import re_line, re_lines
class CoverageCoreTest(CoverageTest):
"""Test that cores are chosen correctly."""
# This doesn't test failure modes, only successful requests.
try:
from coverage.tracer import CTracer
has_ctracer = True
except ImportError:
has_ctracer = False
def setUp(self) -> None:
super().setUp()
# Clean out the environment variable the test suite uses to control the
# core it cares about.
self.del_environ("COVERAGE_CORE")
self.make_file("numbers.py", "print(123, 456)")
def test_core_default(self) -> None:
out = self.run_command("coverage run --debug=sys numbers.py")
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
warns = re_lines(r"\(no-ctracer\)", out)
if env.SYSMON_DEFAULT:
assert core == "core: SysMonitor"
assert not warns
elif self.has_ctracer:
assert core == "core: CTracer"
assert not warns
else:
assert core == "core: PyTracer"
assert bool(warns) == env.CPYTHON
@pytest.mark.skipif(not has_ctracer, reason="No CTracer to request")
def test_core_request_ctrace(self) -> None:
self.set_environ("COVERAGE_CORE", "ctrace")
out = self.run_command("coverage run --debug=sys numbers.py")
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
assert core == "core: CTracer"
@pytest.mark.skipif(has_ctracer, reason="CTracer needs to be missing")
def test_core_request_ctrace_but_missing(self) -> None:
self.make_file(".coveragerc", "[run]\ncore = ctrace\n")
out = self.run_command("coverage run --debug=sys,pybehave numbers.py")
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
assert core == "core: PyTracer"
warns = re_lines(r"\(no-ctracer\)", out)
assert bool(warns) == env.SHIPPING_WHEELS
def test_core_request_pytrace(self) -> None:
self.set_environ("COVERAGE_CORE", "pytrace")
out = self.run_command("coverage run --debug=sys numbers.py")
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
assert core == "core: PyTracer"
def test_core_request_sysmon(self) -> None:
self.set_environ("COVERAGE_CORE", "sysmon")
if env.PYBEHAVIOR.pep669:
status = 0
else:
status = 1
out = self.run_command("coverage run --debug=sys numbers.py", status=status)
if status == 0:
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
assert core == "core: SysMonitor"
else:
assert "Can't use core=sysmon: sys.monitoring isn't available in this version;" in out
def test_core_request_sysmon_no_dyncontext(self) -> None:
# Use config core= for this test just to be different.
self.make_file(
".coveragerc",
"""\
[run]
core = sysmon
dynamic_context = test_function
""",
)
out = self.run_command("coverage run --debug=sys numbers.py", status=1)
if env.PYBEHAVIOR.pep669:
assert "Can't use core=sysmon: it doesn't yet support dynamic contexts;" in out
else:
assert "Can't use core=sysmon: sys.monitoring isn't available in this version;" in out
def test_core_request_sysmon_no_branches(self) -> None:
# Use config core= for this test just to be different.
self.make_file(
".coveragerc",
"""\
[run]
core = sysmon
branch = True
""",
)
if env.PYBEHAVIOR.branch_right_left:
status = 0
elif env.PYBEHAVIOR.pep669:
status = 1
msg = "Can't use core=sysmon: sys.monitoring can't measure branches in this version;"
else:
status = 1
msg = "Can't use core=sysmon: sys.monitoring isn't available in this version;"
out = self.run_command("coverage run --debug=sys numbers.py", status=status)
if status == 0:
assert out.endswith("123 456\n")
core = re_line(r" core:", out).strip()
assert core == "core: SysMonitor"
else:
assert msg in out # pylint: disable=possibly-used-before-assignment
def test_core_request_nosuchcore(self) -> None:
# Test the coverage misconfigurations in-process with pytest. Running a
# subprocess doesn't capture the metacov in the subprocess because
# coverage is misconfigured.
self.set_environ("COVERAGE_CORE", "nosuchcore")
cov = coverage.Coverage()
with pytest.raises(ConfigError, match=r"Unknown core value: 'nosuchcore'"):
self.start_import_stop(cov, "numbers")