@@ -25,6 +25,7 @@ import { ExperimentFlags } from '../code_assist/experiments/flagNames.js';
2525import { debugLogger } from '../utils/debugLogger.js' ;
2626import { coreEvents } from '../utils/events.js' ;
2727import { ApprovalMode } from '../policy/types.js' ;
28+ import { execFileSync } from 'node:child_process' ;
2829import {
2930 HookType ,
3031 HookEventName ,
@@ -154,6 +155,14 @@ vi.mock('../tools/memoryTool', async (importOriginal) => {
154155
155156vi . mock ( '../core/contentGenerator.js' ) ;
156157
158+ vi . mock ( 'node:child_process' , async ( importOriginal ) => {
159+ const actual = await importOriginal < typeof import ( 'node:child_process' ) > ( ) ;
160+ return {
161+ ...actual ,
162+ execFileSync : vi . fn ( ) ,
163+ } ;
164+ } ) ;
165+
157166vi . mock ( '../core/client.js' , ( ) => ( {
158167 GeminiClient : vi . fn ( ) . mockImplementation ( ( ) => ( {
159168 initialize : vi . fn ( ) . mockResolvedValue ( undefined ) ,
@@ -2377,6 +2386,33 @@ describe('setApprovalMode with folder trust', () => {
23772386 expect ( event . error ) . toBe ( String ( error ) ) ;
23782387 } ) ;
23792388
2389+ it ( 'should register GrepTool as a fallback when the ripgrep binary execution check throws an error' , async ( ) => {
2390+ vi . mocked ( resolveRipgrepPath ) . mockResolvedValue ( '/mock/rg' ) ;
2391+ const error = new Error ( 'spawn EFTYPE' ) ;
2392+ vi . mocked ( execFileSync ) . mockImplementation ( ( ) => {
2393+ throw error ;
2394+ } ) ;
2395+ const config = new Config ( { ...baseParams , useRipgrep : true } ) ;
2396+ await config . initialize ( ) ;
2397+
2398+ const calls = vi . mocked ( ToolRegistry . prototype . registerTool ) . mock . calls ;
2399+ const wasRipGrepRegistered = calls . some (
2400+ ( call ) => call [ 0 ] instanceof vi . mocked ( RipGrepTool ) ,
2401+ ) ;
2402+ const wasGrepRegistered = calls . some (
2403+ ( call ) => call [ 0 ] instanceof vi . mocked ( GrepTool ) ,
2404+ ) ;
2405+
2406+ expect ( wasRipGrepRegistered ) . toBe ( false ) ;
2407+ expect ( wasGrepRegistered ) . toBe ( true ) ;
2408+ expect ( logRipgrepFallback ) . toHaveBeenCalledWith (
2409+ config ,
2410+ expect . any ( RipgrepFallbackEvent ) ,
2411+ ) ;
2412+ const event = vi . mocked ( logRipgrepFallback ) . mock . calls [ 0 ] [ 1 ] ;
2413+ expect ( event . error ) . toBe ( String ( error ) ) ;
2414+ } ) ;
2415+
23802416 it ( 'should register GrepTool when useRipgrep is false' , async ( ) => {
23812417 const config = new Config ( { ...baseParams , useRipgrep : false } ) ;
23822418 await config . initialize ( ) ;
0 commit comments