From baa2c84c3f2480b4254202bbedcc98ee1761575d Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Tue, 21 Apr 2026 11:57:54 +0000 Subject: [PATCH] feat: Add test_freshness.py (#200) --- tests/test_freshness.py | 227 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 tests/test_freshness.py diff --git a/tests/test_freshness.py b/tests/test_freshness.py new file mode 100644 index 0000000..0568664 --- /dev/null +++ b/tests/test_freshness.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +"""Tests for scripts/freshness.py — 8 tests.""" + +import json +import os +import sys +import tempfile + +sys.path.insert(0, os.path.join(os.path.dirname(__file__) or ".", "..")) +import importlib.util +spec = importlib.util.spec_from_file_location( + "freshness", os.path.join(os.path.dirname(__file__) or ".", "..", "scripts", "freshness.py")) +mod = importlib.util.module_from_spec(spec) +spec.loader.exec_module(mod) + +compute_file_hash = mod.compute_file_hash +check_freshness = mod.check_freshness +load_knowledge_entries = mod.load_knowledge_entries + + +def test_compute_file_hash(): + """File hash should be computed correctly.""" + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + f.write("test content") + f.flush() + h = compute_file_hash(f.name) + assert h is not None + assert h.startswith("sha256:") + os.unlink(f.name) + print("PASS: test_compute_file_hash") + + +def test_compute_file_hash_nonexistent(): + """Nonexistent file should return None.""" + h = compute_file_hash("/nonexistent/file.txt") + assert h is None + print("PASS: test_compute_file_hash_nonexistent") + + +def test_load_knowledge_entries_empty(): + """Empty knowledge dir should return empty list.""" + with tempfile.TemporaryDirectory() as tmpdir: + entries = load_knowledge_entries(tmpdir) + assert entries == [] + print("PASS: test_load_knowledge_entries_empty") + + +def test_load_knowledge_entries_from_index(): + """Should load entries from index.json.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Create index.json + index_path = os.path.join(tmpdir, "index.json") + with open(index_path, "w") as f: + json.dump({ + "facts": [ + { + "fact": "Test fact", + "source_file": "test.py", + "source_hash": "sha256:abc123", + "category": "fact", + "confidence": 0.9 + } + ] + }, f) + + entries = load_knowledge_entries(tmpdir) + assert len(entries) == 1 + assert entries[0]["fact"] == "Test fact" + assert entries[0]["source_file"] == "test.py" + print("PASS: test_load_knowledge_entries_from_index") + + +def test_load_knowledge_entries_from_yaml(): + """Should load entries from YAML files.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Create global directory + global_dir = os.path.join(tmpdir, "global") + os.makedirs(global_dir) + + # Create YAML file + yaml_path = os.path.join(global_dir, "test.yaml") + with open(yaml_path, "w") as f: + f.write(""" +pitfalls: + - description: "Test pitfall" + source_file: "test.py" + source_hash: "sha256:def456" + category: "pitfall" + confidence: 0.8 +""") + + entries = load_knowledge_entries(tmpdir) + assert len(entries) == 1 + assert entries[0]["fact"] == "Test pitfall" + assert entries[0]["category"] == "pitfall" + print("PASS: test_load_knowledge_entries_from_yaml") + + +def test_check_freshness_no_changes(): + """With no source file reference, entries should be counted correctly.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Create knowledge dir + knowledge_dir = os.path.join(tmpdir, "knowledge") + os.makedirs(knowledge_dir) + + # Create repo dir + repo_dir = os.path.join(tmpdir, "repo") + os.makedirs(repo_dir) + + # Create index.json with entry that has no source_file + index_path = os.path.join(knowledge_dir, "index.json") + with open(index_path, "w") as f: + json.dump({ + "facts": [ + { + "fact": "General knowledge", + "category": "fact", + "confidence": 0.9 + # No source_file or source_hash + } + ] + }, f) + + result = check_freshness(knowledge_dir, repo_dir, days=1) + + # Entry without source_file should be counted as "fresh" (no_source status) + assert result["summary"]["total"] == 1 + assert result["summary"]["stale"] == 0 + assert result["summary"]["fresh"] == 1 + assert result["fresh_entries"][0]["status"] == "no_source" + print("PASS: test_check_freshness_no_changes") + + +def test_check_freshness_with_hash_mismatch(): + """Hash mismatch should mark entry as stale.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Create knowledge dir + knowledge_dir = os.path.join(tmpdir, "knowledge") + os.makedirs(knowledge_dir) + + # Create repo dir with a file + repo_dir = os.path.join(tmpdir, "repo") + os.makedirs(repo_dir) + + test_file = os.path.join(repo_dir, "test.py") + with open(test_file, "w") as f: + f.write("print('hello')") + + # Create index.json with wrong hash + index_path = os.path.join(knowledge_dir, "index.json") + with open(index_path, "w") as f: + json.dump({ + "facts": [ + { + "fact": "Test fact", + "source_file": "test.py", + "source_hash": "sha256:wronghash", + "category": "fact", + "confidence": 0.9 + } + ] + }, f) + + # Initialize git repo + os.system(f"cd {repo_dir} && git init && git add . && git commit -m 'init' 2>/dev/null") + + result = check_freshness(knowledge_dir, repo_dir, days=1) + + assert result["summary"]["total"] == 1 + assert result["summary"]["stale"] == 1 + assert result["summary"]["fresh"] == 0 + assert result["stale_entries"][0]["reason"] == "hash_mismatch" + print("PASS: test_check_freshness_with_hash_mismatch") + + +def test_check_freshness_missing_source(): + """Missing source file should mark entry as stale.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Create knowledge dir + knowledge_dir = os.path.join(tmpdir, "knowledge") + os.makedirs(knowledge_dir) + + # Create repo dir (without the referenced file) + repo_dir = os.path.join(tmpdir, "repo") + os.makedirs(repo_dir) + + # Create index.json referencing nonexistent file + index_path = os.path.join(knowledge_dir, "index.json") + with open(index_path, "w") as f: + json.dump({ + "facts": [ + { + "fact": "Test fact", + "source_file": "nonexistent.py", + "source_hash": "sha256:abc123", + "category": "fact", + "confidence": 0.9 + } + ] + }, f) + + # Initialize git repo + os.system(f"cd {repo_dir} && git init && git add . && git commit -m 'init' 2>/dev/null") + + result = check_freshness(knowledge_dir, repo_dir, days=1) + + assert result["summary"]["total"] == 1 + assert result["summary"]["stale"] == 1 + assert result["summary"]["fresh"] == 0 + assert result["stale_entries"][0]["reason"] == "source_missing" + print("PASS: test_check_freshness_missing_source") + + +def run_all(): + test_compute_file_hash() + test_compute_file_hash_nonexistent() + test_load_knowledge_entries_empty() + test_load_knowledge_entries_from_index() + test_load_knowledge_entries_from_yaml() + test_check_freshness_no_changes() + test_check_freshness_with_hash_mismatch() + test_check_freshness_missing_source() + print("\nAll 8 tests passed!") + + +if __name__ == "__main__": + run_all() \ No newline at end of file