@@ -9,7 +9,7 @@ it("node:child_process should be the same as child_process", () => {
99 expect ( defaultImport ) . toStrictEqual ( legacyImport ) ;
1010} ) ;
1111
12- const { spawn } = defaultImport ;
12+ const { spawn, exec , execFile } = defaultImport ;
1313
1414describe ( "spawn" , ( ) => {
1515 it ( "should spawn a child process" , ( done ) => {
@@ -227,3 +227,205 @@ describe("spawn", () => {
227227 } ) ;
228228 } ) ;
229229} ) ;
230+
231+ describe ( "exec" , ( ) => {
232+ it ( "should execute a shell command and return stdout" , ( done ) => {
233+ exec ( "echo Hello" , ( error , stdout , stderr ) => {
234+ try {
235+ expect ( error ) . toBeNull ( ) ;
236+ expect ( stdout . trim ( ) ) . toEqual ( "Hello" ) ;
237+ expect ( stderr ) . toEqual ( "" ) ;
238+ done ( ) ;
239+ } catch ( err ) {
240+ done ( err ) ;
241+ }
242+ } ) ;
243+ } ) ;
244+
245+ it ( "should execute a command with options" , ( done ) => {
246+ const cwd = IS_WINDOWS ? process . cwd ( ) : "/tmp" ;
247+ const pwdCmd = IS_WINDOWS ? "cd" : "pwd" ;
248+ exec ( pwdCmd , { cwd } , ( error , stdout , stderr ) => {
249+ try {
250+ expect ( error ) . toBeNull ( ) ;
251+ if ( IS_WINDOWS ) {
252+ expect ( stdout . trim ( ) . toLowerCase ( ) ) . toContain (
253+ process . cwd ( ) . toLowerCase ( )
254+ ) ;
255+ } else {
256+ expect ( stdout . trim ( ) ) . toContain ( "/tmp" ) ;
257+ }
258+ expect ( stderr ) . toEqual ( "" ) ;
259+ done ( ) ;
260+ } catch ( err ) {
261+ done ( err ) ;
262+ }
263+ } ) ;
264+ } ) ;
265+
266+ it ( "should capture stderr on command failure" , ( done ) => {
267+ if ( process . env . _VIRTUAL_ENV ) {
268+ // QEMU may handle errors differently
269+ return done ( ) ;
270+ }
271+ // Use a command that writes to stderr and exits with error
272+ const cmd = IS_WINDOWS
273+ ? "cmd /c exit 1"
274+ : "sh -c 'echo error >&2 && exit 1'" ;
275+ exec ( cmd , ( error , stdout , stderr ) => {
276+ try {
277+ expect ( error ) . not . toBeNull ( ) ;
278+ expect ( error ! . code ) . toEqual ( 1 ) ;
279+ done ( ) ;
280+ } catch ( err ) {
281+ done ( err ) ;
282+ }
283+ } ) ;
284+ } ) ;
285+
286+ it ( "should handle nonexistent commands" , ( done ) => {
287+ if ( process . env . _VIRTUAL_ENV ) {
288+ // QEMU may handle errors differently
289+ return done ( ) ;
290+ }
291+ exec ( "nonexistent_command_12345" , ( error , stdout , stderr ) => {
292+ try {
293+ expect ( error ) . not . toBeNull ( ) ;
294+ done ( ) ;
295+ } catch ( err ) {
296+ done ( err ) ;
297+ }
298+ } ) ;
299+ } ) ;
300+
301+ it ( "should respect maxBuffer option" , ( done ) => {
302+ // Generate output larger than maxBuffer
303+ const cmd = IS_WINDOWS
304+ ? 'cmd /c "echo AAAAAAAAAA"'
305+ : "echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ;
306+ exec ( cmd , { maxBuffer : 10 } , ( error , stdout , stderr ) => {
307+ try {
308+ expect ( error ) . not . toBeNull ( ) ;
309+ expect ( error ! . message ) . toContain ( "maxBuffer" ) ;
310+ done ( ) ;
311+ } catch ( err ) {
312+ done ( err ) ;
313+ }
314+ } ) ;
315+ } ) ;
316+ } ) ;
317+
318+ describe ( "execFile" , ( ) => {
319+ it ( "should execute a file and return stdout" , ( done ) => {
320+ execFile ( "echo" , [ "Hello" , "World" ] , ( error , stdout , stderr ) => {
321+ try {
322+ expect ( error ) . toBeNull ( ) ;
323+ expect ( stdout . trim ( ) ) . toEqual ( "Hello World" ) ;
324+ expect ( stderr ) . toEqual ( "" ) ;
325+ done ( ) ;
326+ } catch ( err ) {
327+ done ( err ) ;
328+ }
329+ } ) ;
330+ } ) ;
331+
332+ it ( "should execute a file without arguments" , ( done ) => {
333+ const cmd = IS_WINDOWS ? "cmd" : "pwd" ;
334+ const args = IS_WINDOWS ? [ "/c" , "cd" ] : [ ] ;
335+ execFile ( cmd , args , ( error , stdout , stderr ) => {
336+ try {
337+ expect ( error ) . toBeNull ( ) ;
338+ expect ( stdout . length ) . toBeGreaterThan ( 0 ) ;
339+ expect ( stderr ) . toEqual ( "" ) ;
340+ done ( ) ;
341+ } catch ( err ) {
342+ done ( err ) ;
343+ }
344+ } ) ;
345+ } ) ;
346+
347+ it ( "should execute with options" , ( done ) => {
348+ const cwd = IS_WINDOWS ? process . cwd ( ) : "/tmp" ;
349+ const cmd = IS_WINDOWS ? "cmd" : "pwd" ;
350+ const args = IS_WINDOWS ? [ "/c" , "cd" ] : [ ] ;
351+ execFile ( cmd , args , { cwd } , ( error , stdout , stderr ) => {
352+ try {
353+ expect ( error ) . toBeNull ( ) ;
354+ if ( IS_WINDOWS ) {
355+ expect ( stdout . trim ( ) . toLowerCase ( ) ) . toContain (
356+ process . cwd ( ) . toLowerCase ( )
357+ ) ;
358+ } else {
359+ expect ( stdout . trim ( ) ) . toContain ( "/tmp" ) ;
360+ }
361+ done ( ) ;
362+ } catch ( err ) {
363+ done ( err ) ;
364+ }
365+ } ) ;
366+ } ) ;
367+
368+ it ( "should handle nonexistent executable" , ( done ) => {
369+ if ( process . env . _VIRTUAL_ENV ) {
370+ // QEMU may handle errors differently
371+ return done ( ) ;
372+ }
373+ execFile ( "nonexistent_command_12345" , [ ] , ( error , stdout , stderr ) => {
374+ try {
375+ expect ( error ) . not . toBeNull ( ) ;
376+ done ( ) ;
377+ } catch ( err ) {
378+ done ( err ) ;
379+ }
380+ } ) ;
381+ } ) ;
382+
383+ it ( "should handle executable failure with exit code" , ( done ) => {
384+ if ( process . env . _VIRTUAL_ENV ) {
385+ // QEMU may handle errors differently
386+ return done ( ) ;
387+ }
388+ const cmd = IS_WINDOWS ? "cmd" : "sh" ;
389+ const args = IS_WINDOWS ? [ "/c" , "exit 42" ] : [ "-c" , "exit 42" ] ;
390+ execFile ( cmd , args , ( error , stdout , stderr ) => {
391+ try {
392+ expect ( error ) . not . toBeNull ( ) ;
393+ expect ( error ! . code ) . toEqual ( 42 ) ;
394+ done ( ) ;
395+ } catch ( err ) {
396+ done ( err ) ;
397+ }
398+ } ) ;
399+ } ) ;
400+
401+ it ( "should respect maxBuffer option" , ( done ) => {
402+ execFile (
403+ "echo" ,
404+ [ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ] ,
405+ { maxBuffer : 10 } ,
406+ ( error , stdout , stderr ) => {
407+ try {
408+ expect ( error ) . not . toBeNull ( ) ;
409+ expect ( error ! . message ) . toContain ( "maxBuffer" ) ;
410+ done ( ) ;
411+ } catch ( err ) {
412+ done ( err ) ;
413+ }
414+ }
415+ ) ;
416+ } ) ;
417+
418+ it ( "should execute with shell option" , ( done ) => {
419+ // When shell is true, execFile should use shell to execute
420+ const cmd = IS_WINDOWS ? "echo %PATH%" : "echo $PATH" ;
421+ execFile ( cmd , [ ] , { shell : true } , ( error , stdout , stderr ) => {
422+ try {
423+ expect ( error ) . toBeNull ( ) ;
424+ expect ( stdout . length ) . toBeGreaterThan ( 0 ) ;
425+ done ( ) ;
426+ } catch ( err ) {
427+ done ( err ) ;
428+ }
429+ } ) ;
430+ } ) ;
431+ } ) ;
0 commit comments