from __future__ import annotations
import typing as typ
import pytest
from coverage_shape_rules import measuring_lanes
from test_coverage_shape_probes import CI, repository
STEP: typ.Final = " with:\n"
JOB: typ.Final = " runs-on: ubuntu-latest\n"
def guarded(step_if: str | None = None, job_lines: str = "") -> str:
ci = CI.replace(JOB, JOB + job_lines)
return (
ci if step_if is None else ci.replace(STEP, f" if: {step_if}\n" + STEP)
)
def matrix(lines: str) -> str:
return " strategy:\n matrix:\n" + lines
def test_the_base_pull_request_lane_measures() -> None:
assert len(measuring_lanes(repository())) == 1, (
"the base workflow's unconditioned coverage step must count as measuring"
)
NEVER_RUNS: typ.Final = {
"the step disabled": guarded("false"),
"the job disabled": guarded(job_lines=" if: ${{ false }}\n"),
"a matrix value no leg carries": guarded(
"${{ matrix.privilege == 'unprivileged' }}",
matrix(" privilege: [root]\n"),
),
"a push-only event guard": guarded("github.event_name == 'push'"),
"two include rows that never meet": guarded(
"matrix.os == 'linux' && matrix.privilege == 'unprivileged'",
matrix(
" include:\n"
" - os: linux\n"
" - privilege: unprivileged\n"
),
),
}
@pytest.mark.parametrize("ci", NEVER_RUNS.values(), ids=NEVER_RUNS.keys())
def test_a_coverage_step_that_cannot_run_does_not_measure(ci: str) -> None:
found = measuring_lanes(repository(ci=ci))
assert found == [], f"a coverage step that cannot run was counted: {found}"
RUNS: typ.Final = {
"the repository's own matrix guard": guarded(
"${{ matrix.privilege == 'unprivileged' }}",
matrix(" privilege: [unprivileged, root]\n"),
),
"one include row carrying both values": guarded(
"matrix.os == 'linux' && matrix.privilege == 'unprivileged'",
matrix(
" include:\n"
" - os: linux\n"
" privilege: unprivileged\n"
),
),
"an include row extending a crossed leg": guarded(
"matrix.os == 'linux' && matrix.privilege == 'unprivileged'",
matrix(
" os: [linux, mac]\n"
" include:\n"
" - os: linux\n"
" privilege: unprivileged\n"
),
),
}
@pytest.mark.parametrize("ci", RUNS.values(), ids=RUNS.keys())
def test_a_guard_some_leg_satisfies_still_measures(ci: str) -> None:
found = measuring_lanes(repository(ci=ci))
assert len(found) == 1, f"a coverage step some leg runs was not counted: {found}"