Add tests for core words

This commit is contained in:
Starfflame 2021-05-23 22:22:27 -05:00
parent cb1214dcdb
commit c2c9a6bcc2
4 changed files with 185 additions and 25 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*.lua *.lua
!*tlconfig.lua !*tlconfig.lua
!*tests.lua !*tests.lua
luacov.*

View File

@ -78,7 +78,7 @@ end
-- I/O operations -- I/O operations
local function dot(state: Environment) local function dot(state: Environment)
local out = state.activeDataStack:pop() local out = state.activeDataStack:pop()
io.write(out as string.."\n") io.write(tostring(out) as string.."\n")
end end
local function twoDup(state: Environment) local function twoDup(state: Environment)
over(state) over(state)

View File

@ -9,9 +9,9 @@ local Environment = require("DataStructures").Environment
--interpreters.start(fileStream("codetest.txt")) --interpreters.start(fileStream("codetest.txt"))
local core_dicts = {CoreWords} local core_dicts = {CoreWords}
--local env = Environment:new(istream:new(standardInputRefill), core_dicts) local env = Environment:new(istream:new(standardInputRefill), core_dicts)
local env = Environment:new(oneReadInputStream("14 11 + ."), core_dicts) --local env = Environment:new(oneReadInputStream("14 11 + ."), core_dicts)
interpreters.start(env) interpreters.start(env)

203
tests.lua
View File

