1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 09:00:06 +08:00
SpaceVim/bundle/plenary.nvim/tests/plenary/job_spec.lua
2022-05-16 22:20:10 +08:00

833 lines
20 KiB
Lua
Vendored

local Job = require "plenary.job"
local has_all_executables = function(execs)
for _, e in ipairs(execs) do
if vim.fn.executable(e) == 0 then
return false
end
end
return true
end
describe("Job", function()
describe("> cat manually >", function()
it("should split simple stdin", function()
local results = {}
local job = Job:new {
command = "cat",
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:start()
job:send "hello\n"
job:send "world\n"
job:shutdown()
assert.are.same(job:result(), { "hello", "world" })
assert.are.same(job:result(), results)
end)
it("should allow empty strings", function()
local results = {}
local job = Job:new {
command = "cat",
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:start()
job:send "hello\n"
job:send "\n"
job:send "world\n"
job:send "\n"
job:shutdown()
assert.are.same(job:result(), { "hello", "", "world", "" })
assert.are.same(job:result(), results)
end)
it("should split stdin across newlines", function()
local results = {}
local job = Job:new {
-- writer = "hello\nword\nthis is\ntj",
command = "cat",
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:start()
job:send "hello\nwor"
job:send "ld\n"
job:shutdown()
assert.are.same(job:result(), { "hello", "world" })
assert.are.same(job:result(), results)
end)
pending("should split stdin across newlines with no ending newline", function()
local results = {}
local job = Job:new {
-- writer = "hello\nword\nthis is\ntj",
command = "cat",
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:start()
job:send "hello\nwor"
job:send "ld"
job:shutdown()
assert.are.same(job:result(), { "hello", "world" })
assert.are.same(job:result(), results)
end)
it("should return last line when there is ending newline", function()
local results = {}
local job = Job:new {
command = "echo",
args = { "-e", "test1\ntest2" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "test1", "test2" })
assert.are.same(job:result(), results)
end)
pending("should return last line when there is no ending newline", function()
local results = {}
local job = Job:new {
command = "echo",
args = { "-en", "test1\ntest2" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "test1", "test2" })
assert.are.same(job:result(), results)
end)
end)
describe("env", function()
it("should be possible to set one env variable with an array", function()
local results = {}
local job = Job:new {
command = "env",
env = { "A=100" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "A=100" })
assert.are.same(job:result(), results)
end)
it("should be possible to set multiple env variables with an array", function()
local results = {}
local job = Job:new {
command = "env",
env = { "A=100", "B=test" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "A=100", "B=test" })
assert.are.same(job:result(), results)
end)
it("should be possible to set one env variable with a map", function()
local results = {}
local job = Job:new {
command = "env",
env = { "A=100" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "A=100" })
assert.are.same(job:result(), results)
end)
it("should be possible to set one env variable with spaces", function()
local results = {}
local job = Job:new {
command = "env",
env = { "A=This is a long env var" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "A=This is a long env var" })
assert.are.same(job:result(), results)
end)
it("should be possible to set one env variable with spaces and a map", function()
local results = {}
local job = Job:new {
command = "env",
env = { ["A"] = "This is a long env var" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
assert.are.same(job:result(), { "A=This is a long env var" })
assert.are.same(job:result(), results)
end)
it("should be possible to set multiple env variables with a map", function()
local results = {}
local job = Job:new {
command = "env",
env = { ["A"] = 100, ["B"] = "test" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
local expected = { "A=100", "B=test" }
local found = { false, false }
for k, v in ipairs(job:result()) do
for _, w in ipairs(expected) do
if v == w then
found[k] = true
end
end
end
assert.are.same({ true, true }, found)
assert.are.same(job:result(), results)
end)
it("should be possible to set multiple env variables with both, array and map", function()
local results = {}
local job = Job:new {
command = "env",
env = { ["A"] = 100, "B=test" },
on_stdout = function(_, data)
table.insert(results, data)
end,
}
job:sync()
local expected = { "A=100", "B=test" }
local found = { false, false }
for k, v in ipairs(job:result()) do
for _, w in ipairs(expected) do
if v == w then
found[k] = true
end
end
end
assert.are.same({ true, true }, found)
assert.are.same(job:result(), results)
end)
end)
describe("> simple ls >", function()
it("should match systemlist", function()
local ls_results = vim.fn.systemlist "ls -l"
local job = Job:new {
command = "ls",
args = { "-l" },
}
job:sync()
assert.are.same(job:result(), ls_results)
end)
it("should match larger systemlist", function()
local results = vim.fn.systemlist "find"
local stdout_results = {}
local job = Job:new {
command = "find",
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
job:sync()
assert.are.same(job:result(), results)
assert.are.same(job:result(), stdout_results)
end)
it("should not timeout when completing fast jobs", function()
local start = vim.loop.hrtime()
local job = Job:new { command = "ls" }
job:sync()
assert((vim.loop.hrtime() - start) / 1e9 < 1, "Should not take one second to complete")
end)
it("should return the return code as well", function()
local job = Job:new { command = "false" }
local _, ret = job:sync()
assert.are.same(1, job.code)
assert.are.same(1, ret)
end)
end)
describe("chain", function()
it("should always run the next job when using and_then", function()
local results = {}
local first_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local second_job = Job:new {
command = "env",
env = { ["b"] = "2" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local third_job = Job:new { command = "false" }
local fourth_job = Job:new {
command = "env",
env = { ["c"] = "3" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
first_job:and_then(second_job)
second_job:and_then(third_job)
third_job:and_then(fourth_job)
first_job:sync()
second_job:wait()
third_job:wait()
fourth_job:wait()
assert.are.same({ "a=1", "b=2", "c=3" }, results)
assert.are.same({ "a=1" }, first_job:result())
assert.are.same({ "b=2" }, second_job:result())
assert.are.same(1, third_job.code)
assert.are.same({ "c=3" }, fourth_job:result())
end)
it("should only run the next job on success when using and_then_on_success", function()
local results = {}
local first_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local second_job = Job:new {
command = "env",
env = { ["b"] = "2" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local third_job = Job:new { command = "false" }
local fourth_job = Job:new {
command = "env",
env = { ["c"] = "3" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
first_job:and_then_on_success(second_job)
second_job:and_then_on_success(third_job)
third_job:and_then_on_success(fourth_job)
first_job:sync()
second_job:wait()
third_job:wait()
assert.are.same({ "a=1", "b=2" }, results)
assert.are.same({ "a=1" }, first_job:result())
assert.are.same({ "b=2" }, second_job:result())
assert.are.same(1, third_job.code)
assert.are.same(nil, fourth_job.handle, "Job never started")
end)
it("should only run the next job on failure when using and_then_on_failure", function()
local results = {}
local first_job = Job:new {
command = "false",
}
local second_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local third_job = Job:new {
command = "env",
env = { ["b"] = "2" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
first_job:and_then_on_failure(second_job)
second_job:and_then_on_failure(third_job)
local _, ret = first_job:sync()
second_job:wait()
assert.are.same(1, first_job.code)
assert.are.same(1, ret)
assert.are.same({ "a=1" }, results)
assert.are.same({ "a=1" }, second_job:result())
assert.are.same(nil, third_job.handle, "Job never started")
end)
it("should run all normal functions when using after", function()
local results = {}
local code = 0
local first_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local second_job = Job:new { command = "false" }
first_job
:after(function()
code = code + 10
end)
:and_then(second_job)
second_job:after(function(_, c)
code = code + c
end)
first_job:sync()
second_job:wait()
assert.are.same({ "a=1" }, results)
assert.are.same({ "a=1" }, first_job:result())
assert.are.same(1, second_job.code)
assert.are.same(11, code)
end)
it("should run only on success normal functions when using after_success", function()
local results = {}
local code = 0
local first_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local second_job = Job:new { command = "false" }
local third_job = Job:new { command = "true" }
first_job:after_success(function()
code = code + 10
end)
first_job:and_then_on_success(second_job)
second_job:after_success(function(_, c)
code = code + c
end)
second_job:and_then_on_success(third_job)
first_job:sync()
second_job:wait()
assert.are.same({ "a=1" }, results)
assert.are.same({ "a=1" }, first_job:result())
assert.are.same(1, second_job.code)
assert.are.same(10, code)
assert.are.same(nil, third_job.handle)
end)
it("should run only on failure normal functions when using after_failure", function()
local results = {}
local code = 0
local first_job = Job:new { command = "false" }
local second_job = Job:new {
command = "env",
env = { ["a"] = "1" },
on_stdout = function(_, line)
table.insert(results, line)
end,
}
local third_job = Job:new { command = "true" }
first_job:after_failure(function(_, c)
code = code + c
end)
first_job:and_then_on_failure(second_job)
second_job:after_failure(function()
code = code + 10
end)
second_job:and_then_on_failure(third_job)
local _, ret = first_job:sync()
second_job:wait()
assert.are.same({ "a=1" }, results)
assert.are.same({ "a=1" }, second_job:result())
assert.are.same(1, ret)
assert.are.same(1, first_job.code)
assert.are.same(1, code)
assert.are.same(0, second_job.code)
assert.are.same(nil, third_job.handle)
end)
end)
describe(".writer", function()
pending("should allow using things like fzf", function()
if not has_all_executables { "fzf", "fdfind" } then
return
end
local stdout_results = {}
local fzf = Job:new {
writer = Job:new {
command = "fdfind",
cwd = vim.fn.expand "~/plugins/plenary.nvim/",
},
command = "fzf",
args = { "--filter", "job.lua" },
cwd = vim.fn.expand "~/plugins/plenary.nvim/",
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
local results = fzf:sync()
assert.are.same(results, stdout_results)
-- 'job.lua' should be the best file from fzf.
-- So make sure we're processing correctly.
assert.are.same("lua/plenary/job.lua", results[1])
end)
it("should work with a table", function()
if not has_all_executables { "fzf" } then
return
end
local stdout_results = {}
local fzf = Job:new {
writer = { "hello", "world", "job.lua" },
command = "fzf",
args = { "--filter", "job.lua" },
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
local results = fzf:sync()
assert.are.same(results, stdout_results)
-- 'job.lua' should be the best file from fzf.
-- So make sure we're processing correctly.
assert.are.same("job.lua", results[1])
assert.are.same(1, #results)
end)
it("should work with a string", function()
if not has_all_executables { "fzf" } then
return
end
local stdout_results = {}
local fzf = Job:new {
writer = "hello\nworld\njob.lua",
command = "fzf",
args = { "--filter", "job.lua" },
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
local results = fzf:sync()
assert.are.same(results, stdout_results)
-- 'job.lua' should be the best file from fzf.
-- So make sure we're processing correctly.
assert.are.same("job.lua", results[1])
assert.are.same(1, #results)
end)
it("should work with a pipe", function()
if not has_all_executables { "fzf" } then
return
end
local input_pipe = vim.loop.new_pipe(false)
local stdout_results = {}
local fzf = Job:new {
writer = input_pipe,
command = "fzf",
args = { "--filter", "job.lua" },
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
fzf:start()
input_pipe:write "hello\n"
input_pipe:write "world\n"
input_pipe:write "job.lua\n"
input_pipe:close()
fzf:shutdown()
local results = fzf:result()
assert.are.same(results, stdout_results)
-- 'job.lua' should be the best file from fzf.
-- So make sure we're processing correctly.
assert.are.same("job.lua", results[1])
assert.are.same(1, #results)
end)
it("should work with a pipe, but no final newline", function()
if not has_all_executables { "fzf" } then
return
end
local input_pipe = vim.loop.new_pipe(false)
local stdout_results = {}
local fzf = Job:new {
writer = input_pipe,
command = "fzf",
args = { "--filter", "job.lua" },
on_stdout = function(_, line)
table.insert(stdout_results, line)
end,
}
fzf:start()
input_pipe:write "hello\n"
input_pipe:write "world\n"
input_pipe:write "job.lua"
input_pipe:close()
fzf:shutdown()
local results = fzf:result()
assert.are.same(results, stdout_results)
-- 'job.lua' should be the best file from fzf.
-- So make sure we're processing correctly.
assert.are.same("job.lua", results[1])
assert.are.same(1, #results)
end)
end)
describe(":wait()", function()
it("should respect timeout", function()
local j = Job:new {
command = "sleep",
args = { "10" },
}
local ok = pcall(j.sync, j, 500)
assert(not ok, "Job should fail")
end)
end)
describe("enable_.*", function()
it("should not add things to results when disabled", function()
local job = Job:new {
command = "ls",
args = { "-l" },
enable_recording = false,
}
local res = job:sync()
assert(res == nil, "No results should exist")
assert(job._stdout_results == nil, "No result table")
end)
it("should not call callbacks when disabled", function()
local was_called = false
local job = Job:new {
command = "ls",
args = { "-l" },
enable_handlers = false,
on_stdout = function()
was_called = true
end,
}
job:sync()
assert(not was_called, "Should not be called.")
assert(job._stdout_results == nil, "No result table")
end)
end)
describe("enable_.*", function()
it("should not add things to results when disabled", function()
local job = Job:new {
command = "ls",
args = { "-l" },
enable_recording = false,
}
local res = job:sync()
assert(res == nil, "No results should exist")
assert(job._stdout_results == nil, "No result table")
end)
it("should not call callbacks when disbaled", function()
local was_called = false
local job = Job:new {
command = "ls",
args = { "-l" },
enable_handlers = false,
on_stdout = function()
was_called = true
end,
}
job:sync()
assert(not was_called, "Should not be called.")
assert(job._stdout_results == nil, "No result table")
end)
end)
describe("validation", function()
it("requires options", function()
local ok = pcall(Job.new, { command = "ls" })
assert(not ok, "Requires options")
end)
it("requires command", function()
local ok = pcall(Job.new, Job, { cmd = "ls" })
assert(not ok, "Requires command")
end)
it("will not spawn jobs with invalid commands", function()
local ok = pcall(Job.new, Job, { command = "dasowlwl" })
assert(not ok, "Should not allow invalid executables")
end)
end)
describe("on_exit", function()
it("should only be called once for wait", function()
local count = 0
local job = Job:new {
command = "ls",
on_exit = function(...)
count = count + 1
end,
}
job:start()
job:wait()
assert.are.same(count, 1)
end)
it("should only be called once for shutdown", function()
local count = 0
local job = Job:new {
command = "ls",
on_exit = function(...)
count = count + 1
end,
}
job:start()
job:shutdown()
assert.are.same(count, 1)
end)
end)
end)