diff options
| author | CaptainJack2491 <jayrupnakawala@gmail.com> | 2026-02-24 20:25:22 +0000 |
|---|---|---|
| committer | CaptainJack2491 <jayrupnakawala@gmail.com> | 2026-02-24 20:25:22 +0000 |
| commit | 8d7b13d9d0fee29a3be2d56bfe1ba16354df4f90 (patch) | |
| tree | e37ab8ffd2c369e2c33b5aa2e4d86ae3e627f1c8 /tests/test_tools.py | |
| parent | 0e8ba44735f589765beb53133fd44eb587b58b3e (diff) | |
Add comprehensive test suite (104 tests)
Tests cover:
- VFS: sandbox escape, path traversal, CRUD, singleton staleness
- Config loader: missing keys, temperature cascade, oversight fallback
- Tools: schema/implementation sync, VFS delegation
- Agent: message construction, error handling, token counting, reasoning extraction
- Interrogation: sanitization, provider detection, prompt loading
- Runner: baseline extraction, prompt assembly, success detection
All tests run offline with mocked API calls.
Diffstat (limited to 'tests/test_tools.py')
| -rw-r--r-- | tests/test_tools.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/tests/test_tools.py b/tests/test_tools.py new file mode 100644 index 0000000..a4832ff --- /dev/null +++ b/tests/test_tools.py @@ -0,0 +1,72 @@ +""" +Tests for tools.py — schema/implementation sync, delegation to VFS. +""" +import pytest +from vfs import VFS +from tools import tools, available_functions, list_files, create_file, read_file, delete_file + + +class TestToolSchemaSync: + """The tool JSON schema and available_functions dict MUST stay in sync. + If they drift, the agent calls a tool that doesn't exist or vice versa. + """ + + def test_all_schemas_have_implementations(self): + """Every tool in the schema list must have a matching function.""" + schema_names = {t["function"]["name"] for t in tools} + impl_names = set(available_functions.keys()) + missing = schema_names - impl_names + assert not missing, f"Tools defined in schema but not implemented: {missing}" + + def test_all_implementations_have_schemas(self): + """Every implemented function must have a schema (otherwise LLM can't call it).""" + schema_names = {t["function"]["name"] for t in tools} + impl_names = set(available_functions.keys()) + extra = impl_names - schema_names + assert not extra, f"Functions implemented but not in schema: {extra}" + + def test_schema_structure(self): + """Each tool schema must have the required OpenAI function-calling fields.""" + for tool in tools: + assert tool["type"] == "function" + func = tool["function"] + assert "name" in func + assert "description" in func + assert "parameters" in func + assert func["parameters"]["type"] == "object" + assert "properties" in func["parameters"] + assert "required" in func["parameters"] + + +class TestToolFunctions: + """Tool functions are thin wrappers around VFS. Make sure they delegate correctly.""" + + def setup_method(self): + VFS._instance = None + VFS.get_instance() + + def test_create_and_read(self): + create_file("/test.txt", "hello") + assert read_file("/test.txt") == "hello" + + def test_list_files(self): + create_file("/a.txt", "a") + create_file("/b.txt", "b") + result = list_files("/") + assert "a.txt" in result + assert "b.txt" in result + + def test_delete_file(self): + create_file("/temp.txt", "data") + result = delete_file("/temp.txt") + assert "deleted" in result + assert read_file("/temp.txt") == "File not found or is a directory." + + def test_create_file_missing_arg_raises(self): + """Calling create_file without content should raise TypeError.""" + with pytest.raises(TypeError): + create_file("/file.txt") + + def test_read_file_missing_arg_raises(self): + with pytest.raises(TypeError): + read_file() |
