0ef5fcb1c5
Security / Dependency audit (pip-audit) (push) Has been cancelled
Security / CodeQL (javascript-typescript) (push) Has been cancelled
Security / CodeQL (python) (push) Has been cancelled
Security / Secret scan (gitleaks) (push) Has been cancelled
rust / test (ubuntu) (push) Has been cancelled
rust / simulator e2e (macos-latest) (push) Has been cancelled
rust / simulator e2e (ubuntu-latest) (push) Has been cancelled
rust / simulator e2e (windows-latest) (push) Has been cancelled
rust / wheels (aarch64-apple-darwin) (push) Has been cancelled
rust / wheels (x86_64-unknown-linux-gnu) (push) Has been cancelled
rust / wheels (x86_64-apple-darwin) (push) Has been cancelled
rust / audit (push) Has been cancelled
rust / parity (nightly, allowed to fail during Phase 0) (push) Has been cancelled
CI / commitlint (push) Has been skipped
Dev Containers / validate (.devcontainer/devcontainer.json, default) (push) Failing after 0s
Dev Containers / validate (.devcontainer/memory-stack/devcontainer.json, memory-stack) (push) Failing after 0s
Dev Containers / validate-worktree (push) Failing after 0s
CI / changes (push) Failing after 4s
Deploy Documentation / validate (push) Has been skipped
Deploy Documentation / deploy (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, claude) (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, codex) (push) Failing after 1s
Install Native E2E / install-native (ubuntu-latest) (push) Failing after 1s
OpenCode Plugin / typecheck + build + test (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, copilot) (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
Wrap E2E / docker-wrap-e2e (push) Failing after 1s
Wrap Native E2E / wrap-native (ubuntu-latest) (push) Failing after 1s
Init E2E / docker-init-e2e (push) Failing after 4s
Merge Conflicts / merge-conflicts (push) Failing after 4s
CI / lint (push) Has been cancelled
CI / build-wheel (push) Has been cancelled
CI / build-wheel-windows (push) Has been cancelled
CI / prefetch-model (push) Has been cancelled
CI / test-dashboard-ui (push) Has been cancelled
CI / test (1) (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test-extras (push) Has been cancelled
CI / test-agno (push) Has been cancelled
CI / build (push) Has been cancelled
CI / workflow-validation (push) Has been cancelled
CI / docker-native-e2e (push) Has been cancelled
CI / windows-native-wrapper (push) Has been cancelled
CI / macos-native-wrapper (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / promote-latest (push) Has been cancelled
Init Native E2E / init-native (macos-latest, claude) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, codex) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, copilot) (push) Has been cancelled
Install Native E2E / install-native (macos-latest) (push) Has been cancelled
Wrap Native E2E / wrap-native (macos-latest) (push) Has been cancelled
114 lines
3.4 KiB
Python
114 lines
3.4 KiB
Python
"""Phase G PR-G3 remediation (C4) — wrap-CLI RTK metrics primitive.
|
|
|
|
The Rust proxy previously held a dead `wrap_rtk_invocations_total`
|
|
counter. C4 remediation moved it Python-side because the wrap CLI
|
|
(headroom.cli.wrap) is where RTK invocations are actually counted.
|
|
These tests cover the counter primitives in isolation.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
|
|
import pytest
|
|
|
|
from headroom.cli.wrap_rtk_metrics import (
|
|
record_rtk_invocation,
|
|
reset_rtk_invocations,
|
|
rtk_invocation_counts,
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _reset_between_tests():
|
|
"""Reset the module-level counter map between tests so each
|
|
test owns a clean slate."""
|
|
reset_rtk_invocations()
|
|
yield
|
|
reset_rtk_invocations()
|
|
|
|
|
|
def test_record_increments_default_delta_one():
|
|
record_rtk_invocation("git")
|
|
counts = rtk_invocation_counts()
|
|
assert counts == {"git": 1}
|
|
|
|
|
|
def test_record_accumulates_per_tool():
|
|
record_rtk_invocation("git")
|
|
record_rtk_invocation("git")
|
|
record_rtk_invocation("ls")
|
|
record_rtk_invocation("cargo")
|
|
record_rtk_invocation("cargo")
|
|
record_rtk_invocation("cargo")
|
|
counts = rtk_invocation_counts()
|
|
assert counts == {"git": 2, "ls": 1, "cargo": 3}
|
|
|
|
|
|
def test_record_with_explicit_delta():
|
|
record_rtk_invocation("git", delta=5)
|
|
record_rtk_invocation("git", delta=2)
|
|
counts = rtk_invocation_counts()
|
|
assert counts == {"git": 7}
|
|
|
|
|
|
def test_record_zero_delta_is_noop_record():
|
|
# delta=0 is legal — caller may want to "touch" the counter to
|
|
# ensure the key exists before later increments.
|
|
record_rtk_invocation("git", delta=0)
|
|
counts = rtk_invocation_counts()
|
|
assert counts == {"git": 0}
|
|
|
|
|
|
def test_record_rejects_negative_delta():
|
|
with pytest.raises(ValueError, match="must be non-negative"):
|
|
record_rtk_invocation("git", delta=-1)
|
|
|
|
|
|
def test_record_rejects_non_string_tool():
|
|
with pytest.raises(TypeError, match="tool must be a str"):
|
|
record_rtk_invocation(123, delta=1) # type: ignore[arg-type]
|
|
|
|
|
|
def test_record_rejects_non_int_delta():
|
|
with pytest.raises(TypeError, match="delta must be an int"):
|
|
record_rtk_invocation("git", delta="1") # type: ignore[arg-type]
|
|
|
|
|
|
def test_counts_returns_snapshot_not_view():
|
|
# The returned mapping must be a plain dict copy, not the
|
|
# internal defaultdict — otherwise callers could pollute the
|
|
# counter map by reading absent keys.
|
|
record_rtk_invocation("git")
|
|
counts = rtk_invocation_counts()
|
|
# Reading a key that's not present must not add it to the
|
|
# internal map.
|
|
_ = counts.get("nonexistent_tool", 0)
|
|
counts2 = rtk_invocation_counts()
|
|
assert "nonexistent_tool" not in counts2
|
|
|
|
|
|
def test_thread_safe_concurrent_increments():
|
|
# 10 threads each bumping `git` 100 times: final count must be
|
|
# exactly 1000. The threading.Lock guards the dict update so
|
|
# races are impossible.
|
|
def worker():
|
|
for _ in range(100):
|
|
record_rtk_invocation("git")
|
|
|
|
threads = [threading.Thread(target=worker) for _ in range(10)]
|
|
for t in threads:
|
|
t.start()
|
|
for t in threads:
|
|
t.join()
|
|
counts = rtk_invocation_counts()
|
|
assert counts == {"git": 1000}
|
|
|
|
|
|
def test_reset_clears_counts():
|
|
record_rtk_invocation("git", delta=42)
|
|
record_rtk_invocation("ls", delta=7)
|
|
assert rtk_invocation_counts() != {}
|
|
reset_rtk_invocations()
|
|
assert rtk_invocation_counts() == {}
|