mirror of
https://github.com/pesde-pkg/tooling.git
synced 2025-05-04 10:43:58 +01:00
test: initialize unit tests when update tool version
This commit is contained in:
parent
07a8d04523
commit
70f77385f3
6 changed files with 485 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
**/*_packages/
|
||||
toolchainlib/pesde.lock
|
||||
|
||||
**/tests/output/**
|
||||
|
|
|
@ -79,6 +79,7 @@ local BINS_SRC_DIR = pathfs.getAbsolutePathOf(pathfs.Path.from("bins"))
|
|||
|
||||
for _, binSrc in pathfs.readDir(BINS_SRC_DIR) do
|
||||
local absPath = BINS_SRC_DIR:join(binSrc)
|
||||
local testsPath = absPath:join("tests/init.spec.luau")
|
||||
local binEntrypoint = absPath:join("init.luau")
|
||||
local manifestPath = absPath:join("pesde.toml")
|
||||
local readmePath = absPath:join("README.md")
|
||||
|
@ -170,6 +171,18 @@ for _, binSrc in pathfs.readDir(BINS_SRC_DIR) do
|
|||
|
||||
pathfs.writeFile(manifestPath, updatedManifest)
|
||||
end
|
||||
|
||||
-- Check if the tool has any tests, and run them if they do
|
||||
if pathfs.isFile(testsPath) then
|
||||
local success, result = pcall(require, testsPath:toString())
|
||||
if not success then
|
||||
warn(`Rollbacking tool {binSrc} version due failed tests:`, result)
|
||||
pathfs.writeFile(manifestPath, manifestContents)
|
||||
continue
|
||||
end
|
||||
else
|
||||
warn(`Unit tests not found for {binSrc}, assuming that they pass`)
|
||||
end
|
||||
end
|
||||
|
||||
-- Fetch README for the tool repo, if present
|
||||
|
|
8
bins/zap/tests/input.zap
Normal file
8
bins/zap/tests/input.zap
Normal file
|
@ -0,0 +1,8 @@
|
|||
opt server_output = "tests/output/server.luau"
|
||||
opt client_output = "tests/output/client.luau"
|
||||
|
||||
funct Test = {
|
||||
call: Async,
|
||||
args: (Foo: u8, Bar: string),
|
||||
rets: enum { Success, Fail }
|
||||
}
|
12
bins/zap/tests/run.luau
Normal file
12
bins/zap/tests/run.luau
Normal file
|
@ -0,0 +1,12 @@
|
|||
local toolchainlib = require("../lune_packages/core")
|
||||
local process = require("@lune/process")
|
||||
local fs = require("@lune/fs")
|
||||
|
||||
-- not working, needing support
|
||||
-- process.args = { "bins/zap/tests/input.zap" }
|
||||
local success, err = pcall(require, "bins/zap/init.luau")
|
||||
|
||||
assert(success, `failed to execute zap: {err}`)
|
||||
|
||||
assert(fs.readFile("tests/output/client.luau") == fs.readFile("tests/snapshots/client.luau"), `invalid output`)
|
||||
assert(fs.readFile("tests/output/server.luau") == fs.readFile("tests/snapshots/server.luau"), `invalid output`)
|
216
bins/zap/tests/snapshots/client.luau
Normal file
216
bins/zap/tests/snapshots/client.luau
Normal file
|
@ -0,0 +1,216 @@
|
|||
--!native
|
||||
--!optimize 2
|
||||
--!nocheck
|
||||
--!nolint
|
||||
--#selene: allow(unused_variable, global_usage)
|
||||
-- Client generated by Zap v0.6.20 (https://github.com/red-blox/zap)
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
local outgoing_buff: buffer
|
||||
local outgoing_used: number
|
||||
local outgoing_size: number
|
||||
local outgoing_inst: { Instance }
|
||||
local outgoing_apos: number
|
||||
local outgoing_ids: { number }
|
||||
|
||||
local incoming_buff: buffer
|
||||
local incoming_read: number
|
||||
local incoming_inst: { Instance }
|
||||
local incoming_ipos: number
|
||||
local incoming_ids: { number }
|
||||
|
||||
-- thanks to https://dom.rojo.space/binary.html#cframe
|
||||
local CFrameSpecialCases = {
|
||||
CFrame.Angles(0, 0, 0),
|
||||
CFrame.Angles(math.rad(90), 0, 0),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(180)),
|
||||
CFrame.Angles(math.rad(-90), 0, 0),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(90)),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(90)),
|
||||
CFrame.Angles(0, 0, math.rad(90)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(90)),
|
||||
CFrame.Angles(math.rad(-90), math.rad(-90), 0),
|
||||
CFrame.Angles(0, math.rad(-90), 0),
|
||||
CFrame.Angles(math.rad(90), math.rad(-90), 0),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(180)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(180)),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(0)),
|
||||
CFrame.Angles(math.rad(-90), math.rad(-180), math.rad(0)),
|
||||
CFrame.Angles(0, math.rad(0), math.rad(180)),
|
||||
CFrame.Angles(math.rad(90), math.rad(180), math.rad(0)),
|
||||
CFrame.Angles(0, math.rad(0), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(-180), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(-90)),
|
||||
CFrame.Angles(math.rad(90), math.rad(90), 0),
|
||||
CFrame.Angles(0, math.rad(90), 0),
|
||||
CFrame.Angles(math.rad(-90), math.rad(90), 0),
|
||||
}
|
||||
|
||||
local function alloc(len: number)
|
||||
if outgoing_used + len > outgoing_size then
|
||||
while outgoing_used + len > outgoing_size do
|
||||
outgoing_size = outgoing_size * 2
|
||||
end
|
||||
|
||||
local new_buff = buffer.create(outgoing_size)
|
||||
buffer.copy(new_buff, 0, outgoing_buff, 0, outgoing_used)
|
||||
|
||||
outgoing_buff = new_buff
|
||||
end
|
||||
|
||||
outgoing_apos = outgoing_used
|
||||
outgoing_used = outgoing_used + len
|
||||
|
||||
return outgoing_apos
|
||||
end
|
||||
|
||||
local function read(len: number)
|
||||
local pos = incoming_read
|
||||
incoming_read = incoming_read + len
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
local function save()
|
||||
return {
|
||||
buff = outgoing_buff,
|
||||
used = outgoing_used,
|
||||
size = outgoing_size,
|
||||
inst = outgoing_inst,
|
||||
outgoing_ids = outgoing_ids,
|
||||
incoming_ids = incoming_ids,
|
||||
}
|
||||
end
|
||||
|
||||
local function load(data: {
|
||||
buff: buffer,
|
||||
used: number,
|
||||
size: number,
|
||||
inst: { Instance },
|
||||
outgoing_ids: { number },
|
||||
incoming_ids: { number },
|
||||
})
|
||||
outgoing_buff = data.buff
|
||||
outgoing_used = data.used
|
||||
outgoing_size = data.size
|
||||
outgoing_inst = data.inst
|
||||
outgoing_ids = data.outgoing_ids
|
||||
incoming_ids = data.incoming_ids
|
||||
end
|
||||
|
||||
local function load_empty()
|
||||
outgoing_buff = buffer.create(64)
|
||||
outgoing_used = 0
|
||||
outgoing_size = 64
|
||||
outgoing_inst = {}
|
||||
outgoing_ids = {}
|
||||
incoming_ids = {}
|
||||
end
|
||||
|
||||
load_empty()
|
||||
|
||||
local types = {}
|
||||
|
||||
local polling_queues_reliable = {}
|
||||
local polling_queues_unreliable = {}
|
||||
if not RunService:IsRunning() then
|
||||
local noop = function() end
|
||||
return table.freeze({
|
||||
SendEvents = noop,
|
||||
Test = table.freeze({
|
||||
Call = noop,
|
||||
}),
|
||||
}) :: Events
|
||||
end
|
||||
if RunService:IsServer() then
|
||||
error("Cannot use the client module on the server!")
|
||||
end
|
||||
local remotes = ReplicatedStorage:WaitForChild("ZAP")
|
||||
|
||||
local reliable = remotes:WaitForChild("ZAP_RELIABLE")
|
||||
assert(reliable:IsA("RemoteEvent"), "Expected ZAP_RELIABLE to be a RemoteEvent")
|
||||
|
||||
local function SendEvents()
|
||||
if outgoing_used ~= 0 then
|
||||
local buff = buffer.create(outgoing_used)
|
||||
buffer.copy(buff, 0, outgoing_buff, 0, outgoing_used)
|
||||
|
||||
reliable:FireServer(buff, outgoing_inst)
|
||||
|
||||
outgoing_buff = buffer.create(64)
|
||||
outgoing_used = 0
|
||||
outgoing_size = 64
|
||||
table.clear(outgoing_inst)
|
||||
end
|
||||
end
|
||||
|
||||
RunService.Heartbeat:Connect(SendEvents)
|
||||
|
||||
local reliable_events = table.create(1)
|
||||
local reliable_event_queue: { [number]: { any } } = table.create(1)
|
||||
local function_call_id = 0
|
||||
reliable_event_queue[0] = table.create(255)
|
||||
reliable.OnClientEvent:Connect(function(buff, inst)
|
||||
incoming_buff = buff
|
||||
incoming_inst = inst
|
||||
incoming_read = 0
|
||||
incoming_ipos = 0
|
||||
local len = buffer.len(buff)
|
||||
while incoming_read < len do
|
||||
local id = buffer.readu8(buff, read(1))
|
||||
if id == 0 then
|
||||
local call_id = buffer.readu8(incoming_buff, read(1))
|
||||
local value
|
||||
value = {}
|
||||
local enum_value_1 = buffer.readu8(incoming_buff, read(1))
|
||||
if enum_value_1 == 0 then
|
||||
value = "Success"
|
||||
elseif enum_value_1 == 1 then
|
||||
value = "Fail"
|
||||
else
|
||||
error("Invalid enumerator")
|
||||
end
|
||||
local thread = reliable_event_queue[0][call_id]
|
||||
-- When using actors it's possible for multiple Zap clients to exist, but only one called the Zap remote function.
|
||||
if thread then
|
||||
task.spawn(thread, value)
|
||||
end
|
||||
reliable_event_queue[0][call_id] = nil
|
||||
else
|
||||
error("Unknown event id")
|
||||
end
|
||||
end
|
||||
end)
|
||||
table.freeze(polling_queues_reliable)
|
||||
table.freeze(polling_queues_unreliable)
|
||||
|
||||
local returns = {
|
||||
SendEvents = SendEvents,
|
||||
Test = {
|
||||
Call = function(Foo: number, Bar: string): "Success" | "Fail"
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, 0)
|
||||
function_call_id += 1
|
||||
function_call_id %= 256
|
||||
if reliable_event_queue[0][function_call_id] then
|
||||
function_call_id -= 1
|
||||
error("Zap has more than 256 calls awaiting a response, and therefore this packet has been dropped")
|
||||
end
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, function_call_id)
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, Foo)
|
||||
local len_1 = #Bar
|
||||
alloc(2)
|
||||
buffer.writeu16(outgoing_buff, outgoing_apos, len_1)
|
||||
alloc(len_1)
|
||||
buffer.writestring(outgoing_buff, outgoing_apos, Bar, len_1)
|
||||
reliable_event_queue[0][function_call_id] = coroutine.running()
|
||||
return coroutine.yield()
|
||||
end,
|
||||
},
|
||||
}
|
||||
type Events = typeof(returns)
|
||||
return returns
|
234
bins/zap/tests/snapshots/server.luau
Normal file
234
bins/zap/tests/snapshots/server.luau
Normal file
|
@ -0,0 +1,234 @@
|
|||
--!native
|
||||
--!optimize 2
|
||||
--!nocheck
|
||||
--!nolint
|
||||
--#selene: allow(unused_variable, global_usage)
|
||||
-- Server generated by Zap v0.6.20 (https://github.com/red-blox/zap)
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
local outgoing_buff: buffer
|
||||
local outgoing_used: number
|
||||
local outgoing_size: number
|
||||
local outgoing_inst: { Instance }
|
||||
local outgoing_apos: number
|
||||
local outgoing_ids: { number }
|
||||
|
||||
local incoming_buff: buffer
|
||||
local incoming_read: number
|
||||
local incoming_inst: { Instance }
|
||||
local incoming_ipos: number
|
||||
local incoming_ids: { number }
|
||||
|
||||
-- thanks to https://dom.rojo.space/binary.html#cframe
|
||||
local CFrameSpecialCases = {
|
||||
CFrame.Angles(0, 0, 0),
|
||||
CFrame.Angles(math.rad(90), 0, 0),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(180)),
|
||||
CFrame.Angles(math.rad(-90), 0, 0),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(90)),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(90)),
|
||||
CFrame.Angles(0, 0, math.rad(90)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(90)),
|
||||
CFrame.Angles(math.rad(-90), math.rad(-90), 0),
|
||||
CFrame.Angles(0, math.rad(-90), 0),
|
||||
CFrame.Angles(math.rad(90), math.rad(-90), 0),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(180)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(180)),
|
||||
CFrame.Angles(0, math.rad(180), math.rad(0)),
|
||||
CFrame.Angles(math.rad(-90), math.rad(-180), math.rad(0)),
|
||||
CFrame.Angles(0, math.rad(0), math.rad(180)),
|
||||
CFrame.Angles(math.rad(90), math.rad(180), math.rad(0)),
|
||||
CFrame.Angles(0, math.rad(0), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(-90), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(-180), math.rad(-90)),
|
||||
CFrame.Angles(0, math.rad(90), math.rad(-90)),
|
||||
CFrame.Angles(math.rad(90), math.rad(90), 0),
|
||||
CFrame.Angles(0, math.rad(90), 0),
|
||||
CFrame.Angles(math.rad(-90), math.rad(90), 0),
|
||||
}
|
||||
|
||||
local function alloc(len: number)
|
||||
if outgoing_used + len > outgoing_size then
|
||||
while outgoing_used + len > outgoing_size do
|
||||
outgoing_size = outgoing_size * 2
|
||||
end
|
||||
|
||||
local new_buff = buffer.create(outgoing_size)
|
||||
buffer.copy(new_buff, 0, outgoing_buff, 0, outgoing_used)
|
||||
|
||||
outgoing_buff = new_buff
|
||||
end
|
||||
|
||||
outgoing_apos = outgoing_used
|
||||
outgoing_used = outgoing_used + len
|
||||
|
||||
return outgoing_apos
|
||||
end
|
||||
|
||||
local function read(len: number)
|
||||
local pos = incoming_read
|
||||
incoming_read = incoming_read + len
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
local function save()
|
||||
return {
|
||||
buff = outgoing_buff,
|
||||
used = outgoing_used,
|
||||
size = outgoing_size,
|
||||
inst = outgoing_inst,
|
||||
outgoing_ids = outgoing_ids,
|
||||
incoming_ids = incoming_ids,
|
||||
}
|
||||
end
|
||||
|
||||
local function load(data: {
|
||||
buff: buffer,
|
||||
used: number,
|
||||
size: number,
|
||||
inst: { Instance },
|
||||
outgoing_ids: { number },
|
||||
incoming_ids: { number },
|
||||
})
|
||||
outgoing_buff = data.buff
|
||||
outgoing_used = data.used
|
||||
outgoing_size = data.size
|
||||
outgoing_inst = data.inst
|
||||
outgoing_ids = data.outgoing_ids
|
||||
incoming_ids = data.incoming_ids
|
||||
end
|
||||
|
||||
local function load_empty()
|
||||
outgoing_buff = buffer.create(64)
|
||||
outgoing_used = 0
|
||||
outgoing_size = 64
|
||||
outgoing_inst = {}
|
||||
outgoing_ids = {}
|
||||
incoming_ids = {}
|
||||
end
|
||||
|
||||
load_empty()
|
||||
|
||||
local types = {}
|
||||
|
||||
local polling_queues_reliable = {}
|
||||
local polling_queues_unreliable = {}
|
||||
if not RunService:IsRunning() then
|
||||
local noop = function() end
|
||||
return table.freeze({
|
||||
SendEvents = noop,
|
||||
Test = table.freeze({
|
||||
SetCallback = noop,
|
||||
}),
|
||||
}) :: Events
|
||||
end
|
||||
local Players = game:GetService("Players")
|
||||
|
||||
if RunService:IsClient() then
|
||||
error("Cannot use the server module on the client!")
|
||||
end
|
||||
|
||||
local remotes = ReplicatedStorage:FindFirstChild("ZAP")
|
||||
if remotes == nil then
|
||||
remotes = Instance.new("Folder")
|
||||
remotes.Name = "ZAP"
|
||||
remotes.Parent = ReplicatedStorage
|
||||
end
|
||||
|
||||
local reliable = remotes:FindFirstChild("ZAP_RELIABLE")
|
||||
if reliable == nil then
|
||||
reliable = Instance.new("RemoteEvent")
|
||||
reliable.Name = "ZAP_RELIABLE"
|
||||
reliable.Parent = remotes
|
||||
end
|
||||
|
||||
local player_map = {}
|
||||
|
||||
local function load_player(player: Player)
|
||||
if player_map[player] then
|
||||
load(player_map[player])
|
||||
else
|
||||
load_empty()
|
||||
end
|
||||
end
|
||||
|
||||
Players.PlayerRemoving:Connect(function(player)
|
||||
player_map[player] = nil
|
||||
end)
|
||||
|
||||
local function SendEvents()
|
||||
for player, outgoing in player_map do
|
||||
if outgoing.used > 0 then
|
||||
local buff = buffer.create(outgoing.used)
|
||||
buffer.copy(buff, 0, outgoing.buff, 0, outgoing.used)
|
||||
|
||||
reliable:FireClient(player, buff, outgoing.inst)
|
||||
|
||||
outgoing.buff = buffer.create(64)
|
||||
outgoing.used = 0
|
||||
outgoing.size = 64
|
||||
table.clear(outgoing.inst)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RunService.Heartbeat:Connect(SendEvents)
|
||||
|
||||
local reliable_events = table.create(1)
|
||||
reliable.OnServerEvent:Connect(function(player, buff, inst)
|
||||
incoming_buff = buff
|
||||
incoming_inst = inst
|
||||
incoming_read = 0
|
||||
incoming_ipos = 0
|
||||
local len = buffer.len(buff)
|
||||
while incoming_read < len do
|
||||
local id = buffer.readu8(buff, read(1))
|
||||
if id == 0 then
|
||||
local call_id = buffer.readu8(buff, read(1))
|
||||
local value, value2
|
||||
value = buffer.readu8(incoming_buff, read(1))
|
||||
local len_1 = buffer.readu16(incoming_buff, read(2))
|
||||
value2 = buffer.readstring(incoming_buff, read(len_1), len_1)
|
||||
if reliable_events[0] then
|
||||
task.spawn(function(player_2, call_id_2, value_1, value_2)
|
||||
local ret_1 = reliable_events[0](player_2, value_1, value_2)
|
||||
load_player(player_2)
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, 0)
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, call_id_2)
|
||||
if ret_1 == "Success" then
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, 0)
|
||||
elseif ret_1 == "Fail" then
|
||||
alloc(1)
|
||||
buffer.writeu8(outgoing_buff, outgoing_apos, 1)
|
||||
else
|
||||
error("Invalid enumerator")
|
||||
end
|
||||
player_map[player_2] = save()
|
||||
end, player, call_id, value, value2)
|
||||
end
|
||||
else
|
||||
error("Unknown event id")
|
||||
end
|
||||
end
|
||||
end)
|
||||
table.freeze(polling_queues_reliable)
|
||||
table.freeze(polling_queues_unreliable)
|
||||
|
||||
local returns = {
|
||||
SendEvents = SendEvents,
|
||||
Test = {
|
||||
SetCallback = function(Callback: (Player: Player, Foo: number, Bar: string) -> "Success" | "Fail"): () -> ()
|
||||
reliable_events[0] = Callback
|
||||
return function()
|
||||
reliable_events[0] = nil
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
type Events = typeof(returns)
|
||||
return returns
|
Loading…
Add table
Reference in a new issue