11cb0ef41Sopenharmony_ci// Flags: --expose-internals 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst assert = require('assert'); 51cb0ef41Sopenharmony_ciconst cp = require('child_process'); 61cb0ef41Sopenharmony_ciconst internalCp = require('internal/child_process'); 71cb0ef41Sopenharmony_ciconst oldSpawnSync = internalCp.spawnSync; 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci// Verify that a shell is, in fact, executed 101cb0ef41Sopenharmony_ciconst doesNotExist = cp.spawnSync('does-not-exist', { shell: true }); 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciassert.notStrictEqual(doesNotExist.file, 'does-not-exist'); 131cb0ef41Sopenharmony_ciassert.strictEqual(doesNotExist.error, undefined); 141cb0ef41Sopenharmony_ciassert.strictEqual(doesNotExist.signal, null); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciif (common.isWindows) 171cb0ef41Sopenharmony_ci assert.strictEqual(doesNotExist.status, 1); // Exit code of cmd.exe 181cb0ef41Sopenharmony_cielse 191cb0ef41Sopenharmony_ci assert.strictEqual(doesNotExist.status, 127); // Exit code of /bin/sh 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// Verify that passing arguments works 221cb0ef41Sopenharmony_ciinternalCp.spawnSync = common.mustCall(function(opts) { 231cb0ef41Sopenharmony_ci assert.strictEqual(opts.args[opts.args.length - 1].replace(/"/g, ''), 241cb0ef41Sopenharmony_ci 'echo foo'); 251cb0ef41Sopenharmony_ci return oldSpawnSync(opts); 261cb0ef41Sopenharmony_ci}); 271cb0ef41Sopenharmony_ciconst echo = cp.spawnSync('echo', ['foo'], { shell: true }); 281cb0ef41Sopenharmony_ciinternalCp.spawnSync = oldSpawnSync; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciassert.strictEqual(echo.stdout.toString().trim(), 'foo'); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// Verify that shell features can be used 331cb0ef41Sopenharmony_ciconst cmd = 'echo bar | cat'; 341cb0ef41Sopenharmony_ciconst command = cp.spawnSync(cmd, { shell: true }); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ciassert.strictEqual(command.stdout.toString().trim(), 'bar'); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci// Verify that the environment is properly inherited 391cb0ef41Sopenharmony_ciconst env = cp.spawnSync(`"${process.execPath}" -pe process.env.BAZ`, { 401cb0ef41Sopenharmony_ci env: { ...process.env, BAZ: 'buzz' }, 411cb0ef41Sopenharmony_ci shell: true 421cb0ef41Sopenharmony_ci}); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ciassert.strictEqual(env.stdout.toString().trim(), 'buzz'); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci// Verify that the shell internals work properly across platforms. 471cb0ef41Sopenharmony_ci{ 481cb0ef41Sopenharmony_ci const originalComspec = process.env.comspec; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci // Enable monkey patching process.platform. 511cb0ef41Sopenharmony_ci const originalPlatform = process.platform; 521cb0ef41Sopenharmony_ci let platform = null; 531cb0ef41Sopenharmony_ci Object.defineProperty(process, 'platform', { get: () => platform }); 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci function test(testPlatform, shell, shellOutput) { 561cb0ef41Sopenharmony_ci platform = testPlatform; 571cb0ef41Sopenharmony_ci const isCmd = /^(?:.*\\)?cmd(?:\.exe)?$/i.test(shellOutput); 581cb0ef41Sopenharmony_ci const cmd = 'not_a_real_command'; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci const shellFlags = isCmd ? ['/d', '/s', '/c'] : ['-c']; 611cb0ef41Sopenharmony_ci const outputCmd = isCmd ? `"${cmd}"` : cmd; 621cb0ef41Sopenharmony_ci const windowsVerbatim = isCmd ? true : undefined; 631cb0ef41Sopenharmony_ci internalCp.spawnSync = common.mustCall(function(opts) { 641cb0ef41Sopenharmony_ci assert.strictEqual(opts.file, shellOutput); 651cb0ef41Sopenharmony_ci assert.deepStrictEqual(opts.args, 661cb0ef41Sopenharmony_ci [shellOutput, ...shellFlags, outputCmd]); 671cb0ef41Sopenharmony_ci assert.strictEqual(opts.shell, shell); 681cb0ef41Sopenharmony_ci assert.strictEqual(opts.file, opts.file); 691cb0ef41Sopenharmony_ci assert.deepStrictEqual(opts.args, opts.args); 701cb0ef41Sopenharmony_ci assert.strictEqual(opts.windowsHide, false); 711cb0ef41Sopenharmony_ci assert.strictEqual(opts.windowsVerbatimArguments, 721cb0ef41Sopenharmony_ci !!windowsVerbatim); 731cb0ef41Sopenharmony_ci }); 741cb0ef41Sopenharmony_ci cp.spawnSync(cmd, { shell }); 751cb0ef41Sopenharmony_ci internalCp.spawnSync = oldSpawnSync; 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci // Test Unix platforms with the default shell. 791cb0ef41Sopenharmony_ci test('darwin', true, '/bin/sh'); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // Test Unix platforms with a user specified shell. 821cb0ef41Sopenharmony_ci test('darwin', '/bin/csh', '/bin/csh'); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci // Test Android platforms. 851cb0ef41Sopenharmony_ci test('android', true, '/system/bin/sh'); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // Test Windows platforms with a user specified shell. 881cb0ef41Sopenharmony_ci test('win32', 'powershell.exe', 'powershell.exe'); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci // Test Windows platforms with the default shell and no comspec. 911cb0ef41Sopenharmony_ci delete process.env.comspec; 921cb0ef41Sopenharmony_ci test('win32', true, 'cmd.exe'); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci // Test Windows platforms with the default shell and a comspec value. 951cb0ef41Sopenharmony_ci process.env.comspec = 'powershell.exe'; 961cb0ef41Sopenharmony_ci test('win32', true, process.env.comspec); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci // Restore the original value of process.platform. 991cb0ef41Sopenharmony_ci platform = originalPlatform; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci // Restore the original comspec environment variable if necessary. 1021cb0ef41Sopenharmony_ci if (originalComspec) 1031cb0ef41Sopenharmony_ci process.env.comspec = originalComspec; 1041cb0ef41Sopenharmony_ci} 105