Meh I'll figure out submodules later
This commit is contained in:
parent
4ca9d44a90
commit
8cb281f436
352 changed files with 66107 additions and 0 deletions
|
|
@ -0,0 +1,53 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
|
||||
describe("async", function()
|
||||
a.it("void functions can call wrapped functions", function()
|
||||
local stat = 0
|
||||
local saved_arg
|
||||
|
||||
local wrapped = a.wrap(function(inc, callback)
|
||||
stat = stat + inc
|
||||
callback()
|
||||
end, 2)
|
||||
|
||||
local voided = a.void(function(arg)
|
||||
wrapped(1)
|
||||
wrapped(2)
|
||||
wrapped(3)
|
||||
stat = stat + 1
|
||||
saved_arg = arg
|
||||
end)
|
||||
|
||||
voided "hello"
|
||||
|
||||
assert(stat == 7)
|
||||
assert(saved_arg == "hello")
|
||||
end)
|
||||
|
||||
a.it("void functions can call wrapped functions with ignored arguments", function()
|
||||
local stat = 0
|
||||
local saved_arg
|
||||
|
||||
local wrapped = a.wrap(function(inc, nil1, nil2, callback)
|
||||
assert(type(inc) == "number")
|
||||
assert(nil1 == nil)
|
||||
assert(nil2 == nil)
|
||||
assert(type(callback) == "function")
|
||||
stat = stat + inc
|
||||
callback()
|
||||
end, 4)
|
||||
|
||||
local voided = a.void(function(arg)
|
||||
wrapped(1)
|
||||
wrapped(2, nil)
|
||||
wrapped(3, nil, nil)
|
||||
stat = stat + 1
|
||||
saved_arg = arg
|
||||
end)
|
||||
|
||||
voided "hello"
|
||||
|
||||
assert(stat == 7)
|
||||
assert(saved_arg == "hello")
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
local channel = a.control.channel
|
||||
local eq = assert.are.same
|
||||
local apcall = a.util.apcall
|
||||
|
||||
describe("channel", function()
|
||||
describe("oneshot", function()
|
||||
a.it("should work when rx is used first", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
a.run(function()
|
||||
local got = rx()
|
||||
|
||||
eq("sent value", got)
|
||||
end)
|
||||
|
||||
tx "sent value"
|
||||
end)
|
||||
|
||||
a.it("should work when tx is used first", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
tx "sent value"
|
||||
|
||||
local got = rx()
|
||||
|
||||
eq("sent value", got)
|
||||
end)
|
||||
|
||||
a.it("should work with multiple returns", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
a.run(function()
|
||||
local got, got2 = rx()
|
||||
eq("sent value", got)
|
||||
eq("another sent value", got2)
|
||||
end)
|
||||
|
||||
tx("sent value", "another sent value")
|
||||
end)
|
||||
|
||||
a.it("should work when sending a falsey value", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
tx(false)
|
||||
|
||||
local res = rx()
|
||||
eq(res, false)
|
||||
|
||||
local stat, ret = apcall(rx)
|
||||
eq(stat, false)
|
||||
local stat, ret = apcall(rx)
|
||||
eq(stat, false)
|
||||
end)
|
||||
|
||||
a.it("should work when sending a nil value", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
tx(nil)
|
||||
|
||||
local res = rx()
|
||||
eq(res, nil)
|
||||
|
||||
local stat, ret = apcall(rx)
|
||||
eq(stat, false)
|
||||
local stat, ret = apcall(rx)
|
||||
eq(stat, false)
|
||||
end)
|
||||
|
||||
a.it("should error when sending mulitple times", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
|
||||
tx()
|
||||
local stat = pcall(tx)
|
||||
eq(stat, false)
|
||||
end)
|
||||
|
||||
a.it("should block receiving multiple times", function()
|
||||
local tx, rx = channel.oneshot()
|
||||
tx(true)
|
||||
rx()
|
||||
local stat = apcall(rx)
|
||||
eq(stat, false)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("mpsc", function()
|
||||
a.it("should wait multiple recv before any send", function()
|
||||
local sender, receiver = channel.mpsc()
|
||||
|
||||
local expected_count = 10
|
||||
|
||||
a.run(function()
|
||||
for i = 1, expected_count do
|
||||
a.util.sleep(250)
|
||||
sender.send(i)
|
||||
end
|
||||
end)
|
||||
|
||||
local receive_count = 0
|
||||
while receive_count < expected_count do
|
||||
receive_count = receive_count + 1
|
||||
local i = receiver.recv()
|
||||
eq(receive_count, i)
|
||||
end
|
||||
end)
|
||||
|
||||
a.it("should queues multiple sends before any read", function()
|
||||
local sender, receiver = channel.mpsc()
|
||||
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
counter = counter + 1
|
||||
sender.send(10)
|
||||
|
||||
counter = counter + 1
|
||||
sender.send(20)
|
||||
end)
|
||||
|
||||
a.util.sleep(1000)
|
||||
|
||||
eq(10, receiver.recv())
|
||||
eq(20, receiver.recv())
|
||||
eq(2, counter)
|
||||
end)
|
||||
|
||||
a.it("should queues multiple sends from multiple producers before any read", function()
|
||||
local sender, receiver = channel.mpsc()
|
||||
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
counter = counter + 1
|
||||
sender.send(10)
|
||||
|
||||
counter = counter + 1
|
||||
sender.send(20)
|
||||
end)
|
||||
|
||||
a.run(function()
|
||||
counter = counter + 1
|
||||
sender.send(30)
|
||||
|
||||
counter = counter + 1
|
||||
sender.send(40)
|
||||
end)
|
||||
|
||||
a.util.sleep(1000)
|
||||
|
||||
local read_counter = 0
|
||||
a.util.block_on(function()
|
||||
for _ = 1, 4 do
|
||||
receiver.recv()
|
||||
read_counter = read_counter + 1
|
||||
end
|
||||
end, 1000)
|
||||
eq(4, counter)
|
||||
eq(4, read_counter)
|
||||
end)
|
||||
|
||||
a.it("should read only the last value", function()
|
||||
local sender, receiver = channel.mpsc()
|
||||
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
counter = counter + 1
|
||||
sender.send(10)
|
||||
|
||||
counter = counter + 1
|
||||
sender.send(20)
|
||||
end)
|
||||
|
||||
a.util.sleep(1000)
|
||||
|
||||
eq(20, receiver.last())
|
||||
eq(2, counter)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("counter", function()
|
||||
a.it("should work", function()
|
||||
local tx, rx = channel.counter()
|
||||
|
||||
tx.send()
|
||||
tx.send()
|
||||
tx.send()
|
||||
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
for i = 1, 3 do
|
||||
rx.recv()
|
||||
counter = counter + 1
|
||||
end
|
||||
end)
|
||||
|
||||
eq(counter, 3)
|
||||
end)
|
||||
|
||||
a.it("should work when getting last", function()
|
||||
local tx, rx = channel.counter()
|
||||
|
||||
tx.send()
|
||||
tx.send()
|
||||
tx.send()
|
||||
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
rx.last()
|
||||
counter = counter + 1
|
||||
end)
|
||||
|
||||
eq(counter, 1)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
local Condvar = a.control.Condvar
|
||||
local eq = assert.are.same
|
||||
local join, run_all = a.util.join, a.util.run_all
|
||||
|
||||
describe("condvar", function()
|
||||
a.it("should allow blocking", function()
|
||||
local var = false
|
||||
|
||||
local condvar = Condvar.new()
|
||||
|
||||
a.run(function()
|
||||
condvar:wait()
|
||||
var = true
|
||||
end)
|
||||
|
||||
eq(var, false)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(var, true)
|
||||
end)
|
||||
|
||||
a.it("should be able to notify one when running", function()
|
||||
local counter = 0
|
||||
|
||||
local condvar = Condvar.new()
|
||||
|
||||
local first = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local second = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local third = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
a.run(function()
|
||||
join { first, second, third }
|
||||
end)
|
||||
|
||||
eq(0, counter)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(1, counter)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(counter, 2)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(counter, 3)
|
||||
end)
|
||||
|
||||
a.it("should allow notify_one to work when using await_all", function()
|
||||
local counter = 0
|
||||
|
||||
local condvar = Condvar.new()
|
||||
|
||||
local first = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local second = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local third = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
run_all { first, second, third }
|
||||
|
||||
eq(0, counter)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(1, counter)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(counter, 2)
|
||||
|
||||
condvar:notify_one()
|
||||
|
||||
eq(counter, 3)
|
||||
end)
|
||||
|
||||
a.it("should notify_all", function()
|
||||
local counter = 0
|
||||
|
||||
local condvar = Condvar.new()
|
||||
|
||||
local first = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local second = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
local third = function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
run_all { first, second, third }
|
||||
|
||||
eq(0, counter)
|
||||
|
||||
condvar:notify_all()
|
||||
|
||||
eq(3, counter)
|
||||
end)
|
||||
|
||||
a.it("notify all works multiple times", function()
|
||||
local condvar = Condvar.new()
|
||||
local counter = 0
|
||||
|
||||
a.run(function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end)
|
||||
|
||||
a.run(function()
|
||||
condvar:wait()
|
||||
counter = counter + 1
|
||||
end)
|
||||
|
||||
eq(0, counter)
|
||||
|
||||
condvar:notify_all()
|
||||
|
||||
eq(2, counter)
|
||||
|
||||
a.run(function()
|
||||
condvar:wait()
|
||||
counter = 0
|
||||
end)
|
||||
|
||||
condvar:notify_all()
|
||||
|
||||
eq(0, counter)
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
local Deque = require("plenary.async.structs").Deque
|
||||
local eq = assert.are.same
|
||||
|
||||
-- just a helper to create the test deque
|
||||
local function new_deque()
|
||||
local deque = Deque.new()
|
||||
eq(deque:len(), 0)
|
||||
|
||||
deque:pushleft(1)
|
||||
eq(deque:len(), 1)
|
||||
|
||||
deque:pushleft(2)
|
||||
eq(deque:len(), 2)
|
||||
|
||||
deque:pushright(3)
|
||||
eq(deque:len(), 3)
|
||||
|
||||
deque:pushright(4)
|
||||
eq(deque:len(), 4)
|
||||
|
||||
deque:pushright(5)
|
||||
eq(deque:len(), 5)
|
||||
|
||||
return deque
|
||||
end
|
||||
|
||||
describe("deque", function()
|
||||
it("should allow pushing and popping and finding len", function()
|
||||
new_deque()
|
||||
end)
|
||||
|
||||
it("should be able to iterate from left", function()
|
||||
local deque = new_deque()
|
||||
|
||||
local iter = deque:ipairs_left()
|
||||
|
||||
local i, v = iter()
|
||||
eq(i, -2)
|
||||
eq(v, 2)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, -1)
|
||||
eq(v, 1)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, 0)
|
||||
eq(v, 3)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, 1)
|
||||
eq(v, 4)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, 2)
|
||||
eq(v, 5)
|
||||
end)
|
||||
|
||||
it("should be able to iterate from right", function()
|
||||
local deque = new_deque()
|
||||
|
||||
local iter = deque:ipairs_right()
|
||||
|
||||
local i, v = iter()
|
||||
eq(i, 2)
|
||||
eq(v, 5)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, 1)
|
||||
eq(v, 4)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, 0)
|
||||
eq(v, 3)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, -1)
|
||||
eq(v, 1)
|
||||
|
||||
i, v = iter()
|
||||
eq(i, -2)
|
||||
eq(v, 2)
|
||||
end)
|
||||
|
||||
it("should allow clearing", function()
|
||||
local deque = new_deque()
|
||||
|
||||
deque:clear()
|
||||
|
||||
assert(deque:is_empty())
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
local Semaphore = a.control.Semaphore
|
||||
|
||||
local eq = assert.are.same
|
||||
|
||||
describe("semaphore", function()
|
||||
a.it("should validate arguments", function()
|
||||
local status = pcall(Semaphore.new, -1)
|
||||
eq(status, false)
|
||||
|
||||
local status = pcall(Semaphore.new)
|
||||
eq(status, false)
|
||||
end)
|
||||
|
||||
a.it("should acquire a permit if available", function()
|
||||
local sem = Semaphore.new(1)
|
||||
local permit = sem:acquire()
|
||||
assert(permit ~= nil)
|
||||
end)
|
||||
|
||||
a.it("should block if no permit is available", function()
|
||||
local sem = Semaphore.new(1)
|
||||
sem:acquire()
|
||||
|
||||
local completed = false
|
||||
local blocking = function()
|
||||
sem:acquire()
|
||||
completed = true
|
||||
end
|
||||
a.run(blocking)
|
||||
|
||||
eq(completed, false)
|
||||
end)
|
||||
|
||||
a.it("should give another permit when an acquired permit is released", function()
|
||||
local sem = Semaphore.new(1)
|
||||
local permit = sem:acquire()
|
||||
permit:forget()
|
||||
local next_permit = sem:acquire()
|
||||
assert(next_permit ~= nil)
|
||||
end)
|
||||
|
||||
a.it("should permit the next waiting client when a permit is released", function()
|
||||
local sem = Semaphore.new(1)
|
||||
local permit = sem:acquire()
|
||||
|
||||
local completed = false
|
||||
local blocking = function()
|
||||
sem:acquire()
|
||||
completed = true
|
||||
end
|
||||
|
||||
a.run(blocking)
|
||||
permit:forget()
|
||||
|
||||
eq(completed, true)
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
|
||||
a.describe("a.before_each", function()
|
||||
local counter = 0
|
||||
|
||||
local set_counter_to_one = a.wrap(function(callback)
|
||||
a.util.sleep(5)
|
||||
counter = 1
|
||||
end, 1)
|
||||
|
||||
a.before_each(a.void(function()
|
||||
set_counter_to_one()
|
||||
end))
|
||||
|
||||
a.it("should run in async context", function()
|
||||
counter = counter + 1
|
||||
assert.are.same(counter, 2)
|
||||
end)
|
||||
|
||||
a.it("should run for all tests", function()
|
||||
counter = counter + 2
|
||||
assert.are.same(counter, 3)
|
||||
end)
|
||||
end)
|
||||
|
||||
a.describe("a.after_each", function()
|
||||
local counter = 0
|
||||
|
||||
local set_counter_to_one = a.wrap(function(callback)
|
||||
a.util.sleep(5)
|
||||
counter = 1
|
||||
end, 1)
|
||||
|
||||
a.after_each(a.void(function()
|
||||
set_counter_to_one()
|
||||
end))
|
||||
|
||||
a.it("should not run before first test", function()
|
||||
counter = counter + 1
|
||||
assert.are.same(counter, 1)
|
||||
end)
|
||||
|
||||
a.it("should run before the second test", function()
|
||||
counter = counter + 2
|
||||
assert.are.same(counter, 3)
|
||||
end)
|
||||
|
||||
a.it("should run before the third test", function()
|
||||
counter = counter + 3
|
||||
assert.are.same(counter, 4)
|
||||
end)
|
||||
end)
|
||||
|
||||
a.describe("a.pending", function()
|
||||
a.pending("This test is disabled", function()
|
||||
assert(false, "Should not run")
|
||||
end)
|
||||
end)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
require("plenary.async").tests.add_to_env()
|
||||
local block_on = a.util.block_on
|
||||
local eq = assert.are.same
|
||||
local id = a.util.id
|
||||
|
||||
describe("async await util", function()
|
||||
describe("block_on", function()
|
||||
a.it("should block_on", function()
|
||||
local fn = function()
|
||||
a.util.sleep(100)
|
||||
return "hello"
|
||||
end
|
||||
|
||||
local res = fn()
|
||||
eq(res, "hello")
|
||||
end)
|
||||
|
||||
a.it("should work even when failing", function()
|
||||
local nonleaf = function()
|
||||
eq(true, false)
|
||||
end
|
||||
|
||||
local stat = pcall(block_on, nonleaf)
|
||||
eq(stat, false)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("protect", function()
|
||||
a.it("should be able to protect a non-leaf future", function()
|
||||
local nonleaf = function()
|
||||
error "This should error"
|
||||
return "return"
|
||||
end
|
||||
|
||||
local stat, ret = pcall(nonleaf)
|
||||
eq(false, stat)
|
||||
assert(ret:match "This should error")
|
||||
end)
|
||||
|
||||
a.it("should be able to protect a non-leaf future that doesnt fail", function()
|
||||
local nonleaf = function()
|
||||
return "didnt fail"
|
||||
end
|
||||
|
||||
local stat, ret = pcall(nonleaf)
|
||||
eq(stat, true)
|
||||
eq(ret, "didnt fail")
|
||||
end)
|
||||
end)
|
||||
|
||||
local function sleep(msec)
|
||||
return function()
|
||||
a.util.sleep(msec)
|
||||
return msec
|
||||
end
|
||||
end
|
||||
|
||||
describe("race", function()
|
||||
a.it("should return the first result", function()
|
||||
local funcs = vim.tbl_map(sleep, { 300, 400, 100, 200 })
|
||||
local result = a.util.race(funcs)
|
||||
eq(result, 100)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("run_first", function()
|
||||
a.it("should return the first result", function()
|
||||
local async_functions = vim.tbl_map(function(num)
|
||||
return function(callback)
|
||||
return a.run(sleep(num), callback)
|
||||
end
|
||||
end, { 300, 400, 100, 200 })
|
||||
local result = a.util.run_first(async_functions)
|
||||
eq(result, 100)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
Loading…
Add table
Add a link
Reference in a new issue