mirror of
https://github.com/jmagar/unraid-mcp.git
synced 2026-03-23 12:39:24 -07:00
fix: address 18 PR review comments (threads 1-18)
Threads 1, 2, 3 — test hygiene:
- Move elicit_and_configure/elicit_reset_confirmation to module-level imports
in unraid.py so tests can patch at unraid_mcp.tools.unraid.* (thread 2)
- Add return type annotations to _make_tool() in test_customization.py (thread 1)
- Replace unused _mock_ensure_started fixture params with @usefixtures (thread 3)
Thread 4 — remove dead 'connect' subaction from _SYSTEM_QUERIES; the subaction
was always rejected with a ToolError, creating an inconsistent contract.
Thread 5 — centralize two inline "query { online }" strings by reusing
_SYSTEM_QUERIES["online"]; add _DOCKER_QUERIES["_resolve"] for container-name
resolution instead of an inline query literal.
Threads 14, 15, 16, 17, 18 — test improvements:
- test-tools.sh: reword header to "broad non-destructive smoke coverage" (t14)
- test-tools.sh: add _json_payload() helper using jq --arg for safe JSON
construction; replace all printf-based payloads (thread 15)
- test_input_validation.py: add return type annotations to _make_tool and all
nested _run_test coroutines (thread 16)
- test_query_validation.py: extract _all_domain_dicts() shared helper to
eliminate the duplicate 22-item registry (thread 17)
- test_query_validation.py: tighten regression threshold from 50 → 90 (thread 18)
This commit is contained in:
@@ -60,7 +60,7 @@ def _assert_only_tool_error(exc: BaseException) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _make_tool():
|
||||
def _make_tool() -> Any:
|
||||
return make_tool_fn("unraid_mcp.tools.unraid", "register_unraid_tool", "unraid")
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class TestDockerContainerIdFuzzing:
|
||||
def test_details_arbitrary_container_id(self, container_id: str) -> None:
|
||||
"""Arbitrary container IDs for 'details' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -99,7 +99,7 @@ class TestDockerContainerIdFuzzing:
|
||||
def test_start_arbitrary_container_id(self, container_id: str) -> None:
|
||||
"""Arbitrary container IDs for 'start' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -115,7 +115,7 @@ class TestDockerContainerIdFuzzing:
|
||||
def test_stop_arbitrary_container_id(self, container_id: str) -> None:
|
||||
"""Arbitrary container IDs for 'stop' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -131,7 +131,7 @@ class TestDockerContainerIdFuzzing:
|
||||
def test_restart_arbitrary_container_id(self, container_id: str) -> None:
|
||||
"""Arbitrary container IDs for 'restart' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -172,7 +172,7 @@ class TestDockerInvalidActions:
|
||||
if subaction in valid_subactions:
|
||||
return # Skip valid subactions — they have different semantics
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch("unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock):
|
||||
try:
|
||||
@@ -209,7 +209,7 @@ class TestNotificationsEnumFuzzing:
|
||||
if importance.upper() in valid_importances:
|
||||
return # Skip valid values
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -242,7 +242,7 @@ class TestNotificationsEnumFuzzing:
|
||||
if list_type.upper() in valid_list_types:
|
||||
return # Skip valid values
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -273,7 +273,7 @@ class TestNotificationsEnumFuzzing:
|
||||
must raise ToolError for oversized values, never truncate silently or crash.
|
||||
"""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -308,7 +308,7 @@ class TestNotificationsEnumFuzzing:
|
||||
if notif_type.upper() in valid_types:
|
||||
return
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -353,7 +353,7 @@ class TestNotificationsEnumFuzzing:
|
||||
if subaction in valid_subactions:
|
||||
return
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -389,7 +389,7 @@ class TestKeysInputFuzzing:
|
||||
def test_get_arbitrary_key_id(self, key_id: str) -> None:
|
||||
"""Arbitrary key_id for 'get' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -409,7 +409,7 @@ class TestKeysInputFuzzing:
|
||||
def test_create_arbitrary_key_name(self, name: str) -> None:
|
||||
"""Arbitrary name strings for 'create' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -431,7 +431,7 @@ class TestKeysInputFuzzing:
|
||||
def test_add_role_arbitrary_roles(self, roles: list[str]) -> None:
|
||||
"""Arbitrary role lists for 'add_role' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -456,7 +456,7 @@ class TestKeysInputFuzzing:
|
||||
if subaction in valid_subactions:
|
||||
return
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch("unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock):
|
||||
try:
|
||||
@@ -489,7 +489,7 @@ class TestVMInputFuzzing:
|
||||
def test_start_arbitrary_vm_id(self, vm_id: str) -> None:
|
||||
"""Arbitrary vm_id for 'start' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -510,7 +510,7 @@ class TestVMInputFuzzing:
|
||||
def test_stop_arbitrary_vm_id(self, vm_id: str) -> None:
|
||||
"""Arbitrary vm_id for 'stop' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -531,7 +531,7 @@ class TestVMInputFuzzing:
|
||||
def test_details_arbitrary_vm_id(self, vm_id: str) -> None:
|
||||
"""Arbitrary vm_id for 'details' must not crash the tool."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -566,7 +566,7 @@ class TestVMInputFuzzing:
|
||||
if subaction in valid_subactions:
|
||||
return
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -616,7 +616,7 @@ class TestBoundaryValues:
|
||||
def test_docker_details_adversarial_inputs(self, container_id: str) -> None:
|
||||
"""Adversarial container_id values must not crash the Docker domain."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -649,7 +649,7 @@ class TestBoundaryValues:
|
||||
def test_notifications_importance_adversarial(self, importance: str) -> None:
|
||||
"""Adversarial importance values must raise ToolError, not crash."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request",
|
||||
@@ -687,7 +687,7 @@ class TestBoundaryValues:
|
||||
def test_keys_get_adversarial_key_ids(self, key_id: str) -> None:
|
||||
"""Adversarial key_id values must not crash the keys get action."""
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch(
|
||||
"unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock
|
||||
@@ -739,7 +739,7 @@ class TestInfoActionGuard:
|
||||
if action in valid_actions:
|
||||
return
|
||||
|
||||
async def _run_test():
|
||||
async def _run_test() -> None:
|
||||
tool_fn = _make_tool()
|
||||
with patch("unraid_mcp.tools.unraid.make_graphql_request", new_callable=AsyncMock):
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user