local helpers = require('test.functional.helpers')(after_each)
local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim,
testprg, ok, source, write_file, mkdir, rmdir = helpers.clear,
helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed,
helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
helpers.testprg, helpers.ok, helpers.source,
helpers.write_file, helpers.mkdir, helpers.rmdir
local assert_alive = helpers.assert_alive
local command = helpers.command
local funcs = helpers.funcs
local os_kill = helpers.os_kill
local retry = helpers.retry
local meths = helpers.meths
local NIL = helpers.NIL
local poke_eventloop = helpers.poke_eventloop
local iswin = helpers.iswin
local get_pathsep = helpers.get_pathsep
local pathroot = helpers.pathroot
local exec_lua = helpers.exec_lua
local nvim_set = helpers.nvim_set
local expect_twostreams = helpers.expect_twostreams
local expect_msg_seq = helpers.expect_msg_seq
local pcall_err = helpers.pcall_err
local matches = helpers.matches
local Screen = require('test.functional.ui.screen')
describe('jobs', function()
local channel
before_each(function()
clear()
channel = nvim('get_api_info')[1]
nvim('set_var', 'channel', channel)
source([[
function! Normalize(data) abort
" Windows: remove ^M and term escape sequences
return type([]) == type(a:data)
\ ? map(a:data, 'substitute(substitute(v:val, "\r", "", "g"), "\x1b\\%(\\]\\d\\+;.\\{-}\x07\\|\\[.\\{-}[\x40-\x7E]\\)", "", "g")')
\ : a:data
endfunction
function! OnEvent(id, data, event) dict
let userdata = get(self, 'user')
let data = Normalize(a:data)
call rpcnotify(g:channel, a:event, userdata, data)
endfunction
let g:job_opts = {
\ 'on_stdout': function('OnEvent'),
\ 'on_exit': function('OnEvent'),
\ 'user': 0
\ }
]])
end)
it('must specify env option as a dict', function()
command("let g:job_opts.env = v:true")
local _, err = pcall(function()
if iswin() then
nvim('command', "let j = jobstart('set', g:job_opts)")
else
nvim('command', "let j = jobstart('env', g:job_opts)")
end
end)
ok(string.find(err, "E475: Invalid argument: env") ~= nil)
end)
it('append environment #env', function()
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
if iswin() then
nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
else
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
expect_msg_seq(
{
{'notification', 'stdout', {0, {'hello world abc'}}},
{'notification', 'stdout', {0, {'', ''}}},
},
{
{'notification', 'stdout', {0, {'hello world abc', ''}}},
{'notification', 'stdout', {0, {''}}}
}
)
end)
it('append environment with pty #env', function()
if helpers.pending_win32(pending) then return end
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.pty = v:true")
nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
if iswin() then
nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
else
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
expect_msg_seq(
{
{'notification', 'stdout', {0, {'hello world abc'}}},
{'notification', 'stdout', {0, {'', ''}}},
},
{
{'notification', 'stdout', {0, {'hello world abc', ''}}},
{'notification', 'stdout', {0, {''}}}
}
)
end)
it('replace environment #env', function()
nvim('command', "let $VAR = 'abc'")
nvim('command', "let $TOTO = 'goodbye world'")
nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
nvim('command', "let g:job_opts.clear_env = 1")
-- libuv ensures that certain "required" environment variables are
-- preserved if the user doesn't provide them in a custom environment
-- https://github.com/libuv/libuv/blob/635e0ce6073c5fbc96040e336b364c061441b54b/src/win/process.c#L672
-- https://github.com/libuv/libuv/blob/635e0ce6073c5fbc96040e336b364c061441b54b/src/win/process.c#L48-L60
--
-- Rather than expecting a completely empty environment, ensure that $VAR
-- is *not* in the environment but $TOTO is.
if iswin() then
nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
expect_msg_seq({
{'notification', 'stdout', {0, {'hello world %VAR%', ''}}}
})
else
nvim('command', "set shell=/bin/sh")
nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
expect_msg_seq({
{'notification', 'stdout', {0, {'hello world', ''}}}
})
end
end)
it('handles case-insensitively matching #env vars', function()
nvim('command', "let $TOTO = 'abc'")
-- Since $Toto is being set in the job, it should take precedence over the
-- global $TOTO on Windows
nvim('command', "let g:job_opts = {'env': {'Toto': 'def'}, 'stdout_buffered': v:true}")
if iswin() then
nvim('command', [[let j = jobstart('set | find /I "toto="', g:job_opts)]])
else
nvim('command', [[let j = jobstart('env | grep -i toto=', g:job_opts)]])
end
nvim('command', "call jobwait([j])")
nvim('command', "let g:output = Normalize(g:job_opts.stdout)")
local actual = eval('g:output')
local expected
if iswin() then
-- Toto is normal
|