Skip to content

Commit b2d17ab

Browse files
committed
test(roots): close two CI coverage gaps
- Add a test for a decorated tool that takes a non-path string parameter alongside a path parameter. Covers the previously unexercised loop-continue branch in within_roots_check when a str/Path argument is found whose name isn't `path` / `*_path`. - Replace placeholder return bodies in the "decorator denies" tests with `raise AssertionError(...) # pragma: no cover`, so the unreachable tool bodies don't drop project coverage below CI's fail_under=100 threshold while still documenting that they must not run.
1 parent 5306da2 commit b2d17ab

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

tests/server/mcpserver/test_roots.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ async def test_decorator_raises_outside_root():
131131

132132
@within_roots_check
133133
async def read_file(path: str, ctx: MagicMock) -> str:
134-
return "file contents"
134+
raise AssertionError("tool body must not run when decorator denies access") # pragma: no cover
135135

136136
with pytest.raises(PermissionError):
137137
await read_file(path="/etc/passwd", ctx=ctx)
@@ -142,7 +142,7 @@ async def test_decorator_checks_star_path_params():
142142

143143
@within_roots_check
144144
async def copy_file(source_path: str, dest_path: str, ctx: MagicMock) -> str:
145-
return "copied"
145+
raise AssertionError("tool body must not run when decorator denies access") # pragma: no cover
146146

147147
with pytest.raises(PermissionError):
148148
await copy_file(
@@ -152,10 +152,25 @@ async def copy_file(source_path: str, dest_path: str, ctx: MagicMock) -> str:
152152
)
153153

154154

155+
async def test_decorator_ignores_non_path_string_params():
156+
ctx = make_ctx(["file:///home/user/project"])
157+
158+
@within_roots_check
159+
async def tool(name: str, path: str, ctx: MagicMock) -> str:
160+
return f"{name}:{path}"
161+
162+
result = await tool(
163+
name="greeting",
164+
path="/home/user/project/file.txt",
165+
ctx=ctx,
166+
)
167+
assert result == "greeting:/home/user/project/file.txt"
168+
169+
155170
async def test_decorator_raises_without_ctx():
156171
@within_roots_check
157172
async def bad_tool(path: str) -> str:
158-
return "oops"
173+
raise AssertionError("tool body must not run when ctx is missing") # pragma: no cover
159174

160175
with pytest.raises(ValueError, match="ctx"):
161176
await bad_tool(path="/some/path")

0 commit comments

Comments
 (0)