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: with:
name: love-x86_64-AppImage-debug name: love-x86_64-AppImage-debug
path: love-${{ github.sha }}.AppImage-debug.tar.gz 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: windows-os:
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
@@ -208,25 +218,22 @@ jobs:
- name: Build Test Exe - name: Build Test Exe
if: steps.vars.outputs.arch != 'ARM64' if: steps.vars.outputs.arch != 'ARM64'
run: cmake --build build --config Release --target install 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' if: steps.vars.outputs.arch != 'ARM64'
run: install\lovec.exe testing/main.lua run: install\lovec.exe testing/main.lua
- name: Love Test Report (OpenGL) - name: Love Test Report
if: steps.vars.outputs.arch != 'ARM64' if: steps.vars.outputs.arch != 'ARM64'
uses: ellraiser/love-test-report@main uses: ellraiser/love-test-report@main
with: with:
name: Love Testsuite Windows (OpenGL) name: Love Testsuite Windows
title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-opengl title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report
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
path: testing/output/lovetest_runAllTests.md path: testing/output/lovetest_runAllTests.md
macOS: macOS:
runs-on: macos-latest runs-on: macos-latest
@@ -256,21 +263,13 @@ jobs:
with: with:
name: love-macos name: love-macos
path: love-macos.zip path: love-macos.zip
- name: Run All Tests (OpenGL) - name: Run All Tests
run: love-macos/love.app/Contents/MacOS/love testing run: love-macos/love.app/Contents/MacOS/love testing
- name: Love Test Report (OpenGL) - name: Love Test Report
uses: ellraiser/love-test-report@main uses: ellraiser/love-test-report@main
with: with:
name: Love Testsuite MacOS (OpenGL) name: Love Testsuite MacOS
title: macos-test-report-opengl title: macos-test-report
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
path: testing/output/lovetest_runAllTests.md path: testing/output/lovetest_runAllTests.md
iOS-Simulator: iOS-Simulator:
runs-on: macos-latest runs-on: macos-latest
+34 -3
View File
@@ -25,11 +25,19 @@ TestMethod = {
result = {}, result = {},
colors = { colors = {
red = {1, 0, 0, 1}, red = {1, 0, 0, 1},
redpale = {1, 0.5, 0.5, 1},
red07 = {0.7, 0, 0, 1},
green = {0, 1, 0, 1}, green = {0, 1, 0, 1},
greenhalf = {0, 0.5, 0, 1},
greenfade = {0, 1, 0, 0.5},
blue = {0, 0, 1, 1}, blue = {0, 0, 1, 1},
bluefade = {0, 0, 1, 0.5},
yellow = {1, 1, 0, 1},
black = {0, 0, 0, 1}, black = {0, 0, 0, 1},
white = {1, 1, 1, 1} white = {1, 1, 1, 1}
} },
delay = 0,
delayed = false
} }
setmetatable(test, self) setmetatable(test, self)
self.__index = self self.__index = self
@@ -69,6 +77,11 @@ TestMethod = {
local coord = pixels[p] local coord = pixels[p]
local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2]) local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2])
local compare_id = tostring(coord[1]) .. ',' .. tostring(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 -- @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[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[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')')
@@ -201,12 +214,19 @@ TestMethod = {
-- @desc - quick assert for value not nil -- @desc - quick assert for value not nil
-- @param {any} value - value to check not nil -- @param {any} value - value to check not nil
-- @return {nil} -- @return {nil}
assertNotNil = function (self, value) assertNotNil = function (self, value, err)
self:assertNotEquals(nil, value, 'check not nil') 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, end,
-- @method - TestMethod:skipTest() -- @method - TestMethod:skipTest()
-- @desc - used to mark this test as skipped for a specific reason -- @desc - used to mark this test as skipped for a specific reason
-- @param {string} reason - reason why method is being skipped -- @param {string} reason - reason why method is being skipped
@@ -217,6 +237,17 @@ TestMethod = {
end, 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() -- @method - TestMethod:evaluateTest()
-- @desc - evaluates the results of all assertions for a final restult -- @desc - evaluates the results of all assertions for a final restult
-- @return {nil} -- @return {nil}
+43 -14
View File
@@ -10,6 +10,7 @@ TestSuite = {
-- testsuite internals -- testsuite internals
modules = {}, modules = {},
module = nil, module = nil,
test = nil,
testcanvas = nil, testcanvas = nil,
current = 1, current = 1,
output = '', output = '',
@@ -19,6 +20,7 @@ TestSuite = {
html = '', html = '',
mdrows = '', mdrows = '',
mdfailures = '', mdfailures = '',
delayed = nil,
fakequit = false, fakequit = false,
windowmode = true, windowmode = true,
@@ -70,7 +72,8 @@ TestSuite = {
if self.module.called[self.module.index] == nil then if self.module.called[self.module.index] == nil then
self.module.called[self.module.index] = true self.module.called[self.module.index] = true
local method = self.module.running[self.module.index] 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 -- 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 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, tested .. matching,
' ==> FAIL (0/0) - call failed - method does not exist' ' ==> FAIL (0/0) - call failed - method does not exist'
) )
-- otherwise run the test method then eval the asserts -- otherwise run the test method
else 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 if ok == false then
print("FATAL", chunk, err) print("FATAL", chunk, err)
test.fatal = tostring(chunk) .. tostring(err) self.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
end end
-- save having to :release() anything we made in the last test
-- 7251ms > 7543ms -- once we've run check delay + eval
collectgarbage("collect") else
-- move onto the next test
self.module.index = self.module.index + 1 -- @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 end
-- once all tests have run
else else
-- print module results and add to output -- print module results and add to output
+2 -2
View File
@@ -1,8 +1,8 @@
function love.conf(t) function love.conf(t)
t.console = true t.console = true
t.window.name = 'love.test' t.window.name = 'love.test'
t.window.width = 256 t.window.width = 360
t.window.height = 256 t.window.height = 240
t.window.resizable = true t.window.resizable = true
t.renderers = {"opengl"} t.renderers = {"opengl"}
t.modules.audio = true t.modules.audio = true
+31 -13
View File
@@ -33,7 +33,7 @@ love.load = function(args)
-- setup basic img to display -- setup basic img to display
if love.window ~= nil then if love.window ~= nil then
love.window.setMode(256, 256, { love.window.setMode(360, 240, {
fullscreen = false, fullscreen = false,
resizable = true, resizable = true,
centered = true centered = true
@@ -47,6 +47,9 @@ love.load = function(args)
img = nil img = nil
} }
Logo.img = love.graphics.newQuad(0, 0, 64, 64, Logo.texture) 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
end end
@@ -63,6 +66,7 @@ love.load = function(args)
local testcmd = '--runAllTests' local testcmd = '--runAllTests'
local module = '' local module = ''
local method = '' local method = ''
local cmderr = 'Invalid flag used'
local modules = { local modules = {
'audio', 'data', 'event', 'filesystem', 'font', 'graphics', 'audio', 'data', 'event', 'filesystem', 'font', 'graphics',
'image', 'math', 'objects', 'physics', 'sound', 'system', 'image', 'math', 'objects', 'physics', 'sound', 'system',
@@ -97,9 +101,14 @@ love.load = function(args)
if testcmd == '--runSpecificMethod' then if testcmd == '--runSpecificMethod' then
local testmodule = TestModule:new(module, method) local testmodule = TestModule:new(module, method)
table.insert(love.test.modules, testmodule) table.insert(love.test.modules, testmodule)
love.test.module = testmodule if module ~= '' and method ~= '' then
love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"') love.test.module = testmodule
love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method 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 end
-- runSpecificModules runs all methods for all the modules given -- 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(love.test.modules, testmodule)
table.insert(modulelist, modules[m]) table.insert(modulelist, modules[m])
end end
if #modulelist > 0 then
love.test.module = love.test.modules[1] love.test.module = love.test.modules[1]
love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"') love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"')
love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_') love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_')
else
cmderr = 'No modules specified'
end
end end
-- otherwise default runs all methods for all modules -- otherwise default runs all methods for all modules
@@ -129,12 +141,14 @@ love.load = function(args)
-- invalid command -- invalid command
if love.test.module == nil then 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 end
-- start first module
love.test.module:runTests()
end end
-- love.update -- love.update
@@ -147,7 +161,11 @@ end
-- love.draw -- love.draw
-- draw a little logo to the screen -- draw a little logo to the screen
love.draw = function() 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 end
+22 -29
View File
@@ -12,6 +12,7 @@ Currently written for löve 12
- [x] No platform-specific dependencies / scripts - [x] No platform-specific dependencies / scripts
- [x] Ability to run a subset of tests - [x] Ability to run a subset of tests
- [x] Ability to easily run an individual test. - [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 ## Coverage
This is the status of all module tests currently. 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 "objects" is a special module to cover any object specific tests, i.e. testing a File object functions as expected
```lua | Module | Passed | Failed | Skipped | Time |
-- [x] audio 26 PASSED | 0 FAILED | 0 SKIPPED | --------------------- | ------ | ------ | ------- | ------ |
-- [x] data 7 PASSED | 0 FAILED | 3 SKIPPED [SEE BELOW] | 🟢 love.audio | 26 | 0 | 0 | 2.602s |
-- [x] event 4 PASSED | 0 FAILED | 2 SKIPPED [SEE BELOW] | 🟢 love.data | 7 | 0 | 3 | 1.003s |
-- [x] filesystem 27 PASSED | 0 FAILED | 2 SKIPPED | 🟢 love.event | 4 | 0 | 2 | 0.599s |
-- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW] | 🟢 love.filesystem | 27 | 0 | 2 | 2.900s |
-- [ ] graphics 65 PASSED | 0 FAILED | 31 SKIPPED [SEE BELOW] | 🟢 love.font | 4 | 0 | 1 | 0.500s |
-- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.graphics | 81 | 0 | 15 | 10.678s |
-- [x] math 17 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.image | 3 | 0 | 0 | 0.300s |
-- [x] physics 22 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.math | 17 | 0 | 0 | 1.678s |
-- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.objects | 1 | 0 | 0 | 0.121s |
-- [x] system 6 PASSED | 0 FAILED | 2 SKIPPED | 🟢 love.physics | 22 | 0 | 0 | 2.197s |
-- [x] thread 3 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.sound | 2 | 0 | 0 | 0.200s |
-- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.system | 6 | 0 | 2 | 0.802s |
-- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED | 🟢 love.thread | 3 | 0 | 0 | 0.300s |
-- [x] window 32 PASSED | 2 FAILED | 2 SKIPPED [SEE BELOW] | 🟢 love.timer | 6 | 0 | 0 | 2.358s |
| 🟢 love.video | 1 | 0 | 0 | 0.100s |
-- [ ] objects STILL TO BE DONE | 🟢 love.window | 34 | 0 | 2 | 8.050s |
-------------------------------------------------------------------------------- **271** tests were completed in **34.387s** with **244** passed, **0** failed, and **27** skipped
-- [x] totals 226 PASSED | 4 FAILED | 43 SKIPPED
```
The following modules are not covered as we can't really emulate input nicely: The following modules are not covered as we can't really emulate input nicely:
`joystick`, `keyboard`, `mouse`, and `touch` `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.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.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.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.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.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back
- **love.objects** - not started properly yet - **love.objects** - not started properly yet
- **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode()
---
## Failures
- **love.window.isMaximized()** - returns false after calling love.window.maximize?
- **love.window.maximize()** - same as above
--- ---
## Stretch Goals ## Stretch Goals
- [ ] Tests can compare visual results to a reference image - [ ] Tests can compare visual results to a reference image
- [ ] Ability to see all visual results at a glance - [ ] Ability to see all visual results at a glance
- [ ] Automatic testing that happens after every commit
- [ ] Ability to test loading different combinations of modules - [ ] Ability to test loading different combinations of modules
- [ ] Performance tests - [ ] Performance tests
+293 -28
View File
@@ -112,11 +112,10 @@ love.test.graphics.rectangle = function(test)
love.graphics.setCanvas() love.graphics.setCanvas()
local imgdata1 = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) local imgdata1 = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
-- test, check red bg and blue central square -- test, check red bg and blue central square
local comparepixels = { test:assertPixels(imgdata1, {
red = {{0,0},{15,0},{15,15},{0,15}}, red = {{0,0},{15,0},{15,15},{0,15}},
blue = {{6,6},{9,6},{9,9},{6,9}} blue = {{6,6},{9,6},{9,9},{6,9}}
} }, 'fill')
test:assertPixels(imgdata1, comparepixels, 'fill')
-- clear canvas to do some line testing -- clear canvas to do some line testing
love.graphics.setCanvas(canvas) love.graphics.setCanvas(canvas)
love.graphics.clear(0, 0, 0, 1) 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.rectangle('line', 1, 1, 2, 15) -- 3x16 left aligned blue outline
love.graphics.setColor(0, 1, 0, 1) love.graphics.setColor(0, 1, 0, 1)
love.graphics.rectangle('line', 11, 1, 5, 15) -- 6x16 right aligned green outline love.graphics.rectangle('line', 11, 1, 5, 15) -- 6x16 right aligned green outline
love.graphics.setColor(1, 1, 1, 1)
love.graphics.setCanvas() love.graphics.setCanvas()
local imgdata2 = love.graphics.readbackTexture(canvas, {1, 1, 0, 0, 16, 16}) local imgdata2 = love.graphics.readbackTexture(canvas, {1, 1, 0, 0, 16, 16})
-- -- check corners and inner corners -- -- check corners and inner corners
comparepixels = { test:assertPixels(imgdata2, {
red = {{3,0},{9,0},{3,15,9,15}}, red = {{3,0},{9,0},{3,15,9,15}},
blue = {{0,0},{2,0},{0,15},{2,15}}, blue = {{0,0},{2,0},{0,15},{2,15}},
green = {{10,0},{15,0},{10,15},{15,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}} black = {
} {1,1},{1,14},{3,1},{9,1},{3,14},
test:assertPixels(imgdata2, comparepixels, 'line') {9,14},{11,1},{14,1},{11,14},{14,14}
}
}, 'line')
end end
@@ -147,10 +149,15 @@ end
-- love.graphics.captureScreenshot -- 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) 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 end
@@ -611,34 +618,117 @@ love.test.graphics.setBackgroundColor = function(test)
test:assertEquals(0, g, 'check set bg g') test:assertEquals(0, g, 'check set bg g')
test:assertEquals(0, b, 'check set bg b') test:assertEquals(0, b, 'check set bg b')
test:assertEquals(1, a, 'check set bg a') test:assertEquals(1, a, 'check set bg a')
love.graphics.setBackgroundColor(0, 0, 0, 1)
end end
-- love.graphics.setBlendMode -- love.graphics.setBlendMode
love.test.graphics.setBlendMode = function(test) love.test.graphics.setBlendMode = function(test)
-- set mode, write to canvas, check output -- create fully white canvas, then draw diff. pixels through blendmodes
test:skipTest('test method needs writing') 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 end
-- love.graphics.setCanvas -- love.graphics.setCanvas
love.test.graphics.setCanvas = function(test) love.test.graphics.setCanvas = function(test)
-- make 2 canvas, set to each, draw one to the other, check output -- 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 end
-- love.graphics.setColor -- love.graphics.setColor
love.test.graphics.setColor = function(test) love.test.graphics.setColor = function(test)
-- set colors, draw rect, check color -- 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 end
-- love.graphics.setColorMask -- love.graphics.setColorMask
love.test.graphics.setColorMask = function(test) love.test.graphics.setColorMask = function(test)
-- set mask, draw stuff, check output pixels -- 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 end
@@ -656,67 +746,243 @@ end
-- love.graphics.setDepthMode -- love.graphics.setDepthMode
love.test.graphics.setDepthMode = function(test) 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 end
-- love.graphics.setFont -- love.graphics.setFont
love.test.graphics.setFont = function(test) 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 end
-- love.graphics.setFrontFaceWinding -- love.graphics.setFrontFaceWinding
love.test.graphics.setFrontFaceWinding = function(test) 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 end
-- love.graphics.setLineJoin -- love.graphics.setLineJoin
love.test.graphics.setLineJoin = function(test) 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 end
-- love.graphics.setLineStyle -- love.graphics.setLineStyle
love.test.graphics.setLineStyle = function(test) 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 end
-- love.graphics.setLineWidth -- love.graphics.setLineWidth
love.test.graphics.setLineWidth = function(test) 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 end
-- love.graphics.setMeshCullMode -- love.graphics.setMeshCullMode
love.test.graphics.setMeshCullMode = function(test) 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 end
-- love.graphics.setScissor -- love.graphics.setScissor
love.test.graphics.setScissor = function(test) 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 end
-- love.graphics.setShader -- love.graphics.setShader
love.test.graphics.setShader = function(test) 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 end
-- love.graphics.setStencilTest -- love.graphics.setStencilTest
love.test.graphics.setStencilMode = function(test) love.test.graphics.setStencilTest = function(test)
test:skipTest('test method needs writing') 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 end
-- love.graphics.setWireframe -- love.graphics.setWireframe
love.test.graphics.setWireframe = function(test) 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 end
@@ -860,7 +1126,6 @@ love.test.graphics.rotate = function(test)
love.graphics.setCanvas() love.graphics.setCanvas()
local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) 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') test:assertPixels(imgdata, { red = {{0,0},{3,0},{3,3},{0,3}} }, 'rotate 90')
imgdata:encode('png', 'rotate.png')
end end
+2 -2
View File
@@ -30,10 +30,10 @@ love.test.system.getPowerInfo = function(test)
test:assertMatch(states, state, 'check value matches') test:assertMatch(states, state, 'check value matches')
-- if percent/seconds check within expected range -- if percent/seconds check within expected range
if percent ~= nil then if percent ~= nil then
test:assertRange(percent, 0, 100, 'check value within range') test:assertRange(percent, 0, 100, 'check battery percent within range')
end end
if seconds ~= nil then if seconds ~= nil then
test:assertRange(seconds, 0, 100, 'check value within range') test:assertNotNil(seconds)
end end
end end
+31 -27
View File
@@ -5,15 +5,13 @@
love.test.window.close = function(test) love.test.window.close = function(test)
-- closing window should cause graphics to not be active -- closing window should cause graphics to not be active
love.window.close() love.window.close()
local active = false local active = love.graphics.isActive()
if love.graphics ~= nil then test:assertEquals(false, active, 'check window not active')
active = love.graphics.isActive() love.window.updateMode(360, 240) -- reset
end active = love.graphics.isActive()
test:assertEquals(false, active, 'check window active') test:assertEquals(true, active, 'check window active again')
love.window.setMode(256, 256) -- reset
end 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
@@ -93,8 +91,8 @@ end
-- @NOTE could prob add more checks on the flags here based on conf.lua -- @NOTE could prob add more checks on the flags here based on conf.lua
love.test.window.getMode = function(test) love.test.window.getMode = function(test)
local w, h, flags = love.window.getMode() local w, h, flags = love.window.getMode()
test:assertEquals(256, w, 'check w') test:assertEquals(360, w, 'check w')
test:assertEquals(256, h, 'check h') test:assertEquals(240, h, 'check h')
test:assertEquals(false, flags["fullscreen"], 'check fullscreen') test:assertEquals(false, flags["fullscreen"], 'check fullscreen')
end end
@@ -169,13 +167,14 @@ end
-- love.window.isMaximized -- love.window.isMaximized
love.test.window.isMaximized = function(test) love.test.window.isMaximized = function(test)
-- check minimized to start if test:isDelayed() == false then
love.window.minimize() love.window.maximize()
test:assertEquals(false, love.window.isMaximized(), 'check window maximized') test:setDelay(10)
-- try to mazimize else
love.window.maximize() -- on MACOS maximize wont get recognised immedietely so wait a few frames
test:assertEquals(true, love.window.isMaximized(), 'check window not maximized') test:assertEquals(true, love.window.isMaximized(), 'check window now maximized')
love.window.restore() love.window.restore()
end
end end
@@ -197,7 +196,7 @@ love.test.window.isOpen = function(test)
-- try closing -- try closing
love.window.close() love.window.close()
test:assertEquals(false, love.window.isOpen(), 'check window closed') test:assertEquals(false, love.window.isOpen(), 'check window closed')
love.window.setMode(256, 256) -- reset love.window.updateMode(360, 240) -- reset
end end
@@ -208,16 +207,21 @@ love.test.window.isVisible = function(test)
-- check closing makes window not visible -- check closing makes window not visible
love.window.close() love.window.close()
test:assertEquals(false, love.window.isVisible(), 'check window not visible') test:assertEquals(false, love.window.isVisible(), 'check window not visible')
love.window.setMode(256, 256) -- reset love.window.updateMode(360, 240) -- reset
end end
-- love.window.maximize -- love.window.maximize
love.test.window.maximize = function(test) love.test.window.maximize = function(test)
-- check maximizing is set if test:isDelayed() == false then
love.window.maximize() -- check maximizing is set
test:assertEquals(true, love.window.isMaximized(), 'check window maximized') love.window.maximize()
love.window.restore() 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 end
@@ -293,7 +297,7 @@ love.test.window.setMode = function(test)
test:assertEquals(512, height, 'check window h match') test:assertEquals(512, height, 'check window h match')
test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen') test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen')
test:assertEquals(false, flags["resizable"], 'check window not resizeable') test:assertEquals(false, flags["resizable"], 'check window not resizeable')
love.window.setMode(256, 256, { love.window.setMode(360, 240, {
fullscreen = false, fullscreen = false,
resizable = true resizable = true
}) })
@@ -353,14 +357,14 @@ love.test.window.updateMode = function(test)
resizable = false resizable = false
}) })
-- update mode with some props but not others -- 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 -- check only changed values changed
local width, height, flags = love.window.getMode() local width, height, flags = love.window.getMode()
test:assertEquals(256, width, 'check window w match') test:assertEquals(360, width, 'check window w match')
test:assertEquals(256, height, 'check window h match') test:assertEquals(240, height, 'check window h match')
test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen') test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen')
test:assertEquals(false, flags["resizable"], 'check window not resizeable') test:assertEquals(false, flags["resizable"], 'check window not resizeable')
love.window.setMode(256, 256, { -- reset love.window.setMode(360, 240, { -- reset
fullscreen = false, fullscreen = false,
resizable = true resizable = true
}) })
+26 -10
View File
@@ -1,18 +1,34 @@
`/Applications/love_12.app/Contents/MacOS/love ./testing` `/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 ## TESTSUITE
- [ ] finish graphics state methods - [ ] setStencilMode to replace setStencilTest
- [ ] start graphics drawing methods - [ ] start graphics drawing methods
- [ ] start object methods - [ ] start object methods
## GRAPHICS
Methods that need a better actual graphics check if possible:
- [ ] setDepthMode
- [ ] setFrontFaceWinding
- [ ] setMeshCullMode
## FUTURE ## 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) - [ ] 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.