Skip to content
File

Blob: src/workerd/api/node/tests/child_process-nodejs-test.js

javascript719 lines
1// Copyright (c) 2025 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import { strictEqual, throws, ok, deepStrictEqual } from 'node:assert';
5import * as child_process from 'node:child_process';
6import {
7 ChildProcess,
8 _forkChild,
9 exec,
10 execFile,
11 execFileSync,
12 execSync,
13 fork,
14 spawn,
15 spawnSync,
16} from 'node:child_process';
17 
18export const testExports = {
19 async test() {
20 strictEqual(typeof ChildProcess, 'function');
21 strictEqual(typeof _forkChild, 'function');
22 strictEqual(typeof exec, 'function');
23 strictEqual(typeof execFile, 'function');
24 strictEqual(typeof execFileSync, 'function');
25 strictEqual(typeof execSync, 'function');
26 strictEqual(typeof fork, 'function');
27 strictEqual(typeof spawn, 'function');
28 strictEqual(typeof spawnSync, 'function');
29 
30 strictEqual(child_process.default.ChildProcess, ChildProcess);
31 strictEqual(child_process.default._forkChild, _forkChild);
32 strictEqual(child_process.default.exec, exec);
33 strictEqual(child_process.default.execFile, execFile);
34 strictEqual(child_process.default.execFileSync, execFileSync);
35 strictEqual(child_process.default.execSync, execSync);
36 strictEqual(child_process.default.fork, fork);
37 strictEqual(child_process.default.spawn, spawn);
38 strictEqual(child_process.default.spawnSync, spawnSync);
39 },
40};
41 
42export const testChildProcessConstructor = {
43 async test() {
44 throws(
45 () => {
46 new ChildProcess();
47 },
48 {
49 code: 'ERR_METHOD_NOT_IMPLEMENTED',
50 }
51 );
52 },
53};
54 
55export const testForkChild = {
56 async test() {
57 throws(
58 () => {
59 _forkChild(1, 2);
60 },
61 {
62 code: 'ERR_METHOD_NOT_IMPLEMENTED',
63 }
64 );
65 },
66};
67 
68export const testExec = {
69 async test() {
70 throws(
71 () => {
72 exec(123);
73 },
74 {
75 code: 'ERR_INVALID_ARG_TYPE',
76 }
77 );
78 
79 throws(
80 () => {
81 exec(null);
82 },
83 {
84 code: 'ERR_INVALID_ARG_TYPE',
85 }
86 );
87 
88 throws(
89 () => {
90 exec('ls', 'invalid');
91 },
92 {
93 code: 'ERR_INVALID_ARG_TYPE',
94 }
95 );
96 
97 throws(
98 () => {
99 exec('ls', {}, 'invalid');
100 },
101 {
102 code: 'ERR_INVALID_ARG_TYPE',
103 }
104 );
105 
106 throws(
107 () => {
108 exec('ls');
109 },
110 {
111 code: 'ERR_METHOD_NOT_IMPLEMENTED',
112 }
113 );
114 
115 throws(
116 () => {
117 exec('ls', {});
118 },
119 {
120 code: 'ERR_METHOD_NOT_IMPLEMENTED',
121 }
122 );
123 
124 throws(
125 () => {
126 exec('ls', null);
127 },
128 {
129 code: 'ERR_METHOD_NOT_IMPLEMENTED',
130 }
131 );
132 
133 throws(
134 () => {
135 exec('ls', {}, () => {});
136 },
137 {
138 code: 'ERR_METHOD_NOT_IMPLEMENTED',
139 }
140 );
141 },
142};
143 
144export const testExecFile = {
145 async test() {
146 throws(
147 () => {
148 execFile('node');
149 },
150 {
151 code: 'ERR_METHOD_NOT_IMPLEMENTED',
152 }
153 );
154 
155 throws(
156 () => {
157 execFile('node', ['-v']);
158 },
159 {
160 code: 'ERR_METHOD_NOT_IMPLEMENTED',
161 }
162 );
163 
164 throws(
165 () => {
166 execFile('node', ['-v'], {});
167 },
168 {
169 code: 'ERR_METHOD_NOT_IMPLEMENTED',
170 }
171 );
172 
173 throws(
174 () => {
175 execFile('node', ['-v'], {}, () => {});
176 },
177 {
178 code: 'ERR_METHOD_NOT_IMPLEMENTED',
179 }
180 );
181 },
182};
183 
184export const testExecFileSync = {
185 async test() {
186 throws(
187 () => {
188 execFileSync('node');
189 },
190 {
191 code: 'ERR_METHOD_NOT_IMPLEMENTED',
192 }
193 );
194 
195 throws(
196 () => {
197 execFileSync('node', ['-v']);
198 },
199 {
200 code: 'ERR_METHOD_NOT_IMPLEMENTED',
201 }
202 );
203 
204 throws(
205 () => {
206 execFileSync('node', ['-v'], {});
207 },
208 {
209 code: 'ERR_METHOD_NOT_IMPLEMENTED',
210 }
211 );
212 },
213};
214 
215export const testExecSync = {
216 async test() {
217 throws(
218 () => {
219 execSync('ls');
220 },
221 {
222 code: 'ERR_METHOD_NOT_IMPLEMENTED',
223 }
224 );
225 
226 throws(
227 () => {
228 execSync('ls', {});
229 },
230 {
231 code: 'ERR_METHOD_NOT_IMPLEMENTED',
232 }
233 );
234 },
235};
236 
237export const testFork = {
238 async test() {
239 throws(
240 () => {
241 fork('script.js');
242 },
243 {
244 code: 'ERR_METHOD_NOT_IMPLEMENTED',
245 }
246 );
247 
248 throws(
249 () => {
250 fork('script.js', ['arg1', 'arg2']);
251 },
252 {
253 code: 'ERR_METHOD_NOT_IMPLEMENTED',
254 }
255 );
256 
257 throws(
258 () => {
259 fork('script.js', ['arg1'], {});
260 },
261 {
262 code: 'ERR_METHOD_NOT_IMPLEMENTED',
263 }
264 );
265 
266 throws(
267 () => {
268 fork('script.js', {});
269 },
270 {
271 code: 'ERR_METHOD_NOT_IMPLEMENTED',
272 }
273 );
274 
275 throws(
276 () => {
277 fork('script.js', 'invalid');
278 },
279 {
280 code: 'ERR_INVALID_ARG_TYPE',
281 }
282 );
283 
284 throws(
285 () => {
286 fork('script.js', 123);
287 },
288 {
289 code: 'ERR_INVALID_ARG_TYPE',
290 }
291 );
292 
293 throws(
294 () => {
295 fork('script.js', [], 'invalid');
296 },
297 {
298 code: 'ERR_INVALID_ARG_TYPE',
299 }
300 );
301 },
302};
303 
304export const testSpawn = {
305 async test() {
306 throws(
307 () => {
308 spawn();
309 },
310 {
311 code: 'ERR_METHOD_NOT_IMPLEMENTED',
312 }
313 );
314 
315 throws(
316 () => {
317 spawn('ls');
318 },
319 {
320 code: 'ERR_METHOD_NOT_IMPLEMENTED',
321 }
322 );
323 
324 throws(
325 () => {
326 spawn('ls', ['-l']);
327 },
328 {
329 code: 'ERR_METHOD_NOT_IMPLEMENTED',
330 }
331 );
332 },
333};
334 
335export const testSpawnSync = {
336 async test() {
337 throws(
338 () => {
339 spawnSync(123);
340 },
341 {
342 code: 'ERR_INVALID_ARG_TYPE',
343 }
344 );
345 
346 throws(
347 () => {
348 spawnSync(null);
349 },
350 {
351 code: 'ERR_INVALID_ARG_TYPE',
352 }
353 );
354 
355 throws(
356 () => {
357 spawnSync(undefined);
358 },
359 {
360 code: 'ERR_INVALID_ARG_TYPE',
361 }
362 );
363 
364 throws(
365 () => {
366 spawnSync('ls');
367 },
368 {
369 code: 'ERR_METHOD_NOT_IMPLEMENTED',
370 }
371 );
372 
373 throws(
374 () => {
375 spawnSync('ls', ['-l']);
376 },
377 {
378 code: 'ERR_METHOD_NOT_IMPLEMENTED',
379 }
380 );
381 
382 throws(
383 () => {
384 spawnSync('ls', ['-l'], {});
385 },
386 {
387 code: 'ERR_METHOD_NOT_IMPLEMENTED',
388 }
389 );
390 },
391};
392 
393export const testChildProcessProperties = {
394 async test() {
395 const proto = ChildProcess.prototype;
396 
397 strictEqual(typeof proto.kill, 'function');
398 strictEqual(typeof proto.send, 'function');
399 strictEqual(typeof proto.disconnect, 'function');
400 strictEqual(typeof proto.unref, 'function');
401 strictEqual(typeof proto.ref, 'function');
402 
403 ok(Symbol.dispose in proto);
404 strictEqual(typeof proto[Symbol.dispose], 'function');
405 },
406};
407 
408export const testExecReturnsChildProcess = {
409 async test() {
410 let _result;
411 try {
412 _result = exec('ls');
413 } catch (_e) {
414 // Expected to throw
415 }
416 ok(true);
417 },
418};
419 
420export const testForkEdgeCases = {
421 async test() {
422 throws(
423 () => {
424 fork('script.js', null);
425 },
426 {
427 code: 'ERR_METHOD_NOT_IMPLEMENTED',
428 }
429 );
430 
431 throws(
432 () => {
433 fork('script.js', undefined);
434 },
435 {
436 code: 'ERR_METHOD_NOT_IMPLEMENTED',
437 }
438 );
439 
440 throws(
441 () => {
442 fork('script.js', [], null);
443 },
444 {
445 code: 'ERR_METHOD_NOT_IMPLEMENTED',
446 }
447 );
448 
449 throws(
450 () => {
451 fork('script.js', [], undefined);
452 },
453 {
454 code: 'ERR_METHOD_NOT_IMPLEMENTED',
455 }
456 );
457 },
458};
459 
460export const testExecCallbacks = {
461 async test() {
462 throws(
463 () => {
464 exec('ls', {}, null);
465 },
466 {
467 code: 'ERR_METHOD_NOT_IMPLEMENTED',
468 }
469 );
470 
471 throws(
472 () => {
473 exec('ls', {}, undefined);
474 },
475 {
476 code: 'ERR_METHOD_NOT_IMPLEMENTED',
477 }
478 );
479 
480 throws(
481 () => {
482 exec('ls', {}, (error, stdout, stderr) => {});
483 },
484 {
485 code: 'ERR_METHOD_NOT_IMPLEMENTED',
486 }
487 );
488 
489 throws(
490 () => {
491 exec('ls', {}, function (error, stdout, stderr) {});
492 },
493 {
494 code: 'ERR_METHOD_NOT_IMPLEMENTED',
495 }
496 );
497 },
498};
499 
500export const testSpawnSyncWithOptions = {
501 async test() {
502 throws(
503 () => {
504 spawnSync('ls', ['-l'], { cwd: '/tmp' });
505 },
506 {
507 code: 'ERR_METHOD_NOT_IMPLEMENTED',
508 }
509 );
510 
511 throws(
512 () => {
513 spawnSync('ls', { cwd: '/tmp' });
514 },
515 {
516 code: 'ERR_METHOD_NOT_IMPLEMENTED',
517 }
518 );
519 
520 throws(
521 () => {
522 spawnSync('ls', []);
523 },
524 {
525 code: 'ERR_METHOD_NOT_IMPLEMENTED',
526 }
527 );
528 
529 throws(
530 () => {
531 spawnSync('ls', [], {});
532 },
533 {
534 code: 'ERR_METHOD_NOT_IMPLEMENTED',
535 }
536 );
537 },
538};
539 
540export const testDefaultExport = {
541 async test() {
542 const defaultExport = child_process.default;
543 
544 ok(defaultExport);
545 strictEqual(typeof defaultExport, 'object');
546 
547 ok('ChildProcess' in defaultExport);
548 ok('_forkChild' in defaultExport);
549 ok('exec' in defaultExport);
550 ok('execFile' in defaultExport);
551 ok('execFileSync' in defaultExport);
552 ok('execSync' in defaultExport);
553 ok('fork' in defaultExport);
554 ok('spawn' in defaultExport);
555 ok('spawnSync' in defaultExport);
556 
557 const expectedKeys = [
558 'ChildProcess',
559 '_forkChild',
560 'exec',
561 'execFile',
562 'execFileSync',
563 
564 'execSync',
565 'fork',
566 'spawn',
567 'spawnSync',
568 ];
569 deepStrictEqual(Object.keys(defaultExport).sort(), expectedKeys.sort());
570 },
571};
572 
573export const testExecEmptyCommand = {
574 async test() {
575 throws(
576 () => {
577 exec('');
578 },
579 {
580 code: 'ERR_METHOD_NOT_IMPLEMENTED',
581 }
582 );
583 
584 throws(
585 () => {
586 exec('', {});
587 },
588 {
589 code: 'ERR_METHOD_NOT_IMPLEMENTED',
590 }
591 );
592 
593 throws(
594 () => {
595 exec('', {}, () => {});
596 },
597 {
598 code: 'ERR_METHOD_NOT_IMPLEMENTED',
599 }
600 );
601 },
602};
603 
604export const testSpawnSyncEmptyCommand = {
605 async test() {
606 throws(
607 () => {
608 spawnSync('');
609 },
610 {
611 code: 'ERR_METHOD_NOT_IMPLEMENTED',
612 }
613 );
614 
615 throws(
616 () => {
617 spawnSync('', []);
618 },
619 {
620 code: 'ERR_METHOD_NOT_IMPLEMENTED',
621 }
622 );
623 
624 throws(
625 () => {
626 spawnSync('', [], {});
627 },
628 {
629 code: 'ERR_METHOD_NOT_IMPLEMENTED',
630 }
631 );
632 },
633};
634 
635export const testErrorCodes = {
636 async test() {
637 throws(
638 () => {
639 new ChildProcess();
640 },
641 {
642 code: 'ERR_METHOD_NOT_IMPLEMENTED',
643 }
644 );
645 
646 throws(
647 () => {
648 _forkChild(1, 2);
649 },
650 {
651 code: 'ERR_METHOD_NOT_IMPLEMENTED',
652 }
653 );
654 
655 throws(
656 () => {
657 exec('ls');
658 },
659 {
660 code: 'ERR_METHOD_NOT_IMPLEMENTED',
661 }
662 );
663 
664 throws(
665 () => {
666 execFile('node');
667 },
668 {
669 code: 'ERR_METHOD_NOT_IMPLEMENTED',
670 }
671 );
672 
673 throws(
674 () => {
675 execFileSync('node');
676 },
677 {
678 code: 'ERR_METHOD_NOT_IMPLEMENTED',
679 }
680 );
681 
682 throws(
683 () => {
684 execSync('ls');
685 },
686 {
687 code: 'ERR_METHOD_NOT_IMPLEMENTED',
688 }
689 );
690 
691 throws(
692 () => {
693 fork('script.js');
694 },
695 {
696 code: 'ERR_METHOD_NOT_IMPLEMENTED',
697 }
698 );
699 
700 throws(
701 () => {
702 spawn();
703 },
704 {
705 code: 'ERR_METHOD_NOT_IMPLEMENTED',
706 }
707 );
708 
709 throws(
710 () => {
711 spawnSync('ls');
712 },
713 {
714 code: 'ERR_METHOD_NOT_IMPLEMENTED',
715 }
716 );
717 },
718};