Initial commit of a basic test framework, see readme.md for more

Most modules are covered with basic unit tests, and there's an example test for a graphics draw (rectangle) and object (File) - for object tests doing more scenario based so we can check multiple things together
This commit is contained in:
ell
2023-10-04 14:43:44 +01:00
parent 03b6b9ff13
commit 19df8040df
32 changed files with 3667 additions and 0 deletions
+359
View File
@@ -0,0 +1,359 @@
-- @class - TestMethod
-- @desc - used to run a specific method from a module's /test/ suite
-- each assertion is tracked and then printed to output
TestMethod = {
-- @method - TestMethod:new()
-- @desc - create a new TestMethod object
-- @param {string} method - string of method name to run
-- @param {TestMethod} testmethod - parent testmethod this test belongs to
-- @return {table} - returns the new Test object
new = function(self, method, testmodule)
local test = {
testmodule = testmodule,
method = method,
asserts = {},
start = love.timer.getTime(),
finish = 0,
count = 0,
passed = false,
skipped = false,
skipreason = '',
fatal = '',
message = nil,
result = {},
colors = {
red = {1, 0, 0, 1},
green = {0, 1, 0, 1},
blue = {0, 0, 1, 1},
black = {0, 0, 0, 1},
white = {1, 1, 1, 1}
}
}
setmetatable(test, self)
self.__index = self
return test
end,
-- @method - TestMethod:assertEquals()
-- @desc - used to assert two values are equals
-- @param {any} expected - expected value of the test
-- @param {any} actual - actual value of the test
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertEquals = function(self, expected, actual, label)
self.count = self.count + 1
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = expected == actual,
message = 'expected \'' .. tostring(expected) .. '\' got \'' ..
tostring(actual) .. '\'',
test = label
})
end,
-- @method - TestMethod:assertPixels()
-- @desc - checks a list of coloured pixels agaisnt given imgdata
-- @param {ImageData} imgdata - image data to check
-- @param {table} pixels - map of colors to list of pixel coords, i.e.
-- { blue = { {1, 1}, {2, 2}, {3, 4} } }
-- @return {nil}
assertPixels = function(self, imgdata, pixels, label)
for i, v in pairs(pixels) do
local col = self.colors[i]
local pixels = v
for p=1,#pixels do
local coord = pixels[p]
local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2])
local compare_id = tostring(coord[1]) .. ',' .. tostring(coord[2])
-- @TODO add some sort pixel tolerance to the coords
self:assertEquals(col[1], tr, 'check pixel r for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')')
self:assertEquals(col[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')')
self:assertEquals(col[3], tb, 'check pixel b for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')')
self:assertEquals(col[4], ta, 'check pixel a for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')')
end
end
end,
-- @method - TestMethod:assertNotEquals()
-- @desc - used to assert two values are not equal
-- @param {any} expected - expected value of the test
-- @param {any} actual - actual value of the test
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertNotEquals = function(self, expected, actual, label)
self.count = self.count + 1
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = expected ~= actual,
message = 'avoiding \'' .. tostring(expected) .. '\' got \'' ..
tostring(actual) .. '\'',
test = label
})
end,
-- @method - TestMethod:assertRange()
-- @desc - used to check a value is within an expected range
-- @param {number} actual - actual value of the test
-- @param {number} min - minimum value the actual should be >= to
-- @param {number} max - maximum value the actual should be <= to
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertRange = function(self, actual, min, max, label)
self.count = self.count + 1
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = actual >= min and actual <= max,
message = 'value \'' .. tostring(actual) .. '\' out of range \'' ..
tostring(min) .. '-' .. tostring(max) .. '\'',
test = label
})
end,
-- @method - TestMethod:assertMatch()
-- @desc - used to check a value is within a list of values
-- @param {number} list - list of valid values for the test
-- @param {number} actual - actual value of the test to check is in the list
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertMatch = function(self, list, actual, label)
self.count = self.count + 1
local found = false
for l=1,#list do
if list[l] == actual then found = true end;
end
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = found == true,
message = 'value \'' .. tostring(actual) .. '\' not found in \'' ..
table.concat(list, ',') .. '\'',
test = label
})
end,
-- @method - TestMethod:assertGreaterEqual()
-- @desc - used to check a value is >= than a certain target value
-- @param {any} target - value to check the test agaisnt
-- @param {any} actual - actual value of the test
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertGreaterEqual = function(self, target, actual, label)
self.count = self.count + 1
local passing = false
if target ~= nil and actual ~= nil then
passing = actual >= target
end
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = passing,
message = 'value \'' .. tostring(actual) .. '\' not >= \'' ..
tostring(target) .. '\'',
test = label
})
end,
-- @method - TestMethod:assertLessEqual()
-- @desc - used to check a value is <= than a certain target value
-- @param {any} target - value to check the test agaisnt
-- @param {any} actual - actual value of the test
-- @param {string} label - label for this test to use in exports
-- @return {nil}
assertLessEqual = function(self, target, actual, label)
self.count = self.count + 1
local passing = false
if target ~= nil and actual ~= nil then
passing = actual <= target
end
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = passing,
message = 'value \'' .. tostring(actual) .. '\' not <= \'' ..
tostring(target) .. '\'',
test = label
})
end,
-- @method - TestMethod:assertObject()
-- @desc - used to check a table is a love object, this runs 3 seperate
-- tests to check table has the basic properties of an object
-- @note - actual object functionality tests are done in the objects module
-- @param {table} obj - table to check is a valid love object
-- @return {nil}
assertObject = function(self, obj)
self:assertNotEquals(nil, obj, 'check not nill')
self:assertEquals('userdata', type(obj), 'check is userdata')
if obj ~= nil then
self:assertNotEquals(nil, obj:type(), 'check has :type()')
end
end,
-- @method - TestMethod:skipTest()
-- @desc - used to mark this test as skipped for a specific reason
-- @param {string} reason - reason why method is being skipped
-- @return {nil}
skipTest = function(self, reason)
self.skipped = true
self.skipreason = reason
end,
-- @method - TestMethod:evaluateTest()
-- @desc - evaluates the results of all assertions for a final restult
-- @return {nil}
evaluateTest = function(self)
local failure = ''
local failures = 0
for a=1,#self.asserts do
-- @TODO just return first failed assertion msg? or all?
-- currently just shows the first assert that failed
if self.asserts[a].passed == false and self.skipped == false then
if failure == '' then failure = self.asserts[a] end
failures = failures + 1
end
end
if self.fatal ~= '' then failure = self.fatal end
local passed = tostring(#self.asserts - failures)
local total = '(' .. passed .. '/' .. tostring(#self.asserts) .. ')'
if self.skipped == true then
self.testmodule.skipped = self.testmodule.skipped + 1
love.test.totals[3] = love.test.totals[3] + 1
self.result = {
total = '',
result = "SKIP",
passed = false,
message = '(0/0) - method skipped [' .. self.skipreason .. ']'
}
else
if failure == '' and #self.asserts > 0 then
self.passed = true
self.testmodule.passed = self.testmodule.passed + 1
love.test.totals[1] = love.test.totals[1] + 1
self.result = {
total = total,
result = 'PASS',
passed = true,
message = nil
}
else
self.passed = false
self.testmodule.failed = self.testmodule.failed + 1
love.test.totals[2] = love.test.totals[2] + 1
if #self.asserts == 0 then
local msg = 'no asserts defined'
if self.fatal ~= '' then msg = self.fatal end
self.result = {
total = total,
result = 'FAIL',
passed = false,
key = 'test',
message = msg
}
else
local key = failure['key']
if failure['test'] ~= nil then
key = key .. ' [' .. failure['test'] .. ']'
end
self.result = {
total = total,
result = 'FAIL',
passed = false,
key = key,
message = failure['message']
}
end
end
end
self:printResult()
end,
-- @method - TestMethod:printResult()
-- @desc - prints the result of the test to the console as well as appends
-- the XML + HTML for the test to the testsuite output
-- @return {nil}
printResult = function(self)
-- get total timestamp
-- @TODO make nicer, just need a 3DP ms value
self.finish = love.timer.getTime() - self.start
love.test.time = love.test.time + self.finish
self.testmodule.time = self.testmodule.time + self.finish
local endtime = tostring(math.floor((love.timer.getTime() - self.start)*1000))
if string.len(endtime) == 1 then endtime = ' ' .. endtime end
if string.len(endtime) == 2 then endtime = ' ' .. endtime end
if string.len(endtime) == 3 then endtime = ' ' .. endtime end
-- get failure/skip message for output (if any)
local failure = ''
local output = ''
if self.passed == false and self.skipped == false then
failure = '\t\t\t<failure message="' .. self.result.key .. ' ' ..
self.result.message .. '"></failure>\n'
output = self.result.key .. ' ' .. self.result.message
end
if output == '' and self.skipped == true then
output = self.skipreason
end
-- append XML for the test class result
self.testmodule.xml = self.testmodule.xml .. '\t\t<testclass classname="' ..
self.method .. '" name="' .. self.method ..
'" time="' .. tostring(self.finish*1000) .. '">\n' ..
failure .. '\t\t</testclass>\n'
-- unused currently, adds a preview image for certain graphics methods to the output
local preview = ''
-- if self.testmodule.module == 'graphics' then
-- local filename = 'love_test_graphics_rectangle'
-- preview = '<div class="preview">' .. '<img src="' .. filename .. '_expected.png"/><p>Expected</p></div>' ..
-- '<div class="preview"><img src="' .. filename .. '_actual.png"/><p>Actual</p></div>'
-- end
-- append HTML for the test class result
local status = '🔴'
local cls = 'red'
if self.passed == true then status = '🟢'; cls = '' end
if self.skipped == true then status = '🟡'; cls = '' end
self.testmodule.html = self.testmodule.html ..
'<tr class=" ' .. cls .. '">' ..
'<td>' .. status .. '</td>' ..
'<td>' .. self.method .. '</td>' ..
'<td>' .. tostring(self.finish*1000) .. 'ms</td>' ..
'<td>' .. output .. preview .. '</td>' ..
'</tr>'
-- add message if assert failed
local msg = ''
if self.result.message ~= nil and self.skipped == false then
msg = ' - ' .. self.result.key ..
' failed - (' .. self.result.message .. ')'
end
if self.skipped == true then
msg = self.result.message
end
-- log final test result to console
-- i know its hacky but its neat soz
local tested = 'love.' .. self.testmodule.module .. '.' .. self.method .. '()'
local matching = string.sub(self.testmodule.spacer, string.len(tested), 40)
self.testmodule:log(
self.testmodule.colors[self.result.result],
' ' .. tested .. matching,
' ==> ' .. self.result.result .. ' - ' .. endtime .. 'ms ' ..
self.result.total .. msg
)
end
}
+114
View File
@@ -0,0 +1,114 @@
-- @class - TestModule
-- @desc - used to run tests for a given module, each test method will spawn
-- a love.test.Test object
TestModule = {
-- @method - TestModule:new()
-- @desc - create a new Suite object
-- @param {string} module - string of love module the suite is for
-- @return {table} - returns the new Suite object
new = function(self, module, method)
local testmodule = {
timer = 0,
time = 0,
delay = 0.1,
spacer = ' ',
colors = {
PASS = 'green', FAIL = 'red', SKIP = 'grey'
},
colormap = {
grey = '\27[37m',
green = '\27[32m',
red = '\27[31m',
yellow = '\27[33m'
},
xml = '',
html = '',
tests = {},
running = {},
called = {},
passed = 0,
failed = 0,
skipped = 0,
module = module,
method = method,
index = 1,
start = false,
}
setmetatable(testmodule, self)
self.__index = self
return testmodule
end,
-- @method - TestModule:log()
-- @desc - log to console with specific colors, split out to make it easier
-- to adjust all console output across the tests
-- @param {string} color - color key to use for the log
-- @param {string} line - main message to write (LHS)
-- @param {string} result - result message to write (RHS)
-- @return {nil}
log = function(self, color, line, result)
if result == nil then result = '' end
print(self.colormap[color] .. line .. result)
end,
-- @method - TestModule:runTests()
-- @desc - starts the running of tests and sets up the list of methods to test
-- @param {string} module - module to set for the test suite
-- @param {string} method - specific method to test, if nil all methods tested
-- @return {nil}
runTests = function(self)
self.running = {}
self.passed = 0
self.failed = 0
if self.method ~= nil then
table.insert(self.running, self.method)
else
for i,_ in pairs(love.test[self.module]) do
table.insert(self.running, i)
end
table.sort(self.running)
end
self.index = 1
self.start = true
self:log('yellow', '\nlove.' .. self.module .. '.testmodule.start')
end,
-- @method - TestModule:printResult()
-- @desc - prints the result of the module to the console as well as appends
-- the XML + HTML for the test to the testsuite output
-- @return {nil}
printResult = function(self)
-- add xml to main output
love.test.xml = love.test.xml .. '\t<testsuite name="love.' .. self.module ..
'" tests="' .. tostring(self.passed) ..
'" failures="' .. tostring(self.failed) ..
'" skipped="' .. tostring(self.skipped) ..
'" time="' .. tostring(self.time*1000) .. '">\n' .. self.xml .. '\t</testsuite>\n'
-- add html to main output
local status = '🔴'
if self.failed == 0 then status = '🟢' end
love.test.html = love.test.html .. '<h2>' .. status .. '&nbsp;love.' .. self.module .. '</h2><ul class="summary">' ..
'<li>🟢&nbsp;' .. tostring(self.passed) .. ' Tests</li>' ..
'<li>🔴&nbsp;' .. tostring(self.failed) .. ' Failures</li>' ..
'<li>🟡&nbsp;' .. tostring(self.skipped) .. ' Skipped</li>' ..
'<li>' .. tostring(self.time*1000) .. 'ms</li>' .. '<ul><br/><br/>' ..
'<table><thead><tr><td width="20px"></td><td width="100px">Method</td><td width="100px">Time</td><td>Details</td></tr></thead><tbody>' ..
self.html .. '</tbody></table>'
-- print module results to console
self:log('yellow', 'love.' .. self.module .. '.testmodule.end')
local failedcol = '\27[31m'
if self.failed == 0 then failedcol = '\27[37m' end
self:log('green', tostring(self.passed) .. ' PASSED' .. ' || ' ..
failedcol .. tostring(self.failed) .. ' FAILED || \27[37m' ..
tostring(self.skipped) .. ' SKIPPED')
self.start = false
self.fakequit = false
end
}
+159
View File
@@ -0,0 +1,159 @@
TestSuite = {
-- @method - TestSuite:new()
-- @desc - creates a new TestSuite object that handles all the tests
-- @return {table} - returns the new TestSuite object
new = function(self)
local test = {
-- testsuite internals
modules = {},
module = nil,
testcanvas = love.graphics.newCanvas(16, 16),
current = 1,
output = '',
totals = {0, 0, 0},
time = 0,
xml = '',
html = '',
fakequit = false,
windowmode = true,
-- love modules to test
audio = {},
data = {},
event = {},
filesystem = {},
font = {},
graphics = {},
image = {},
joystick = {},
math = {},
mouse = {},
objects = {}, -- special for all object class contructor tests
physics = {},
sound = {},
system = {},
thread = {},
timer = {},
touch = {},
video = {},
window = {}
}
setmetatable(test, self)
self.__index = self
return test
end,
-- @method - TestSuite:runSuite()
-- @desc - called in love.update, runs through every method or every module
-- @param {number} delta - delta from love.update to track time elapsed
-- @return {nil}
runSuite = function(self, delta)
-- stagger 0.1s between tests
if self.module ~= nil then
self.module.timer = self.module.timer + delta
if self.module.timer >= self.module.delay then
self.module.timer = self.module.timer - self.module.delay
if self.module.start == true then
-- work through each test method 1 by 1
if self.module.index <= #self.module.running then
-- run method once
if self.module.called[self.module.index] == nil then
self.module.called[self.module.index] = true
local method = self.module.running[self.module.index]
local test = TestMethod:new(method, self.module)
-- check method exists in love first
if self.module.module ~= 'objects' and (love[self.module.module] == nil or love[self.module.module][method] == nil) then
local tested = 'love.' .. self.module.module .. '.' .. method .. '()'
local matching = string.sub(self.module.spacer, string.len(tested), 40)
self.module:log(self.module.colors['FAIL'],
tested .. matching,
' ==> FAIL (0/0) - call failed - method does not exist'
)
-- otherwise run the test method then eval the asserts
else
local ok, chunk, err = pcall(self[self.module.module][method], test)
if ok == false then
print("FATAL", chunk, err)
test.fatal = tostring(chunk) .. tostring(err)
end
local ok, chunk, err = pcall(test.evaluateTest, test)
if ok == false then
print("FATAL", chunk, err)
test.fatal = tostring(chunk) .. tostring(err)
end
end
-- move onto the next test
self.module.index = self.module.index + 1
end
else
-- print module results and add to output
self.module:printResult()
-- if we have more modules to go run the next one
self.current = self.current + 1
if #self.modules >= self.current then
self.module = self.modules[self.current]
self.module:runTests()
-- otherwise print the final results and export output
else
self:printResult()
love.event.quit(0)
end
end
end
end
end
end,
-- @method - TestSuite:printResult()
-- @desc - prints the result of the whole test suite as well as writes
-- the XML + HTML of the testsuite output
-- @return {nil}
printResult = function(self)
local finaltime = tostring(math.floor(self.time*1000))
if string.len(finaltime) == 1 then finaltime = ' ' .. finaltime end
if string.len(finaltime) == 2 then finaltime = ' ' .. finaltime end
if string.len(finaltime) == 3 then finaltime = ' ' .. finaltime end
local xml = '<testsuites name="love.test" tests="' .. tostring(self.totals[1]) ..
'" failures="' .. tostring(self.totals[2]) ..
'" skipped="' .. tostring(self.totals[3]) ..
'" time="' .. tostring(self.time*1000) .. '">\n'
local status = '🔴'
if self.totals[2] == 0 then status = '🟢' end
local html = '<html><head><style>* { font-family: monospace; margin: 0; font-size: 11px; padding: 0; } body { margin: 50px; } h1 { padding-bottom: 10px; font-size: 13px; } h2 { padding: 20px 0 10px 0; font-size: 12px; } .summary { list-style: none; margin: 0; padding: 0; } .summary li { float: left; background: #eee; padding: 5px; margin-right: 10px; } table { background: #eee; margin-top: 10px; width: 100%; max-width: 800px; border-collapse: collapse } table thead { background: #ddd; } table th, table td { padding: 2px; } tr.red { color: red } .wrap { max-width: 800px; margin: auto; } .preview { width: 64px; height: 80px; float: left; margin-right: 10px; } .preview img { width: 100% } .preview p { text-align: center; }</style></head><body><div class="wrap"><h1>' .. status .. '&nbsp;love.test</h1><ul class="summary">'
html = html ..
'<li>🟢&nbsp;' .. tostring(self.totals[1]) .. ' Tests</li>' ..
'<li>🔴&nbsp;' .. tostring(self.totals[2]) .. ' Failures</li>' ..
'<li>🟡&nbsp;' .. tostring(self.totals[3]) .. ' Skipped</li>' ..
'<li>' .. tostring(self.time*1000) .. 'ms</li></ul><br/><br/>'
-- @TODO use mountFullPath to write output to src?
love.filesystem.createDirectory('output')
love.filesystem.write('output/' .. self.output .. '.xml', xml .. self.xml .. '</testsuites>')
love.filesystem.write('output/' .. self.output .. '.html', html .. self.html .. '</div></body></html>')
self.module:log('grey', '\nFINISHED - ' .. finaltime .. 'ms\n')
local failedcol = '\27[31m'
if self.totals[2] == 0 then failedcol = '\27[37m' end
self.module:log('green', tostring(self.totals[1]) .. ' PASSED' .. ' || ' .. failedcol .. tostring(self.totals[2]) .. ' FAILED || \27[37m' .. tostring(self.totals[3]) .. ' SKIPPED')
end
}
+24
View File
@@ -0,0 +1,24 @@
function love.conf(t)
t.console = true
t.window.name = 'love.test'
t.window.width = 256
t.window.height = 256
t.window.resizable = true
t.renderers = {"opengl"}
t.modules.audio = true
t.modules.data = true
t.modules.event = true
t.modules.filesystem = true
t.modules.font = true
t.modules.graphics = true
t.modules.image = true
t.modules.math = true
t.modules.objects = true
t.modules.physics = true
t.modules.sound = true
t.modules.system = true
t.modules.thread = true
t.modules.timer = true
t.modules.video = true
t.modules.window = true
end
+172
View File
@@ -0,0 +1,172 @@
-- & 'c:\Program Files\LOVE\love.exe' ./ --console
-- /Applications/love.app/Contents/MacOS/love ./
-- load test objs
require('classes.TestSuite')
require('classes.TestModule')
require('classes.TestMethod')
-- create testsuite obj
love.test = TestSuite:new()
-- load test scripts if module is active
if love.audio ~= nil then require('tests.audio') end
if love.data ~= nil then require('tests.data') end
if love.event ~= nil then require('tests.event') end
if love.filesystem ~= nil then require('tests.filesystem') end
if love.font ~= nil then require('tests.font') end
if love.graphics ~= nil then require('tests.graphics') end
if love.image ~= nil then require('tests.image') end
if love.math ~= nil then require('tests.math') end
if love.physics ~= nil then require('tests.physics') end
if love.sound ~= nil then require('tests.sound') end
if love.system ~= nil then require('tests.system') end
if love.thread ~= nil then require('tests.thread') end
if love.timer ~= nil then require('tests.timer') end
if love.video ~= nil then require('tests.video') end
if love.window ~= nil then require('tests.window') end
require('tests.objects')
-- love.load
-- load given arguments and run the test suite
love.load = function(args)
-- setup basic img to display
if love.window ~= nil then
love.window.setMode(256, 256, {
fullscreen = false,
resizable = true,
centered = true
})
if love.graphics ~= nil then
love.graphics.setDefaultFilter("nearest", "nearest")
love.graphics.setLineStyle('rough')
love.graphics.setLineWidth(1)
Logo = {
texture = love.graphics.newImage('resources/love.png'),
img = nil
}
Logo.img = love.graphics.newQuad(0, 0, 64, 64, Logo.texture)
end
end
-- get all args with any comma lists split out as seperate
local arglist = {}
for a=1,#args do
local splits = UtilStringSplit(args[a], '([^,]+)')
for s=1,#splits do
table.insert(arglist, splits[s])
end
end
-- convert args to the cmd to run, modules, method (if any) and disabled
local testcmd = '--runAllTests'
local module = ''
local method = ''
local modules = {
'audio', 'data', 'event', 'filesystem', 'font', 'graphics',
'image', 'math', 'objects', 'physics', 'sound', 'system',
'thread', 'timer', 'video', 'window'
}
for a=1,#arglist do
if testcmd == '--runSpecificMethod' then
if module == '' and love[ arglist[a] ] ~= nil then
module = arglist[a]
table.insert(modules, module)
end
if module ~= '' and love[module][ arglist[a] ] ~= nil and method == '' then
method = arglist[a]
end
end
if testcmd == '--runSpecificModules' then
if love[ arglist[a] ] ~= nil or arglist[a] == 'objects' then
table.insert(modules, arglist[a])
end
end
if arglist[a] == '--runSpecificMethod' then
testcmd = arglist[a]
modules = {}
end
if arglist[a] == '--runSpecificModules' then
testcmd = arglist[a]
modules = {}
end
end
-- runSpecificMethod uses the module + method given
if testcmd == '--runSpecificMethod' then
local testmodule = TestModule:new(module, method)
table.insert(love.test.modules, testmodule)
love.test.module = testmodule
love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"')
love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method
end
-- runSpecificModules runs all methods for all the modules given
if testcmd == '--runSpecificModules' then
local modulelist = {}
for m=1,#modules do
local testmodule = TestModule:new(modules[m])
table.insert(love.test.modules, testmodule)
table.insert(modulelist, modules[m])
end
love.test.module = love.test.modules[1]
love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"')
love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_')
end
-- otherwise default runs all methods for all modules
if arglist[1] == nil or arglist[1] == '' or arglist[1] == '--runAllTests' then
for m=1,#modules do
local testmodule = TestModule:new(modules[m])
table.insert(love.test.modules, testmodule)
end
love.test.module = love.test.modules[1]
love.test.module:log('grey', '--runAllTests')
love.test.output = 'lovetest_runAllTests'
end
-- invalid command
if love.test.module == nil then
print("Wrong flags used")
end
-- start first module
love.test.module:runTests()
end
-- love.update
-- run test suite logic
love.update = function(delta)
love.test:runSuite(delta)
end
-- love.draw
-- draw a little logo to the screen
love.draw = function()
love.graphics.draw(Logo.texture, Logo.img, 64, 64, 0, 2, 2)
end
-- love.quit
-- add a hook to allow test modules to fake quit
love.quit = function()
if love.test.module ~= nil and love.test.module.fakequit == true then
return true
else
return false
end
end
-- string split helper
function UtilStringSplit(str, splitter)
local splits = {}
for word in string.gmatch(str, splitter) do
table.insert(splits, word)
end
return splits
end
File diff suppressed because one or more lines are too long
+385
View File
@@ -0,0 +1,385 @@
<testsuites name="love.test" tests="157" failures="5" skipped="11" time="7341.71">
<testsuite name="love.audio" tests="26" failures="0" skipped="0" time="0.40991666666712">
<testclass classname="getActiveEffects" name="getActiveEffects" time="0.045083333333418">
</testclass>
<testclass classname="getActiveSourceCount" name="getActiveSourceCount" time="1.1385">
</testclass>
<testclass classname="getDistanceModel" name="getDistanceModel" time="0.018125000000202">
</testclass>
<testclass classname="getDopplerScale" name="getDopplerScale" time="0.012208333333374">
</testclass>
<testclass classname="getEffect" name="getEffect" time="0.035250000000042">
</testclass>
<testclass classname="getMaxSceneEffects" name="getMaxSceneEffects" time="0.0089583333331422">
</testclass>
<testclass classname="getMaxSourceEffects" name="getMaxSourceEffects" time="0.022874999999978">
</testclass>
<testclass classname="getOrientation" name="getOrientation" time="0.037541666666696">
</testclass>
<testclass classname="getPosition" name="getPosition" time="0.024500000000316">
</testclass>
<testclass classname="getRecordingDevices" name="getRecordingDevices" time="0.039250000000157">
</testclass>
<testclass classname="getVelocity" name="getVelocity" time="0.021333333333207">
</testclass>
<testclass classname="getVolume" name="getVolume" time="0.046083333333335">
</testclass>
<testclass classname="isEffectsSupported" name="isEffectsSupported" time="0.016749999999899">
</testclass>
<testclass classname="newQueueableSource" name="newQueueableSource" time="0.041958333333314">
</testclass>
<testclass classname="newSource" name="newSource" time="2.8378333333332">
</testclass>
<testclass classname="pause" name="pause" time="2.6265416666664">
</testclass>
<testclass classname="play" name="play" time="1.7924166666665">
</testclass>
<testclass classname="setDistanceModel" name="setDistanceModel" time="0.023249999999919">
</testclass>
<testclass classname="setDopplerScale" name="setDopplerScale" time="0.094375000000646">
</testclass>
<testclass classname="setEffect" name="setEffect" time="0.024166666666936">
</testclass>
<testclass classname="setMixWithSystem" name="setMixWithSystem" time="0.0052083333330621">
</testclass>
<testclass classname="setOrientation" name="setOrientation" time="0.017000000000156">
</testclass>
<testclass classname="setPosition" name="setPosition" time="0.0091666666666157">
</testclass>
<testclass classname="setVelocity" name="setVelocity" time="0.0070416666657636">
</testclass>
<testclass classname="setVolume" name="setVolume" time="0.0075833333332831">
</testclass>
<testclass classname="stop" name="stop" time="1.787666666667">
</testclass>
</testsuite>
<testsuite name="love.data" tests="7" failures="0" skipped="3" time="0.34008333333449">
<testclass classname="compress" name="compress" time="0.39495833333403">
</testclass>
<testclass classname="decode" name="decode" time="0.027791666666666">
</testclass>
<testclass classname="decompress" name="decompress" time="0.28366666666635">
</testclass>
<testclass classname="encode" name="encode" time="0.044000000000377">
</testclass>
<testclass classname="getPackedSize" name="getPackedSize" time="0.0069999999996462">
</testclass>
<testclass classname="hash" name="hash" time="0.12045833333341">
</testclass>
<testclass classname="newByteData" name="newByteData" time="0.021916666666844">
</testclass>
<testclass classname="newDataView" name="newDataView" time="0.025416666666889">
</testclass>
<testclass classname="pack" name="pack" time="0.0070833333332132">
</testclass>
<testclass classname="unpack" name="unpack" time="0.0091250000000542">
</testclass>
</testsuite>
<testsuite name="love.event" tests="4" failures="0" skipped="2" time="0.47999999999884">
<testclass classname="clear" name="clear" time="0.028666666666233">
</testclass>
<testclass classname="poll" name="poll" time="0.022374999999464">
</testclass>
<testclass classname="pump" name="pump" time="0.0079583333327804">
</testclass>
<testclass classname="push" name="push" time="0.022500000000036">
</testclass>
<testclass classname="quit" name="quit" time="0.014125000000753">
</testclass>
<testclass classname="wait" name="wait" time="0.0069166666669673">
</testclass>
</testsuite>
<testsuite name="love.filesystem" tests="26" failures="1" skipped="2" time="1.0150000000023">
<testclass classname="append" name="append" time="1.3135833333333">
</testclass>
<testclass classname="areSymlinksEnabled" name="areSymlinksEnabled" time="0.01433333333356">
</testclass>
<testclass classname="createDirectory" name="createDirectory" time="0.39929166666663">
</testclass>
<testclass classname="getAppdataDirectory" name="getAppdataDirectory" time="0.014166666668203">
</testclass>
<testclass classname="getCRequirePath" name="getCRequirePath" time="0.015749999999315">
</testclass>
<testclass classname="getDirectoryItems" name="getDirectoryItems" time="1.0962083333332">
</testclass>
<testclass classname="getIdentity" name="getIdentity" time="0.10579166666691">
</testclass>
<testclass classname="getInfo" name="getInfo" time="0.9892916666665">
</testclass>
<testclass classname="getRealDirectory" name="getRealDirectory" time="0.98024999999957">
</testclass>
<testclass classname="getRequirePath" name="getRequirePath" time="0.097583333333873">
</testclass>
<testclass classname="getSaveDirectory" name="getSaveDirectory" time="0.01891666666598">
</testclass>
<testclass classname="getSource" name="getSource" time="0.020666666666003">
</testclass>
<testclass classname="getSourceBaseDirectory" name="getSourceBaseDirectory" time="0.015083333334331">
</testclass>
<testclass classname="getUserDirectory" name="getUserDirectory" time="0.043666666666553">
</testclass>
<testclass classname="getWorkingDirectory" name="getWorkingDirectory" time="0.018791666667184">
</testclass>
<testclass classname="isFused" name="isFused" time="0.017999999998963">
</testclass>
<testclass classname="lines" name="lines" time="13.630166666666">
</testclass>
<testclass classname="load" name="load" time="7.9870833333331">
</testclass>
<testclass classname="mount" name="mount" time="0.48216666666789">
</testclass>
<testclass classname="newFile" name="newFile" time="0.37395833333331">
<failure message="assert #2 [check file made] avoiding 'nil' got 'nil'"></failure>
</testclass>
<testclass classname="newFileData" name="newFileData" time="0.030666666666512">
</testclass>
<testclass classname="read" name="read" time="0.19545833333368">
</testclass>
<testclass classname="remove" name="remove" time="0.81487500000055">
</testclass>
<testclass classname="setCRequirePath" name="setCRequirePath" time="0.017416666667103">
</testclass>
<testclass classname="setIdentity" name="setIdentity" time="0.086666666666346">
</testclass>
<testclass classname="setRequirePath" name="setRequirePath" time="0.014500000001583">
</testclass>
<testclass classname="setSource" name="setSource" time="0.0082916666652721">
</testclass>
<testclass classname="unmount" name="unmount" time="1.1363333333341">
</testclass>
<testclass classname="write" name="write" time="1.0965416666666">
</testclass>
</testsuite>
<testsuite name="love.font" tests="4" failures="0" skipped="1" time="0.11233333333444">
<testclass classname="newBMFontRasterizer" name="newBMFontRasterizer" time="0.007625000002065">
</testclass>
<testclass classname="newGlyphData" name="newGlyphData" time="0.28787499999972">
</testclass>
<testclass classname="newImageRasterizer" name="newImageRasterizer" time="0.22408333333424">
</testclass>
<testclass classname="newRasterizer" name="newRasterizer" time="0.18954166666596">
</testclass>
<testclass classname="newTrueTypeRasterizer" name="newTrueTypeRasterizer" time="0.18991666666501">
</testclass>
</testsuite>
<testsuite name="love.graphics" tests="0" failures="1" skipped="0" time="0.94387500000009">
<testclass classname="rectangle" name="rectangle" time="3.7313333333344">
<failure message="assert #2 [check 0x,0y G] expected '1' got '0'"></failure>
</testclass>
</testsuite>
<testsuite name="love.image" tests="3" failures="0" skipped="0" time="1.2476249999999">
<testclass classname="isCompressed" name="isCompressed" time="0.21679166666644">
</testclass>
<testclass classname="newCompressedData" name="newCompressedData" time="0.19920833333309">
</testclass>
<testclass classname="newImageData" name="newImageData" time="0.40049999999958">
</testclass>
</testsuite>
<testsuite name="love.math" tests="16" failures="0" skipped="0" time="0.062999999998231">
<testclass classname="colorFromBytes" name="colorFromBytes" time="0.29325000000036">
</testclass>
<testclass classname="colorToBytes" name="colorToBytes" time="0.27899999999903">
</testclass>
<testclass classname="gammaToLinear" name="gammaToLinear" time="0.021624999998693">
</testclass>
<testclass classname="getRandomSeed" name="getRandomSeed" time="0.014708333333502">
</testclass>
<testclass classname="getRandomState" name="getRandomState" time="0.071791666666599">
</testclass>
<testclass classname="isConvex" name="isConvex" time="0.056666666665706">
</testclass>
<testclass classname="linearToGamma" name="linearToGamma" time="0.01791666666584">
</testclass>
<testclass classname="newBezierCurve" name="newBezierCurve" time="0.053125000000875">
</testclass>
<testclass classname="newRandomGenerator" name="newRandomGenerator" time="0.019874999999558">
</testclass>
<testclass classname="newTransform" name="newTransform" time="0.02287499999909">
</testclass>
<testclass classname="noise" name="noise" time="0.076916666666094">
</testclass>
<testclass classname="random" name="random" time="0.17783333333377">
</testclass>
<testclass classname="randomNormal" name="randomNormal" time="0.020458333334972">
</testclass>
<testclass classname="setRandomSeed" name="setRandomSeed" time="0.019541666667067">
</testclass>
<testclass classname="setRandomState" name="setRandomState" time="0.053750000001074">
</testclass>
<testclass classname="triangulate" name="triangulate" time="0.023874999998341">
</testclass>
</testsuite>
<testsuite name="love.objects" tests="0" failures="0" skipped="0" time="1.6546249999983">
</testsuite>
<testsuite name="love.physics" tests="21" failures="1" skipped="0" time="0.014583333332624">
<testclass classname="getDistance" name="getDistance" time="0.075333333334981">
</testclass>
<testclass classname="getMeter" name="getMeter" time="0.015125000000893">
</testclass>
<testclass classname="newBody" name="newBody" time="0.03362500000037">
</testclass>
<testclass classname="newChainShape" name="newChainShape" time="0.028624999998783">
</testclass>
<testclass classname="newCircleShape" name="newCircleShape" time="0.020624999999441">
</testclass>
<testclass classname="newDistanceJoint" name="newDistanceJoint" time="0.037833333333737">
</testclass>
<testclass classname="newEdgeShape" name="newEdgeShape" time="0.020624999999441">
</testclass>
<testclass classname="newFixture" name="newFixture" time="0.077750000000876">
</testclass>
<testclass classname="newFrictionJoint" name="newFrictionJoint" time="0.031708333333214">
</testclass>
<testclass classname="newGearJoint" name="newGearJoint" time="0.12670833333139">
<failure message="test tests/physics.lua:134: Box2D assertion failed: m_bodyA->m_type == b2_dynamicBody"></failure>
</testclass>
<testclass classname="newMotorJoint" name="newMotorJoint" time="0.092416666667816">
</testclass>
<testclass classname="newMouseJoint" name="newMouseJoint" time="0.050208333334467">
</testclass>
<testclass classname="newPolygonShape" name="newPolygonShape" time="0.025333333333322">
</testclass>
<testclass classname="newPrismaticJoint" name="newPrismaticJoint" time="0.034124999999108">
</testclass>
<testclass classname="newPulleyJoint" name="newPulleyJoint" time="0.035041666665236">
</testclass>
<testclass classname="newRectangleShape" name="newRectangleShape" time="0.077833333332222">
</testclass>
<testclass classname="newRevoluteJoint" name="newRevoluteJoint" time="0.040416666667653">
</testclass>
<testclass classname="newRopeJoint" name="newRopeJoint" time="0.03037500000147">
</testclass>
<testclass classname="newWeldJoint" name="newWeldJoint" time="0.074916666664038">
</testclass>
<testclass classname="newWheelJoint" name="newWheelJoint" time="0.1102083333322">
</testclass>
<testclass classname="newWorld" name="newWorld" time="0.075416666666328">
</testclass>
<testclass classname="setMeter" name="setMeter" time="0.031208333336252">
</testclass>
</testsuite>
<testsuite name="love.sound" tests="2" failures="0" skipped="0" time="0.93524999999842">
<testclass classname="newDecoder" name="newDecoder" time="0.31383333333501">
</testclass>
<testclass classname="newSoundData" name="newSoundData" time="1.1787083333292">
</testclass>
</testsuite>
<testsuite name="love.system" tests="6" failures="0" skipped="2" time="1.3057500000059">
<testclass classname="getClipboardText" name="getClipboardText" time="1.6217916666665">
</testclass>
<testclass classname="getOS" name="getOS" time="0.034041666669538">
</testclass>
<testclass classname="getPowerInfo" name="getPowerInfo" time="0.080041666665309">
</testclass>
<testclass classname="getProcessorCount" name="getProcessorCount" time="0.017791666669709">
</testclass>
<testclass classname="hasBackgroundMusic" name="hasBackgroundMusic" time="0.086708333334684">
</testclass>
<testclass classname="openURL" name="openURL" time="0.016333333334728">
</testclass>
<testclass classname="setClipboardText" name="setClipboardText" time="0.59291666666716">
</testclass>
<testclass classname="vibrate" name="vibrate" time="0.0090416666651549">
</testclass>
</testsuite>
<testsuite name="love.thread" tests="3" failures="0" skipped="0" time="0.96195833333323">
<testclass classname="getChannel" name="getChannel" time="0.47320833333231">
</testclass>
<testclass classname="newChannel" name="newChannel" time="0.028374999999414">
</testclass>
<testclass classname="newThread" name="newThread" time="0.2556250000012">
</testclass>
</testsuite>
<testsuite name="love.timer" tests="6" failures="0" skipped="0" time="3713.5796666667">
<testclass classname="getAverageDelta" name="getAverageDelta" time="0.023208333331581">
</testclass>
<testclass classname="getDelta" name="getDelta" time="0.015708333332753">
</testclass>
<testclass classname="getFPS" name="getFPS" time="0.011125000000334">
</testclass>
<testclass classname="getTime" name="getTime" time="1001.1531666667">
</testclass>
<testclass classname="sleep" name="sleep" time="1000.4330833333">
</testclass>
<testclass classname="step" name="step" time="0.032958333331834">
</testclass>
</testsuite>
<testsuite name="love.video" tests="1" failures="0" skipped="0" time="0.67754166666772">
<testclass classname="newVideoStream" name="newVideoStream" time="3.4201249999981">
</testclass>
</testsuite>
<testsuite name="love.window" tests="32" failures="2" skipped="1" time="7985.3964583333">
<testclass classname="close" name="close" time="11.641583333336">
</testclass>
<testclass classname="fromPixels" name="fromPixels" time="0.015333333330148">
</testclass>
<testclass classname="getDPIScale" name="getDPIScale" time="0.014499999998918">
</testclass>
<testclass classname="getDesktopDimensions" name="getDesktopDimensions" time="0.015083333330779">
</testclass>
<testclass classname="getDisplayCount" name="getDisplayCount" time="0.010291666665552">
</testclass>
<testclass classname="getDisplayName" name="getDisplayName" time="0.014875000001524">
</testclass>
<testclass classname="getDisplayOrientation" name="getDisplayOrientation" time="0.016250000001605">
</testclass>
<testclass classname="getFullscreen" name="getFullscreen" time="1305.7451666667">
</testclass>
<testclass classname="getFullscreenModes" name="getFullscreenModes" time="0.48033333332853">
</testclass>
<testclass classname="getIcon" name="getIcon" time="2.0577083333322">
</testclass>
<testclass classname="getMode" name="getMode" time="0.10416666667012">
</testclass>
<testclass classname="getPosition" name="getPosition" time="4.9660833333327">
</testclass>
<testclass classname="getSafeArea" name="getSafeArea" time="0.067875000002715">
</testclass>
<testclass classname="getTitle" name="getTitle" time="0.55745833333276">
</testclass>
<testclass classname="getVSync" name="getVSync" time="0.095124999997864">
</testclass>
<testclass classname="hasFocus" name="hasFocus" time="0.055624999998116">
</testclass>
<testclass classname="hasMouseFocus" name="hasMouseFocus" time="0.022541666666598">
</testclass>
<testclass classname="isDisplaySleepEnabled" name="isDisplaySleepEnabled" time="0.14775000000355">
</testclass>
<testclass classname="isMaximized" name="isMaximized" time="642.02083333333">
<failure message="assert #2 [check window not maximized] expected 'true' got 'false'"></failure>
</testclass>
<testclass classname="isMinimized" name="isMinimized" time="641.41475">
</testclass>
<testclass classname="isOpen" name="isOpen" time="25.519625000001">
</testclass>
<testclass classname="isVisible" name="isVisible" time="18.191791666666">
</testclass>
<testclass classname="maximize" name="maximize" time="0.23570833333508">
<failure message="assert #1 [check window maximized] expected 'true' got 'false'"></failure>
</testclass>
<testclass classname="minimize" name="minimize" time="640.26066666666">
</testclass>
<testclass classname="restore" name="restore" time="643.01916666667">
</testclass>
<testclass classname="setDisplaySleepEnabled" name="setDisplaySleepEnabled" time="0.59508333333014">
</testclass>
<testclass classname="setFullscreen" name="setFullscreen" time="1329.778375">
</testclass>
<testclass classname="setIcon" name="setIcon" time="2.0223750000028">
</testclass>
<testclass classname="setMode" name="setMode" time="4.5707499999992">
</testclass>
<testclass classname="setPosition" name="setPosition" time="0.16512499999521">
</testclass>
<testclass classname="setTitle" name="setTitle" time="0.47262500000045">
</testclass>
<testclass classname="setVSync" name="setVSync" time="0.022583333333159">
</testclass>
<testclass classname="showMessageBox" name="showMessageBox" time="0.068958333333313">
</testclass>
<testclass classname="toPixels" name="toPixels" time="0.067666666666355">
</testclass>
<testclass classname="updateMode" name="updateMode" time="6.8227083333348">
</testclass>
</testsuite>
</testsuites>
+139
View File
@@ -0,0 +1,139 @@
# löve.test
Basic testing suite for the löve APIs, based off of [this issue](https://github.com/love2d/love/issues/1745)
Currently written for löve 12
---
## Primary Goals
- [x] Simple pass/fail tests in Lua with minimal setup
- [x] Ability to run all tests with a simple command.
- [x] Ability to see how many tests are passing/failing
- [x] No platform-specific dependencies / scripts
- [x] Ability to run a subset of tests
- [x] Ability to easily run an individual test.
---
## Running Tests
The initial pass is to keep things as simple as possible, and just run all the tests inside Löve to match how they'd be used by developers in-engine.
To run the tests, download the repo and then run the main.lua as you would a löve game, i.e:
WINDOWS: `& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER --console`
MACOS: `/Applications/love.app/Contents/MacOS/love PATH_TO_TESTING_FOLDER`
By default all tests will be run for all modules.
If you want to specify a module you can add:
`--runSpecificModules filesystem`
For multiple modules, provide a comma seperate list:
`--runSpecificModules filesystem,audio,data"`
If you want to specify only 1 specific method only you can use:
`--runSpecificMethod filesystem write`
All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level.
An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in your save directory, along with a `HTML` file with a summary of all tests (including visuals for love.graphics tests).
> Note that this can only be viewed properly locally as the generated images are written to the save directory.
> An example of both types of output can be found in the `/output` folder
---
## Architecture
Each method has it's own test method written in `/tests` under the matching module name.
When you run the tests, a single TestSuite object is created which handles the progress + totals for all the tests.
Each module has a TestModule object created, and each test method has a TestMethod object created which keeps track of assertions for that method. You can currently do the following assertions:
- **assertEquals**(expected, actual)
- **assertNotEquals**(expected, actual)
- **assertRange**(actual, min, max)
- **assertMatch**({option1, option2, option3 ...}, actual)
- **assertGreaterEqual**(expected, actual)
- **assertLessEqual**(expected, actual)
- **assertObject**(table)
Example test method:
```lua
-- love.filesystem.read test method
-- all methods should be put under love.test.MODULE.METHOD, matching the API
love.test.filesystem.read = function(test)
-- setup any data needed then run any asserts using the passed test object
local content, size = love.filesystem.read('resources/test.txt')
test:assertNotEquals(nil, content, 'check not nil')
test:assertEquals('helloworld', content, 'check content match')
test:assertEquals(10, size, 'check size match')
content, size = love.filesystem.read('resources/test.txt', 5)
test:assertNotEquals(nil, content, 'check not nil')
test:assertEquals('hello', content, 'check content match')
test:assertEquals(5, size, 'check size match')
-- no need to return anything just cleanup any objs if needed
end
```
After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any)
For sanity-checking, if it's currently not covered or we're not sure how to test yet we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the tests without it affected the pass/fail totals
---
## Coverage
This is the status of all module tests currently.
"objects" is a special module to cover any object specific tests, i.e. testing a File object functions as expected
```lua
-- [x] audio 26 PASSED | 0 FAILED | 0 SKIPPED
-- [x] data 7 PASSED | 0 FAILED | 3 SKIPPED [SEE BELOW]
-- [x] event 4 PASSED | 0 FAILED | 2 SKIPPED [SEE BELOW]
-- [x] filesystem 26 PASSED | 1 FAILED | 2 SKIPPED [SEE BELOW]
-- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW]
-- [ ] graphics STILL TO BE DONE
-- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED
-- [x] math 16 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW]
-- [x] physics 21 PASSED | 1 FAILED | 0 SKIPPED [SEE BELOW]
-- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED
-- [x] system 7 PASSED | 0 FAILED | 1 SKIPPED
-- [ ] thread 3 PASSED | 0 FAILED | 0 SKIPPED
-- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW]
-- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED
-- [x] window 32 PASSED | 2 FAILED | 1 SKIPPED [SEE BELOW]
-- [ ] objects STILL TO BE DONE
```
The following modules are not covered as we can't really emulate input nicely:
`joystick`, `keyboard`, `mouse`, and `touch`
---
## Todo / Skipped
Modules with some small bits needed or needing sense checking:
- **love.data** - packing methods need writing cos i dont really get what they are
- **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check
- **love.filesystem** - getSource() / setSource() dont think we can test
- **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected
- **love.timer** - couple methods I don't know if you could reliably test specific values
- **love.image** - ideally isCompressed should have an example of all compressed files love can take
- **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back
- **love.window** - couple stuff just nil checked as I think it's hardware dependent, needs checking
Modules still to be completed or barely started
- **love.graphics** - done 1 as an example of how we can test the drawing but not really started
- **love.objects** - done 1 as an example of how we can test objs with mini scenarios
---
## Failures
- **love.window.isMaximized()** - returns false after calling love.window.maximize?
- **love.window.maximize()** - same as above
- **love.filesystem.newFile()** - something changed in 12
- **love.physics.newGearJoint()** - something changed in 12
---
## Stretch Goals
- [ ] Tests can compare visual results to a reference image
- [ ] Ability to see all visual results at a glance
- [ ] Automatic testing that happens after every commit
- [ ] Ability to test loading different combinations of modules
- [ ] Performance tests
There is some unused code in the Test.lua class to add preview vs actual images to the HTML output
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.
+1
View File
@@ -0,0 +1 @@
helloworld
Binary file not shown.
+296
View File
@@ -0,0 +1,296 @@
-- love.audio
-- love.audio.getActiveEffects
love.test.audio.getActiveEffects = function(test)
-- tests
test:assertNotEquals(nil, love.audio.getActiveEffects(), 'check not nil')
test:assertEquals(0, #love.audio.getActiveEffects(), 'check no effects running')
love.audio.setEffect('testeffect', {
type = 'chorus',
volume = 10
})
test:assertEquals(1, #love.audio.getActiveEffects(), 'check 1 effect running')
test:assertEquals('testeffect', love.audio.getActiveEffects()[1], 'check effect details')
end
-- love.audio.getActiveSourceCount
love.test.audio.getActiveSourceCount = function(test)
-- tests
test:assertNotEquals(nil, love.audio.getActiveSourceCount(), 'check not nil')
test:assertEquals(0, love.audio.getActiveSourceCount(), 'check 0 by default')
local testsource = love.audio.newSource('resources/click.ogg', 'static')
test:assertEquals(0, love.audio.getActiveSourceCount(), 'check not active')
love.audio.play(testsource)
test:assertEquals(1, love.audio.getActiveSourceCount(), 'check now active')
love.audio.pause()
testsource:release()
end
-- love.audio.getDistanceModel
love.test.audio.getDistanceModel = function(test)
-- tests
test:assertNotEquals(nil, love.audio.getDistanceModel(), 'check not nil')
test:assertEquals('inverseclamped', love.audio.getDistanceModel(), 'check default value')
love.audio.setDistanceModel('inverse')
test:assertEquals('inverse', love.audio.getDistanceModel(), 'check setting model')
end
-- love.audio.getDopplerScale
love.test.audio.getDopplerScale = function(test)
test:assertEquals(1, love.audio.getDopplerScale(), 'check default 1')
love.audio.setDopplerScale(0)
test:assertEquals(0, love.audio.getDopplerScale(), 'check setting to 0')
love.audio.setDopplerScale(1)
end
-- love.audio.getEffect
love.test.audio.getEffect = function(test)
-- setup
love.audio.setEffect('testeffect', {
type = 'chorus',
volume = 10
})
-- tests
test:assertEquals(nil, love.audio.getEffect('madeupname'), 'check wrong name')
test:assertNotEquals(nil, love.audio.getEffect('testeffect'), 'check not nil')
test:assertEquals('chorus', love.audio.getEffect('testeffect').type, 'check effect type')
test:assertEquals(10, love.audio.getEffect('testeffect').volume, 'check effect volume')
end
-- love.audio.getMaxSceneEffects
-- @NOTE feel like this is platform specific number so best we can do is a nil?
love.test.audio.getMaxSceneEffects = function(test)
test:assertNotEquals(nil, love.audio.getMaxSceneEffects(), 'check not nil')
end
-- love.audio.getMaxSourceEffects
-- @NOTE feel like this is platform specific number so best we can do is a nil?
love.test.audio.getMaxSourceEffects = function(test)
test:assertNotEquals(nil, love.audio.getMaxSourceEffects(), 'check not nil')
end
-- love.audio.getOrientation
-- @NOTE is there an expected default listener pos?
love.test.audio.getOrientation = function(test)
-- setup
love.audio.setOrientation(1, 2, 3, 4, 5, 6)
-- tests
local fx, fy, fz, ux, uy, uz = love.audio.getOrientation()
test:assertEquals(1, fx, 'check fx orientation')
test:assertEquals(2, fy, 'check fy orientation')
test:assertEquals(3, fz, 'check fz orientation')
test:assertEquals(4, ux, 'check ux orientation')
test:assertEquals(5, uy, 'check uy orientation')
test:assertEquals(6, uz, 'check uz orientation')
end
-- love.audio.getPosition
-- @NOTE is there an expected default listener pos?
love.test.audio.getPosition = function(test)
-- setup
love.audio.setPosition(1, 2, 3)
-- tests
local x, y, z = love.audio.getPosition()
test:assertEquals(1, x, 'check x position')
test:assertEquals(2, y, 'check y position')
test:assertEquals(3, z, 'check z position')
end
-- love.audio.getRecordingDevices
love.test.audio.getRecordingDevices = function(test)
test:assertNotEquals(nil, love.audio.getRecordingDevices(), 'check not nil')
end
-- love.audio.getVelocity
love.test.audio.getVelocity = function(test)
-- setup
love.audio.setVelocity(1, 2, 3)
-- tests
local x, y, z = love.audio.getVelocity()
test:assertEquals(1, x, 'check x velocity')
test:assertEquals(2, y, 'check y velocity')
test:assertEquals(3, z, 'check z velocity')
end
-- love.audio.getVolume
love.test.audio.getVolume = function(test)
-- setup
love.audio.setVolume(0.5)
-- tests
test:assertNotEquals(nil, love.audio.getVolume(), 'check not nil')
test:assertEquals(0.5, love.audio.getVolume(), 'check matches set')
end
-- love.audio.isEffectsSupported
love.test.audio.isEffectsSupported = function(test)
test:assertNotEquals(nil, love.audio.isEffectsSupported(), 'check not nil')
end
-- love.audio.newQueueableSource
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.audio.newQueueableSource = function(test)
local source = love.audio.newQueueableSource(32, 8, 1, 8)
test:assertObject(source)
source:release()
end
-- love.audio.newSource
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.audio.newSource = function(test)
-- setup
local source1 = love.audio.newSource('resources/click.ogg', 'static')
local source2 = love.audio.newSource('resources/click.ogg', 'stream')
-- tests
test:assertObject(source1)
test:assertObject(source2)
-- cleanup
source1:release()
source2:release()
end
-- love.audio.pause
love.test.audio.pause = function(test)
-- tests
local nopauses = love.audio.pause()
test:assertNotEquals(nil, nopauses, 'check not nil')
test:assertEquals(0, #nopauses, 'check nothing paused')
local source = love.audio.newSource('resources/click.ogg', 'static')
love.audio.play(source)
local onepause = love.audio.pause()
test:assertEquals(1, #onepause, 'check 1 paused')
source:release()
end
-- love.audio.play
love.test.audio.play = function(test)
-- setup
local source = love.audio.newSource('resources/click.ogg', 'static')
-- tests
love.audio.play(source)
test:assertEquals(true, source:isPlaying(), 'check something playing')
love.audio.pause()
source:release()
end
-- love.audio.setDistanceModel
love.test.audio.setDistanceModel = function(test)
-- tests
local distancemodel = {
'none', 'inverse', 'inverseclamped', 'linear', 'linearclamped',
'exponent', 'exponentclamped'
}
for d=1,#distancemodel do
love.audio.setDistanceModel(distancemodel[d])
test:assertEquals(distancemodel[d], love.audio.getDistanceModel(), 'check model set to ' .. distancemodel[d])
end
end
-- love.audio.setDopplerScale
love.test.audio.setDopplerScale = function(test)
-- tests
love.audio.setDopplerScale(0)
test:assertEquals(0, love.audio.getDopplerScale(), 'check set to 0')
love.audio.setDopplerScale(1)
test:assertEquals(1, love.audio.getDopplerScale(), 'check set to 1')
end
-- love.audio.setEffect
love.test.audio.setEffect = function(test)
-- tests
local effect = love.audio.setEffect('testeffect', {
type = 'chorus',
volume = 10
})
test:assertEquals(true, effect, 'check effect created')
local settings = love.audio.getEffect('testeffect')
test:assertEquals('chorus', settings.type, 'check effect type')
test:assertEquals(10, settings.volume, 'check effect volume')
end
-- love.audio.setMixWithSystem
love.test.audio.setMixWithSystem = function(test)
test:assertNotEquals(nil, love.audio.setMixWithSystem(true), 'check not nil')
end
-- love.audio.setOrientation
love.test.audio.setOrientation = function(test)
-- setup
love.audio.setOrientation(1, 2, 3, 4, 5, 6)
-- tests
local fx, fy, fz, ux, uy, uz = love.audio.getOrientation()
test:assertEquals(1, fx, 'check fx orientation')
test:assertEquals(2, fy, 'check fy orientation')
test:assertEquals(3, fz, 'check fz orientation')
test:assertEquals(4, ux, 'check ux orientation')
test:assertEquals(5, uy, 'check uy orientation')
test:assertEquals(6, uz, 'check uz orientation')
end
-- love.audio.setPosition
love.test.audio.setPosition = function(test)
-- setup
love.audio.setPosition(1, 2, 3)
-- tests
local x, y, z = love.audio.getPosition()
test:assertEquals(1, x, 'check x position')
test:assertEquals(2, y, 'check y position')
test:assertEquals(3, z, 'check z position')
end
-- love.audio.setVelocity
love.test.audio.setVelocity = function(test)
-- setup
love.audio.setVelocity(1, 2, 3)
-- tests
local x, y, z = love.audio.getVelocity()
test:assertEquals(1, x, 'check x velocity')
test:assertEquals(2, y, 'check y velocity')
test:assertEquals(3, z, 'check z velocity')
end
-- love.audio.setVolume
love.test.audio.setVolume = function(test)
-- setup
love.audio.setVolume(0.5)
-- tests
test:assertNotEquals(nil, love.audio.getVolume(), 'check not nil')
test:assertEquals(0.5, love.audio.getVolume(), 'check set to 0.5')
end
-- love.audio.stop
love.test.audio.stop = function(test)
-- setup
local source = love.audio.newSource('resources/click.ogg', 'static')
love.audio.play(source)
-- tests
test:assertEquals(true, source:isPlaying(), 'check is playing')
love.audio.stop()
test:assertEquals(false, source:isPlaying(), 'check stopped playing')
source:release()
end
+182
View File
@@ -0,0 +1,182 @@
-- love.data
-- love.data.compress
love.test.data.compress = function(test)
-- here just testing each combo 'works', in decompress's test method
-- we actually check the compress + decompress give the right value back
-- setup
local compressions = {
{ love.data.compress('string', 'lz4', 'helloworld', -1), 'string'},
{ love.data.compress('string', 'lz4', 'helloworld', 0), 'string'},
{ love.data.compress('string', 'lz4', 'helloworld', 9), 'string'},
{ love.data.compress('string', 'zlib', 'helloworld', -1), 'string'},
{ love.data.compress('string', 'zlib', 'helloworld', 0), 'string'},
{ love.data.compress('string', 'zlib', 'helloworld', 9), 'string'},
{ love.data.compress('string', 'gzip', 'helloworld', -1), 'string'},
{ love.data.compress('string', 'gzip', 'helloworld', 0), 'string'},
{ love.data.compress('string', 'gzip', 'helloworld', 9), 'string'},
{ love.data.compress('data', 'lz4', 'helloworld', -1), 'userdata'},
{ love.data.compress('data', 'lz4', 'helloworld', 0), 'userdata'},
{ love.data.compress('data', 'lz4', 'helloworld', 9), 'userdata'},
{ love.data.compress('data', 'zlib', 'helloworld', -1), 'userdata'},
{ love.data.compress('data', 'zlib', 'helloworld', 0), 'userdata'},
{ love.data.compress('data', 'zlib', 'helloworld', 9), 'userdata'},
{ love.data.compress('data', 'gzip', 'helloworld', -1), 'userdata'},
{ love.data.compress('data', 'gzip', 'helloworld', 0), 'userdata'},
{ love.data.compress('data', 'gzip', 'helloworld', 9), 'userdata'}
}
-- tests
for c=1,#compressions do
test:assertNotEquals(nil, compressions[c][1], 'check not nil')
-- sense check return type and make sure bytedata returns are an object
test:assertEquals(compressions[c][2], type(compressions[c][1]), 'check is userdata')
if compressions[c][2] == 'userdata' then
test:assertNotEquals(nil, compressions[c][1]:type(), 'check has :type()')
end
end
end
-- love.data.decode
love.test.data.decode = function(test)
-- setup
local str1 = love.data.encode('string', 'base64', 'helloworld', 0)
local str2 = love.data.encode('string', 'hex', 'helloworld')
local str3 = love.data.encode('data', 'base64', 'helloworld', 0)
local str4 = love.data.encode('data', 'hex', 'helloworld')
-- tests
test:assertEquals('helloworld', love.data.decode('string', 'base64', str1), 'check string base64 decode')
test:assertEquals('helloworld', love.data.decode('string', 'hex', str2), 'check string hex decode')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decode('data', 'base64', str3):getString(), 'check data base64 decode')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decode('data', 'hex', str4):getString(), 'check data hex decode')
end
-- love.data.decompress
love.test.data.decompress = function(test)
-- setup
local str1 = love.data.compress('string', 'lz4', 'helloworld', -1)
local str2 = love.data.compress('string', 'lz4', 'helloworld', 0)
local str3 = love.data.compress('string', 'lz4', 'helloworld', 9)
local str4 = love.data.compress('string', 'zlib', 'helloworld', -1)
local str5 = love.data.compress('string', 'zlib', 'helloworld', 0)
local str6 = love.data.compress('string', 'zlib', 'helloworld', 9)
local str7 = love.data.compress('string', 'gzip', 'helloworld', -1)
local str8 = love.data.compress('string', 'gzip', 'helloworld', 0)
local str9 = love.data.compress('string', 'gzip', 'helloworld', 9)
local str10 = love.data.compress('data', 'lz4', 'helloworld', -1)
local str11 = love.data.compress('data', 'lz4', 'helloworld', 0)
local str12 = love.data.compress('data', 'lz4', 'helloworld', 9)
local str13 = love.data.compress('data', 'zlib', 'helloworld', -1)
local str14 = love.data.compress('data', 'zlib', 'helloworld', 0)
local str15 = love.data.compress('data', 'zlib', 'helloworld', 9)
local str16 = love.data.compress('data', 'gzip', 'helloworld', -1)
local str17 = love.data.compress('data', 'gzip', 'helloworld', 0)
local str18 = love.data.compress('data', 'gzip', 'helloworld', 9)
-- tests
test:assertEquals('helloworld', love.data.decompress('string', 'lz4', str1), 'check string lz4 decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'lz4', str2), 'check string lz4 decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'lz4', str3), 'check string lz4 decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'zlib', str4), 'check string zlib decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'zlib', str5), 'check string zlib decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'zlib', str6), 'check string zlib decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'gzip', str7), 'check string glib decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'gzip', str8), 'check string glib decompress')
test:assertEquals('helloworld', love.data.decompress('string', 'gzip', str9), 'check string glib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'lz4', str10):getString(), 'check data lz4 decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'lz4', str11):getString(), 'check data lz4 decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'lz4', str12):getString(), 'check data lz4 decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'zlib', str13):getString(), 'check data zlib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'zlib', str14):getString(), 'check data zlib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'zlib', str15):getString(), 'check data zlib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'gzip', str16):getString(), 'check data glib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'gzip', str17):getString(), 'check data glib decompress')
test:assertEquals(love.data.newByteData('helloworld'):getString(), love.data.decompress('data', 'gzip', str18):getString(), 'check data glib decompress')
end
-- love.data.encode
love.test.data.encode = function(test)
-- here just testing each combo 'works', in decode's test method
-- we actually check the encode + decode give the right value back
-- setup
local encodes = {
{ love.data.encode('string', 'base64', 'helloworld', 0), 'string'},
{ love.data.encode('string', 'base64', 'helloworld', 2), 'string'},
{ love.data.encode('string', 'hex', 'helloworld'), 'string'},
{ love.data.encode('data', 'base64', 'helloworld', 0), 'userdata'},
{ love.data.encode('data', 'base64', 'helloworld', 2), 'userdata'},
{ love.data.encode('data', 'hex', 'helloworld'), 'userdata'}
}
-- tests
for e=1,#encodes do
test:assertNotEquals(nil, encodes[e][1], 'check not nil')
-- sense check return type and make sure bytedata returns are an object
test:assertEquals(encodes[e][2], type(encodes[e][1]), 'check is usedata')
if encodes[e][2] == 'userdata' then
test:assertNotEquals(nil, encodes[e][1]:type(), 'check has :type()')
end
end
end
-- love.data.getPackedSize
-- @NOTE I dont really get the packing types of lua so best someone else writes this one
love.test.data.getPackedSize = function(test)
test:skipTest('dont understand lua packing types')
end
-- love.data.hash
love.test.data.hash = function(test)
-- setup
local str1 = love.data.hash('md5', 'helloworld')
local str2 = love.data.hash('sha1', 'helloworld')
local str3 = love.data.hash('sha224', 'helloworld')
local str4 = love.data.hash('sha256', 'helloworld')
local str5 = love.data.hash('sha384', 'helloworld')
local str6 = love.data.hash('sha512', 'helloworld')
-- tests
test:assertEquals('fc5e038d38a57032085441e7fe7010b0', love.data.encode("string", "hex", str1), 'check md5 encode')
test:assertEquals('6adfb183a4a2c94a2f92dab5ade762a47889a5a1', love.data.encode("string", "hex", str2), 'check sha1 encode')
test:assertEquals('b033d770602994efa135c5248af300d81567ad5b59cec4bccbf15bcc', love.data.encode("string", "hex", str3), 'check sha224 encode')
test:assertEquals('936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af', love.data.encode("string", "hex", str4), 'check sha256 encode')
test:assertEquals('97982a5b1414b9078103a1c008c4e3526c27b41cdbcf80790560a40f2a9bf2ed4427ab1428789915ed4b3dc07c454bd9', love.data.encode("string", "hex", str5), 'check sha384 encode')
test:assertEquals('1594244d52f2d8c12b142bb61f47bc2eaf503d6d9ca8480cae9fcf112f66e4967dc5e8fa98285e36db8af1b8ffa8b84cb15e0fbcf836c3deb803c13f37659a60', love.data.encode("string", "hex", str6), 'check sha512 encode')
end
-- love.data.newByteData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.data.newByteData = function(test)
-- setup
local bytedata = love.data.newByteData('helloworld')
-- tests
test:assertObject(bytedata)
end
-- love.data.newDataView
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.data.newDataView = function(test)
-- setup
local dataview = love.data.newDataView(love.data.newByteData('helloworld'), 0, 10)
-- tests
test:assertObject(dataview)
end
-- love.data.pack
-- @NOTE i dont really get the packing types of lua so best someone else writes this one
love.test.data.pack = function(test)
test:skipTest('dont understand lua packing types')
end
-- love.data.unpack
-- @NOTE i dont really get the packing types of lua so best someone else writes this one
love.test.data.unpack = function(test)
test:skipTest('dont understand lua packing types')
end
+73
View File
@@ -0,0 +1,73 @@
-- love.event
-- love.event.clear
love.test.event.clear = function(test)
-- setup
love.event.push('test', 1, 2, 3)
love.event.push('test', 1, 2, 3)
love.event.push('test', 1, 2, 3)
-- tests
love.event.clear()
local count = 0
for n, a, b, c, d, e, f in love.event.poll() do
count = count + 1
end
test:assertEquals(0, count, 'check no events')
end
-- love.event.poll
love.test.event.poll = function(test)
-- setup
love.event.push('test', 1, 2, 3)
love.event.push('test', 1, 2, 3)
love.event.push('test', 1, 2, 3)
-- tests
local count = 0
for n, a, b, c, d, e, f in love.event.poll() do
count = count + 1
end
test:assertEquals(3, count, 'check 3 events')
end
-- love.event.pump
-- @NOTE dont think can really test as internal?
love.test.event.pump = function(test)
test:skipTest('not sure we can test when its internal?')
end
-- love.event.push
love.test.event.push = function(test)
-- test
love.event.push('add', 1, 2, 3)
love.event.push('ignore', 1, 2, 3)
love.event.push('add', 1, 2, 3)
love.event.push('ignore', 1, 2, 3)
local count = 0
for n, a, b, c, d, e, f in love.event.poll() do
if n == 'add' then
count = count + a + b + c
end
end
test:assertEquals(12, count, 'check total events')
end
-- love.event.quit
love.test.event.quit = function(test)
love.test.module.fakequit = true
-- this should call love.quit, which will prevent the quit
-- if this fails then the test would just abort here
love.event.quit(0)
test:assertEquals(true, true, 'check quit hook called')
end
-- love.event.wait
-- @NOTE not sure best way to test this one
love.test.event.wait = function(test)
test:skipTest('not sure on best way to test this')
end
+354
View File
@@ -0,0 +1,354 @@
-- love.filesystem
-- love.filesystem.append
love.test.filesystem.append = function(test)
-- setup
love.filesystem.write('filesystem.append.txt', 'foo')
-- test
local success, message = love.filesystem.append('filesystem.append.txt', 'bar')
test:assertNotEquals(false, success, 'check success')
test:assertEquals(nil, message, 'check no error msg')
local contents, size = love.filesystem.read('filesystem.append.txt')
test:assertEquals(contents, 'foobar', 'check file contents')
test:assertEquals(size, 6, 'check file size')
love.filesystem.append('filesystem.append.txt', 'foobarfoobarfoo', 6)
contents, size = love.filesystem.read('filesystem.append.txt')
test:assertEquals(contents, 'foobarfoobar', 'check appended contents')
test:assertEquals(size, 12, 'check appended size')
-- cleanup
love.filesystem.remove('filesystem.append.txt')
end
-- love.filesystem.areSymlinksEnabled
-- @NOTE this one, need to see if default val is consistent on platforms?
love.test.filesystem.areSymlinksEnabled = function(test)
test:assertNotEquals(nil, love.filesystem.areSymlinksEnabled())
end
-- love.filesystem.createDirectory
love.test.filesystem.createDirectory = function(test)
local success = love.filesystem.createDirectory('foo/bar')
test:assertNotEquals(false, success, 'check success')
test:assertNotEquals(nil, love.filesystem.getInfo('foo', 'directory'), 'check directory created')
test:assertNotEquals(nil, love.filesystem.getInfo('foo/bar', 'directory'), 'check subdirectory created')
-- cleanup
love.filesystem.remove('foo/bar')
love.filesystem.remove('foo')
end
-- love.filesystem.getAppdataDirectory
-- @NOTE i think this is too platform dependent to be tested nicely
love.test.filesystem.getAppdataDirectory = function(test)
test:assertNotEquals(nil, love.filesystem.getAppdataDirectory(), 'check not nill')
end
-- love.filesystem.getCRequirePath
love.test.filesystem.getCRequirePath = function(test)
test:assertEquals('??', love.filesystem.getCRequirePath(), 'check default value')
end
-- love.filesystem.getDirectoryItems
love.test.filesystem.getDirectoryItems = function(test)
-- setup
love.filesystem.createDirectory('foo/bar')
love.filesystem.write('foo/file1.txt', 'file1')
love.filesystem.write('foo/bar/file2.txt', 'file2')
-- tests
local files = love.filesystem.getDirectoryItems('foo')
local hasfile = false
local hasdir = false
for _,v in ipairs(files) do
local info = love.filesystem.getInfo('foo/'..v)
if v == 'bar' and info.type == 'directory' then hasdir = true end
if v == 'file1.txt' and info.type == 'file' then hasfile = true end
end
test:assertEquals(true, hasfile, 'check file exists')
test:assertEquals(true, hasdir, 'check directory exists')
-- cleanup
love.filesystem.remove('foo/file1.txt')
love.filesystem.remove('foo/bar/file2.txt')
love.filesystem.remove('foo/bar')
love.filesystem.remove('foo')
end
-- love.filesystem.getIdentity
love.test.filesystem.getIdentity = function(test)
-- setup
local original = love.filesystem.getIdentity()
love.filesystem.setIdentity('lover')
-- test
test:assertEquals('lover', love.filesystem.getIdentity(), 'check identity matches')
-- cleanup
love.filesystem.setIdentity(original)
end
-- love.filesystem.getRealDirectory
love.test.filesystem.getRealDirectory = function(test)
-- setup
love.filesystem.createDirectory('foo')
love.filesystem.write('foo/test.txt', 'test')
-- test
test:assertEquals(love.filesystem.getSaveDirectory(), love.filesystem.getRealDirectory('foo/test.txt'), 'check directory matches')
-- cleanup
love.filesystem.remove('foo/test.txt')
love.filesystem.remove('foo')
end
-- love.filesystem.getRequirePath
love.test.filesystem.getRequirePath = function(test)
test:assertEquals('?.lua;?/init.lua', love.filesystem.getRequirePath(), 'check default value')
end
-- love.filesystem.getSource
-- @NOTE i dont think we can test this cos love calls it first
love.test.filesystem.getSource = function(test)
test:skipTest('not sure we can test when its internal?')
end
-- love.filesystem.getSourceBaseDirectory
-- @NOTE i think this is too platform dependent to be tested nicely
love.test.filesystem.getSourceBaseDirectory = function(test)
test:assertNotEquals(nil, love.filesystem.getSourceBaseDirectory(), 'check not nil')
end
-- love.filesystem.getUserDirectory
-- @NOTE i think this is too platform dependent to be tested nicely
love.test.filesystem.getUserDirectory = function(test)
test:assertNotEquals(nil, love.filesystem.getUserDirectory(), 'check not nil')
end
-- love.filesystem.getWorkingDirectory
-- @NOTE i think this is too platform dependent to be tested nicely
love.test.filesystem.getWorkingDirectory = function(test)
test:assertNotEquals(nil, love.filesystem.getWorkingDirectory(), 'check not nil')
end
-- love.filesystem.getSaveDirectory
-- @NOTE i think this is too platform dependent to be tested nicely
love.test.filesystem.getSaveDirectory = function(test)
test:assertNotEquals(nil, love.filesystem.getSaveDirectory(), 'check not nil')
end
-- love.filesystem.getInfo
love.test.filesystem.getInfo = function(test)
-- setup
love.filesystem.createDirectory('foo/bar')
love.filesystem.write('foo/bar/file2.txt', 'file2')
-- tests
test:assertEquals(nil, love.filesystem.getInfo('foo/bar/file2.txt', 'directory'), 'check not directory')
test:assertNotEquals(nil, love.filesystem.getInfo('foo/bar/file2.txt'), 'check info not nil')
test:assertEquals(love.filesystem.getInfo('foo/bar/file2.txt').size, 5, 'check info size match')
-- @TODO test modified timestamp from info.modtime?
-- cleanup
love.filesystem.remove('foo/bar/file2.txt')
love.filesystem.remove('foo/bar')
love.filesystem.remove('foo')
end
-- love.filesystem.isFused
love.test.filesystem.isFused = function(test)
-- kinda assuming you'd run the testsuite in a non-fused game
test:assertEquals(love.filesystem.isFused(), false, 'check default value')
end
-- love.filesystem.lines
love.test.filesystem.lines = function(test)
-- setup
love.filesystem.write('file.txt', 'line1\nline2\nline3')
-- tests
local linenum = 1
for line in love.filesystem.lines('file.txt') do
test:assertEquals('line' .. tostring(linenum), line, 'check line matches')
test:assertEquals(nil, string.find(line, '\n'), 'check newline removed')
linenum = linenum + 1
end
-- cleanup
love.filesystem.remove('file.txt')
end
-- love.filesystem.load
love.test.filesystem.load = function(test)
-- setup
love.filesystem.write('test1.lua', 'function test()\nreturn 1\nend\nreturn test()')
love.filesystem.write('test2.lua', 'function test()\nreturn 1')
-- tests
local chunk, errormsg = love.filesystem.load('faker.lua')
test:assertEquals(nil, chunk, 'check file doesnt exist')
chunk, errormsg = love.filesystem.load('test1.lua')
test:assertEquals(nil, errormsg, 'check no error message')
test:assertEquals(1, chunk(), 'check lua file runs')
local ok, chunk, err = pcall(love.filesystem.load, 'test2.lua')
test:assertEquals(false, ok, 'check invalid lua file')
-- cleanup
love.filesystem.remove('test1.lua')
love.filesystem.remove('test2.lua')
end
-- love.filesystem.mount
love.test.filesystem.mount = function(test)
-- setup
local contents, size = love.filesystem.read('resources/test.zip') -- contains test.txt
love.filesystem.write('test.zip', contents, size)
-- tests
local success = love.filesystem.mount('test.zip', 'test')
test:assertEquals(true, success, 'check success')
test:assertNotEquals(nil, love.filesystem.getInfo('test'), 'check mount not nil')
test:assertEquals('directory', love.filesystem.getInfo('test').type, 'check directory made')
test:assertNotEquals(nil, love.filesystem.getInfo('test/test.txt'), 'check file not nil')
test:assertEquals('file', love.filesystem.getInfo('test/test.txt').type, 'check file type')
-- cleanup
love.filesystem.remove('test/test.txt')
love.filesystem.remove('test')
love.filesystem.remove('test.zip')
end
-- love.filesystem.newFile
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.filesystem.newFile = function(test)
-- setup
local file = love.filesystem.newFile('file1')
local file_r, err_r = love.filesystem.newFile('file2', 'r')
local file_w, err_w = love.filesystem.newFile('file2', 'w')
local file_a, err_a = love.filesystem.newFile('file2', 'a')
local file_c, err_c = love.filesystem.newFile('file2', 'c')
-- tests
test:assertNotEquals(nil, file, 'check file made')
test:assertNotEquals(nil, file_r, 'check file made')
test:assertNotEquals(nil, file_w, 'check file made')
test:assertNotEquals(nil, file_a, 'check file made')
test:assertNotEquals(nil, file_c, 'check file made')
-- cleanup
if file ~= nil then file:release() end
if file_r ~= nil then file_r:release() end
if file_w ~= nil then file_w:release() end
if file_a ~= nil then file_a:release() end
if file_c ~= nil then file_c:release() end
end
-- love.filesystem.newFileData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.filesystem.newFileData = function(test)
local data = love.filesystem.newFileData('helloworld', 'file1')
test:assertNotEquals(nil, data, 'check not nil')
data:release()
end
-- love.filesystem.read
love.test.filesystem.read = function(test)
local content, size = love.filesystem.read('resources/test.txt')
test:assertNotEquals(nil, content, 'check not nil')
test:assertEquals('helloworld', content, 'check content match')
test:assertEquals(10, size, 'check size match')
content, size = love.filesystem.read('resources/test.txt', 5)
test:assertNotEquals(nil, content, 'check not nil')
test:assertEquals('hello', content, 'check content match')
test:assertEquals(5, size, 'check size match')
end
-- love.filesystem.remove
love.test.filesystem.remove = function(test)
-- setup
love.filesystem.createDirectory('foo/bar')
love.filesystem.write('foo/bar/file2.txt', 'helloworld')
-- tests
test:assertEquals(false, love.filesystem.remove('foo'), 'check fail when file inside')
test:assertEquals(false, love.filesystem.remove('foo/bar'), 'check fail when file inside')
test:assertEquals(true, love.filesystem.remove('foo/bar/file2.txt'), 'check file removed')
test:assertEquals(true, love.filesystem.remove('foo/bar'), 'check subdirectory removed')
test:assertEquals(true, love.filesystem.remove('foo'), 'check directory removed')
-- cleanup not needed here
end
-- love.filesystem.setCRequirePath
love.test.filesystem.setCRequirePath = function(test)
love.filesystem.setCRequirePath('/??')
test:assertEquals('/??', love.filesystem.getCRequirePath(), 'check crequirepath value')
love.filesystem.setCRequirePath('??')
end
-- love.filesystem.setIdentity
love.test.filesystem.setIdentity = function(test)
-- setup
local original = love.filesystem.getIdentity()
-- test
love.filesystem.setIdentity('lover')
test:assertEquals('lover', love.filesystem.getIdentity(), 'check indentity value')
-- cleanup
love.filesystem.setIdentity(original)
end
-- love.filesystem.setRequirePath
love.test.filesystem.setRequirePath = function(test)
-- test
love.filesystem.setRequirePath('?.lua;?/start.lua')
test:assertEquals('?.lua;?/start.lua', love.filesystem.getRequirePath(), 'check require path')
-- cleanup
love.filesystem.setRequirePath('?.lua;?/init.lua')
end
-- love.filesystem.setSource
-- @NOTE dont think can test this cos used internally?
love.test.filesystem.setSource = function(test)
test:skipTest('not sure we can test when its internal?')
end
-- love.filesystem.unmount
love.test.filesystem.unmount = function(test)
--setup
local contents, size = love.filesystem.read('resources/test.zip') -- contains test.txt
love.filesystem.write('test.zip', contents, size)
love.filesystem.mount('test.zip', 'test')
-- tests
test:assertNotEquals(nil, love.filesystem.getInfo('test/test.txt'), 'check mount exists')
love.filesystem.unmount('test.zip')
test:assertEquals(nil, love.filesystem.getInfo('test/test.txt'), 'check unmounted')
-- cleanup
love.filesystem.remove('test/test.txt')
love.filesystem.remove('test')
love.filesystem.remove('test.zip')
end
-- love.filesystem.write
love.test.filesystem.write = function(test)
-- setup
love.filesystem.write('test1.txt', 'helloworld')
love.filesystem.write('test2.txt', 'helloworld', 10)
love.filesystem.write('test3.txt', 'helloworld', 5)
-- test
test:assertEquals('helloworld', love.filesystem.read('test1.txt'), 'check read file')
test:assertEquals('helloworld', love.filesystem.read('test2.txt'), 'check read all')
test:assertEquals('hello', love.filesystem.read('test3.txt'), 'check read partial')
-- cleanup
love.filesystem.remove('test1.txt')
love.filesystem.remove('test2.txt')
love.filesystem.remove('test3.txt')
end
+54
View File
@@ -0,0 +1,54 @@
-- love.font
-- love.font.newBMFontRasterizer
-- @NOTE the wiki specifies diff. params to source code and trying to do
-- what source code wants gives some errors still
love.test.font.newBMFontRasterizer = function(test)
test:skipTest('wiki and source dont match, not sure expected usage')
end
-- love.font.newGlyphData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.font.newGlyphData = function(test)
local img = love.image.newImageData('resources/love.png')
local rasterizer = love.font.newImageRasterizer(img, 'ABC', 0, 1);
local glyphdata = love.font.newGlyphData(rasterizer, 65)
test:assertObject(glyphdata)
img:release()
rasterizer:release()
glyphdata:release()
end
-- love.font.newImageRasterizer
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.font.newImageRasterizer = function(test)
local img = love.image.newImageData('resources/love.png')
local rasterizer = love.font.newImageRasterizer(img, 'ABC', 0, 1);
test:assertObject(rasterizer)
img:release()
rasterizer:release()
end
-- love.font.newRasterizer
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.font.newRasterizer = function(test)
local rasterizer = love.font.newRasterizer('resources/font.ttf');
test:assertObject(rasterizer)
rasterizer:release()
end
-- love.font.newTrueTypeRasterizer
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.font.newTrueTypeRasterizer = function(test)
local defaltraster = love.font.newTrueTypeRasterizer(12, "normal", 1)
local customraster = love.font.newTrueTypeRasterizer('resources/font.ttf', 8, "normal", 1)
test:assertObject(defaltraster)
test:assertObject(customraster)
defaltraster:release()
customraster:release()
end
+158
View File
@@ -0,0 +1,158 @@
-- love.graphics
-- DRAWING
-- love.graphics.rectangle
love.test.graphics.rectangle = function(test)
-- setup, draw a 16x16 red rectangle with a blue central square
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setColor(1, 0, 0, 1)
love.graphics.rectangle('fill', 0, 0, 16, 16)
love.graphics.setColor(0, 0, 1, 1)
love.graphics.rectangle('fill', 6, 6, 4, 4)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata1 = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
-- test, check red bg and blue central square
local comparepixels = {
red = {{0,0},{15,0},{15,15},{0,15}},
blue = {{6,6},{9,6},{9,9},{6,9}}
}
test:assertPixels(imgdata1, comparepixels, 'fill')
-- clear canvas to do some line testing
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setColor(1, 0, 0, 1)
love.graphics.rectangle('line', 1, 1, 15, 15) -- red border
love.graphics.setColor(0, 0, 1, 1)
love.graphics.rectangle('line', 1, 1, 2, 15) -- 3x16 left aligned blue outline
love.graphics.setColor(0, 1, 0, 1)
love.graphics.rectangle('line', 11, 1, 5, 15) -- 6x16 right aligned green outline
love.graphics.setCanvas()
local imgdata2 = love.graphics.readbackTexture(canvas, {1, 1, 0, 0, 16, 16})
-- -- check corners and inner corners
comparepixels = {
red = {{3,0},{9,0},{3,15,9,15}},
blue = {{0,0},{2,0},{0,15},{2,15}},
green = {{10,0},{15,0},{10,15},{15,15}},
black = {{1,1},{1,14},{3,1},{9,1},{3,14},{9,14},{11,1},{14,1},{11,14},{14,14}}
}
test:assertPixels(imgdata2, comparepixels, 'line')
-- -- write to save data for sanity checking
-- imgdata1:encode('png', 'love_test_graphics_rectangle_actual1.png')
-- imgdata2:encode('png', 'love_test_graphics_rectangle_actual2.png')
imgdata1:release()
imgdata2:release()
end
-- love.graphics.arc
-- love.graphics.circle
-- love.graphics.clear
-- love.graphics.discard
-- love.graphics.draw
-- love.graphics.drawInstanced
-- love.graphics.drawInstanced
-- love.graphics.drawLayer
-- love.graphics.ellipse
-- love.graphics.flushBatch
-- love.graphics.line
-- love.graphics.points
-- love.graphics.polygon
-- love.graphics.present
-- love.graphics.print
-- love.graphics.printf
-- love.graphics.rectangle
-- love.graphics.captureScreenshot
-- love.graphics.newArrayImage
-- love.graphics.newCanvas
-- love.graphics.newCubeImage
-- love.graphics.newFont
-- love.graphics.newImage
-- love.graphics.newImageFont
-- love.graphics.newMesh
-- love.graphics.newParticleSystem
-- love.graphics.newQuad
-- love.graphics.newShader
-- love.graphics.newSpriteBatch
-- love.graphics.newText
-- love.graphics.newVideo
-- love.graphics.newVolumeImage
-- love.graphics.setNewFont
-- love.graphics.validateShader
-- love.graphics.getBackgroundColor
-- love.graphics.getBlendMode
-- love.graphics.getCanvas
-- love.graphics.getColor
-- love.graphics.getColorMask
-- love.graphics.getDefaultFilter
-- love.graphics.getDepthMode
-- love.graphics.getFont
-- love.graphics.getFrontFaceWinding
-- love.graphics.getLineJoin
-- love.graphics.getLineStyle
-- love.graphics.getLineWidth
-- love.graphics.getMeshCullMode
-- love.graphics.getPointSize
-- love.graphics.getScissor
-- love.graphics.getShader
-- love.graphics.getStackDepth
-- love.graphics.getStencilTest
-- love.graphics.intersectScissor
-- love.graphics.isActive
-- love.graphics.isGammaCorrect
-- love.graphics.isSupported
-- love.graphics.isWireframe
-- love.graphics.reset
-- love.graphics.setBackgroundColor
-- love.graphics.setBlendMode
-- love.graphics.setCanvas
-- love.graphics.setColor
-- love.graphics.setColorMask
-- love.graphics.setDefaultFilter
-- love.graphics.setDepthMode
-- love.graphics.setFont
-- love.graphics.setFrontFaceWinding
-- love.graphics.setLineJoin
-- love.graphics.setLineStyle
-- love.graphics.setLineWidth
-- love.graphics.setMeshCullMode
-- love.graphics.setPointStyle
-- love.graphics.setScissor
-- love.graphics.setShader
-- love.graphics.setStencilTest
-- love.graphics.setWireframe
-- love.graphics.applyTransform
-- love.graphics.inverseTransformPoint
-- love.graphics.origin
-- love.graphics.pop
-- love.graphics.push
-- love.graphics.replaceTransform
-- love.graphics.rotate
-- love.graphics.scale
-- love.graphics.shear
-- love.graphics.transformPoint
-- love.graphics.translate
-- love.graphics.getDPIScale
-- love.graphics.getDimensions
-- love.graphics.getHeight
-- love.graphics.getPixelDimensions
-- love.graphics.getPixelHeight
-- love.graphics.getPixelWidth
-- love.graphics.getWidth
-- love.graphics.getCanvasformats
-- love.graphics.getImageFormats
-- love.graphics.getRendererInfo
-- love.graphics.getStats
-- love.graphics.getSupported
-- love.graphics.getSystemLimits
-- love.graphics.getTextureTypes
+31
View File
@@ -0,0 +1,31 @@
-- love.image
-- love.image.isCompressed
-- @NOTE really we need to test each of the files listed here:
-- https://love2d.org/wiki/CompressedImageFormat
love.test.image.isCompressed = function(test)
local compressed = love.image.isCompressed('resources/love.dxt1')
test:assertEquals(true, compressed, 'check dxt1 valid compressed image')
end
-- love.image.newCompressedData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.image.newCompressedData = function(test)
local imgdata = love.image.newCompressedData('resources/love.dxt1')
test:assertObject(imgdata)
imgdata:release()
end
-- love.image.newImageData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.image.newImageData = function(test)
local imgdata = love.image.newImageData('resources/love.png')
local rawdata = love.image.newImageData(16, 16, 'rgba8', nil)
test:assertObject(imgdata)
test:assertObject(rawdata)
imgdata:release()
rawdata:release()
end
+178
View File
@@ -0,0 +1,178 @@
-- love.math
-- love.math.colorFromBytes
love.test.math.colorFromBytes = function(test)
local r, g, b, a = love.math.colorFromBytes(51, 51, 51, 51)
test:assertEquals(r, 0.2, 'check r from bytes')
test:assertEquals(g, 0.2, 'check g from bytes')
test:assertEquals(b, 0.2, 'check b from bytes')
test:assertEquals(a, 0.2, 'check a from bytes')
r, g, b, a = love.math.colorFromBytes(255, 255, 255, 255)
test:assertEquals(r, 1, 'check r from bytes')
test:assertEquals(g, 1, 'check g from bytes')
test:assertEquals(b, 1, 'check b from bytes')
test:assertEquals(a, 1, 'check a from bytes')
r, g, b, a = love.math.colorFromBytes(0, 0, 0, 0)
test:assertEquals(r, 0, 'check r from bytes')
test:assertEquals(g, 0, 'check g from bytes')
test:assertEquals(b, 0, 'check b from bytes')
test:assertEquals(a, 0, 'check a from bytes')
end
-- love.math.colorToBytes
love.test.math.colorToBytes = function(test)
local r, g, b, a = love.math.colorToBytes(0.2, 0.2, 0.2, 0.2)
test:assertEquals(r, 51, 'check bytes from r')
test:assertEquals(g, 51, 'check bytes from g')
test:assertEquals(b, 51, 'check bytes from b')
test:assertEquals(a, 51, 'check bytes from a')
r, g, b, a = love.math.colorToBytes(1, 1, 1, 1)
test:assertEquals(r, 255, 'check bytes from r')
test:assertEquals(g, 255, 'check bytes from g')
test:assertEquals(b, 255, 'check bytes from b')
test:assertEquals(a, 255, 'check bytes from a')
r, g, b, a = love.math.colorToBytes(0, 0, 0, 0)
test:assertEquals(r, 0, 'check bytes from r')
test:assertEquals(g, 0, 'check bytes from g')
test:assertEquals(b, 0, 'check bytes from b')
test:assertEquals(a, 0, 'check bytes from a')
end
-- love.math.gammaToLinear
-- @NOTE I tried doing the same formula as the source from MathModule.cpp
-- but get test failues due to slight differences
love.test.math.gammaToLinear = function(test)
local lr, lg, lb = love.math.gammaToLinear(1, 0.8, 0.02)
--local eg = ((0.8 + 0.055) / 1.055)^2.4
--local eb = 0.02 / 12.92
test:assertGreaterEqual(0, lr, 'check gamma r to linear')
test:assertGreaterEqual(0, lg, 'check gamma g to linear')
test:assertGreaterEqual(0, lb, 'check gamma b to linear')
end
-- love.math.getRandomSeed
-- @NOTE whenever i run this high is always 0, is that intended?
love.test.math.getRandomSeed = function(test)
local low, high = love.math.getRandomSeed()
test:assertGreaterEqual(0, low, 'check random seed low')
test:assertGreaterEqual(0, high, 'check random seed high')
end
-- love.math.getRandomState
love.test.math.getRandomState = function(test)
local state = love.math.getRandomState()
test:assertNotEquals(nil, state, 'check not nil')
end
-- love.math.isConvex
love.test.math.isConvex = function(test)
local isconvex = love.math.isConvex({0, 0, 1, 0, 1, 1, 1, 0, 0, 0}) -- square
local notconvex = love.math.isConvex({1, 2, 2, 4, 3, 4, 2, 1, 3, 1}) -- weird shape
test:assertEquals(true, isconvex, 'check polygon convex')
test:assertEquals(false, notconvex, 'check polygon not convex')
end
-- love.math.linearToGammer
-- @NOTE I tried doing the same formula as the source from MathModule.cpp
-- but get test failues due to slight differences
love.test.math.linearToGamma = function(test)
local gr, gg, gb = love.math.linearToGamma(1, 0.8, 0.001)
--local eg = 1.055 * (0.8^1/2.4) - 0.055
--local eb = 0.001 * 12.92
test:assertGreaterEqual(0, gr, 'check linear r to gamme')
test:assertGreaterEqual(0, gg, 'check linear g to gamme')
test:assertGreaterEqual(0, gb, 'check linear b to gamme')
end
-- love.math.newBezierCurve
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.math.newBezierCurve = function(test)
local curve = love.math.newBezierCurve({0, 0, 0, 1, 1, 1, 2, 1})
test:assertObject(curve)
curve:release()
end
-- love.math.newRandomGenerator
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.math.newRandomGenerator = function(test)
local rangen = love.math.newRandomGenerator()
test:assertObject(rangen)
rangen:release()
end
-- love.math.newTransform
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.math.newTransform = function(test)
local transform = love.math.newTransform()
test:assertObject(transform)
transform:release()
end
-- love.math.noise
love.test.math.noise = function(test)
local noise1 = love.math.noise(100)
local noise2 = love.math.noise(1, 10)
local noise3 = love.math.noise(1043, 31.123, 999)
local noise4 = love.math.noise(99.222, 10067, 8, 1843)
test:assertEquals(50000, math.floor(noise1*100000), 'check noise 1 dimension')
test:assertEquals(47863, math.floor(noise2*100000), 'check noise 2 dimensions')
test:assertEquals(56297, math.floor(noise3*100000), 'check noise 3 dimensions')
test:assertEquals(52579, math.floor(noise4*100000), 'check noise 4 dimensions')
end
-- love.math.random
love.test.math.random = function(test)
local random = love.math.random(10)
local randomminmax = love.math.random(5, 100)
test:assertRange(random, 1, 10, 'check within 1 - 10')
test:assertRange(randomminmax, 5, 100, 'check within 5 - 100')
end
-- love.math.randomNormal
-- @NOTE i dont _really_ get the range expected based on stddev + mean
-- so feel free to change to be more accurate
love.test.math.randomNormal = function(test)
local random = love.math.randomNormal(1, 0)
test:assertRange(random, -3, 3, 'check within -3 - 3')
end
-- love.math.setRandomSeed
-- @NOTE same with getRandomSeed, high is always 0 when I tested it?
love.test.math.setRandomSeed = function(test)
love.math.setRandomSeed(9001)
local low, high = love.math.getRandomSeed()
test:assertEquals(9001, low, 'check seed low set')
test:assertEquals(0, high, 'check seed high set')
end
-- love.math.setRandomState
love.test.math.setRandomState = function(test)
local rs1 = love.math.getRandomState()
love.math.setRandomState(rs1)
local rs2 = love.math.getRandomState()
test:assertEquals(rs1, rs2, 'check random state set')
end
-- love.math.triangulate
love.test.math.triangulate = function(test)
local triangles1 = love.math.triangulate({0, 0, 1, 0, 1, 1, 1, 0, 0, 0}) -- square
local triangles2 = love.math.triangulate({1, 2, 2, 4, 3, 4, 2, 1, 3, 1}) -- weird shape
test:assertEquals(3, #triangles1, 'check polygon triangles')
test:assertEquals(3, #triangles2, 'check polygon triangles')
end
+175
View File
@@ -0,0 +1,175 @@
-- objects put in their own test methods to test all attributes and class methods
-- File (love.filesystem.newFile)
love.test.objects.File = function(test)
-- setup a file to play with
local file1 = love.filesystem.openFile('data.txt', 'w')
file1:write('helloworld')
test:assertObject(file1)
file1:close()
-- test read mode
file1:open('r')
test:assertEquals('r', file1:getMode(), 'check read mode')
local contents, size = file1:read()
test:assertEquals('helloworld', contents)
test:assertEquals(10, size, 'check file read')
test:assertEquals(10, file1:getSize())
local ok, err = file1:write('hello')
test:assertNotEquals(nil, err, 'check cant write in read mode')
local iterator = file1:lines()
test:assertNotEquals(nil, iterator, 'check can read lines')
test:assertEquals('data.txt', file1:getFilename(), 'check filename matches')
file1:close()
-- test write mode
file1:open('w')
test:assertEquals('w', file1:getMode(), 'check write mode')
contents, size = file1:read()
test:assertEquals(nil, contents, 'check cant read file in write mode')
test:assertEquals('string', type(size), 'check err message shown')
ok, err = file1:write('helloworld')
test:assertEquals(true, ok, 'check file write')
test:assertEquals(nil, err, 'check no err writing')
-- test open/closing
file1:open('r')
test:assertEquals(true, file1:isOpen(), 'check file is open')
file1:close()
test:assertEquals(false, file1:isOpen(), 'check file gets closed')
file1:close()
-- test buffering
-- @NOTE think I'm just not understanding how this is supposed to work?
-- I thought if buffering is enabled then nothing should get written until
-- buffer overflows?
file1:open('a')
ok, err = file1:setBuffer('full', 10000)
test:assertEquals(true, ok)
test:assertEquals('full', file1:getBuffer())
file1:write('morecontent')
file1:close()
file1:open('r')
contents, size = file1:read()
test:assertEquals('helloworld', contents, 'check buffered content wasnt written')
file1:close()
-- test buffering and flushing
file1:open('w')
ok, err = file1:setBuffer('full', 10000)
test:assertEquals(true, ok)
test:assertEquals('full', file1:getBuffer())
file1:write('replacedcontent')
file1:flush()
file1:close()
file1:open('r')
contents, size = file1:read()
test:assertEquals('replacedcontent', contents, 'check buffered content was written')
file1:close()
-- loop through file data with seek/tell until EOF
file1:open('r')
local counter = 0
for i=1,100 do
file1:seek(i)
test:assertEquals(i, file1:tell())
if file1:isEOF() == true then
counter = i
break
end
end
test:assertEquals(counter, 15)
file1:close()
file1:release()
end
-- Source (love.audio.newSource)
-- love.test.objects.Source = function(test)
-- local source1 = love.audio.newSource('resources/click.ogg', 'static')
--source1:clone()
--source1:getChannelCount()
--source1:getDuration()
--source1:isRelative()
--source1:queue()
--source1:getFreeBufferCount()
--source1:getType()
--source1:isPlaying()
--source1:play()
--source1:pause()
--source1:stop()
--source1:seek()
--source1:tell()
--source1:isLooping()
--source1:setLooping()
--source1:setAirAbsorption()
--source1:getAirAbsorption()
--source1:setAttenuationDistances()
--source1:getAttenuationDistances()
--source1:setCone()
--source1:getCone()
--source1:setDirection()
--source1:getDirection()
--source1:setEffect()
--source1:getEffect()
--source1:getActiveEffects()
--source1:setFilter()
--source1:getFilter()
--source1:setPitch()
--source1:getPitch()
--source1:setPosition()
--source1:getPosition()
--source1:setRelative()
--source1:setRolloff()
--source1:getRolloff()
--source1:setVelocity()
--source1:getVelocity()
--source1:setVolume()
--source1:getVolume()
--source1:setVolumeLimits()
--source1:getVolumeLimits()
-- end
-- FileData (love.filesystem.newFileData)
-- ByteData (love.data.newByteData)
-- DataView (love.data.newDataView)
-- FontData (love.font.newFontData)
-- GlyphData (love.font.newGlyphData)
-- Rasterizer (love.font.newRasterizer)
-- CompressedImageData (love.image.newCompressedImageData)
-- ImageData (love.image.newImageData)
-- BezierCurve (love.math.newBezierCurve)
-- RandomGenerator (love.math.RandomGenerator)
-- Transform (love.math.Transform)
-- Decoder (love.sound.newDecoder)
-- SoundData (love.sound.newSoundData)
-- Channel (love.thread.newChannel)
-- Thread (love.thread.newThread)
-- VideoStream (love.thread.newVideoStream)
-- all the stuff from love.physics! barf
-- (love.graphics objs)
-- Canvas
-- Font
-- Image
-- Framebugger
-- Mesh
-- ParticleSystem
-- PixelEffect
-- Quad
-- Shader
-- SpriteBatch
-- Text
-- Video
+306
View File
@@ -0,0 +1,306 @@
-- love.physics
-- love.physics.getDistance
love.test.physics.getDistance = function(test)
-- setup
local shape1 = love.physics.newEdgeShape(0, 0, 5, 5)
local shape2 = love.physics.newEdgeShape(10, 10, 15, 15)
local world = love.physics.newWorld(0, 0, false)
local body = love.physics.newBody(world, 10, 10, 'static')
local fixture1 = love.physics.newFixture(body, shape1, 1)
local fixture2 = love.physics.newFixture(body, shape2, 1)
-- test
test:assertEquals(647106, math.floor(love.physics.getDistance(fixture1, fixture2)*100000), 'check distance matches')
-- cleanup
fixture1:release()
fixture2:release()
body:release()
world:release()
shape1:release()
shape2:release()
end
-- love.physics.getMeter
love.test.physics.getMeter = function(test)
love.physics.setMeter(30)
test:assertEquals(30, love.physics.getMeter(), 'check meter matches')
end
-- love.physics.newBody
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newBody = function(test)
-- setup
local world = love.physics.newWorld(1, 1, true)
local body = love.physics.newBody(world, 10, 10, 'static')
-- test
test:assertObject(body)
-- cleanup
body:release()
world:release()
end
-- love.physics.newChainShape
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newChainShape = function(test)
local obj = love.physics.newChainShape(true, 0, 0, 1, 0, 1, 1, 0, 1)
test:assertObject(obj)
obj:release()
end
-- love.physics.newCircleShape
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newCircleShape = function(test)
local obj = love.physics.newCircleShape(10)
test:assertObject(obj)
obj:release()
end
-- love.physics.newDistanceJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newDistanceJoint = function(test)
-- setup
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
-- test
local obj = love.physics.newDistanceJoint(body1, body2, 10, 10, 20, 20, true)
test:assertObject(obj)
-- cleanup
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newEdgeShape
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newEdgeShape = function(test)
local obj = love.physics.newEdgeShape(0, 0, 10, 10)
test:assertObject(obj)
obj:release()
end
-- love.physics.newFixture
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newFixture = function(test)
-- setup
local world = love.physics.newWorld(1, 1, true)
local body = love.physics.newBody(world, 10, 10, 'static')
local shape = love.physics.newCircleShape(10)
-- test
local obj = love.physics.newFixture(body, shape, 1)
test:assertObject(obj)
-- cleanup
obj:release()
shape:release()
body:release()
world:release()
end
-- love.physics.newFrictionJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newFrictionJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newFrictionJoint(body1, body2, 15, 15, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newGearJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newGearJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local body3 = love.physics.newBody(world, 30, 30, 'static')
local body4 = love.physics.newBody(world, 40, 40, 'static')
local joint1 = love.physics.newPrismaticJoint(body1, body2, 10, 10, 20, 20, true)
local joint2 = love.physics.newPrismaticJoint(body3, body4, 30, 30, 40, 40, true)
local obj = love.physics.newGearJoint(joint1, joint2, 1, true)
test:assertObject(obj)
obj:release()
joint1:release()
joint2:release()
body1:release()
body2:release()
body3:release()
body4:release()
world:release()
end
-- love.physics.newMotorJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newMotorJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newMotorJoint(body1, body2, 1)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newMouseJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newMouseJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body = love.physics.newBody(world, 10, 10, 'static')
local obj = love.physics.newMouseJoint(body, 10, 10)
test:assertObject(obj)
obj:release()
body:release()
world:release()
end
-- love.physics.newPolygonShape
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newPolygonShape = function(test)
local obj = love.physics.newPolygonShape({0, 0, 2, 3, 2, 1, 3, 1, 5, 1})
test:assertObject(obj)
obj:release()
end
-- love.physics.newPrismaticJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newPrismaticJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newPrismaticJoint(body1, body2, 10, 10, 20, 20, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newPulleyJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newPulleyJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newPulleyJoint(body1, body2, 10, 10, 20, 20, 15, 15, 25, 25, 1, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newRectangleShape
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newRectangleShape = function(test)
local shape1 = love.physics.newRectangleShape(10, 20)
local shape2 = love.physics.newRectangleShape(10, 10, 40, 30, 10)
test:assertObject(shape1)
test:assertObject(shape2)
end
-- love.physics.newRevoluteJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newRevoluteJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newRevoluteJoint(body1, body2, 10, 10, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newRopeJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newRopeJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newRopeJoint(body1, body2, 10, 10, 20, 20, 50, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newWeldJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newWeldJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newWeldJoint(body1, body2, 10, 10, true)
test:assertObject(obj)
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newWheelJoint
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newWheelJoint = function(test)
local world = love.physics.newWorld(1, 1, true)
local body1 = love.physics.newBody(world, 10, 10, 'static')
local body2 = love.physics.newBody(world, 20, 20, 'static')
local obj = love.physics.newWheelJoint(body1, body2, 10, 10, 5, 5, true)
test:assertNotEquals(nil, obj)
test:assertEquals('userdata', type(obj))
test:assertNotEquals(nil, obj:type())
obj:release()
body1:release()
body2:release()
world:release()
end
-- love.physics.newWorld
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.physics.newWorld = function(test)
local world = love.physics.newWorld(1, 1, true)
test:assertObject(world)
world:release()
end
-- love.physics.setMeter
love.test.physics.setMeter = function(test)
local world = love.physics.newWorld(1, 1, true)
love.physics.setMeter(30)
local body = love.physics.newBody(world, 300, 300, "dynamic")
love.physics.setMeter(10)
local x, y = body:getPosition()
test:assertEquals(100, x, 'check pos x')
test:assertEquals(100, y, 'check pos y')
body:release()
world:release()
end
+19
View File
@@ -0,0 +1,19 @@
-- love.sound
-- love.sound.newDecoder
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.sound.newDecoder = function(test)
local decoder = love.sound.newDecoder('resources/click.ogg')
test:assertObject(decoder)
end
-- love.sound.newSoundData
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.sound.newSoundData = function(test)
local sounddata = love.sound.newSoundData('resources/click.ogg')
test:assertObject(sounddata)
local soundbeep = love.sound.newSoundData(math.floor((1/32)*44100), 44100, 16, 1)
test:assertObject(soundbeep)
end
+68
View File
@@ -0,0 +1,68 @@
-- love.system
-- love.system.getClipboardText
love.test.system.getClipboardText = function(test)
-- ignore if not using window
if love.test.windowmode == false then return test:skipTest('clipboard only available in window mode') end
-- setup
love.system.setClipboardText('helloworld')
-- test
test:assertEquals('helloworld', love.system.getClipboardText(), 'check clipboard match')
end
-- love.system.getOS
love.test.system.getOS = function(test)
local os = love.system.getOS()
test:assertMatch({'OS X', 'Windows', 'Linux', 'Android', 'iOS'}, os, 'check value matches')
end
-- love.system.getPowerInfo
love.test.system.getPowerInfo = function(test)
local state, percent, seconds = love.system.getPowerInfo()
test:assertMatch({'unknown', 'battery', 'nobattery', 'charging', 'charged'}, state, 'check value matches')
if percent ~= nil then
test:assertRange(percent, 0, 100, 'check value within range')
end
if seconds ~= nil then
test:assertRange(seconds, 0, 100, 'check value within range')
end
end
-- love.system.getProcessorCount
love.test.system.getProcessorCount = function(test)
test:assertGreaterEqual(0, love.system.getProcessorCount(), 'check not nil') -- youd hope right
end
-- love.system.hasBackgroundMusic
love.test.system.hasBackgroundMusic = function(test)
test:assertNotEquals(nil, love.system.hasBackgroundMusic(), 'check not nil')
end
-- love.system.openURL
love.test.system.openURL = function(test)
test:skipTest('gets annoying to test everytime')
--test:assertNotEquals(nil, love.system.openURL('https://love2d.org'), 'check open URL')
end
-- love.system.getClipboardText
love.test.system.setClipboardText = function(test)
-- ignore if not using window
if love.test.windowmode == false then return test:skipTest('clipboard only available in window mode') end
-- test
love.system.setClipboardText('helloworld')
test:assertEquals('helloworld', love.system.getClipboardText(), 'check set text')
end
-- love.system.vibrate
-- @NOTE cant really test this
love.test.system.vibrate = function(test)
test:skipTest('cant really test this')
end
+28
View File
@@ -0,0 +1,28 @@
-- love.thread
-- love.thread.getChannel
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.thread.getChannel = function(test)
local channel = love.thread.getChannel('test')
test:assertObject(channel)
channel:release()
end
-- love.thread.newChannel
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.thread.newChannel = function(test)
local channel = love.thread.newChannel()
test:assertObject(channel)
channel:release()
end
-- love.thread.newThread
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.thread.newThread = function(test)
local thread = love.thread.newThread('classes/TestSuite.lua')
test:assertObject(thread)
thread:release()
end
+45
View File
@@ -0,0 +1,45 @@
-- love.timer
-- love.timer.getAverageDelta
-- @NOTE not sure if you could reliably get a specific delta?
love.test.timer.getAverageDelta = function(test)
test:assertNotEquals(nil, love.timer.getAverageDelta(), 'check not nil')
end
-- love.timer.getDelta
-- @NOTE not sure if you could reliably get a specific delta?
love.test.timer.getDelta = function(test)
test:assertNotEquals(nil, love.timer.getDelta(), 'check not nil')
end
-- love.timer.getFPS
-- @NOTE not sure if you could reliably get a specific FPS?
love.test.timer.getFPS = function(test)
test:assertNotEquals(nil, love.timer.getFPS(), 'check not nil')
end
-- love.timer.getTime
love.test.timer.getTime = function(test)
local starttime = love.timer.getTime()
love.timer.sleep(1)
local endtime = love.timer.getTime() - starttime
test:assertEquals(1, math.floor(endtime), 'check 1s passes')
end
-- love.timer.sleep
love.test.timer.sleep = function(test)
local starttime = love.timer.getTime()
love.timer.sleep(1)
test:assertEquals(1, math.floor(love.timer.getTime() - starttime), 'check 1s passes')
end
-- love.timer.step
-- @NOTE not sure if you could reliably get a specific step val?
love.test.timer.step = function(test)
test:assertNotEquals(nil, love.timer.step(), 'check not nil')
end
+10
View File
@@ -0,0 +1,10 @@
-- love.video
-- love.video.newVideoStream
-- @NOTE this is just basic nil checking, full obj test are in objects.lua
love.test.video.newVideoStream = function(test)
local videostream = love.video.newVideoStream('resources/sample.ogv')
test:assertObject(videostream)
videostream:release()
end
+336
View File
@@ -0,0 +1,336 @@
-- love.window
-- love.window.close
-- @NOTE closing window should cause graphics to no longer be active
love.test.window.close = function(test)
love.window.close()
local active = false
if love.graphics ~= nil then active = love.graphics.isActive() end
test:assertEquals(false, active, 'check window active')
love.window.setMode(256, 256) -- reset
end
-- love.window.fromPixels
-- @NOTE dependent on the DPI value returned I think
love.test.window.fromPixels = function(test)
local dpi = love.window.getDPIScale()
local pixels = love.window.fromPixels(100)
test:assertEquals(100/dpi, pixels, 'check dpi ratio')
end
-- love.window.getDPIScale
-- @NOTE i dont think there's a clever way to check this
love.test.window.getDPIScale = function(test)
test:assertNotEquals(nil, test, 'check not nil')
end
-- love.window.getDesktopDimensions
-- @NOTE dependent on hardware so best can do is not nil
love.test.window.getDesktopDimensions = function(test)
local w, h = love.window.getDesktopDimensions()
test:assertNotEquals(nil, w, 'check not nil')
test:assertNotEquals(nil, h, 'check not nil')
end
-- love.window.getDisplayCount
-- @NOTE cant wait for the test suite to be run headless and fail here
love.test.window.getDisplayCount = function(test)
local count = love.window.getDisplayCount()
test:assertGreaterEqual(1, count, 'check 1 display')
end
-- love.window.getDisplayName
-- @NOTE dependent on hardware so best can do is not nil
love.test.window.getDisplayName = function(test)
local name = love.window.getDisplayName(1)
test:assertNotEquals(nil, name, 'check not nil')
end
-- love.window.getDisplayOrientation
-- @NOTE dependent on hardware so best can do is not nil
love.test.window.getDisplayOrientation = function(test)
local orientation = love.window.getDisplayOrientation(1)
test:assertNotEquals(nil, orientation, 'check not nil')
end
-- love.window.getFullscreen
love.test.window.getFullscreen = function(test)
test:assertEquals(false, love.window.getFullscreen(), 'check not fullscreen')
love.window.setFullscreen(true)
test:assertEquals(true, love.window.getFullscreen(), 'check now fullscreen')
love.window.setFullscreen(false)
end
-- love.window.getFullscreenModes
-- @NOTE dependent on hardware so best can do is not nil
love.test.window.getFullscreenModes = function(test)
local modes = love.window.getFullscreenModes(1)
test:assertNotEquals(nil, modes, 'check not nil')
end
-- love.window.getIcon
love.test.window.getIcon = function(test)
test:assertEquals(nil, love.window.getIcon(), 'check nil by default') -- nil if not set
local icon = love.image.newImageData('resources/love.png')
love.window.setIcon(icon)
test:assertNotEquals(nil, love.window.getIcon(), 'check not nil')
icon:release()
end
-- love.window.getMode
-- @NOTE could prob add more checks on the flags here based on conf.lua
love.test.window.getMode = function(test)
local w, h, flags = love.window.getMode()
test:assertEquals(256, w, 'check w')
test:assertEquals(256, h, 'check h')
test:assertEquals(false, flags["fullscreen"], 'check fullscreen')
end
-- love.window.getPosition
-- @NOTE anything we could check display index agaisn't in getPosition return?
love.test.window.getPosition = function(test)
love.window.setPosition(100, 100, 1)
local x, y, _ = love.window.getPosition()
test:assertEquals(100, x, 'check position x')
test:assertEquals(100, y, 'check position y')
end
-- love.window.getSafeArea
-- @NOTE dependent on hardware so best can do is not nil
love.test.window.getSafeArea = function(test)
local x, y, w, h = love.window.getSafeArea()
test:assertNotEquals(nil, x, 'check not nil')
test:assertNotEquals(nil, y, 'check not nil')
test:assertNotEquals(nil, w, 'check not nil')
test:assertNotEquals(nil, h, 'check not nil')
end
-- love.window.getTitle
love.test.window.getTitle = function(test)
love.window.setTitle('love.testing')
test:assertEquals('love.testing', love.window.getTitle(), 'check title match')
love.window.setTitle('love.test')
end
-- love.window.getVSync
love.test.window.getVSync = function(test)
test:assertNotEquals(nil, love.window.getVSync(), 'check not nil')
love.window.setVSync(false)
test:assertEquals(0, love.window.getVSync(), 'check vsync off')
love.window.setVSync(true)
test:assertEquals(1, love.window.getVSync(), 'check vsync on')
end
-- love.window.hasFocus
-- @NOTE cant really test as cant force focus?
love.test.window.hasFocus = function(test)
test:assertNotEquals(nil, love.window.hasFocus(), 'check not nil')
end
-- love.window.hasMouseFocus
-- @NOTE cant really test as cant force focus?
love.test.window.hasMouseFocus = function(test)
test:assertNotEquals(nil, love.window.hasMouseFocus(), 'check not nil')
end
-- love.window.isDisplaySleepEnabled
love.test.window.isDisplaySleepEnabled = function(test)
test:assertNotEquals(nil, love.window.isDisplaySleepEnabled(), 'check not nil')
love.window.setDisplaySleepEnabled(false)
test:assertEquals(false, love.window.isDisplaySleepEnabled(), 'check sleep disabled')
love.window.setDisplaySleepEnabled(true)
test:assertEquals(true, love.window.isDisplaySleepEnabled(), 'check sleep enabled')
end
-- love.window.isMaximized
love.test.window.isMaximized = function(test)
love.window.minimize()
test:assertEquals(false, love.window.isMaximized(), 'check window maximized')
love.window.maximize()
test:assertEquals(true, love.window.isMaximized(), 'check window not maximized')
love.window.restore()
end
-- love.window.isMinimized
love.test.window.isMinimized = function(test)
test:assertEquals(false, love.window.isMinimized(), 'check window not minimized')
love.window.minimize()
test:assertEquals(true, love.window.isMinimized(), 'check window minimized')
love.window.restore()
end
-- love.window.isOpen
love.test.window.isOpen = function(test)
test:assertEquals(true, love.window.isOpen(), 'check window open')
love.window.close()
test:assertEquals(false, love.window.isOpen(), 'check window closed')
love.window.setMode(256, 256) -- reset
end
-- love.window.isVisible
love.test.window.isVisible = function(test)
test:assertEquals(true, love.window.isVisible(), 'check window visible')
love.window.close()
test:assertEquals(false, love.window.isVisible(), 'check window not visible')
love.window.setMode(256, 256) -- reset
end
-- love.window.maximize
love.test.window.maximize = function(test)
love.window.maximize()
test:assertEquals(true, love.window.isMaximized(), 'check window maximized')
love.window.restore()
end
-- love.window.minimize
love.test.window.minimize = function(test)
love.window.minimize()
test:assertEquals(true, love.window.isMinimized(), 'check window minimized')
love.window.restore()
end
-- love.window.requestAttention
love.window.requestAttention = function(test)
test:skipTest('cant really test this')
end
-- love.window.restore
love.test.window.restore = function(test)
love.window.minimize()
test:assertEquals(true, love.window.isMinimized(), 'check window minimized')
love.window.restore()
test:assertEquals(false, love.window.isMinimized(), 'check window restored')
end
-- love.window.setDisplaySleepEnabled
love.test.window.setDisplaySleepEnabled = function(test)
love.window.setDisplaySleepEnabled(false)
test:assertEquals(false, love.window.isDisplaySleepEnabled(), 'check sleep disabled')
love.window.setDisplaySleepEnabled(true)
test:assertEquals(true, love.window.isDisplaySleepEnabled(), 'check sleep enabled')
end
-- love.window.setFullscreen
love.test.window.setFullscreen = function(test)
love.window.setFullscreen(true)
test:assertEquals(true, love.window.getFullscreen(), 'check fullscreen')
love.window.setFullscreen(false)
test:assertEquals(false, love.window.getFullscreen(), 'check not fullscreen')
end
-- love.window.setIcon
-- @NOTE could check the image data itself?
love.test.window.setIcon = function(test)
local icon = love.image.newImageData('resources/love.png')
love.window.setIcon(icon)
test:assertNotEquals(nil, love.window.getIcon(), 'check icon not nil')
icon:release()
end
-- love.window.setMode
-- @NOTE same as getMode could be checking more flag properties
love.test.window.setMode = function(test)
love.window.setMode(512, 512, {
fullscreen = false,
resizable = false
})
local width, height, flags = love.window.getMode()
test:assertEquals(512, width, 'check window w match')
test:assertEquals(512, height, 'check window h match')
test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen')
test:assertEquals(false, flags["resizable"], 'check window not resizeable')
love.window.setMode(256, 256, {
fullscreen = false,
resizable = true
})
end
-- love.window.setPosition
love.test.window.setPosition = function(test)
love.window.setPosition(100, 100, 1)
local x, y, _ = love.window.getPosition()
test:assertEquals(100, x, 'check position x')
test:assertEquals(100, y, 'check position y')
end
-- love.window.setTitle
love.test.window.setTitle = function(test)
love.window.setTitle('love.testing')
test:assertEquals('love.testing', love.window.getTitle(), 'check title matches')
love.window.setTitle('love.test')
end
-- love.window.setVSync
love.test.window.setVSync = function(test)
love.window.setVSync(false)
test:assertEquals(0, love.window.getVSync(), 'check vsync off')
love.window.setVSync(true)
test:assertEquals(1, love.window.getVSync(), 'check vsync on')
end
-- love.window.showMessageBox
-- @NOTE if running headless would need to skip anyway cos can't press it
-- skipping here cos it's annoying
love.test.window.showMessageBox = function(test)
test:skipTest('skipping cos annoying to test with')
end
-- love.window.toPixels
love.test.window.toPixels = function(test)
local dpi = love.window.getDPIScale()
local pixels = love.window.toPixels(50)
test:assertEquals(50*dpi, pixels, 'check dpi ratio')
end
-- love.window.updateMode
love.test.window.updateMode = function(test)
love.window.setMode(512, 512, {
fullscreen = false,
resizable = false
})
love.window.updateMode(256, 256, nil)
local width, height, flags = love.window.getMode()
test:assertEquals(256, width, 'check window w match')
test:assertEquals(256, height, 'check window h match')
test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen')
test:assertEquals(false, flags["resizable"], 'check window not resizeable')
love.window.setMode(256, 256, {
fullscreen = false,
resizable = true
})
end