more tests

- added custom error handler so that love is closed if a crash occurs rather than hang on the graphic screen (for runner crashes mainly)

- updated missing functions left todo in todo.md and removed list from readme.md to make it easier to keep track of

- added love.audio.getPlaybackDevice(), love.audio.getPlaybackDevices(), love.audio.setPlaybackDevice()

- added love.data.ByteData:setString()

- added love.filesystem.getFullCommonPath(), love.filesystem.mountFullPath(), love.filesystem.unmountFullPath(), love.filesystem.moundCommonPath(), plus optional b/t/bt params to love.filesystem.load()

- added love.keyboard.isModifierActive()

- added love.sound.SoundData:copy() and love.sound.SoundData:slice()

- added love.graphics.Texture:isCanvas() and love.graphics.Texture:isComputeWritable()

- added love.image.ImageData:isLinear(), love.image.ImageData:setLinear(), and love.image.ImageData:encode("*.exr")

- added love.image.CompressedImageData:isLinear() and love.image.CompressedImageData:setLinear()

- added love.system.getPreferredLocales()

- added love.window.focus() and removed love.window.close() (now deprecated)
This commit is contained in:
ell
2024-02-28 17:49:51 +00:00
parent ff06718f8a
commit 990259edf9
16 changed files with 317 additions and 33 deletions
+9 -1
View File
@@ -367,11 +367,19 @@ TestMethod = {
end, end,
-- @method - TestMethod:waitFrames()
-- @desc - yields the method for x amount of frames
-- @param {number} frames - no. frames to wait
-- @return {nil}
waitFrames = function(self, frames) waitFrames = function(self, frames)
for i=1,frames do coroutine.yield() end for _=1,frames do coroutine.yield() end
end, end,
-- @method - TestMethod:waitSeconds()
-- @desc - yields the method for x amount of seconds
-- @param {number} seconds - no. seconds to wait
-- @return {nil}
waitSeconds = function(self, seconds) waitSeconds = function(self, seconds)
local start = love.timer.getTime() local start = love.timer.getTime()
while love.timer.getTime() < start + seconds do while love.timer.getTime() < start + seconds do
+14
View File
@@ -1,4 +1,7 @@
print("conf.lua")
function love.conf(t) function love.conf(t)
print("love.conf")
t.console = true t.console = true
t.window.name = 'love.test' t.window.name = 'love.test'
t.window.width = 360 t.window.width = 360
@@ -8,3 +11,14 @@ function love.conf(t)
t.window.stencil = true t.window.stencil = true
t.renderers = {"opengl"} t.renderers = {"opengl"}
end end
-- custom crash message here to catch anything that might occur with modules
-- loading before we hit main.lua
local function error_printer(msg, layer)
print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end
function love.errorhandler(msg)
msg = tostring(msg)
error_printer(msg, 2)
os.exit(1)
end
+2
View File
@@ -1,3 +1,5 @@
print('main.lua')
-- load test objs -- load test objs
require('classes.TestSuite') require('classes.TestSuite')
require('classes.TestModule') require('classes.TestModule')
+1 -8
View File
@@ -114,14 +114,7 @@ For sanity-checking, if it's currently not covered or it's not possible to test
## Todo ## Todo
If you would like to contribute to the test suite please raise a PR with the main [love-test](https://github.com/ellraiser/love-test) repo. If you would like to contribute to the test suite please raise a PR with the main [love-test](https://github.com/ellraiser/love-test) repo.
The following items are all the things still outstanding, expanding on any existing tests is also very welcome! There is a list of outstanding methods that require test coverage in `todo.md`, expanding on any existing tests is also very welcome!
- [ ] check for any 12.0 methods in the changelog not yet covered in the test suite
- [ ] add BMfont alt. tests for font class tests (Rasterizer + GlyphData)
- [ ] graphics.isCompressed() should have an example of all compressed files
- [ ] graphics.Mesh should have some graphical tests ideally to check vertex settings w/ shaders
- [ ] ability to test loading different combinations of modules if needed
- [ ] more scenario based tests similar to some of the obj class tests
- [ ] performance tests? need to discuss what + how
--- ---
Binary file not shown.
Binary file not shown.
+60
View File
@@ -299,6 +299,20 @@ love.test.audio.getOrientation = function(test)
end end
-- love.audio.getPlaybackDevice
love.test.audio.getPlaybackDevice = function(test)
test:assertNotNil(love.audio.getPlaybackDevice)
test:assertNotNil(love.audio.getPlaybackDevice())
end
-- love.audio.getPlaybackDevices
love.test.audio.getPlaybackDevices = function(test)
test:assertNotNil(love.audio.getPlaybackDevices)
test:assertGreaterEqual(0, #love.audio.getPlaybackDevices(), 'check table')
end
-- love.audio.getPosition -- love.audio.getPosition
-- @NOTE is there an expected default listener pos? -- @NOTE is there an expected default listener pos?
love.test.audio.getPosition = function(test) love.test.audio.getPosition = function(test)
@@ -442,6 +456,52 @@ love.test.audio.setOrientation = function(test)
end end
-- love.audio.setPlaybackDevice
love.test.audio.setPlaybackDevice = function(test)
-- check method
test:assertNotNil(love.audio.setPlaybackDevice)
-- check blank string name
local success1, msg1 = love.audio.setPlaybackDevice('')
-- check invalid name
local success2, msg2 = love.audio.setPlaybackDevice('loveFM')
-- check setting already set
local success3, msg3 = love.audio.setPlaybackDevice(love.audio.getPlaybackDevice()) -- current name
-- rn on macos all 3 return false
-- whereas linux/windows return true for blank/current, which is expected
-- as openalsoft treats blank as current
if love.system.getOS() == 'OS X' then
test:assertFalse(success1, 'check blank device fails')
test:assertFalse(success2, 'check invalid device fails')
test:assertFalse(success3, 'check existing device fails')
else
test:assertTrue(success1, 'check blank device is fine')
test:assertFalse(success2, 'check invalid device fails')
test:assertTrue(success3, 'check existing device is fine')
end
-- if other devices to play with lets set a different one
local devices = love.audio.getPlaybackDevices()
if #devices > 1 then
local another = ''
local current = love.audio.getPlaybackDevice()
for a=1,#devices do
if devices[a] ~= current then
another = devices[a]
break
end
end
if another ~= '' then
-- check setting new device
local success4, msg4 = love.audio.setPlaybackDevice(another)
test:assertTrue(success4, 'check setting different device')
-- check resetting to default
local success5, msg5 = love.audio.setPlaybackDevice()
test:assertTrue(success5, 'check resetting')
test:assertEquals(current, love.audio.getPlaybackDevice())
end
end
end
-- love.audio.setPosition -- love.audio.setPosition
love.test.audio.setPosition = function(test) love.test.audio.setPosition = function(test)
-- check setting position vals are returned -- check setting position vals are returned
+4
View File
@@ -33,6 +33,10 @@ love.test.data.ByteData = function(test)
test:assertEquals('o', byte5) test:assertEquals('o', byte5)
end end
-- check overwriting the byte data string
data:setString('love!', 5)
test:assertEquals('hellolove!', data:getString(), 'check change string')
end end
+114 -6
View File
@@ -187,6 +187,27 @@ love.test.filesystem.getDirectoryItems = function(test)
end end
-- love.filesystem.getFullCommonPath
love.test.filesystem.getFullCommonPath = function(test)
-- check standard paths
local appsavedir = love.filesystem.getFullCommonPath('appsavedir')
local appdocuments = love.filesystem.getFullCommonPath('appdocuments')
local userhome = love.filesystem.getFullCommonPath('userhome')
local userappdata = love.filesystem.getFullCommonPath('userappdata')
local userdesktop = love.filesystem.getFullCommonPath('userdesktop')
local userdocuments = love.filesystem.getFullCommonPath('userdocuments')
test:assertNotNil(appsavedir)
test:assertNotNil(appdocuments)
test:assertNotNil(userhome)
test:assertNotNil(userappdata)
test:assertNotNil(userdesktop)
test:assertNotNil(userdocuments)
-- check invalid path
local ok = pcall(love.filesystem.getFullCommonPath, 'fakepath')
test:assertFalse(ok, 'check invalid common path')
end
-- love.filesystem.getIdentity -- love.filesystem.getIdentity
love.test.filesystem.getIdentity = function(test) love.test.filesystem.getIdentity = function(test)
-- check setting identity matches -- check setting identity matches
@@ -263,6 +284,7 @@ love.test.filesystem.getInfo = function(test)
test:assertEquals(nil, love.filesystem.getInfo('foo/bar/file2.txt', 'directory'), 'check not directory') 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: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') test:assertEquals(love.filesystem.getInfo('foo/bar/file2.txt').size, 5, 'check info size match')
test:assertFalse(love.filesystem.getInfo('foo/bar/file2.txt').readonly, 'check readonly')
-- @TODO test modified timestamp from info.modtime? -- @TODO test modified timestamp from info.modtime?
-- cleanup -- cleanup
love.filesystem.remove('foo/bar/file2.txt') love.filesystem.remove('foo/bar/file2.txt')
@@ -300,12 +322,16 @@ love.test.filesystem.load = function(test)
love.filesystem.write('test1.lua', 'function test()\nreturn 1\nend\nreturn test()') love.filesystem.write('test1.lua', 'function test()\nreturn 1\nend\nreturn test()')
love.filesystem.write('test2.lua', 'function test()\nreturn 1') love.filesystem.write('test2.lua', 'function test()\nreturn 1')
-- check file that doesn't exist -- check file that doesn't exist
local chunk, errormsg = love.filesystem.load('faker.lua') local chunk1, errormsg1 = love.filesystem.load('faker.lua', 'b')
test:assertEquals(nil, chunk, 'check file doesnt exist') test:assertEquals(nil, chunk1, 'check file doesnt exist')
-- check valid lua file -- check valid lua file (text load)
chunk, errormsg = love.filesystem.load('test1.lua') local chunk2, errormsg2 = love.filesystem.load('test1.lua', 't')
test:assertEquals(nil, errormsg, 'check no error message') test:assertEquals(nil, errormsg2, 'check no error message')
test:assertEquals(1, chunk(), 'check lua file runs') test:assertEquals(1, chunk2(), 'check lua file runs')
-- check valid lua file (any load)
local chunk4, errormsg4 = love.filesystem.load('test1.lua', 'bt')
test:assertEquals(nil, errormsg2, 'check no error message')
test:assertEquals(1, chunk4(), 'check lua file runs')
-- check invalid lua file -- check invalid lua file
local ok, chunk, err = pcall(love.filesystem.load, 'test2.lua') local ok, chunk, err = pcall(love.filesystem.load, 'test2.lua')
test:assertFalse(ok, 'check invalid lua file') test:assertFalse(ok, 'check invalid lua file')
@@ -334,6 +360,88 @@ love.test.filesystem.mount = function(test)
end end
-- love.filesystem.mountFullPath
love.test.filesystem.mountFullPath = function(test)
-- mount something in the working directory
local mount = love.filesystem.mountFullPath(love.filesystem.getSource() .. '/tests', 'tests', 'read')
test:assertTrue(mount, 'check can mount')
-- check reading file through mounted path label
local contents, _ = love.filesystem.read('tests/audio.lua')
test:assertNotEquals(nil, contents)
local unmount = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/tests')
test:assertTrue(unmount, 'reset mount')
end
-- love.filesystem.unmountFullPath
love.test.filesystem.unmountFullPath = function(test)
-- try unmounting something we never mounted
local unmount1 = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/faker')
test:assertFalse(unmount1, 'check not mounted to start with')
-- mount something to unmount after
love.filesystem.mountFullPath(love.filesystem.getSource() .. '/tests', 'tests', 'read')
local unmount2 = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/tests')
test:assertTrue(unmount2, 'check unmounted')
end
-- love.filesystem.mountCommonPath
love.test.filesystem.mountCommonPath = function(test)
-- check if we can mount all the expected paths
local mount1 = love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'readwrite')
local mount2 = love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'readwrite')
local mount3 = love.filesystem.mountCommonPath('userhome', 'userhome', 'readwrite')
local mount4 = love.filesystem.mountCommonPath('userappdata', 'userappdata', 'readwrite')
-- userdesktop isnt valid on linux
if love.system.getOS() ~= 'Linux' then
local mount5 = love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'readwrite')
test:assertTrue(mount5, 'check mount userdesktop')
end
local mount6 = love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'readwrite')
local ok = pcall(love.filesystem.mountCommonPath, 'fakepath', 'fake', 'readwrite')
test:assertTrue(mount1, 'check mount appsavedir')
test:assertTrue(mount2, 'check mount appdocuments')
test:assertTrue(mount3, 'check mount userhome')
test:assertTrue(mount4, 'check mount userappdata')
test:assertTrue(mount6, 'check mount userdocuments')
test:assertFalse(ok, 'check mount invalid common path fails')
end
-- love.filesystem.unmountCommonPath
--love.test.filesystem.unmountCommonPath = function(test)
-- -- check unmounting invalid
-- local ok = pcall(love.filesystem.unmountCommonPath, 'fakepath')
-- test:assertFalse(ok, 'check unmount invalid common path')
-- -- check mounting valid paths
-- love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'read')
-- love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'read')
-- love.filesystem.mountCommonPath('userhome', 'userhome', 'read')
-- love.filesystem.mountCommonPath('userappdata', 'userappdata', 'read')
-- love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'read')
-- love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'read')
-- local unmount1 = love.filesystem.unmountCommonPath('appsavedir')
-- local unmount2 = love.filesystem.unmountCommonPath('appdocuments')
-- local unmount3 = love.filesystem.unmountCommonPath('userhome')
-- local unmount4 = love.filesystem.unmountCommonPath('userappdata')
-- local unmount5 = love.filesystem.unmountCommonPath('userdesktop')
-- local unmount6 = love.filesystem.unmountCommonPath('userdocuments')
-- test:assertTrue(unmount1, 'check unmount appsavedir')
-- test:assertTrue(unmount2, 'check unmount appdocuments')
-- test:assertTrue(unmount3, 'check unmount userhome')
-- test:assertTrue(unmount4, 'check unmount userappdata')
-- test:assertTrue(unmount5, 'check unmount userdesktop')
-- test:assertTrue(unmount6, 'check unmount userdocuments')
-- -- remount or future tests fail
-- love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'readwrite')
-- love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'readwrite')
-- love.filesystem.mountCommonPath('userhome', 'userhome', 'readwrite')
-- love.filesystem.mountCommonPath('userappdata', 'userappdata', 'readwrite')
-- love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'readwrite')
-- love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'readwrite')
--end
-- love.filesystem.openFile -- love.filesystem.openFile
-- @NOTE this is just basic nil checking, objs have their own test method -- @NOTE this is just basic nil checking, objs have their own test method
love.test.filesystem.openFile = function(test) love.test.filesystem.openFile = function(test)
+14
View File
@@ -113,6 +113,8 @@ love.test.graphics.Canvas = function(test)
debugname = 'testcanvas' debugname = 'testcanvas'
}) })
test:assertObject(canvas) test:assertObject(canvas)
test:assertTrue(canvas:isCanvas(), 'check is canvas')
test:assertFalse(canvas:isComputeWritable(), 'check not compute writable')
-- check dpi -- check dpi
test:assertEquals(love.graphics.getDPIScale(), canvas:getDPIScale(), 'check dpi scale') test:assertEquals(love.graphics.getDPIScale(), canvas:getDPIScale(), 'check dpi scale')
@@ -216,6 +218,16 @@ love.test.graphics.Canvas = function(test)
dcanvas:setDepthSampleMode('equal') dcanvas:setDepthSampleMode('equal')
test:assertEquals('equal', dcanvas:getDepthSampleMode(), 'check depth sample mode set') test:assertEquals('equal', dcanvas:getDepthSampleMode(), 'check depth sample mode set')
-- check compute writeable (wont work on opengl mac)
if love.graphics.getSupported().glsl4 then
local ccanvas = love.graphics.newCanvas(100, 100, {
type = '2d',
format = 'rgba8',
computewrite = true
})
test:assertTrue(ccanvas:isComputeWritable())
end
end end
@@ -303,6 +315,8 @@ love.test.graphics.Image = function(test)
mipmaps = true mipmaps = true
}) })
test:assertObject(image) test:assertObject(image)
test:assertFalse(image:isCanvas(), 'check not canvas')
test:assertFalse(image:isComputeWritable(), 'check not compute writable')
-- check dpi -- check dpi
test:assertEquals(love.graphics.getDPIScale(), image:getDPIScale(), 'check dpi scale') test:assertEquals(love.graphics.getDPIScale(), image:getDPIScale(), 'check dpi scale')
+19 -3
View File
@@ -32,6 +32,11 @@ love.test.image.CompressedImageData = function(test)
-- check mipmap count -- check mipmap count
test:assertEquals(7, idata:getMipmapCount(), 'check mipmap count') test:assertEquals(7, idata:getMipmapCount(), 'check mipmap count')
-- check linear
test:assertFalse(idata:isLinear(), 'check not linear')
idata:setLinear(true)
test:assertTrue(idata:isLinear(), 'check now linear')
end end
@@ -78,12 +83,23 @@ love.test.image.ImageData = function(test)
local r2, g2, b2 = idata:getPixel(25, 25) local r2, g2, b2 = idata:getPixel(25, 25)
test:assertEquals(1, r2+g2+b2, 'check set to red') test:assertEquals(1, r2+g2+b2, 'check set to red')
-- check encoding to an image -- check encoding to an image (png)
idata:encode('png', 'test-encode.png') idata:encode('png', 'test-encode.png')
local read = love.filesystem.openFile('test-encode.png', 'r') local read1 = love.filesystem.openFile('test-encode.png', 'r')
test:assertNotNil(read) test:assertNotNil(read1)
love.filesystem.remove('test-encode.png') love.filesystem.remove('test-encode.png')
-- check encoding to an image (exr)
idata:encode('png', 'test-encode.exr')
local read2 = love.filesystem.openFile('test-encode.exr', 'r')
test:assertNotNil(read2)
love.filesystem.remove('test-encode.exr')
-- check linear
test:assertFalse(idata:isLinear(), 'check not linear')
idata:setLinear(true)
test:assertTrue(idata:isLinear(), 'check now linear')
end end
+13
View File
@@ -64,6 +64,19 @@ love.test.keyboard.setKeyRepeat = function(test)
end end
-- love.keyboard.isModifierActive
love.test.keyboard.isModifierActive = function(test)
local active1 = love.keyboard.isModifierActive('numlock')
local active2 = love.keyboard.isModifierActive('capslock')
local active3 = love.keyboard.isModifierActive('scrolllock')
local active4 = love.keyboard.isModifierActive('mode')
test:assertNotNil(active1)
test:assertNotNil(active2)
test:assertNotNil(active3)
test:assertNotNil(active4)
end
-- love.keyboard.setTextInput -- love.keyboard.setTextInput
love.test.keyboard.setTextInput = function(test) love.test.keyboard.setTextInput = function(test)
love.keyboard.setTextInput(false) love.keyboard.setTextInput(false)
+12
View File
@@ -80,6 +80,18 @@ love.test.sound.SoundData = function(test)
sdata:setSample(0.002, 1) sdata:setSample(0.002, 1)
test:assertEquals(1, sdata:getSample(0.002), 'check setting sample manually') test:assertEquals(1, sdata:getSample(0.002), 'check setting sample manually')
-- check copying from another sound
local copy1 = love.sound.newSoundData('resources/tone.ogg')
local copy2 = love.sound.newSoundData('resources/pop.ogg')
local before = copy2:getSample(0.02)
copy2:copyFrom(copy1, 0.01, 1, 0.02)
test:assertNotEquals(before, copy2:getSample(0.02), 'check changed')
-- check slicing
local count = math.floor(copy1:getSampleCount()/2)
local slice = copy1:slice(0, count)
test:assertEquals(count, slice:getSampleCount(), 'check slice length')
end end
+8
View File
@@ -29,6 +29,14 @@ love.test.system.getOS = function(test)
end end
-- love.system.getPreferredLocales
love.test.system.getPreferredLocales = function(test)
local locale = love.system.getPreferredLocales()
test:assertNotNil(locale)
test:assertEquals('table', type(locale), 'check returns table')
end
-- love.system.getPowerInfo -- love.system.getPowerInfo
love.test.system.getPowerInfo = function(test) love.test.system.getPowerInfo = function(test)
-- check battery state is one of the documented states -- check battery state is one of the documented states
+7 -15
View File
@@ -8,6 +8,13 @@
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- love.window.focus
love.test.window.focus = function(test)
-- cant test as doesnt return anything
test:assertEquals('function', type(love.window.focus), 'check method exists')
end
-- love.window.fromPixels -- love.window.fromPixels
love.test.window.fromPixels = function(test) love.test.window.fromPixels = function(test)
-- check dpi/pixel ratio as expected -- check dpi/pixel ratio as expected
@@ -352,18 +359,3 @@ love.test.window.updateMode = function(test)
resizable = true resizable = true
}) })
end end
-- love.window.close
-- calling love.window.close() last as it will stop the main test image drawing
love.test.window.z_close = function(test)
-- closing window should cause graphics to not be active
love.window.close()
local active = love.graphics.isActive()
test:assertFalse(active, 'check window not active')
-- should also mark the window as not open and not visible
test:assertFalse(love.window.isOpen(), 'check window closed')
test:assertFalse(love.window.isVisible(), 'check window not visible')
love.window.updateMode(360, 240) -- reset
active = love.graphics.isActive()
test:assertTrue(active, 'check window active again')
end
+40
View File
@@ -0,0 +1,40 @@
# TODO
These are all the outstanding methods that require test coverage, along with a few bits that still need doing / discussion.
## General
- ability to test loading different combinations of modules if needed?
- performance tests? need to discuss what + how, might be better as a seperate thing
- check expected behaviour of mount + unmount with common path
try uncommenting love.filesystem.unmountCommonPath and you'll see the issues
- revisit love.audio.setPlaybackDevice when we update openal soft for MacOS
## Physics
- love.physics.World:rayCastAny
- love.physics.World:rayCastClosest
- love.physics.World:getShapesInArea
- love.physics.Body:getShapes
- love.physics.Body:getShape
- love.physics.Body:hasCustomMassData
## Graphics
- love.graphics.copyBuffer
- love.graphics.copyBufferToTexture
- love.graphics.copyTextureToBuffer
- love.graphics.readbackTexture
- love.graphics.readbackTextureAsync
- love.graphics.readbackBuffer
- love.graphics.readbackBufferAsync
- love.graphics.newComputeShader
- love.graphics.dispatchThreadgroupos
- love.graphics.dispatchIndirect
- love.graphics.newTexture
- love.graphics.drawFromShader
- love.graphics.drawFromShaderIndirect
- love.graphics.drawIndirect
- love.graphics.getQuadIndexBuffer
- love.graphics.setBlendState
- love.graphics.setOrthoProjection
- love.graphics.setPerspectiveProjection
- love.graphics.resetProjection
- Mesh:getAttachedAttributes
- Shader:hasStage