1
+ #!/usr/bin/env python3
2
+ """
3
+ Unit tests for max_line_length parameter in search functionality.
4
+ Tests both the default behavior (no limit) and the truncation behavior.
5
+ """
6
+
7
+ import pytest
8
+ import tempfile
9
+ import os
10
+ from unittest .mock import Mock , patch
11
+ from src .code_index_mcp .search .base import parse_search_output
12
+ from src .code_index_mcp .search .basic import BasicSearchStrategy
13
+
14
+
15
+ class TestMaxLineLengthParameter :
16
+ """Test class for max_line_length parameter functionality."""
17
+
18
+ def test_parse_search_output_no_limit_default (self ):
19
+ """Test that parse_search_output has no limit by default (None)."""
20
+ # Create test output with a very long line
21
+ long_line = "x" * 1000 # 1000 character line
22
+ test_output = f"test_file.py:10:{ long_line } "
23
+ base_path = "/test/path"
24
+
25
+ result = parse_search_output (test_output , base_path )
26
+
27
+ # Should return full line without truncation
28
+ # Check that we have exactly one result
29
+ assert len (result ) == 1
30
+ # Get the first (and only) key-value pair
31
+ file_path , matches = next (iter (result .items ()))
32
+ assert len (matches ) == 1
33
+ line_num , content = matches [0 ]
34
+ assert line_num == 10
35
+ assert content == long_line
36
+ assert len (content ) == 1000
37
+
38
+ def test_parse_search_output_no_limit_explicit (self ):
39
+ """Test that parse_search_output with explicit None has no limit."""
40
+ # Create test output with a very long line
41
+ long_line = "x" * 500 # 500 character line
42
+ test_output = f"src/module.py:5:{ long_line } "
43
+ base_path = "/project"
44
+
45
+ result = parse_search_output (test_output , base_path , max_line_length = None )
46
+
47
+ # Should return full line without truncation
48
+ assert len (result ) == 1
49
+ file_path , matches = next (iter (result .items ()))
50
+ line_num , content = matches [0 ]
51
+ assert line_num == 5
52
+ assert content == long_line
53
+ assert len (content ) == 500
54
+
55
+ def test_parse_search_output_with_limit (self ):
56
+ """Test that parse_search_output truncates when max_line_length is set."""
57
+ # Create test output with a long line
58
+ long_line = "This is a very long line that should be truncated when max_line_length is applied"
59
+ test_output = f"example.py:1:{ long_line } "
60
+ base_path = "/base"
61
+
62
+ result = parse_search_output (test_output , base_path , max_line_length = 30 )
63
+
64
+ # Should return truncated line with suffix
65
+ assert len (result ) == 1
66
+ file_path , matches = next (iter (result .items ()))
67
+ line_num , content = matches [0 ]
68
+ assert line_num == 1
69
+ assert content == "This is a very long line that ... (truncated)"
70
+ assert len (content ) == 45 # 30 + len("... (truncated)")
71
+
72
+ def test_parse_search_output_exactly_at_limit (self ):
73
+ """Test that lines exactly at the limit are not truncated."""
74
+ exact_line = "x" * 50 # Exactly 50 characters
75
+ test_output = f"file.py:1:{ exact_line } "
76
+ base_path = "/base"
77
+
78
+ result = parse_search_output (test_output , base_path , max_line_length = 50 )
79
+
80
+ # Should return full line without truncation
81
+ assert len (result ) == 1
82
+ file_path , matches = next (iter (result .items ()))
83
+ line_num , content = matches [0 ]
84
+ assert line_num == 1
85
+ assert content == exact_line
86
+ assert len (content ) == 50
87
+ assert "truncated" not in content
88
+
89
+ def test_parse_search_output_under_limit (self ):
90
+ """Test that short lines are never truncated."""
91
+ short_line = "Short line"
92
+ test_output = f"file.py:1:{ short_line } "
93
+ base_path = "/base"
94
+
95
+ result = parse_search_output (test_output , base_path , max_line_length = 100 )
96
+
97
+ # Should return full line without truncation
98
+ assert len (result ) == 1
99
+ file_path , matches = next (iter (result .items ()))
100
+ line_num , content = matches [0 ]
101
+ assert line_num == 1
102
+ assert content == short_line
103
+ assert "truncated" not in content
104
+
105
+ def test_basic_search_strategy_max_line_length (self ):
106
+ """Test that BasicSearchStrategy respects max_line_length parameter."""
107
+ strategy = BasicSearchStrategy ()
108
+
109
+ with tempfile .TemporaryDirectory () as temp_dir :
110
+ # Create test file with long line
111
+ test_file = os .path .join (temp_dir , "test.py" )
112
+ long_line = "def very_long_function_name_that_should_be_cut_when_max_line_length_is_applied():"
113
+
114
+ with open (test_file , "w" ) as f :
115
+ f .write (f"{ long_line } \n " )
116
+ f .write (" pass\n " )
117
+
118
+ # Search with max_line_length
119
+ results = strategy .search (
120
+ pattern = "very_long_function" ,
121
+ base_path = temp_dir ,
122
+ max_line_length = 30
123
+ )
124
+
125
+ # Should find the file and truncate the line
126
+ assert "test.py" in results
127
+ line_num , content = results ["test.py" ][0 ]
128
+ assert line_num == 1
129
+ assert content .endswith ("... (truncated)" )
130
+ # 30 chars + "... (truncated)" (15 chars) = 45 total
131
+ assert len (content ) == 45
132
+
133
+ def test_basic_search_strategy_no_max_line_length (self ):
134
+ """Test that BasicSearchStrategy returns full lines when max_line_length is None."""
135
+ strategy = BasicSearchStrategy ()
136
+
137
+ with tempfile .TemporaryDirectory () as temp_dir :
138
+ # Create test file with long line
139
+ test_file = os .path .join (temp_dir , "test.py" )
140
+ long_line = "def very_long_function_name_that_should_not_be_cut_by_default():"
141
+
142
+ with open (test_file , "w" ) as f :
143
+ f .write (f"{ long_line } \n " )
144
+ f .write (" pass\n " )
145
+
146
+ # Search without max_line_length (default None)
147
+ results = strategy .search (
148
+ pattern = "very_long_function" ,
149
+ base_path = temp_dir ,
150
+ max_line_length = None
151
+ )
152
+
153
+ # Should find the file and return full line
154
+ assert "test.py" in results
155
+ line_num , content = results ["test.py" ][0 ]
156
+ assert line_num == 1
157
+ assert content == long_line
158
+ assert "truncated" not in content
159
+
160
+
161
+ def test_integration_search_service_max_line_length ():
162
+ """Integration test for SearchService with max_line_length parameter."""
163
+ # This would require mocking the full search service setup
164
+ # For now, we'll test the core functionality through parse_search_output
165
+ pass
166
+
167
+
168
+ if __name__ == "__main__" :
169
+ # Run tests directly
170
+ pytest .main ([__file__ , "-v" ])
0 commit comments