1
1
"""Tests for codebase tools."""
2
2
3
- import subprocess
4
-
5
3
import pytest
6
4
7
5
from codegen .extensions .tools import (
17
15
replacement_edit ,
18
16
reveal_symbol ,
19
17
run_codemod ,
20
- search ,
21
18
semantic_edit ,
22
19
semantic_search ,
23
20
view_file ,
@@ -138,10 +135,12 @@ def test_view_file_pagination(large_codebase):
138
135
result = view_file (large_codebase , "src/large_file.py" , start_line = 350 )
139
136
assert result .status == "success"
140
137
assert result .start_line == 350
141
- assert result .has_more is True # File has 2010 lines, so there should be more content
138
+ # File has 2010 lines, so there should be more content
139
+ assert result .has_more is True
142
140
assert "def method_69" in result .content # Regular method
143
141
assert "def class_method_80" in result .content # Class method at 80
144
- assert result .end_line == 599 # Should show 250 lines from start (350 to 599)
142
+ # Should show 250 lines from start (350 to 599)
143
+ assert result .end_line == 599
145
144
146
145
# Test custom max_lines
147
146
result = view_file (large_codebase , "src/large_file.py" , max_lines = 100 )
@@ -189,7 +188,8 @@ def test_view_file_pagination_edge_cases(large_codebase):
189
188
result = view_file (large_codebase , "src/large_file.py" , start_line = 200 , end_line = 2000 )
190
189
assert result .status == "success"
191
190
assert result .start_line == 200
192
- assert result .end_line == min (200 + 250 - 1 , 2010 ) # Should respect max_lines and file length
191
+ # Should respect max_lines and file length
192
+ assert result .end_line == min (200 + 250 - 1 , 2010 )
193
193
194
194
# Test negative start_line (should default to 1)
195
195
result = view_file (large_codebase , "src/large_file.py" , start_line = - 10 )
@@ -205,7 +205,8 @@ def test_list_directory(codebase):
205
205
create_file (codebase , "src/core/models.py" , "" )
206
206
create_file (codebase , "src/utils.py" , "" )
207
207
208
- result = list_directory (codebase , "./" , depth = 2 ) # Ensure we get nested structure
208
+ # Ensure we get nested structure
209
+ result = list_directory (codebase , "./" , depth = 2 )
209
210
assert result .status == "success"
210
211
211
212
# Check directory structure
@@ -232,126 +233,6 @@ def test_list_directory(codebase):
232
233
assert expected_tree in rendered .strip ()
233
234
234
235
235
- def test_search (codebase ):
236
- """Test searching the codebase."""
237
- result = search (codebase , "hello" )
238
- assert result .status == "success"
239
- assert len (result .results ) > 0
240
-
241
- # Check that we found the right content
242
- assert any ("hello" in match .match .lower () for file_result in result .results for match in file_result .matches )
243
-
244
- # Check pagination info
245
- assert result .page == 1
246
- assert result .total_pages >= 1
247
- assert result .files_per_page == 10
248
-
249
-
250
- def test_search_regex (codebase ):
251
- """Test searching with regex."""
252
- # Search for function definitions
253
- result = search (codebase , r"def\s+\w+" , use_regex = True )
254
- assert result .status == "success"
255
- assert len (result .results ) > 0
256
-
257
- # Should find both 'def hello' and 'def greet'
258
- matches = [match .line for file_result in result .results for match in file_result .matches ]
259
- assert any ("def hello" in match for match in matches )
260
- assert any ("def greet" in match for match in matches )
261
-
262
-
263
- def test_search_pagination (codebase , tmpdir ):
264
- """Test search pagination."""
265
- # Create multiple files to test pagination
266
- files_dict = {}
267
- for i in range (15 ): # Create enough files to span multiple pages
268
- content = f"def function_{ i } ():\n print('Hello from function { i } !')"
269
- files_dict [f"src/file_{ i } .py" ] = content
270
-
271
- # Create a new codebase with all the files
272
- with get_codebase_session (tmpdir = tmpdir , files = files_dict ) as pagination_codebase :
273
- # Search with default pagination (page 1)
274
- result_page1 = search (pagination_codebase , "Hello" , files_per_page = 5 )
275
- assert result_page1 .status == "success"
276
- assert result_page1 .page == 1
277
- assert len (result_page1 .results ) <= 5
278
-
279
- # If we have enough results for multiple pages
280
- if result_page1 .total_pages > 1 :
281
- # Get page 2
282
- result_page2 = search (pagination_codebase , "Hello" , page = 2 , files_per_page = 5 )
283
- assert result_page2 .status == "success"
284
- assert result_page2 .page == 2
285
- assert len (result_page2 .results ) <= 5
286
-
287
- # Ensure different files on different pages
288
- page1_files = {r .filepath for r in result_page1 .results }
289
- page2_files = {r .filepath for r in result_page2 .results }
290
- assert not page1_files .intersection (page2_files )
291
-
292
-
293
- def test_search_fallback (codebase , monkeypatch ):
294
- """Test fallback to Python implementation when ripgrep fails."""
295
-
296
- # Mock subprocess.run to simulate ripgrep failure
297
- def mock_subprocess_run (* args , ** kwargs ):
298
- msg = "Simulated ripgrep failure"
299
- raise subprocess .SubprocessError (msg )
300
-
301
- # Apply the mock
302
- monkeypatch .setattr (subprocess , "run" , mock_subprocess_run )
303
-
304
- # Search should still work using Python fallback
305
- result = search (codebase , "hello" )
306
- assert result .status == "success"
307
- assert len (result .results ) > 0
308
-
309
-
310
- def test_search_ripgrep_not_found (codebase , monkeypatch ):
311
- """Test fallback to Python implementation when ripgrep is not installed."""
312
-
313
- # Mock subprocess.run to simulate ripgrep not found
314
- def mock_subprocess_run (* args , ** kwargs ):
315
- msg = "Simulated ripgrep not found"
316
- raise FileNotFoundError (msg )
317
-
318
- # Apply the mock
319
- monkeypatch .setattr (subprocess , "run" , mock_subprocess_run )
320
-
321
- # Search should still work using Python fallback
322
- result = search (codebase , "hello" )
323
- assert result .status == "success"
324
- assert len (result .results ) > 0
325
-
326
-
327
- def test_search_uses_ripgrep (codebase , monkeypatch ):
328
- """Test that ripgrep is used when available."""
329
- # Track if ripgrep was called
330
- ripgrep_called = False
331
-
332
- # Store original subprocess.run
333
- original_run = subprocess .run
334
-
335
- # Mock subprocess.run to track calls and then call the original
336
- def mock_subprocess_run (* args , ** kwargs ):
337
- nonlocal ripgrep_called
338
- # Check if this is a ripgrep call
339
- if args and args [0 ] and isinstance (args [0 ], list ) and args [0 ][0 ] == "rg" :
340
- ripgrep_called = True
341
- # Call the original implementation
342
- return original_run (* args , ** kwargs )
343
-
344
- # Apply the mock
345
- monkeypatch .setattr (subprocess , "run" , mock_subprocess_run )
346
-
347
- # Perform a search
348
- result = search (codebase , "hello" )
349
- assert result .status == "success"
350
-
351
- # Verify ripgrep was called
352
- assert ripgrep_called , "Ripgrep was not used for the search"
353
-
354
-
355
236
def test_edit_file (codebase ):
356
237
"""Test editing a file."""
357
238
result = edit_file (codebase , "src/main.py" , "print('edited')" )
0 commit comments