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:
parent
e71bff9562
commit
53c1c764ba
9 changed files with 263 additions and 1 deletions
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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
13
test/results/persist.ans
Normal 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}
|
||||
37
test/results/resume anchors.ans
Normal file
37
test/results/resume anchors.ans
Normal 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 #--
|
||||
{}
|
||||
11
test/results/symbol alias.ans
Normal file
11
test/results/symbol alias.ans
Normal 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
143
test/run.lua
Normal 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
11
test/tests/persist.ans
Normal 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)
|
||||
34
test/tests/resume anchors.ans
Normal file
34
test/tests/resume anchors.ans
Normal 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)
|
||||
11
test/tests/symbol alias.ans
Normal file
11
test/tests/symbol alias.ans
Normal 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])
|
||||
Loading…
Add table
Add a link
Reference in a new issue