Skip to content

Commit 189dcf7

Browse files
chore: increase coverage for shell, filesystem, and summarization middleware (#33928)
cc generated, just a start here but wanted to bump things up from 70% ish
1 parent 1bc8802 commit 189dcf7

File tree

4 files changed

+837
-96
lines changed

4 files changed

+837
-96
lines changed

libs/langchain_v1/tests/unit_tests/agents/middleware/implementations/test_file_search.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
from langchain.agents.middleware.file_search import (
99
FilesystemFileSearchMiddleware,
10+
_expand_include_patterns,
11+
_is_valid_include_pattern,
12+
_match_include_pattern,
1013
)
1114

1215

@@ -259,3 +262,105 @@ def test_grep_path_traversal_protection(self, tmp_path: Path) -> None:
259262

260263
assert result == "No matches found"
261264
assert "secret" not in result
265+
266+
267+
class TestExpandIncludePatterns:
268+
"""Tests for _expand_include_patterns helper function."""
269+
270+
def test_expand_patterns_basic_brace_expansion(self) -> None:
271+
"""Test basic brace expansion with multiple options."""
272+
result = _expand_include_patterns("*.{py,txt}")
273+
assert result == ["*.py", "*.txt"]
274+
275+
def test_expand_patterns_nested_braces(self) -> None:
276+
"""Test nested brace expansion."""
277+
result = _expand_include_patterns("test.{a,b}.{c,d}")
278+
assert result is not None
279+
assert len(result) == 4
280+
assert "test.a.c" in result
281+
assert "test.b.d" in result
282+
283+
@pytest.mark.parametrize(
284+
"pattern",
285+
[
286+
"*.py}", # closing brace without opening
287+
"*.{}", # empty braces
288+
"*.{py", # unclosed brace
289+
],
290+
)
291+
def test_expand_patterns_invalid_braces(self, pattern: str) -> None:
292+
"""Test patterns with invalid brace syntax return None."""
293+
result = _expand_include_patterns(pattern)
294+
assert result is None
295+
296+
297+
class TestValidateIncludePattern:
298+
"""Tests for _is_valid_include_pattern helper function."""
299+
300+
@pytest.mark.parametrize(
301+
"pattern",
302+
[
303+
"", # empty pattern
304+
"*.py\x00", # null byte
305+
"*.py\n", # newline
306+
],
307+
)
308+
def test_validate_invalid_patterns(self, pattern: str) -> None:
309+
"""Test that invalid patterns are rejected."""
310+
assert not _is_valid_include_pattern(pattern)
311+
312+
313+
class TestMatchIncludePattern:
314+
"""Tests for _match_include_pattern helper function."""
315+
316+
def test_match_pattern_with_braces(self) -> None:
317+
"""Test matching with brace expansion."""
318+
assert _match_include_pattern("test.py", "*.{py,txt}")
319+
assert _match_include_pattern("test.txt", "*.{py,txt}")
320+
assert not _match_include_pattern("test.md", "*.{py,txt}")
321+
322+
def test_match_pattern_invalid_expansion(self) -> None:
323+
"""Test matching with pattern that cannot be expanded returns False."""
324+
assert not _match_include_pattern("test.py", "*.{}")
325+
326+
327+
class TestGrepEdgeCases:
328+
"""Tests for edge cases in grep search."""
329+
330+
def test_grep_with_special_chars_in_pattern(self, tmp_path: Path) -> None:
331+
"""Test grep with special characters in pattern."""
332+
(tmp_path / "test.py").write_text("def test():\n pass\n", encoding="utf-8")
333+
334+
middleware = FilesystemFileSearchMiddleware(root_path=str(tmp_path), use_ripgrep=False)
335+
336+
result = middleware.grep_search.func(pattern="def.*:")
337+
338+
assert "/test.py" in result
339+
340+
def test_grep_case_insensitive(self, tmp_path: Path) -> None:
341+
"""Test grep with case-insensitive search."""
342+
(tmp_path / "test.py").write_text("HELLO world\n", encoding="utf-8")
343+
344+
middleware = FilesystemFileSearchMiddleware(root_path=str(tmp_path), use_ripgrep=False)
345+
346+
result = middleware.grep_search.func(pattern="(?i)hello")
347+
348+
assert "/test.py" in result
349+
350+
def test_grep_with_large_file_skipping(self, tmp_path: Path) -> None:
351+
"""Test that grep skips files larger than max_file_size_mb."""
352+
# Create a file larger than 1MB
353+
large_content = "x" * (2 * 1024 * 1024) # 2MB
354+
(tmp_path / "large.txt").write_text(large_content, encoding="utf-8")
355+
(tmp_path / "small.txt").write_text("x", encoding="utf-8")
356+
357+
middleware = FilesystemFileSearchMiddleware(
358+
root_path=str(tmp_path),
359+
use_ripgrep=False,
360+
max_file_size_mb=1, # 1MB limit
361+
)
362+
363+
result = middleware.grep_search.func(pattern="x")
364+
365+
# Large file should be skipped
366+
assert "/small.txt" in result

0 commit comments

Comments
 (0)