Add tests for core words
This commit is contained in:
parent
cb1214dcdb
commit
c2c9a6bcc2
|
@ -3,3 +3,4 @@
|
||||||
*.lua
|
*.lua
|
||||||
!*tlconfig.lua
|
!*tlconfig.lua
|
||||||
!*tests.lua
|
!*tests.lua
|
||||||
|
luacov.*
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
203
tests.lua
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue