import pytest from app.local_file_client import LocalFileClient @pytest.fixture def client(tmp_path): return LocalFileClient(str(tmp_path)) def test_put_and_get_object_roundtrip(client): client.put_object("产品文档/架构设计.md", b"# hi", "text/markdown") assert client.get_object("产品文档/架构设计.md") == b"# hi" def test_get_object_raises_file_not_found_for_missing_key(client): with pytest.raises(FileNotFoundError): client.get_object("不存在/文档.md") def test_delete_object_removes_file(client): client.put_object("产品文档/旧文档.md", b"old", "text/markdown") client.delete_object("产品文档/旧文档.md") with pytest.raises(FileNotFoundError): client.get_object("产品文档/旧文档.md") def test_delete_object_raises_file_not_found_for_missing_key(client): with pytest.raises(FileNotFoundError): client.delete_object("不存在/文档.md") def test_list_objects_returns_files_and_dirs_at_prefix(client): client.put_object("产品文档/架构设计.md", b"# hi", "text/markdown") client.put_object("团队规范/编码规范.md", b"# rules", "text/markdown") result = client.list_objects("产品文档/") assert len(result) == 1 assert result[0]["key"] == "产品文档/架构设计.md" assert result[0]["size"] == 4 assert result[0]["is_dir"] is False def test_list_objects_returns_empty_list_for_missing_prefix(client): assert client.list_objects("不存在/") == [] def test_resolve_path_rejects_path_traversal(client): with pytest.raises(ValueError): client.get_object("../../etc/passwd")