"""Unit tests for FileCategoryRepository and FileRecordRepository.""" from pathlib import Path import pytest from agenteval.storage.file_repository import FileCategoryRepository, FileRecordRepository from sqlmodel import Session, SQLModel, create_engine @pytest.fixture() def file_db_session(tmp_path: Path): """Isolated SQLite session with file management tables.""" from agenteval.storage.db import ( # noqa: F401 EvalResultDB, EvalRunDB, EvalTargetDB, FileCategoryDB, FileRecordDB, ScenarioDB, TurnDB, ) engine = create_engine( f"sqlite:///{tmp_path / 'file_test.db'}", connect_args={"check_same_thread": False}, ) SQLModel.metadata.create_all(engine) session = Session(engine) try: yield session finally: session.close() engine.dispose() # ── FileCategoryRepository ──────────────────────────────────────────────── def test_create_root_category(file_db_session): repo = FileCategoryRepository(file_db_session) cat = repo.create("文件一类") assert cat.id is not None assert cat.name == "文件一类" assert cat.parent_id is None def test_create_child_category(file_db_session): repo = FileCategoryRepository(file_db_session) root = repo.create("根分类") child = repo.create("子分类", parent_id=root.id) assert child.parent_id == root.id def test_list_all_categories(file_db_session): repo = FileCategoryRepository(file_db_session) repo.create("A") repo.create("B") all_cats = repo.list_all() assert len(all_cats) == 2 def test_get_tree_structure(file_db_session): repo = FileCategoryRepository(file_db_session) root = repo.create("root") repo.create("child1", parent_id=root.id) repo.create("child2", parent_id=root.id) tree = repo.get_tree() assert len(tree) == 1 assert tree[0].id == root.id assert len(tree[0].children) == 2 def test_get_tree_flat(file_db_session): repo = FileCategoryRepository(file_db_session) repo.create("A") repo.create("B") tree = repo.get_tree() assert len(tree) == 2 assert all(len(node.children) == 0 for node in tree) def test_update_category_name(file_db_session): repo = FileCategoryRepository(file_db_session) cat = repo.create("旧名称") updated = repo.update(cat.id, "新名称") assert updated is not None assert updated.name == "新名称" def test_update_nonexistent_returns_none(file_db_session): repo = FileCategoryRepository(file_db_session) assert repo.update("nonexistent-id", "name") is None def test_get_nonexistent_returns_none(file_db_session): repo = FileCategoryRepository(file_db_session) assert repo.get("no-such-id") is None def test_delete_category(file_db_session): repo = FileCategoryRepository(file_db_session) cat = repo.create("删除目标") assert repo.delete(cat.id) is True assert repo.get(cat.id) is None def test_delete_nonexistent_returns_false(file_db_session): repo = FileCategoryRepository(file_db_session) assert repo.delete("ghost-id") is False def test_delete_cascades_to_children(file_db_session): cat_repo = FileCategoryRepository(file_db_session) file_repo = FileRecordRepository(file_db_session) root = cat_repo.create("父") child = cat_repo.create("子", parent_id=root.id) # Create a file in child file_repo.create("f.txt", "f-storage.txt", 10, "text/plain", "txt", category_id=child.id) assert cat_repo.delete(root.id) is True assert cat_repo.get(root.id) is None assert cat_repo.get(child.id) is None assert len(file_repo.list_all()) == 0 # ── FileRecordRepository ────────────────────────────────────────────────── def test_create_file_record(file_db_session): repo = FileRecordRepository(file_db_session) rec = repo.create("test.txt", "stored-uuid.txt", 128, "text/plain", "txt") assert rec.id is not None assert rec.original_name == "test.txt" assert rec.file_size == 128 def test_create_file_with_category(file_db_session): cat_repo = FileCategoryRepository(file_db_session) file_repo = FileRecordRepository(file_db_session) cat = cat_repo.create("分类") rec = file_repo.create("data.json", "stored.json", 256, "application/json", "json", category_id=cat.id) assert rec.category_id == cat.id def test_list_files_all(file_db_session): repo = FileRecordRepository(file_db_session) repo.create("a.txt", "a-s.txt", 1, "text/plain", "txt") repo.create("b.txt", "b-s.txt", 2, "text/plain", "txt") assert len(repo.list_all()) == 2 def test_list_files_by_category(file_db_session): cat_repo = FileCategoryRepository(file_db_session) file_repo = FileRecordRepository(file_db_session) cat_a = cat_repo.create("A") cat_b = cat_repo.create("B") file_repo.create("in_a.txt", "s1.txt", 1, "text/plain", "txt", category_id=cat_a.id) file_repo.create("in_b.txt", "s2.txt", 2, "text/plain", "txt", category_id=cat_b.id) file_repo.create("no_cat.txt", "s3.txt", 3, "text/plain", "txt") only_a = file_repo.list_all(category_id=cat_a.id) assert len(only_a) == 1 assert only_a[0].original_name == "in_a.txt" def test_list_files_includes_subcategory_files(file_db_session): cat_repo = FileCategoryRepository(file_db_session) file_repo = FileRecordRepository(file_db_session) root = cat_repo.create("root") child = cat_repo.create("child", parent_id=root.id) file_repo.create("in_root.txt", "sr.txt", 1, "text/plain", "txt", category_id=root.id) file_repo.create("in_child.txt", "sc.txt", 2, "text/plain", "txt", category_id=child.id) files = file_repo.list_all(category_id=root.id) assert len(files) == 2 def test_get_file_record(file_db_session): repo = FileRecordRepository(file_db_session) rec = repo.create("get_me.txt", "gm.txt", 10, "text/plain", "txt") fetched = repo.get(rec.id) assert fetched is not None assert fetched.id == rec.id def test_get_nonexistent_file_returns_none(file_db_session): repo = FileRecordRepository(file_db_session) assert repo.get("no-such-id") is None def test_delete_file_record(file_db_session): repo = FileRecordRepository(file_db_session) rec = repo.create("del.txt", "del-s.txt", 5, "text/plain", "txt") assert repo.delete(rec.id) is True assert repo.get(rec.id) is None def test_get_subtree_ids(file_db_session): repo = FileCategoryRepository(file_db_session) root = repo.create("root") child = repo.create("child", parent_id=root.id) leaf = repo.create("leaf", parent_id=child.id) assert set(repo.get_subtree_ids(root.id)) == {root.id, child.id, leaf.id} def test_delete_nonexistent_file_returns_false(file_db_session): repo = FileRecordRepository(file_db_session) assert repo.delete("ghost-id") is False