Meh I'll figure out submodules later

This commit is contained in:
mustard 2025-09-16 01:01:02 +02:00
parent 4ca9d44a90
commit 8cb281f436
352 changed files with 66107 additions and 0 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)