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