@ -4,12 +4,21 @@ local Stack, Dictionary, WordInfo, Environment = ds.Stack, ds.Dictionary, ds.Wor
local CoreHelpers = require("CoreHelpers") local CoreHelpers = require("CoreHelpers")
local CoreWords = require("CoreWords") local CoreWords = require("CoreWords")
local interpreters = require("Interpreters") local interpreters = require("Interpreters")
local TEST_REPEAT_COUNT = 200
local NUM_RANGE = 100000000000000
local STACK_RANGE = 100
function pushThree(s) function pushThree(s)
s:push(1) s:push(1)
s:push(2) s:push(2)
s:push(3) s:push(3)
end end
math.randomseed( os.time())
describe("Stack Tests", function() describe("Stack Tests", function()
local stack = Stack:new() local stack = Stack:new()
@ -72,7 +81,7 @@ describe("InputStream tests", function()
for i = 1, #inputstr do for i = 1, #inputstr do
assert.are.same(inputstr:sub(i, i), input:next()) assert.are.same(inputstr:sub(i, i), input:next())
end end
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
assert.are.same(nil, input:next()) assert.are.same(nil, input:next())
end end
end) end)
@ -83,7 +92,7 @@ describe("InputStream tests", function()
for i = 1, #inputstr do for i = 1, #inputstr do
assert.are.same(inputstr:sub(i, i), input:next()) assert.are.same(inputstr:sub(i, i), input:next())
end end
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
assert.are.same(nil, input:next()) assert.are.same(nil, input:next())
end end
end) end)
@ -94,7 +103,7 @@ describe("InputStream tests", function()
for i = 1, #expected_output do for i = 1, #expected_output do
assert.are.same(expected_output:sub(i,i), input:next()) assert.are.same(expected_output:sub(i,i), input:next())
end end
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
assert.are.same(nil, input:next()) assert.are.same(nil, input:next())
end end
end) end)
@ -137,13 +146,25 @@ function buildEnvironment(testString)
return testEnv return testEnv
end end
local twoRandom = function() return math.random(-100000, 100000), math.random(-100000, 100000) end local twoRandom = function() return math.random(-NUM_RANGE, NUM_RANGE), math.random(-NUM_RANGE, NUM_RANGE) end
local function randomDataStackEnv(lowerRange, upperRange)
local stackDepth = math.random(lowerRange, upperRange)
local stackTop = 0
local testEnv = Environment:new(nil, {CoreWords})
for j = 1, stackDepth do
stackTop = math.random(-NUM_RANGE,NUM_RANGE)
testEnv.activeDataStack:push(stackTop)
end
return testEnv, stackDepth
end
describe("Interpreter tests", function() describe("Interpreter tests", function()
describe("Arithmetic tests", function() describe("Arithmetic tests", function()
it("can add two numbers, and leave the sum on the stack", function() it("can add two numbers, and leave the sum on the stack", function()
for i=1, 1000 do for i=1, TEST_REPEAT_COUNT do
local a, b = twoRandom() local a, b = twoRandom()
local expected_sum = a + b local expected_sum = a + b
local testString = a.." "..b.." +" local testString = a.." "..b.." +"
@ -153,7 +174,7 @@ describe("Interpreter tests", function()
end end
end) end)
it("can subtract two numbers, and leave the difference on the stack", function() it("can subtract two numbers, and leave the difference on the stack", function()
for i=1, 1000 do for i=1, TEST_REPEAT_COUNT do
local a, b = twoRandom() local a, b = twoRandom()
local expected_diff = a -b local expected_diff = a -b
local testString = a.." "..b.." -" local testString = a.." "..b.." -"
@ -164,7 +185,7 @@ describe("Interpreter tests", function()
end) end)
it("can multiply two numbers, leaving product on the stack", function() it("can multiply two numbers, leaving product on the stack", function()
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
local a, b = twoRandom() local a, b = twoRandom()
local expected_prod = a*b local expected_prod = a*b
local testString = a.." "..b.." *" local testString = a.." "..b.." *"
@ -175,7 +196,7 @@ describe("Interpreter tests", function()
end) end)
it("can divide two numbers, leaving the quotient on the stack", function() it("can divide two numbers, leaving the quotient on the stack", function()
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
local a, b = twoRandom() local a, b = twoRandom()
local expected_quo = a/b local expected_quo = a/b
local testString = a.." "..b.." /" local testString = a.." "..b.." /"
@ -185,19 +206,19 @@ describe("Interpreter tests", function()
end end
end) end)
it("can evaluate a arithmetic expression with multiple operations", function() it("can evaluate a arithmetic expression with multiple operations", function()
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
operands = {math.random(-100000,100000), math.random(-100000,100000), math.random(-100000,100000), math.random(-100000,100000)} operands = {math.random(-NUM_RANGE,NUM_RANGE), math.random(-NUM_RANGE,NUM_RANGE), math.random(-NUM_RANGE,NUM_RANGE), math.random(-NUM_RANGE,NUM_RANGE)}
local operations = {math.random(4), math.random(4), math.random(4)} local operations = {math.random(4), math.random(4), math.random(4)}
local testString = ""..operands[1] local testString = ""..operands[1]
local expectedResult = operands[1] local expectedResult = operands[1]
for j, op in ipairs(operations) do for j, op in ipairs(operations) do
if j == 1 then if op == 1 then
testString = testString.." "..operands[j + 1].." +" testString = testString.." "..operands[j + 1].." +"
expectedResult = expectedResult + operands[j+1] expectedResult = expectedResult + operands[j+1]
elseif j == 2 then elseif op == 2 then
testString = testString.." "..operands[j + 1].." -" testString = testString.." "..operands[j + 1].." -"
expectedResult = expectedResult - operands[j+1] expectedResult = expectedResult - operands[j+1]
elseif j == 3 then elseif op == 3 then
testString = testString.." "..operands[j + 1].." *" testString = testString.." "..operands[j + 1].." *"
expectedResult = expectedResult * operands[j+1] expectedResult = expectedResult * operands[j+1]
else else
@ -219,18 +240,156 @@ describe("Interpreter tests", function()
assert.are.same(1, testEnv.activeDataStack.contents[2]) assert.are.same(1, testEnv.activeDataStack.contents[2])
end) end)
it("DUPs the top item of a stack with random quantities of random numbers on it.", function() it("DUPs the top item of a stack with random quantities of random numbers on it.", function()
for i = 1, 1000 do for i = 1, TEST_REPEAT_COUNT do
local stack_depth = math.random(100) local stackDepth = math.random(STACK_RANGE)
local stack_top = 0 local stackTop = 0
for j = 1, stack_depth do local testEnv = buildEnvironment("DUP")
stack_top = math.random(-100000,100000) for j = 1, stackDepth do
testEnv.activeDataStack:push(stack_top) stackTop = math.random(-NUM_RANGE,NUM_RANGE)
testEnv.activeDataStack:push(stackTop)
end end
local testEnv = buildEnvironment(stack_top.." DUP") interpreters.start(testEnv)
assert.are.same(stack_top, testEnv.activeDataStack.contents[j+1]) assert.are.same(stackTop, testEnv.activeDataStack.contents[stackDepth+1])
end end
end) end)
end) end)
describe("SWAP tests", function()
it("SWAPS the top two items of a stack with two items on it.", function()
local testEnv = buildEnvironment("1 2 SWAP")
interpreters.start(testEnv)
assert.are.same(2, testEnv.activeDataStack.contents[1])
assert.are.same(1, testEnv.activeDataStack.contents[2])
end)
it("SWAPS the top two items of a stack with random quantities of random numbers on it.", function()
for i = 1, TEST_REPEAT_COUNT do
local testEnv, stackDepth = randomDataStackEnv(2, STACK_RANGE)
testEnv.activeInputStream = CoreHelpers.oneReadInputStream("SWAP")
local a = testEnv.activeDataStack.contents[stackDepth]
local b = testEnv.activeDataStack.contents[stackDepth-1]
interpreters.start(testEnv)
assert.are.equal(testEnv.activeDataStack.contents[stackDepth-1], a)
assert.are.equal(testEnv.activeDataStack.contents[stackDepth], b)
end
end)
end)
describe("ROT tests", function()
it("ROTs the top three items of a stack with three items on it.", function()
local testEnv = buildEnvironment("1 2 3 ROT")
interpreters.start(testEnv)
assert.are.same({2, 3, 1}, testEnv.activeDataStack.contents)
end)
end)
describe("DROP tests", function()
it("Drops the top item of the stack, when stack size is 1.", function()
local testEnv = buildEnvironment("1 DROP")
interpreters.start(testEnv)
assert.are.same(nil, testEnv.activeDataStack.contents[1])
end)
-- TODO: add better tests
end)
describe("OVER tests", function()
it("Places a copy of the item below the top of the stack onto the top, when stack size is 2.", function()
local testEnv = buildEnvironment("1 2 OVER")
interpreters.start(testEnv)
assert.are.same({1, 2, 1}, testEnv.activeDataStack.contents)
end)
end)
-- TODO: test output of DOT.
describe("DOT tests", function()
it("Drops the top item of the stack.", function()
local testEnv = buildEnvironment("1 .")
interpreters.start(testEnv)
assert.are.same({}, testEnv.activeDataStack.contents)
end)
end)
describe("2DUP tests", function()
it("Duplicates the top two items on the stack.", function()
local testEnv = buildEnvironment("1 2 2DUP")
interpreters.start(testEnv)
assert.are.same({1, 2, 1, 2}, testEnv.activeDataStack.contents)
end)
end)
describe("2SWAP tests", function()
it("Exchanges the top two cell pairs.", function()
local testEnv = buildEnvironment("1 2 3 4 2SWAP")
interpreters.start(testEnv)
assert.are.same({3, 4, 1, 2}, testEnv.activeDataStack.contents)
end)
end)
describe("2OVER tests", function()
it("copies the two items below the top two items onto the top of the stack.", function()
local testEnv = buildEnvironment("1 2 3 4 2OVER")
interpreters.start(testEnv)
assert.are.same({1, 2, 3, 4, 1, 2}, testEnv.activeDataStack.contents)
end)
end)
describe("NIP tests", function()
it("drops the first item below the top of stack, when stack size == 2", function()
local testEnv = buildEnvironment("1 2 NIP")
interpreters.start(testEnv)
assert.are.same({2}, testEnv.activeDataStack.contents)
end)
end)
describe("TUCK tests", function()
it("Copies the top below the item just below the top, in a stack of size 2.", function()
local testEnv = buildEnvironment("1 2 TUCK")
interpreters.start(testEnv)
assert.are.same({2, 1, 2}, testEnv.activeDataStack.contents)
end)
end)
describe("ROLL tests", function()
it("is NOOP when u = 0", function()
local testEnv = buildEnvironment("1 2 4 1 1 0 ROLL")
interpreters.start(testEnv)
assert.are.same({1, 2, 4, 1, 1}, testEnv.activeDataStack.contents)
end)
it("is SWAP when u = 1", function()
local testEnv = buildEnvironment("1 2 3 4 5 1 ROLL")
interpreters.start(testEnv)
assert.are.same({1, 2, 3, 5, 4}, testEnv.activeDataStack.contents)
end)
it("is ROT when u = 2", function()
local testEnv = buildEnvironment("1 2 3 4 5 2 ROLL")
interpreters.start(testEnv)
assert.are.same({1, 2, 4, 5, 3}, testEnv.activeDataStack.contents)
end)
it("works properly for u = [3, 100]", function()
local testStr = ""
local expected_output = {}
for i = 3, 100 do
for j = 1, i+1 do
testStr = testStr.." "..j
table.insert(expected_output, j)
end
testStr = testStr.." "..i.." ROLL"
local bottom = table.remove(expected_output, #expected_output - i)
table.insert(expected_output, bottom)
local testEnv = buildEnvironment(testStr)
interpreters.start(testEnv)
assert.are.same(expected_output, testEnv.activeDataStack.contents)
end
end)
end)
describe("' tests", function()
it("places an xt on top of the stack replacing the next word", function()
local cw = CoreWords
local testFunc = function(env) local a, b return a + b end
local customWord = CoreHelpers.defineWord(cw, "TEST", testFunc, false)
local testEnv = buildEnvironment("' TEST")
interpreters.start(testEnv)
assert.are.same(testFunc, testEnv.activeDataStack.contents[1])
end)
end)
describe("EXECUTE tests", function()
it("Given an `add` XT on top of the stack with two numbers beneath it, execute it.", function()
local testEnv = buildEnvironment("1 2 ' + EXECUTE")
interpreters.start(testEnv)
assert.are.equal(3, testEnv.activeDataStack.contents[1])
end)
end)
end) end)
end) end)