1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00

Add testing framework

More tests will arrive shortly...
This commit is contained in:
Étienne Fildadut 2023-12-27 23:19:19 +01:00
parent e71bff9562
commit 53c1c764ba
9 changed files with 263 additions and 1 deletions

View file

@ -71,6 +71,7 @@ Struct = ast.abstract.Runtime {
-- _:_ has higher priority than _,_
table.insert(l, e[1]:format(state, operator_priority["_:_"], ...)..":"..e[2]:format_right(state, operator_priority["_:_"], ...))
end
table.sort(l)
return ("{%s}"):format(table.concat(l, ", "))
end,

View file

@ -207,7 +207,8 @@ Node = class {
end,
-- return a pretty string representation of the node.
-- for non-runtime nodes (what was generated by a parse without any evaluation), this should return valid Anselme code that is functionnally equivalent to the parsed code. note that it currently does not preserve comment. the returned code should additionally always be the same given the same non-runtime input.
-- for non-runtime nodes (what was generated by a parse without any evaluation), this should return valid Anselme code that is functionnally equivalent to the parsed code. note that it currently does not preserve comment.
-- assuming nothing was mutated in the node, the returned string should remain the same - so if make sure the function is deterministic, e.g. sort if you use pairs()
-- redefine _format, not this - note that _format is a mandary method for all nodes.
-- state is optional and should only be relevant for runtime nodes; if specified, only show what is relevant for the current branch.
-- indentation_level and parent_priority are optional value that respectively keep track in nester :format calls of the indentation level (number) and parent operator priority (number); if the node has a strictly lower priority than the parent node, parentheses will be added

13
test/results/persist.ans Normal file
View file

@ -0,0 +1,13 @@
--# run #--
--- text ---
| {}"pouet=" {}"7" {}" (7)"|
--- text ---
| {}"d=" {}"7" {}" (7)"|
--- text ---
| {}"d=" {}"9" {}" (9)"|
--- text ---
| {}"pouet=" {}"9" {}" (9)"|
--- return ---
()
--# saved #--
{"pouet":9}

View file

@ -0,0 +1,37 @@
--# run #--
--- text ---
| {}"<<>>"|
| {}"a"|
--- choice ---
> | {}"A "|
=> | {}"B "|
--- text ---
| {}"boum"|
| {}"h " {}"8" {}""|
--- text ---
| {}"<<>>"|
| {}"a"|
--- choice ---
=> | {}"A "|
> | {}"B "|
--- text ---
| {}"b"|
| {}"c"|
| {}"d"|
| {}"e"|
| {}"f"|
| {}"g"|
| {}"h " {}"8" {}""|
--- text ---
| {}"<<>>"|
| {}"c"|
| {}"d"|
| {}"e"|
| {}"f"|
| {}"g"|
--- text ---
| {}"h " {}"8" {}""|
--- return ---
()
--# saved #--
{}

View file

@ -0,0 +1,11 @@
--# run #--
--- text ---
| {}"c=" {}"2" {}" (2)"|
| {}"l=" {}"*[1, 2, 3]" {}" (*[1,2,3])"|
--- text ---
| {}"c=" {}"5" {}" (5)"|
| {}"l=" {}"*[1, 5, 3]" {}" (*[1,5,3])"|
--- return ---
()
--# saved #--
{}

143
test/run.lua Normal file
View file

@ -0,0 +1,143 @@
local lfs = require("lfs")
local anselme = require("anselme")
local persistent_manager = require("state.persistent_manager")
local function run(path)
local state = anselme:new()
state:load_stdlib()
local run_state = state:branch()
local f = assert(io.open(path, "r"))
local block = anselme.parse(f:read("*a"), path)
f:close()
run_state:run(block)
local out = { "--# run #--" }
while run_state:active() do
local e, data = run_state:step()
table.insert(out, "--- "..e.." ---")
if e == "text" then
for _, l in ipairs(data) do
table.insert(out, l:format(run_state))
end
elseif e == "choice" then
local choice = assert(run_state:eval_local("choice"), "no choice selected"):to_lua()
for i, l in ipairs(data) do
if i == choice then
table.insert(out, "=> "..l:format(run_state))
else
table.insert(out, " > "..l:format(run_state))
end
end
data:choose(choice)
elseif e == "return" then
table.insert(out, data:format(run_state))
run_state:merge()
else
table.insert(out, tostring(data))
end
end
table.insert(out, "--# saved #--")
table.insert(out, persistent_manager:capture(run_state):format(run_state))
return table.concat(out, "\n")
end
local tests = {}
for test in lfs.dir("test/tests/") do
if test:match("%.ans$") then
table.insert(tests, "test/tests/"..test)
end
end
if arg[1] == "help" then
print("usage:")
print("lua test/run.lua: run all the tests")
print("lua test/run.lua write: write missing result files")
print("lua test/run.lua help: display this message")
elseif arg[1] == "write" then
for _, test in ipairs(tests) do
local f = io.open(test:gsub("^test/tests/", "test/results/"), "r")
if f then
f:close()
else
repeat
local rerun = false
print("* "..test)
local c = assert(io.open(test, "r"))
local code = c:read("*a")
c:close()
print(" Code:")
print(" "..code:gsub("\n", "\n "))
local s, result = pcall(run, test)
if not s then
print(" Unexpected error: "..tostring(result))
local r
repeat
io.write("Edit this file? (y/N) ")
r = io.read("*l"):lower()
until r == "y" or r == "n" or r == ""
if r == "y" then
os.execute(("micro %q"):format(test)) -- hardcoded but oh well
rerun = true
end
else
print(" Result:")
print(" "..result:gsub("\n", "\n "))
local r
repeat
io.write("Write this result? (y/N/e) ")
r = io.read("*l"):lower()
until r == "y" or r == "n" or r == "e" or r == ""
if r == "y" then
local o = assert(io.open(test:gsub("^test/tests/", "test/results/"), "w"))
o:write(result)
o:close()
elseif r == "e" then
os.execute(("micro %q"):format(test)) -- hardcoded but oh well
rerun = true
end
end
until not rerun
end
end
elseif not arg[1] then
local total, failure, errored, notfound = #tests, 0, 0, 0
for _, test in ipairs(tests) do
local f = io.open(test:gsub("^test/tests/", "test/results/"), "r")
if f then
local s, result = pcall(run, test)
if not s then
errored = errored + 1
print("* "..test)
print(" Unexpected error: "..tostring(result))
else
local expected = f:read("*a")
if result ~= expected then
failure = failure + 1
print("* "..test)
print(" Expected: \n "..expected:gsub("\n", "\n "))
print(" But received: \n "..result:gsub("\n", "\n "))
print("")
end
end
f:close()
else
notfound = notfound + 1
print("* "..test)
print(" Result file not found.")
print("")
end
end
print("#### Results ####")
print(("%s successes, %s failures, %s errors, %s missing result files, out of %s tests"):format(total-failure-notfound-errored, failure, errored, notfound, total))
else
print("unknown command, run `lua test/run.lua help` for usage")
end

11
test/tests/persist.ans Normal file
View file

@ -0,0 +1,11 @@
| pouet={persist("pouet", 7)} (7)
:&d = persist("pouet", 12)
| d={d} (7)
d = 9
| d={d} (9)
| pouet={persist("pouet", 21)} (9)

View file

@ -0,0 +1,34 @@
:c = ()
:choice = 2
:g = $
|c
#pouet
|d
:f = $(anchor=())
:x = 8
anchor ~>
|a
| A |>
| b
c = #pouet
g!
| e
_
| f
| g
| B |>
| boum
|h {x}
| <<>>
f(c)
| <<>>
choice = 1
f(c)
| <<>>
f(c)

View file

@ -0,0 +1,11 @@
:l = *[1,2,3]
:&c = l(2)
| c={c} (2)
| l={l} (*[1,2,3])
c = 5
| c={c} (5)
| l={l} (*[1,5,3])