Skip to content

Commit deebb56

Browse files
authored
Merge pull request #209 from prometheus-lua/feature/better-tests
Add test cases for various Lua functionalities
2 parents 099f92c + dcd09fe commit deebb56

File tree

9 files changed

+232
-19
lines changed

9 files changed

+232
-19
lines changed

tests.lua

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ local Prometheus = require("src.prometheus")
1313
local noColors = false; -- Wether Colors in the Console output should be enabled
1414
local isWindows = true; -- Wether the Test are Performed on a Windows or Linux System
1515
local ciMode = false; -- Wether the Test error are ignored or not
16+
local iterationCount = 20; -- How often each test should be executed
1617

1718
for _, currArg in pairs(arg) do
1819
if currArg == "--Linux" then
@@ -21,6 +22,10 @@ for _, currArg in pairs(arg) do
2122
if currArg == "--CI" then
2223
ciMode = true
2324
end
25+
local iterationValue = currArg:match("^%-%-iterations=(%d+)$")
26+
if iterationValue then
27+
iterationCount = math.max(tonumber(iterationValue), 1)
28+
end
2429
end
2530

2631
-- Enable/Disable Console Colors - this may be needed because cmd.exe and powershell.exe do not support ANSI Color Escape Sequences. The Windows Terminal Application is needed
@@ -38,7 +43,15 @@ local pipeline = Prometheus.Pipeline:new({
3843
-- "Number" for names like this : _1, _2, _3, ... - Not recomended
3944
pipeline:setNameGenerator("MangledShuffled");
4045

41-
print("Performing Prometheus Tests ...")
46+
local function describePlatform()
47+
return isWindows and "Windows" or "Linux"
48+
end
49+
50+
print(string.format(
51+
"Performing Prometheus Tests (iterations=%d per file/preset, platform=%s)...",
52+
iterationCount,
53+
describePlatform()
54+
))
4255
local function scandir(directory)
4356
local i, t, popen = 0, {}, io.popen
4457
local pfile = popen(isWindows and 'dir "'..directory..'" /b' or 'ls -a "'..directory..'"')
@@ -112,25 +125,27 @@ for i, filename in ipairs(scandir(testdir)) do
112125
table.remove(preset.Steps, i);
113126
end
114127
end
115-
pipeline = Prometheus.Pipeline:fromConfig(preset);
116-
local obfuscated = pipeline:apply(code);
117-
118-
local funca = loadstring(code);
119-
local funcb = loadstring(obfuscated);
120-
121-
if funcb == nil then
122-
print(Prometheus.colors("[FAILED] ", "red") .. "(" .. filename .. "): " .. name .. ", Invalid Lua!");
123-
print("[SOURCE]", obfuscated);
124-
fc = fc + 1;
125-
else
126-
local validated, outa, outb = validate(funca, funcb);
127-
128-
if not validated then
129-
print(Prometheus.colors("[FAILED] ", "red") .. "(" .. filename .. "): " .. name);
130-
print("[OUTA] ", outa);
131-
print("[OUTB] ", outb);
128+
for iteration = 1, iterationCount do
129+
pipeline = Prometheus.Pipeline:fromConfig(preset);
130+
local obfuscated = pipeline:apply(code);
131+
132+
local funca = loadstring(code);
133+
local funcb = loadstring(obfuscated);
134+
135+
if funcb == nil then
136+
print(Prometheus.colors("[FAILED] ", "red") .. "(" .. filename .. "): " .. name .. ", Invalid Lua!");
132137
print("[SOURCE]", obfuscated);
133138
fc = fc + 1;
139+
else
140+
local validated, outa, outb = validate(funca, funcb);
141+
142+
if not validated then
143+
print(Prometheus.colors("[FAILED] ", "red") .. "(" .. filename .. "): " .. name);
144+
print("[OUTA] ", outa);
145+
print("[OUTB] ", outb);
146+
print("[SOURCE]", obfuscated);
147+
fc = fc + 1;
148+
end
134149
end
135150
end
136151
end
@@ -146,4 +161,4 @@ else
146161
error("Test Failed!")
147162
end
148163
return -1;
149-
end
164+
end

tests/coroutines.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Deterministic coroutine driven sequence generator
2+
local function squares(limit)
3+
return coroutine.create(function()
4+
for i = 1, limit do
5+
coroutine.yield(i * i)
6+
end
7+
end)
8+
end
9+
10+
local co = squares(6)
11+
while true do
12+
local ok, value = coroutine.resume(co)
13+
if not ok then
14+
error(value)
15+
end
16+
if value == nil then
17+
break
18+
end
19+
print(value)
20+
end

tests/iterator.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- Custom iterator that creates a predictable countdown
2+
local function countdown(startValue, step)
3+
local value = startValue + step
4+
return function()
5+
value = value - step
6+
if value <= 0 then
7+
return nil
8+
end
9+
return value
10+
end
11+
end
12+
13+
for num in countdown(12, 3) do
14+
print(num)
15+
end

tests/matrix.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-- Deterministic 2x2 matrix multiplication example
2+
local function multiply(a, b)
3+
local result = {
4+
{ a[1][1] * b[1][1] + a[1][2] * b[2][1], a[1][1] * b[1][2] + a[1][2] * b[2][2] },
5+
{ a[2][1] * b[1][1] + a[2][2] * b[2][1], a[2][1] * b[1][2] + a[2][2] * b[2][2] }
6+
}
7+
return result
8+
end
9+
10+
local A = {
11+
{1, 2},
12+
{3, 4}
13+
}
14+
15+
local B = {
16+
{5, 6},
17+
{7, 8}
18+
}
19+
20+
local C = multiply(A, B)
21+
for row = 1, 2 do
22+
print(string.format("%d,%d", C[row][1], C[row][2]))
23+
end

tests/metatables.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-- Example showcasing metamethod driven vector arithmetic
2+
local Vector = {}
3+
Vector.__index = Vector
4+
5+
function Vector:new(x, y)
6+
return setmetatable({ x = x, y = y }, self)
7+
end
8+
9+
function Vector.__add(a, b)
10+
return Vector:new(a.x + b.x, a.y + b.y)
11+
end
12+
13+
function Vector:describe()
14+
return string.format("(%d,%d)", self.x, self.y)
15+
end
16+
17+
local path = {
18+
Vector:new(2, 3),
19+
Vector:new(-1, 4),
20+
Vector:new(0, -2)
21+
}
22+
23+
local position = Vector:new(0, 0)
24+
for idx, delta in ipairs(path) do
25+
position = position + delta
26+
print(string.format("step%d:%s", idx, position:describe()))
27+
end

tests/state-machine.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-- Simple deterministic finite-state machine demonstration
2+
local transitions = {
3+
idle = { start = "running" },
4+
running = { pause = "paused", stop = "stopped" },
5+
paused = { resume = "running", stop = "stopped" }
6+
}
7+
8+
local steps = {
9+
{ event = "start", expect = "running" },
10+
{ event = "pause", expect = "paused" },
11+
{ event = "resume", expect = "running" },
12+
{ event = "stop", expect = "stopped" }
13+
}
14+
15+
local state = "idle"
16+
for idx, step in ipairs(steps) do
17+
local rule = transitions[state]
18+
state = rule and rule[step.event]
19+
assert(state == step.expect, string.format("bad transition at %d", idx))
20+
print(string.format("%d:%s->%s", idx, step.event, state))
21+
end
22+
23+
print("final:" .. state)

tests/strings.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- Deterministic text statistics for repeated words
2+
local passage = "lorem ipsum dolor sit amet ipsum lorem"
3+
local counts = {}
4+
5+
for word in passage:gmatch("%w+") do
6+
counts[word] = (counts[word] or 0) + 1
7+
end
8+
9+
local order = {"lorem", "ipsum", "dolor", "sit", "amet"}
10+
for _, word in ipairs(order) do
11+
print(string.format("%s:%d", word, counts[word] or 0))
12+
end

tests/table-merge.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Demonstrate deterministic table merging and traversal
2+
local breakfast = { eggs = 4, bacon = 3 }
3+
local lunch = { bacon = 1, toast = 5 }
4+
5+
local function mergeQuantities(a, b)
6+
local totals = {}
7+
for k, v in pairs(a) do
8+
totals[k] = v
9+
end
10+
for k, v in pairs(b) do
11+
totals[k] = (totals[k] or 0) + v
12+
end
13+
return totals
14+
end
15+
16+
local merged = mergeQuantities(breakfast, lunch)
17+
local order = {"eggs", "bacon", "toast"}
18+
for _, item in ipairs(order) do
19+
print(string.format("%s:%d", item, merged[item] or 0))
20+
end

tests/upvalues.lua

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-- Deterministic tests covering closure upvalues in nested functions and loops
2+
local function emitList(label, list)
3+
print(label .. ":" .. table.concat(list, ","))
4+
end
5+
6+
local function makeSeries(tag)
7+
local total = 0
8+
local function step(delta)
9+
total = total + delta
10+
return string.format("%s-%d", tag, total)
11+
end
12+
local function runSeries(values)
13+
local out = {}
14+
for _, delta in ipairs(values) do
15+
out[#out + 1] = step(delta)
16+
end
17+
return out
18+
end
19+
return runSeries
20+
end
21+
22+
local alphaSeries = makeSeries("alpha")
23+
emitList("series", alphaSeries({ 1, 2, 1, 3 }))
24+
25+
-- Verify each for-loop iteration captures its own upvalue
26+
local watchers = {}
27+
for i = 1, 4 do
28+
watchers[i] = function(mult)
29+
return i * mult
30+
end
31+
end
32+
33+
for idx, fn in ipairs(watchers) do
34+
print(string.format("watch%d:%d", idx, fn(idx + 1)))
35+
end
36+
37+
-- Nested functions sharing a master accumulator through for-loops
38+
local function buildAccumulators()
39+
local master = 0
40+
local store = {}
41+
for group = 1, 3 do
42+
local localTotal = group
43+
store[group] = function(iterations)
44+
for step = 1, iterations do
45+
localTotal = localTotal + group + step
46+
master = master + group
47+
end
48+
return localTotal, master
49+
end
50+
end
51+
return store
52+
end
53+
54+
local runners = buildAccumulators()
55+
for idx, fn in ipairs(runners) do
56+
local value, master = fn(idx)
57+
print(string.format("acc%d:%d|%d", idx, value, master))
58+
end

0 commit comments

Comments
 (0)