added all graphics 'state' tests

This commit is contained in:
ell
2023-10-08 17:12:07 +01:00
parent 8f10ba907c
commit e1948f6e57
10 changed files with 509 additions and 154 deletions
+25 -26
View File
@@ -49,6 +49,16 @@ jobs:
with:
name: love-x86_64-AppImage-debug
path: love-${{ github.sha }}.AppImage-debug.tar.gz
- name: Make Runnable
run: chmod a+x love-linux-x86_64.AppImage
- name: Run All Tests
run: xvfb-run love-linux-x86_64.AppImage testing
- name: Love Test Report
uses: ellraiser/love-test-report@main
with:
name: Love Testsuite Linux
title: linux-test-report
path: testing/output/lovetest_runAllTests.md
windows-os:
runs-on: windows-latest
strategy:
@@ -208,25 +218,22 @@ jobs:
- name: Build Test Exe
if: steps.vars.outputs.arch != 'ARM64'
run: cmake --build build --config Release --target install
- name: Run All Tests (OpenGL)
- name: Install Mesa
if: steps.vars.outputs.arch != 'ARM64'
run: |
curl.exe -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z
7z x mesa.7z
mklink opengl32.dll "x64\opengl32.dll"
mklink libglapi.dll "x64\libglapi.dll"
- name: Run All Tests
if: steps.vars.outputs.arch != 'ARM64'
run: install\lovec.exe testing/main.lua
- name: Love Test Report (OpenGL)
- name: Love Test Report
if: steps.vars.outputs.arch != 'ARM64'
uses: ellraiser/love-test-report@main
with:
name: Love Testsuite Windows (OpenGL)
title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-opengl
path: testing/output/lovetest_runAllTests.md
- name: Run All Tests (Vulkan)
if: steps.vars.outputs.arch != 'ARM64'
run: install\lovec.exe testing/main.lua --renderers vulkan
- name: Love Test Report (Vulkan)
if: steps.vars.outputs.arch != 'ARM64'
uses: ellraiser/love-test-report@main
with:
name: Love Testsuite Windows (Vulkan)
title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-vulkan
name: Love Testsuite Windows
title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report
path: testing/output/lovetest_runAllTests.md
macOS:
runs-on: macos-latest
@@ -256,21 +263,13 @@ jobs:
with:
name: love-macos
path: love-macos.zip
- name: Run All Tests (OpenGL)
- name: Run All Tests
run: love-macos/love.app/Contents/MacOS/love testing
- name: Love Test Report (OpenGL)
- name: Love Test Report
uses: ellraiser/love-test-report@main
with:
name: Love Testsuite MacOS (OpenGL)
title: macos-test-report-opengl
path: testing/output/lovetest_runAllTests.md
- name: Run All Tests (metal)
run: love-macos/love.app/Contents/MacOS/love testing --renderers metal
- name: Love Test Report (metal)
uses: ellraiser/love-test-report@main
with:
name: Love Testsuite MacOS (Metal)
title: macos-test-report-metal
name: Love Testsuite MacOS
title: macos-test-report
path: testing/output/lovetest_runAllTests.md
iOS-Simulator:
runs-on: macos-latest
+34 -3
View File
@@ -25,11 +25,19 @@ TestMethod = {
result = {},
colors = {
red = {1, 0, 0, 1},
redpale = {1, 0.5, 0.5, 1},
red07 = {0.7, 0, 0, 1},
green = {0, 1, 0, 1},
greenhalf = {0, 0.5, 0, 1},
greenfade = {0, 1, 0, 0.5},
blue = {0, 0, 1, 1},
bluefade = {0, 0, 1, 0.5},
yellow = {1, 1, 0, 1},
black = {0, 0, 0, 1},
white = {1, 1, 1, 1}
}
},
delay = 0,
delayed = false
}
setmetatable(test, self)
self.__index = self
@@ -69,6 +77,11 @@ TestMethod = {
local coord = pixels[p]
local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2])
local compare_id = tostring(coord[1]) .. ',' .. tostring(coord[2])
-- prevent us getting stuff like 0.501960785 for 0.5 red
tr = math.floor((tr*10)+0.5)/10
tg = math.floor((tg*10)+0.5)/10
tb = math.floor((tb*10)+0.5)/10
ta = math.floor((ta*10)+0.5)/10
-- @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 .. ')')
@@ -201,12 +214,19 @@ TestMethod = {
-- @desc - quick assert for value not nil
-- @param {any} value - value to check not nil
-- @return {nil}
assertNotNil = function (self, value)
assertNotNil = function (self, value, err)
self:assertNotEquals(nil, value, 'check not nil')
if err ~= nil then
table.insert(self.asserts, {
key = 'assert #' .. tostring(self.count),
passed = false,
message = err,
test = 'assert not nil catch'
})
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
@@ -217,6 +237,17 @@ TestMethod = {
end,
-- currently unused
setDelay = function(self, frames)
self.delay = frames
self.delayed = true
love.test.delayed = self
end,
isDelayed = function(self)
return self.delayed
end,
-- @method - TestMethod:evaluateTest()
-- @desc - evaluates the results of all assertions for a final restult
-- @return {nil}
+43 -14
View File
@@ -10,6 +10,7 @@ TestSuite = {
-- testsuite internals
modules = {},
module = nil,
test = nil,
testcanvas = nil,
current = 1,
output = '',
@@ -19,6 +20,7 @@ TestSuite = {
html = '',
mdrows = '',
mdfailures = '',
delayed = nil,
fakequit = false,
windowmode = true,
@@ -70,7 +72,8 @@ TestSuite = {
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)
self.test = TestMethod:new(method, self.module)
TextRun:set('love.' .. self.module.module .. '.' .. method)
-- 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
@@ -80,26 +83,52 @@ TestSuite = {
tested .. matching,
' ==> FAIL (0/0) - call failed - method does not exist'
)
-- otherwise run the test method then eval the asserts
-- otherwise run the test method
else
local ok, chunk, err = pcall(self[self.module.module][method], test)
local ok, chunk, err = pcall(self[self.module.module][method], self.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)
self.test.fatal = tostring(chunk) .. tostring(err)
end
end
-- save having to :release() anything we made in the last test
-- 7251ms > 7543ms
collectgarbage("collect")
-- move onto the next test
self.module.index = self.module.index + 1
-- once we've run check delay + eval
else
-- @TODO use coroutines?
-- if we have a test method that needs a delay
-- we wait for the delay to run out first
if self.delayed ~= nil then
self.delayed.delay = self.delayed.delay - 1
-- re-run the test method again when delay ends
-- its up to the test to handle the :isDelayed() property
if self.delayed.delay <= 0 then
local ok, chunk, err = pcall(self[self.module.module][self.delayed.method], self.test)
if ok == false then
print("FATAL", chunk, err)
self.test.fatal = tostring(chunk) .. tostring(err)
end
self.delayed = nil
end
else
-- now we're all done evaluate the test
local ok, chunk, err = pcall(self.test.evaluateTest, self.test)
if ok == false then
print("FATAL", chunk, err)
self.test.fatal = tostring(chunk) .. tostring(err)
end
-- save having to :release() anything we made in the last test
-- 7251ms > 7543ms
collectgarbage("collect")
-- move onto the next test
self.module.index = self.module.index + 1
end
end
-- once all tests have run
else
-- print module results and add to output
+2 -2
View File
@@ -1,8 +1,8 @@
function love.conf(t)
t.console = true
t.window.name = 'love.test'
t.window.width = 256
t.window.height = 256
t.window.width = 360
t.window.height = 240
t.window.resizable = true
t.renderers = {"opengl"}
t.modules.audio = true
+31 -13
View File
@@ -33,7 +33,7 @@ love.load = function(args)
-- setup basic img to display
if love.window ~= nil then
love.window.setMode(256, 256, {
love.window.setMode(360, 240, {
fullscreen = false,
resizable = true,
centered = true
@@ -47,6 +47,9 @@ love.load = function(args)
img = nil
}
Logo.img = love.graphics.newQuad(0, 0, 64, 64, Logo.texture)
Font = love.graphics.newFont('resources/font.ttf', 8, 'normal')
TextCommand = love.graphics.newTextBatch(Font, 'Loading...')
TextRun = love.graphics.newTextBatch(Font, '')
end
end
@@ -63,6 +66,7 @@ love.load = function(args)
local testcmd = '--runAllTests'
local module = ''
local method = ''
local cmderr = 'Invalid flag used'
local modules = {
'audio', 'data', 'event', 'filesystem', 'font', 'graphics',
'image', 'math', 'objects', 'physics', 'sound', 'system',
@@ -97,9 +101,14 @@ love.load = function(args)
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
if module ~= '' and method ~= '' then
love.test.module = testmodule
love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"')
love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method
else
if method == '' then cmderr = 'No valid method specified' end
if module == '' then cmderr = 'No valid module specified' end
end
end
-- runSpecificModules runs all methods for all the modules given
@@ -110,10 +119,13 @@ love.load = function(args)
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, '_')
if #modulelist > 0 then
love.test.module = love.test.modules[1]
love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"')
love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_')
else
cmderr = 'No modules specified'
end
end
-- otherwise default runs all methods for all modules
@@ -129,12 +141,14 @@ love.load = function(args)
-- invalid command
if love.test.module == nil then
print("Wrong flags used")
print(cmderr)
love.event.quit(0)
else
-- start first module
TextCommand:set(testcmd)
love.test.module:runTests()
end
-- start first module
love.test.module:runTests()
end
-- love.update
@@ -147,7 +161,11 @@ 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)
local lw = (love.graphics.getPixelWidth() - 128) / 2
local lh = (love.graphics.getPixelHeight() - 128) / 2
love.graphics.draw(Logo.texture, Logo.img, lw, lh, 0, 2, 2)
love.graphics.draw(TextCommand, 4, 12, 0, 2, 2)
love.graphics.draw(TextRun, 4, 32, 0, 2, 2)
end
+22 -29
View File
@@ -12,6 +12,7 @@ Currently written for löve 12
- [x] No platform-specific dependencies / scripts
- [x] Ability to run a subset of tests
- [x] Ability to easily run an individual test.
- [x] Automatic testing that happens after every commit
---
@@ -81,27 +82,25 @@ For sanity-checking, if it's currently not covered or we're not sure how to test
## 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 27 PASSED | 0 FAILED | 2 SKIPPED
-- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW]
-- [ ] graphics 65 PASSED | 0 FAILED | 31 SKIPPED [SEE BELOW]
-- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED
-- [x] math 17 PASSED | 0 FAILED | 0 SKIPPED
-- [x] physics 22 PASSED | 0 FAILED | 0 SKIPPED
-- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED
-- [x] system 6 PASSED | 0 FAILED | 2 SKIPPED
-- [x] thread 3 PASSED | 0 FAILED | 0 SKIPPED
-- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED
-- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED
-- [x] window 32 PASSED | 2 FAILED | 2 SKIPPED [SEE BELOW]
-- [ ] objects STILL TO BE DONE
--------------------------------------------------------------------------------
-- [x] totals 226 PASSED | 4 FAILED | 43 SKIPPED
```
| Module | Passed | Failed | Skipped | Time |
| --------------------- | ------ | ------ | ------- | ------ |
| 🟢 love.audio | 26 | 0 | 0 | 2.602s |
| 🟢 love.data | 7 | 0 | 3 | 1.003s |
| 🟢 love.event | 4 | 0 | 2 | 0.599s |
| 🟢 love.filesystem | 27 | 0 | 2 | 2.900s |
| 🟢 love.font | 4 | 0 | 1 | 0.500s |
| 🟢 love.graphics | 81 | 0 | 15 | 10.678s |
| 🟢 love.image | 3 | 0 | 0 | 0.300s |
| 🟢 love.math | 17 | 0 | 0 | 1.678s |
| 🟢 love.objects | 1 | 0 | 0 | 0.121s |
| 🟢 love.physics | 22 | 0 | 0 | 2.197s |
| 🟢 love.sound | 2 | 0 | 0 | 0.200s |
| 🟢 love.system | 6 | 0 | 2 | 0.802s |
| 🟢 love.thread | 3 | 0 | 0 | 0.300s |
| 🟢 love.timer | 6 | 0 | 0 | 2.358s |
| 🟢 love.video | 1 | 0 | 0 | 0.100s |
| 🟢 love.window | 34 | 0 | 2 | 8.050s |
**271** tests were completed in **34.387s** with **244** passed, **0** failed, and **27** skipped
The following modules are not covered as we can't really emulate input nicely:
`joystick`, `keyboard`, `mouse`, and `touch`
@@ -113,23 +112,17 @@ 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.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected
- **love.graphics** - still need to do tests for the drawing and state methods
- **love.graphics** - still need to do tests for the main drawing methods
- **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.objects** - not started properly yet
---
## Failures
- **love.window.isMaximized()** - returns false after calling love.window.maximize?
- **love.window.maximize()** - same as above
- **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode()
---
## 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
+293 -28
View File
@@ -112,11 +112,10 @@ love.test.graphics.rectangle = function(test)
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 = {
test:assertPixels(imgdata1, {
red = {{0,0},{15,0},{15,15},{0,15}},
blue = {{6,6},{9,6},{9,9},{6,9}}
}
test:assertPixels(imgdata1, comparepixels, 'fill')
}, 'fill')
-- clear canvas to do some line testing
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
@@ -126,16 +125,19 @@ love.test.graphics.rectangle = function(test)
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.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata2 = love.graphics.readbackTexture(canvas, {1, 1, 0, 0, 16, 16})
-- -- check corners and inner corners
comparepixels = {
test:assertPixels(imgdata2, {
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')
black = {
{1,1},{1,14},{3,1},{9,1},{3,14},
{9,14},{11,1},{14,1},{11,14},{14,14}
}
}, 'line')
end
@@ -147,10 +149,15 @@ end
-- love.graphics.captureScreenshot
-- @NOTE could test this but not with current setup as we need to wait for the
-- draw frame to finish before we could assert the file was created
love.test.graphics.captureScreenshot = function(test)
test:skipTest('cant test this worked (easily)')
if test:isDelayed() == false then
love.graphics.captureScreenshot('example-screenshot.png')
test:setDelay(10)
-- need to wait until end of the frame for the screenshot
else
test:assertNotNil(love.filesystem.openFile('example-screenshot.png', 'r'))
love.filesystem.remove('example-screenshot.png')
end
end
@@ -611,34 +618,117 @@ love.test.graphics.setBackgroundColor = function(test)
test:assertEquals(0, g, 'check set bg g')
test:assertEquals(0, b, 'check set bg b')
test:assertEquals(1, a, 'check set bg a')
love.graphics.setBackgroundColor(0, 0, 0, 1)
end
-- love.graphics.setBlendMode
love.test.graphics.setBlendMode = function(test)
-- set mode, write to canvas, check output
test:skipTest('test method needs writing')
-- create fully white canvas, then draw diff. pixels through blendmodes
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0.5, 0.5, 0.5, 1)
love.graphics.setBlendMode('add', 'alphamultiply')
love.graphics.setColor(1, 0, 0, 1)
love.graphics.points({1,1})
love.graphics.setBlendMode('subtract', 'alphamultiply')
love.graphics.setColor(1, 1, 1, 0.5)
love.graphics.points({16,1})
love.graphics.setBlendMode('multiply', 'premultiplied')
love.graphics.setColor(0, 1, 0, 1)
love.graphics.points({16,16})
love.graphics.setBlendMode('replace', 'premultiplied')
love.graphics.setColor(0, 0, 1, 0.5)
love.graphics.points({1,16})
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
-- check the 4 corners
test:assertPixels(imgdata, {
redpale = {{0,0}},
black = {{15,0}},
greenhalf = {{15,15}},
bluefade = {{0,15}}
}, 'blend mode')
love.graphics.setBlendMode('alpha', 'alphamultiply') -- reset
end
-- love.graphics.setCanvas
love.test.graphics.setCanvas = function(test)
-- make 2 canvas, set to each, draw one to the other, check output
test:skipTest('test method needs writing')
local canvas1 = love.graphics.newCanvas(16, 16)
local canvas2 = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas1)
test:assertEquals(canvas1, love.graphics.getCanvas(), 'check canvas 1 set')
love.graphics.clear(1, 0, 0, 1)
love.graphics.setCanvas(canvas2)
test:assertEquals(canvas2, love.graphics.getCanvas(), 'check canvas 2 set')
love.graphics.clear(0, 0, 0, 1)
love.graphics.draw(canvas1, 0, 0)
love.graphics.setCanvas()
test:assertEquals(nil, love.graphics.getCanvas(), 'check no canvas set')
local imgdata = love.graphics.readbackTexture(canvas2, {16, 0, 0, 0, 16, 16})
-- check 2nd canvas is red
test:assertPixels(imgdata, {
red = {{0,0},{15,0},{15,15},{0,15}}
}, 'set canvas')
end
-- love.graphics.setColor
love.test.graphics.setColor = function(test)
-- set colors, draw rect, check color
test:skipTest('test method needs writing')
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)
local r, g, b, a = love.graphics.getColor()
test:assertEquals(1, r, 'check r set')
test:assertEquals(0, g, 'check g set')
test:assertEquals(0, b, 'check b set')
test:assertEquals(1, a, 'check a set')
love.graphics.points({{1,1},{6,1},{11,1},{16,1}})
love.graphics.setColor(1, 1, 0, 1)
love.graphics.points({{1,2},{6,2},{11,2},{16,2}})
love.graphics.setColor(0, 1, 0, 0.5)
love.graphics.points({{1,3},{6,3},{11,3},{16,3}})
love.graphics.setColor(0, 0, 1, 1)
love.graphics.points({{1,4},{6,4},{11,4},{16,4}})
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
red = {{0,0},{5,0},{10,0},{15,0}},
yellow = {{0,1},{5,1},{10,1},{15,1}},
greenhalf = {{0,2},{5,2},{10,2},{15,2}},
blue = {{0,3},{5,3},{10,3},{15,3}}
}, 'set color')
end
-- love.graphics.setColorMask
love.test.graphics.setColorMask = function(test)
-- set mask, draw stuff, check output pixels
test:skipTest('test method needs writing')
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
-- mask off blue
love.graphics.setColorMask(true, true, false, true)
local r, g, b, a = love.graphics.getColorMask()
test:assertEquals(r, true, 'check r mask')
test:assertEquals(g, true, 'check g mask')
test:assertEquals(b, false, 'check b mask')
test:assertEquals(a, true, 'check a mask')
-- draw "black" which should then turn to yellow
love.graphics.setColor(1, 1, 1, 1)
love.graphics.rectangle('fill', 0, 0, 16, 16)
love.graphics.setColorMask(true, true, true, true)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
yellow = {{0,0},{0,15},{15,15},{15,0}}
}, 'set color mask')
end
@@ -656,67 +746,243 @@ end
-- love.graphics.setDepthMode
love.test.graphics.setDepthMode = function(test)
test:skipTest('test method needs writing')
-- check documented modes are valid
local comparemode, write = love.graphics.getDepthMode()
local modes = {
'equal', 'notequal', 'less', 'lequal', 'gequal',
'greater', 'never', 'always'
}
for m=1,#modes do
love.graphics.setDepthMode(modes[m], true)
test:assertEquals(modes[m], love.graphics.getDepthMode(), 'check depth mode ' .. modes[m] .. ' set')
end
love.graphics.setDepthMode(comparemode, write)
-- @TODO better graphics drawing specific test
end
-- love.graphics.setFont
love.test.graphics.setFont = function(test)
test:skipTest('test method needs writing')
-- set font doesnt return anything so draw with the test font
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setFont(Font)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setColor(1, 0, 0, 1)
love.graphics.print('love', 0, 3)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
red = {
{0,0},{0,6},{2,6},{6,2},
{4,4},{8,4},{6,6},{10,2},
{14,2},{12,6}
}
}, 'set font for print')
end
-- love.graphics.setFrontFaceWinding
love.test.graphics.setFrontFaceWinding = function(test)
test:skipTest('test method needs writing')
-- check documented modes are valid
local original = love.graphics.getFrontFaceWinding()
love.graphics.setFrontFaceWinding('cw')
test:assertEquals('cw', love.graphics.getFrontFaceWinding(), 'check ffw cw set')
love.graphics.setFrontFaceWinding('ccw')
test:assertEquals('ccw', love.graphics.getFrontFaceWinding(), 'check ffw ccw set')
love.graphics.setFrontFaceWinding(original)
-- @TODO better graphics drawing specific test
end
-- love.graphics.setLineJoin
love.test.graphics.setLineJoin = function(test)
test:skipTest('test method needs writing')
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setFont(Font)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
local line = {0,1,8,1,8,8}
love.graphics.setLineStyle('rough')
love.graphics.setLineWidth(2)
love.graphics.setColor(1, 0, 0)
love.graphics.setLineJoin('bevel')
love.graphics.line(line)
love.graphics.translate(0, 4)
love.graphics.setColor(1, 1, 0)
love.graphics.setLineJoin('none')
love.graphics.line(line)
love.graphics.translate(0, 4)
love.graphics.setColor(0, 0, 1)
love.graphics.setLineJoin('miter')
love.graphics.line(line)
love.graphics.setColor(1, 1, 1)
love.graphics.setLineWidth(1)
love.graphics.origin()
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
black = {{8,0}},
red = {{8,4}},
yellow = {{8,7}},
blue = {{8,8}}
}, 'set line join')
end
-- love.graphics.setLineStyle
love.test.graphics.setLineStyle = function(test)
test:skipTest('test method needs writing')
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setFont(Font)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setColor(1, 0, 0)
local line = {0,1,16,1}
love.graphics.setLineStyle('rough')
love.graphics.line(line)
love.graphics.translate(0, 4)
love.graphics.setLineStyle('smooth')
love.graphics.line(line)
love.graphics.setLineStyle('rough')
love.graphics.setColor(1, 1, 1)
love.graphics.origin()
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
red = {{0,0},{7,0},{15,0}},
red07 = {{0,4},{7,4},{15,4}}
}, 'set line style')
end
-- love.graphics.setLineWidth
love.test.graphics.setLineWidth = function(test)
test:skipTest('test method needs writing')
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setFont(Font)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
local line = {0,1,8,1,8,8}
love.graphics.setColor(1, 0, 0)
love.graphics.setLineWidth(2)
love.graphics.line(line)
love.graphics.translate(0, 4)
love.graphics.setColor(1, 1, 0)
love.graphics.setLineWidth(3)
love.graphics.line(line)
love.graphics.translate(0, 4)
love.graphics.setColor(0, 0, 1)
love.graphics.setLineWidth(4)
love.graphics.line(line)
love.graphics.setColor(1, 1, 1)
love.graphics.setLineWidth(1)
love.graphics.origin()
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
black = {{0,2},{6,2},{0,6},{5,6},{0,11},{5,11}},
red = {{0,0},{0,1},{7,2},{8,2}},
yellow = {{0,3},{0,5},{6,6},{8,6}},
blue = {{0,7},{0,10},{6,15},{9,15}}
}, 'set line width')
end
-- love.graphics.setMeshCullMode
love.test.graphics.setMeshCullMode = function(test)
test:skipTest('test method needs writing')
-- check documented modes are valid
local original = love.graphics.getMeshCullMode()
local modes = {'back', 'front', 'none'}
for m=1,#modes do
love.graphics.setMeshCullMode(modes[m])
test:assertEquals(modes[m], love.graphics.getMeshCullMode(), 'check mesh cull mode ' .. modes[m] .. ' was set')
end
love.graphics.setMeshCullMode(original)
-- @TODO better graphics drawing specific test
end
-- love.graphics.setScissor
love.test.graphics.setScissor = function(test)
test:skipTest('test method needs writing')
-- make a scissor for the left half
-- then we should be able to fill the canvas with red and only left is filled
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.origin()
love.graphics.setScissor(0, 0, 8, 16)
love.graphics.clear(1, 0, 0, 1)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setScissor()
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
red = {{0,0},{7,0},{0,15},{7,15}},
black ={{8,0},{8,15},{15,0},{15,15}}
}, 'set scissor')
end
-- love.graphics.setShader
love.test.graphics.setShader = function(test)
test:skipTest('test method needs writing')
-- make a shader that will only ever draw yellow
local pixelcode = 'vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); return vec4(1.0,1.0,0.0,1.0);}'
local vertexcode = 'vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform_projection * vertex_position; }'
local shader = love.graphics.newShader(pixelcode, vertexcode)
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setShader(shader)
-- draw red rectangle
love.graphics.setColor(1, 0, 0, 1)
love.graphics.rectangle('fill', 0, 0, 16, 16)
love.graphics.setShader()
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
yellow = {{0,0},{15,0},{0,15},{15,15}},
}, 'check shader set to yellow')
end
-- love.graphics.setStencilTest
love.test.graphics.setStencilMode = function(test)
test:skipTest('test method needs writing')
love.test.graphics.setStencilTest = function(test)
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas({canvas, stencil=true})
love.graphics.clear(0, 0, 0, 1)
love.graphics.stencil(function()
love.graphics.circle('fill', 8, 8, 6)
end, 'replace', 1)
love.graphics.setStencilTest('greater', 0)
love.graphics.setColor(1, 0, 0, 1)
love.graphics.rectangle('fill', 0, 0, 16, 16)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setStencilTest()
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
red = {{6,2},{9,2},{2,6},{2,9},{13,6},{9,6},{6,13},{9,13}}
}, 'check stencil test')
end
-- love.graphics.setWireframe
love.test.graphics.setWireframe = function(test)
test:skipTest('test method needs writing')
-- check wireframe outlines
love.graphics.setWireframe(true)
local canvas = love.graphics.newCanvas(16, 16)
love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1)
love.graphics.setColor(1, 1, 0, 1)
love.graphics.rectangle('fill', 2, 2, 13, 13)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setWireframe(false)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, {
yellow = {{1,14},{14,1},{14,14},{2,2},{13,13}},
black = {{2,13},{13,2}}
}, 'set wireframe')
end
@@ -860,7 +1126,6 @@ love.test.graphics.rotate = function(test)
love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
test:assertPixels(imgdata, { red = {{0,0},{3,0},{3,3},{0,3}} }, 'rotate 90')
imgdata:encode('png', 'rotate.png')
end
+2 -2
View File
@@ -30,10 +30,10 @@ love.test.system.getPowerInfo = function(test)
test:assertMatch(states, state, 'check value matches')
-- if percent/seconds check within expected range
if percent ~= nil then
test:assertRange(percent, 0, 100, 'check value within range')
test:assertRange(percent, 0, 100, 'check battery percent within range')
end
if seconds ~= nil then
test:assertRange(seconds, 0, 100, 'check value within range')
test:assertNotNil(seconds)
end
end
+31 -27
View File
@@ -5,15 +5,13 @@
love.test.window.close = function(test)
-- closing window should cause graphics to not be active
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
local active = love.graphics.isActive()
test:assertEquals(false, active, 'check window not active')
love.window.updateMode(360, 240) -- reset
active = love.graphics.isActive()
test:assertEquals(true, active, 'check window active again')
end
-- love.window.fromPixels
love.test.window.fromPixels = function(test)
-- check dpi/pixel ratio as expected
@@ -93,8 +91,8 @@ end
-- @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(360, w, 'check w')
test:assertEquals(240, h, 'check h')
test:assertEquals(false, flags["fullscreen"], 'check fullscreen')
end
@@ -169,13 +167,14 @@ end
-- love.window.isMaximized
love.test.window.isMaximized = function(test)
-- check minimized to start
love.window.minimize()
test:assertEquals(false, love.window.isMaximized(), 'check window maximized')
-- try to mazimize
love.window.maximize()
test:assertEquals(true, love.window.isMaximized(), 'check window not maximized')
love.window.restore()
if test:isDelayed() == false then
love.window.maximize()
test:setDelay(10)
else
-- on MACOS maximize wont get recognised immedietely so wait a few frames
test:assertEquals(true, love.window.isMaximized(), 'check window now maximized')
love.window.restore()
end
end
@@ -197,7 +196,7 @@ love.test.window.isOpen = function(test)
-- try closing
love.window.close()
test:assertEquals(false, love.window.isOpen(), 'check window closed')
love.window.setMode(256, 256) -- reset
love.window.updateMode(360, 240) -- reset
end
@@ -208,16 +207,21 @@ love.test.window.isVisible = function(test)
-- check closing makes window not visible
love.window.close()
test:assertEquals(false, love.window.isVisible(), 'check window not visible')
love.window.setMode(256, 256) -- reset
love.window.updateMode(360, 240) -- reset
end
-- love.window.maximize
love.test.window.maximize = function(test)
-- check maximizing is set
love.window.maximize()
test:assertEquals(true, love.window.isMaximized(), 'check window maximized')
love.window.restore()
if test:isDelayed() == false then
-- check maximizing is set
love.window.maximize()
test:setDelay(10)
else
-- on macos we need to wait a few frames
test:assertEquals(true, love.window.isMaximized(), 'check window maximized')
love.window.restore()
end
end
@@ -293,7 +297,7 @@ love.test.window.setMode = function(test)
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, {
love.window.setMode(360, 240, {
fullscreen = false,
resizable = true
})
@@ -353,14 +357,14 @@ love.test.window.updateMode = function(test)
resizable = false
})
-- update mode with some props but not others
love.window.updateMode(256, 256, nil)
love.window.updateMode(360, 240, nil)
-- check only changed values changed
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(360, width, 'check window w match')
test:assertEquals(240, 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, { -- reset
love.window.setMode(360, 240, { -- reset
fullscreen = false,
resizable = true
})
+26 -10
View File
@@ -1,18 +1,34 @@
`/Applications/love_12.app/Contents/MacOS/love ./testing`
## CI
- [ ] ignore test suite for windows AMD
- [ ] add test run to linux (opengl+vulkan) + ios builds (opengl+metal)
## TESTSUITE
- [ ] finish graphics state methods
- [ ] setStencilMode to replace setStencilTest
- [ ] start graphics drawing methods
- [ ] start object methods
## GRAPHICS
Methods that need a better actual graphics check if possible:
- [ ] setDepthMode
- [ ] setFrontFaceWinding
- [ ] setMeshCullMode
## FUTURE
- [ ] pass in err string returns to the test output
maybe even assertNotNil could use the second value automatically
test:assertNotNil(love.filesystem.openFile('file2', 'r')) wouldn't have to change
- [ ] some joystick/input stuff could be at least nil checked maybe?
- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported)
could add platform as global to command and then use in tests?
could add platform as global to command and then use in tests?
- [ ] use coroutines for the delay action? i.e. wrap each test call in coroutine
and then every test can use coroutine.yield() if needed
- [ ] could nil check some joystick and keyboard methods?
## GITHUB ACTION CI
- [ ] linux needs to run xvfb-run with the appimage
- [ ] windows can try installing mesa for opengl replacement
- [ ] ios test run?
Can't run --renderers metal on github action images:
Run love-macos/love.app/Contents/MacOS/love testing --renderers metal
Cannot create Metal renderer: Metal is not supported on this system.
Cannot create graphics: no supported renderer on this system.
Error: Cannot create graphics: no supported renderer on this system.
Can't run test suite on windows as it stands:
Unable to create renderer
This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2.