123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /** @babel */
- 'not strict';
- import path from 'path';
- import childProcess from 'child_process';
- import {
- updateProcessEnv,
- shouldGetEnvFromShell
- } from '../src/update-process-env';
- import mockSpawn from 'mock-spawn';
- const temp = require('temp').track();
- describe('updateProcessEnv(launchEnv)', function() {
- let originalProcessEnv, originalProcessPlatform, originalSpawn, spawn;
- beforeEach(function() {
- originalSpawn = childProcess.spawn;
- spawn = mockSpawn();
- childProcess.spawn = spawn;
- originalProcessEnv = process.env;
- originalProcessPlatform = process.platform;
- process.env = {};
- });
- afterEach(function() {
- if (originalSpawn) {
- childProcess.spawn = originalSpawn;
- }
- process.env = originalProcessEnv;
- process.platform = originalProcessPlatform;
- try {
- temp.cleanupSync();
- } catch (e) {
- // Do nothing
- }
- });
- describe('when the launch environment appears to come from a shell', function() {
- it('updates process.env to match the launch environment because PWD is set', async function() {
- process.env = {
- WILL_BE_DELETED: 'hi',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- const initialProcessEnv = process.env;
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- TERM: 'xterm-something',
- KEY1: 'value1',
- KEY2: 'value2'
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- TERM: 'xterm-something',
- KEY1: 'value1',
- KEY2: 'value2',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- // See #11302. On Windows, `process.env` is a magic object that offers
- // case-insensitive environment variable matching, so we cannot replace it
- // with another object.
- expect(process.env).toBe(initialProcessEnv);
- });
- it('updates process.env to match the launch environment because PROMPT is set', async function() {
- process.env = {
- WILL_BE_DELETED: 'hi',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- const initialProcessEnv = process.env;
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PROMPT: '$P$G',
- KEY1: 'value1',
- KEY2: 'value2'
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PROMPT: '$P$G',
- KEY1: 'value1',
- KEY2: 'value2',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- // See #11302. On Windows, `process.env` is a magic object that offers
- // case-insensitive environment variable matching, so we cannot replace it
- // with another object.
- expect(process.env).toBe(initialProcessEnv);
- });
- it('updates process.env to match the launch environment because PSModulePath is set', async function() {
- process.env = {
- WILL_BE_DELETED: 'hi',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- const initialProcessEnv = process.env;
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PSModulePath:
- 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\\',
- KEY1: 'value1',
- KEY2: 'value2'
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PSModulePath:
- 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\\',
- KEY1: 'value1',
- KEY2: 'value2',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- // See #11302. On Windows, `process.env` is a magic object that offers
- // case-insensitive environment variable matching, so we cannot replace it
- // with another object.
- expect(process.env).toBe(initialProcessEnv);
- });
- it('allows ATOM_HOME to be overwritten only if the new value is a valid path', async function() {
- let newAtomHomePath = temp.mkdirSync('atom-home');
- process.env = {
- WILL_BE_DELETED: 'hi',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir'
- });
- expect(process.env).toEqual({
- PWD: '/the/dir',
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- ATOM_HOME: path.join(newAtomHomePath, 'non-existent')
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- ATOM_HOME: newAtomHomePath
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: newAtomHomePath
- });
- });
- it('allows ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT to be preserved if set', async function() {
- process.env = {
- WILL_BE_DELETED: 'hi',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- await updateProcessEnv({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- await updateProcessEnv({
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- expect(process.env).toEqual({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- PWD: '/the/dir',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- });
- });
- it('allows an existing env variable to be updated', async function() {
- process.env = {
- WILL_BE_UPDATED: 'old-value',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home'
- };
- await updateProcessEnv(process.env);
- expect(process.env).toEqual(process.env);
- let updatedEnv = {
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- WILL_BE_UPDATED: 'new-value',
- NODE_ENV: 'the-node-env',
- NODE_PATH: '/the/node/path',
- ATOM_HOME: '/the/atom/home',
- PWD: '/the/dir'
- };
- await updateProcessEnv(updatedEnv);
- expect(process.env).toEqual(updatedEnv);
- });
- });
- describe('when the launch environment does not come from a shell', function() {
- describe('on macOS', function() {
- it("updates process.env to match the environment in the user's login shell", async function() {
- if (process.platform === 'win32') return; // TestsThatFailOnWin32
- process.platform = 'darwin';
- process.env.SHELL = '/my/custom/bash';
- spawn.setDefault(
- spawn.simple(
- 0,
- 'FOO=BAR=BAZ=QUUX\0MULTILINE\nNAME=multiline\nvalue\0TERM=xterm-something\0PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path'
- )
- );
- await updateProcessEnv(process.env);
- expect(spawn.calls.length).toBe(1);
- expect(spawn.calls[0].command).toBe('/my/custom/bash');
- expect(spawn.calls[0].args).toEqual([
- '-ilc',
- 'command awk \'BEGIN{for(v in ENVIRON) printf("%s=%s%c", v, ENVIRON[v], 0)}\''
- ]);
- expect(process.env).toEqual({
- FOO: 'BAR=BAZ=QUUX',
- 'MULTILINE\nNAME': 'multiline\nvalue',
- TERM: 'xterm-something',
- PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path'
- });
- // Doesn't error
- await updateProcessEnv(null);
- });
- });
- describe('on linux', function() {
- it("updates process.env to match the environment in the user's login shell", async function() {
- if (process.platform === 'win32') return; // TestsThatFailOnWin32
- process.platform = 'linux';
- process.env.SHELL = '/my/custom/bash';
- spawn.setDefault(
- spawn.simple(
- 0,
- 'FOO=BAR=BAZ=QUUX\0MULTILINE\nNAME=multiline\nvalue\0TERM=xterm-something\0PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path'
- )
- );
- await updateProcessEnv(process.env);
- expect(spawn.calls.length).toBe(1);
- expect(spawn.calls[0].command).toBe('/my/custom/bash');
- expect(spawn.calls[0].args).toEqual([
- '-ilc',
- 'command awk \'BEGIN{for(v in ENVIRON) printf("%s=%s%c", v, ENVIRON[v], 0)}\''
- ]);
- expect(process.env).toEqual({
- FOO: 'BAR=BAZ=QUUX',
- 'MULTILINE\nNAME': 'multiline\nvalue',
- TERM: 'xterm-something',
- PATH: '/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path'
- });
- // Doesn't error
- await updateProcessEnv(null);
- });
- });
- describe('on windows', function() {
- it('does not update process.env', async function() {
- process.platform = 'win32';
- spyOn(childProcess, 'spawn');
- process.env = { FOO: 'bar' };
- await updateProcessEnv(process.env);
- expect(childProcess.spawn).not.toHaveBeenCalled();
- expect(process.env).toEqual({ FOO: 'bar' });
- });
- });
- describe('shouldGetEnvFromShell()', function() {
- it('indicates when the environment should be fetched from the shell', function() {
- if (process.platform === 'win32') return; // TestsThatFailOnWin32
- process.platform = 'darwin';
- expect(shouldGetEnvFromShell({ SHELL: '/bin/sh' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/sh' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/bash' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/bash' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/zsh' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/zsh' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/fish' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/fish' })).toBe(
- true
- );
- process.platform = 'linux';
- expect(shouldGetEnvFromShell({ SHELL: '/bin/sh' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/sh' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/bash' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/bash' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/zsh' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/zsh' })).toBe(
- true
- );
- expect(shouldGetEnvFromShell({ SHELL: '/bin/fish' })).toBe(true);
- expect(shouldGetEnvFromShell({ SHELL: '/usr/local/bin/fish' })).toBe(
- true
- );
- });
- it('returns false when the environment indicates that Atom was launched from a shell', function() {
- process.platform = 'darwin';
- expect(
- shouldGetEnvFromShell({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- SHELL: '/bin/sh'
- })
- ).toBe(false);
- process.platform = 'linux';
- expect(
- shouldGetEnvFromShell({
- ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
- SHELL: '/bin/sh'
- })
- ).toBe(false);
- });
- it('returns false when the shell is undefined or empty', function() {
- process.platform = 'darwin';
- expect(shouldGetEnvFromShell(undefined)).toBe(false);
- expect(shouldGetEnvFromShell({})).toBe(false);
- process.platform = 'linux';
- expect(shouldGetEnvFromShell(undefined)).toBe(false);
- expect(shouldGetEnvFromShell({})).toBe(false);
- });
- });
- });
- });
|