""" Smoke-tests for the multi-file processing utilities in main.py. These tests run WITHOUT starting the server (no CUSTOM_API_KEY needed) by importing the utilities directly after patching the environment. """ import io import os import zipfile import tarfile import sys # Patch env so main.py doesn't explode on import os.environ.setdefault("CUSTOM_API_KEY", "test-key-for-ci") os.environ.setdefault("OPENROUTER_API_KEY", "test-key-for-ci") # Add parent to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from main import ( _is_skippable_path, _safe_decode, _build_directory_tree, _build_project_representation, _normalize_archive_path, _strip_common_prefix, _extract_zip, _extract_tar, ) def test_is_skippable_path(): # Skip hidden dirs assert _is_skippable_path(".git/config") is True assert _is_skippable_path(".env") is True # Skip known dirs assert _is_skippable_path("node_modules/express/index.js") is True assert _is_skippable_path("__pycache__/mod.cpython-311.pyc") is True # Skip binary extensions (not on CODE_EXTENSIONS allowlist) assert _is_skippable_path("assets/logo.png") is True assert _is_skippable_path("build/app.exe") is True # Skip unknown extensions (not on allowlist) assert _is_skippable_path("data/file.xyz") is True assert _is_skippable_path("archive.tar.gz") is True # Allow code files (on allowlist) assert _is_skippable_path("src/main.py") is False assert _is_skippable_path("index.js") is False assert _is_skippable_path("README.md") is False assert _is_skippable_path("styles.css") is False assert _is_skippable_path("app.java") is False assert _is_skippable_path("config.yaml") is False # Allow extension-less files (Makefile, Dockerfile, Procfile) assert _is_skippable_path("Makefile") is False assert _is_skippable_path("Dockerfile") is False assert _is_skippable_path("src/Procfile") is False print(" ✅ _is_skippable_path") def test_safe_decode(): # Normal UTF-8 assert _safe_decode(b"hello world") == "hello world" # Binary (null bytes) → None assert _safe_decode(b"hello\x00world") is None # Invalid UTF-8 with replacement result = _safe_decode(b"hello \xff world") assert result is not None assert "hello" in result print(" ✅ _safe_decode") def test_normalize_archive_path(): assert _normalize_archive_path("src/main.py") == "src/main.py" assert _normalize_archive_path("./src/main.py") == "src/main.py" # Traversal attacks assert _normalize_archive_path("../../../etc/passwd") is None assert _normalize_archive_path("/etc/passwd") is None # Windows paths assert _normalize_archive_path("src\\main.py") == "src/main.py" print(" ✅ _normalize_archive_path") def test_build_directory_tree(): paths = ["src/index.js", "src/utils.js", "package.json"] tree = _build_directory_tree(paths) assert "src/" in tree assert "index.js" in tree assert "utils.js" in tree assert "package.json" in tree print(" ✅ _build_directory_tree") print(f" Tree output:\n{tree}") def test_build_project_representation(): file_map = { "src/index.js": "console.log('hi');", "package.json": '{"name": "test"}', } result = _build_project_representation(file_map) assert "[PROJECT DIRECTORY TREE]" in result assert '' in result assert '' in result assert "console.log('hi');" in result print(" ✅ _build_project_representation") def test_strip_common_prefix(): # With common prefix fm = {"myproject/src/a.py": "a", "myproject/src/b.py": "b"} stripped = _strip_common_prefix(fm) assert "a.py" in stripped or "src/a.py" in stripped # Without common prefix fm2 = {"src/a.py": "a", "lib/b.py": "b"} stripped2 = _strip_common_prefix(fm2) assert "src/a.py" in stripped2 print(" ✅ _strip_common_prefix") def test_extract_zip(): # Build a zip in memory buf = io.BytesIO() with zipfile.ZipFile(buf, "w") as zf: zf.writestr("project/src/main.py", "print('hello')") zf.writestr("project/src/utils.py", "def add(a, b): return a + b") zf.writestr("project/README.md", "# My Project") # Binary file — should be skipped zf.writestr("project/logo.png", b"\x89PNG\r\n\x1a\n\x00\x00".decode("latin-1")) result = _extract_zip(buf.getvalue()) assert "src/main.py" in result assert "src/utils.py" in result assert "README.md" in result # .png should be skipped assert "logo.png" not in result print(f" ✅ _extract_zip — extracted {len(result)} files") def test_extract_tar(): buf = io.BytesIO() with tarfile.open(fileobj=buf, mode="w:gz") as tf: for name, content in [ ("project/app.py", "import flask"), ("project/config.yaml", "debug: true"), ]: data = content.encode("utf-8") info = tarfile.TarInfo(name=name) info.size = len(data) tf.addfile(info, io.BytesIO(data)) result = _extract_tar(buf.getvalue()) assert "app.py" in result assert "config.yaml" in result print(f" ✅ _extract_tar — extracted {len(result)} files") if __name__ == "__main__": print("\n🧪 Running multi-file utility tests...\n") test_is_skippable_path() test_safe_decode() test_normalize_archive_path() test_build_directory_tree() test_build_project_representation() test_strip_common_prefix() test_extract_zip() test_extract_tar() print("\n✅ All tests passed!\n")