testsAndMisc/python_pkg/token_dashboard/tests/test_context_files.py
Krzysztof kuhy Rudnicki 1ba202c567
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
token_dashboard: ingester core + detail tables (calls, marks, turn_detail, ab_rows) for the control-panel dashboard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JThjboXTeZ3yJPBzxMx5wS
2026-10-18 14:45:06 +02:00

104 lines
4.0 KiB
Python

from __future__ import annotations
import json
import os
import subprocess
from typing import TYPE_CHECKING
from python_pkg.token_dashboard import context_files, gitcmd, schema
if TYPE_CHECKING:
from pathlib import Path
def _tree(tmp_path: Path) -> tuple[Path, Path]:
claude, src = tmp_path / ".claude", tmp_path / "src"
for rel in (
"CLAUDE.md",
"rules/a.instructions.md",
"rules/deep/b.md",
"memories/mistakes.md",
"skills/x/SKILL.md",
"agents/reviewer.md",
"projects/-home-kuhy/memory/MEMORY.md",
"backups/rules-ondemand/not-loaded.md",
):
(claude / rel).parent.mkdir(parents=True, exist_ok=True)
(claude / rel).write_text("# x\n" * 10, encoding="utf-8")
(src / "repo").mkdir(parents=True)
(src / "repo" / "CLAUDE.md").write_text("## Commands\n", encoding="utf-8")
(src / "repo" / "AGENTS.md").write_text("agents\n", encoding="utf-8")
return claude, src
def test_enumerates_every_loaded_file_and_nothing_on_demand(tmp_path: Path) -> None:
claude, src = _tree(tmp_path)
found = {
f.path.replace(str(tmp_path), ""): f for f in context_files.find(claude, src)
}
assert set(found) == {
"/.claude/CLAUDE.md",
"/.claude/rules/a.instructions.md",
"/.claude/rules/deep/b.md",
"/.claude/memories/mistakes.md",
"/.claude/skills/x/SKILL.md",
"/.claude/agents/reviewer.md",
"/.claude/projects/-home-kuhy/memory/MEMORY.md",
"/src/repo/CLAUDE.md",
"/src/repo/AGENTS.md",
}
assert found["/.claude/rules/deep/b.md"].standing == "always"
assert found["/src/repo/CLAUDE.md"].standing == "in repo"
assert found["/.claude/skills/x/SKILL.md"].standing == "description"
assert found["/.claude/projects/-home-kuhy/memory/MEMORY.md"].limit == 24_400
def _git(repo: Path, *args: str, when: int) -> None:
env = {**os.environ, "GIT_AUTHOR_DATE": f"@{when} +0000"}
env |= {"GIT_COMMITTER_DATE": f"@{when} +0000", "HOME": str(repo)}
env |= {"GIT_AUTHOR_NAME": "t", "GIT_AUTHOR_EMAIL": "t@t"}
env |= {"GIT_COMMITTER_NAME": "t", "GIT_COMMITTER_EMAIL": "t@t"}
subprocess.run(
[gitcmd.GIT, "-C", str(repo), *args], env=env, check=True, capture_output=True
)
def test_size_history_from_git_and_prune_sizes(tmp_path: Path) -> None:
claude, src = _tree(tmp_path)
_git(claude, "init", "-q", when=1000)
_git(claude, "add", "CLAUDE.md", when=1000)
_git(claude, "commit", "-qm", "a", when=1000)
(claude / "CLAUDE.md").write_text("longer\n" * 50, encoding="utf-8")
_git(claude, "commit", "-qam", "b", when=2000)
prune = claude / "token-report" / "prune" / "2026-10-12"
prune.mkdir(parents=True)
(prune / "sizes.json").write_text(json.dumps({"file_bytes": {"CLAUDE.md": 77}}))
conn = schema.connect(tmp_path / "t.sqlite")
context_files.refresh(conn, claude, src)
rows = conn.execute(
"SELECT ts, bytes, source FROM context_sizes WHERE path LIKE '%/CLAUDE.md'"
" AND path NOT LIKE '%/src/%' ORDER BY ts"
).fetchall()
listed = conn.execute("SELECT COUNT(*) FROM context_files").fetchone()[0]
context_files.refresh(conn, claude, src) # incremental: no duplicates
again = conn.execute("SELECT COUNT(*) FROM context_sizes").fetchone()[0]
conn.close()
assert [(r[1], r[2]) for r in rows[:2]] == [(40, "git"), (350, "git")]
assert (77, "prune 2026-10-12") in [(r[1], r[2]) for r in rows]
assert listed == 9
assert again == len(rows)
def test_price_mix_weights_cache_read_price_by_calls(tmp_path: Path) -> None:
conn = schema.connect(tmp_path / "t.sqlite")
rows = [
("claude-opus-5-5", 100.0),
("claude-opus-5-5", 101.0),
("claude-haiku-4-5", 102.0),
("claude-haiku-4-5", 1.0),
]
conn.executemany("INSERT INTO turns (model, ts) VALUES (?, ?)", rows)
price = context_files.price_mix(conn, now=200.0, days=150 / 86400)
conn.close()
assert round(price, 4) == round((0.2 * 2 + 0.1) / 3, 4)