neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

system_spec.lua (5258B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 
      4 local clear = n.clear
      5 local exec_lua = n.exec_lua
      6 local eq = t.eq
      7 
      8 local function system_sync(cmd, opts)
      9  return exec_lua(function()
     10    local obj = vim.system(cmd, opts)
     11 
     12    if opts and opts.timeout then
     13      -- Minor delay before calling wait() so the timeout uv timer can have a headstart over the
     14      -- internal call to vim.wait() in wait().
     15      vim.wait(10)
     16    end
     17 
     18    local res = obj:wait()
     19 
     20    -- Check the process is no longer running
     21    assert(not vim.api.nvim_get_proc(obj.pid), 'process still exists')
     22 
     23    return res
     24  end)
     25 end
     26 
     27 local function system_async(cmd, opts)
     28  return exec_lua(function()
     29    local done = false
     30    local res --- @type vim.SystemCompleted?
     31    local obj = vim.system(cmd, opts, function(obj)
     32      done = true
     33      res = obj
     34    end)
     35 
     36    local ok = vim.wait(10000, function()
     37      return done
     38    end)
     39 
     40    assert(ok, 'process did not exit')
     41 
     42    -- Check the process is no longer running
     43    assert(not vim.api.nvim_get_proc(obj.pid), 'process still exists')
     44 
     45    return res
     46  end)
     47 end
     48 
     49 describe('vim.system', function()
     50  before_each(function()
     51    clear()
     52  end)
     53 
     54  for name, system in pairs { sync = system_sync, async = system_async } do
     55    describe('(' .. name .. ')', function()
     56      it('failure modes', function()
     57        t.matches(
     58          "ENOENT%: no such file .* %(cmd%): 'non%-existent%-cmd'",
     59          t.pcall_err(system, { 'non-existent-cmd', 'arg1', 'arg2' }, { text = true })
     60        )
     61 
     62        t.matches(
     63          "ENOENT%: no such file .* %(cwd%): 'non%-existent%-cwd'",
     64          t.pcall_err(system, { 'echo', 'hello' }, { cwd = 'non-existent-cwd', text = true })
     65        )
     66      end)
     67 
     68      it('can run simple commands', function()
     69        eq('hello\n', system({ 'echo', 'hello' }, { text = true }).stdout)
     70      end)
     71 
     72      it('handle input', function()
     73        eq('hellocat', system({ 'cat' }, { stdin = 'hellocat', text = true }).stdout)
     74      end)
     75 
     76      it('can set environment', function()
     77        local function test_env(opt)
     78          eq('TESTVAL', system({ n.testprg('printenv-test'), 'TEST' }, opt).stdout)
     79        end
     80 
     81        test_env({ env = { TEST = 'TESTVAL' }, text = true })
     82        test_env({ clear_env = true, env = { TEST = 'TESTVAL' }, text = true })
     83      end)
     84 
     85      it('can set environment with clear_env = true and env = nil', function()
     86        exec_lua(function()
     87          vim.env.TEST = 'TESTVAL'
     88        end)
     89 
     90        -- Not passing env with clear_env should not clear the environment
     91        eq(
     92          'TESTVAL',
     93          system({ n.testprg('printenv-test'), 'TEST' }, { clear_env = true, text = true }).stdout
     94        )
     95 
     96        -- Passing env = {} with clear_env should clear the environment
     97        eq(
     98          '',
     99          system(
    100            { n.testprg('printenv-test'), 'TEST' },
    101            { env = {}, clear_env = true, text = true }
    102          ).stdout
    103        )
    104      end)
    105 
    106      it('supports timeout', function()
    107        eq({
    108          code = 124,
    109          signal = 15,
    110          stdout = '',
    111          stderr = '',
    112        }, system({ 'sleep', '10' }, { timeout = 1000 }))
    113      end)
    114    end)
    115  end
    116 
    117  it('kill processes', function()
    118    exec_lua(function()
    119      local signal --- @type integer?
    120      local cmd = vim.system({ 'cat', '-' }, { stdin = true }, function(r)
    121        signal = r.signal
    122      end) -- run forever
    123 
    124      cmd:kill('sigint')
    125 
    126      -- wait for the process not to exist
    127      local done = vim.wait(2000, function()
    128        return signal ~= nil
    129      end)
    130 
    131      assert(done, 'process did not exit')
    132 
    133      -- Check the process is no longer running
    134      local proc = vim.api.nvim_get_proc(cmd.pid)
    135      assert(not proc, 'process still exists')
    136 
    137      assert(signal == 2)
    138    end)
    139  end)
    140 
    141  it('SystemObj:wait() does not process non-fast events #27292', function()
    142    eq(
    143      false,
    144      exec_lua(function()
    145        _G.processed = false
    146        local cmd = vim.system({ 'sleep', '1' })
    147        vim.schedule(function()
    148          _G.processed = true
    149        end)
    150        cmd:wait()
    151        return _G.processed
    152      end)
    153    )
    154    eq(true, exec_lua([[return _G.processed]]))
    155  end)
    156 
    157  if t.is_os('win') then
    158    it('can resolve windows command extensions', function()
    159      t.write_file('test.bat', 'echo hello world')
    160      system_sync({ 'chmod', '+x', 'test.bat' })
    161      system_sync({ './test' })
    162    end)
    163  end
    164 
    165  it('always captures all content of stdout/stderr #30846', function()
    166    t.skip(n.fn.executable('git') == 0, 'missing "git" command')
    167    t.skip(n.fn.isdirectory('.git') == 0, 'missing ".git" directory')
    168    eq(
    169      0,
    170      exec_lua(function()
    171        local done = 0
    172        local fail = 0
    173        for _ = 1, 200 do
    174          vim.system(
    175            { 'git', 'show', ':0:test/functional/plugin/lsp_spec.lua' },
    176            { text = true },
    177            function(o)
    178              if o.code ~= 0 or #o.stdout == 0 then
    179                fail = fail + 1
    180              end
    181              done = done + 1
    182            end
    183          )
    184        end
    185 
    186        local ok = vim.wait(10000, function()
    187          return done == 200
    188        end, 200)
    189        return fail + (ok and 0 or 1)
    190      end)
    191    )
    192  end)
    193 end)