Browse Source

Merge pull request #2043 from ellraiser/main

testsuite updates
Sasha Szpakowski 1 year ago
parent
commit
339c1acde8

+ 1 - 0
.gitignore

@@ -73,3 +73,4 @@ stamp-h1
 /testing/output/*.html
 /testing/output/*.md
 /testing/output/actual/*.png
+/testing/output/difference/*.png

+ 93 - 49
testing/classes/TestMethod.lua

@@ -64,7 +64,7 @@ TestMethod = {
     table.insert(self.asserts, {
       key = 'assert ' .. tostring(self.count),
       passed = expected == actual,
-      message = 'expected \'' .. tostring(expected) .. '\' got \'' .. 
+      message = 'expected \'' .. tostring(expected) .. '\' got \'' ..
         tostring(actual) .. '\'',
       test = label or 'no label given'
     })
@@ -81,7 +81,7 @@ TestMethod = {
     table.insert(self.asserts, {
       key = 'assert ' .. tostring(self.count),
       passed = value == true,
-      message = 'expected \'true\' got \'' .. 
+      message = 'expected \'true\' got \'' ..
         tostring(value) .. '\'',
       test = label or 'no label given'
     })
@@ -98,7 +98,7 @@ TestMethod = {
     table.insert(self.asserts, {
       key = 'assert ' .. tostring(self.count),
       passed = value == false,
-      message = 'expected \'false\' got \'' .. 
+      message = 'expected \'false\' got \'' ..
         tostring(value) .. '\'',
       test = label or 'no label given'
     })
@@ -165,7 +165,7 @@ TestMethod = {
 
 
   -- @method - TestMethod:assertGreaterEqual()
-  -- @desc - used to check a value is >= than a certain target value 
+  -- @desc - used to check a value is >= than a certain target value
   -- @param {any} target - value to check the test agaisnt
   -- @param {any} actual - actual value of the test
   -- @param {string} label - label for this test to use in exports
@@ -187,7 +187,7 @@ TestMethod = {
 
 
   -- @method - TestMethod:assertLessEqual()
-  -- @desc - used to check a value is <= than a certain target value 
+  -- @desc - used to check a value is <= than a certain target value
   -- @param {any} target - value to check the test agaisnt
   -- @param {any} actual - actual value of the test
   -- @param {string} label - label for this test to use in exports
@@ -209,7 +209,7 @@ TestMethod = {
 
 
   -- @method - TestMethod:assertObject()
-  -- @desc - used to check a table is a love object, this runs 3 seperate 
+  -- @desc - used to check a table is a love object, this runs 3 seperate
   --         tests to check table has the basic properties of an object
   -- @note - actual object functionality tests have their own methods
   -- @param {table} obj - table to check is a valid love object
@@ -238,7 +238,7 @@ TestMethod = {
     table.insert(self.asserts, {
       key = 'assert ' .. tostring(self.count),
       passed = passing,
-      message = 'expected \'' .. tostring(expected[1]) .. 'x,' .. 
+      message = 'expected \'' .. tostring(expected[1]) .. 'x,' ..
         tostring(expected[2]) .. 'y\' got \'' ..
         tostring(actual[1]) .. 'x,' .. tostring(actual[2]) .. 'y\'',
       test = label or 'no label given'
@@ -247,7 +247,7 @@ TestMethod = {
 
 
   -- @method - TestMethod:assertNotNil()
-  -- @desc - quick assert for value not nil 
+  -- @desc - quick assert for value not nil
   -- @param {any} value - value to check not nil
   -- @return {nil}
   assertNotNil = function (self, value, err)
@@ -264,8 +264,8 @@ TestMethod = {
 
 
   -- @method - TestMethod:compareImg()
-  -- @desc - compares a given image to the 'expected' version, with a tolerance of 
-  --         1px in any direction, and then saves it as the 'actual' version for 
+  -- @desc - compares a given image to the 'expected' version, with a tolerance of
+  --         1px in any direction, and then saves it as the 'actual' version for
   --         report viewing
   -- @param {table} imgdata - imgdata to save as a png
   -- @return {nil}
@@ -275,24 +275,28 @@ TestMethod = {
     local ok, chunk, _ = pcall(love.image.newImageData, expected_path)
     if ok == false then return self:assertEquals(true, false, chunk) end
     local expected = chunk
-    local iw = imgdata:getWidth()-2
-    local ih = imgdata:getHeight()-2
+    local iw = imgdata:getWidth()-1
+    local ih = imgdata:getHeight()-1
+    local differences = {}
     local rgba_tolerance = self.rgba_tolerance * (1/255)
-    for ix=2,iw do
-      for iy=2,ih do
+
+    -- for each pixel, compare the expected vs the actual pixel data
+    -- by default rgba_tolerance is 0
+    for ix=0,iw do
+      for iy=0,ih do
         local ir, ig, ib, ia = imgdata:getPixel(ix, iy)
         local points = {
           {expected:getPixel(ix, iy)}
         }
         if self.pixel_tolerance > 0 then
-          table.insert(points, {expected:getPixel(ix-1, iy+1)})
-          table.insert(points, {expected:getPixel(ix-1, iy)})
-          table.insert(points, {expected:getPixel(ix-1, iy-1)})
-          table.insert(points, {expected:getPixel(ix, iy+1)})
-          table.insert(points, {expected:getPixel(ix, iy-1)})
-          table.insert(points, {expected:getPixel(ix+1, iy+1)})
-          table.insert(points, {expected:getPixel(ix+1, iy)})
-          table.insert(points, {expected:getPixel(ix+1, iy-1)})
+          if ix > 0 and iy < ih-1 then table.insert(points, {expected:getPixel(ix-1, iy+1)}) end
+          if ix > 0 then table.insert(points, {expected:getPixel(ix-1, iy)}) end
+          if ix > 0 and iy > 0 then table.insert(points, {expected:getPixel(ix-1, iy-1)}) end
+          if iy < ih-1 then table.insert(points, {expected:getPixel(ix, iy+1)}) end
+          if iy > 0 then table.insert(points, {expected:getPixel(ix, iy-1)}) end
+          if ix < iw-1 and iy < ih-1 then table.insert(points, {expected:getPixel(ix+1, iy+1)}) end
+          if ix < iw-1 then table.insert(points, {expected:getPixel(ix+1, iy)}) end
+          if ix < iw-1 and iy > 0 then table.insert(points, {expected:getPixel(ix+1, iy-1)}) end
         end
         local has_match_r = false
         local has_match_g = false
@@ -317,23 +321,48 @@ TestMethod = {
           tostring(ix) .. ',' .. tostring(iy) .. ', matching = ' .. ymatch ..
           ', not matching = ' .. nmatch .. ' (' .. self.method .. '-' .. tostring(self.imgs) .. ')'
         )
+        -- add difference co-ord for rendering later
+        if matching ~= true then
+          table.insert(differences, ix+1)
+          table.insert(differences, iy+1)
+        end
       end
     end
     local path = 'tempoutput/actual/love.test.graphics.' ..
       self.method .. '-' .. tostring(self.imgs) .. '.png'
     imgdata:encode('png', path)
+
+    -- if we have differences draw them to a new canvas to display in HTML report
+    local dpath = 'tempoutput/difference/love.test.graphics.' ..
+      self.method .. '-' .. tostring(self.imgs) .. '.png'
+    if #differences > 0 then
+      local difference = love.graphics.newCanvas(iw+1, ih+1)
+      love.graphics.setCanvas(difference)
+        love.graphics.clear(0, 0, 0, 1)
+        love.graphics.setColor(1, 0, 1, 1)
+        love.graphics.points(differences)
+        love.graphics.setColor(1, 1, 1, 1)
+      love.graphics.setCanvas()
+      love.graphics.readbackTexture(difference):encode('png', dpath)
+
+    -- otherwise clear the old difference file (if any) to stop it coming up 
+    -- in future reports when there's no longer a difference
+    elseif love.filesystem.openFile(dpath, 'r') then
+      love.filesystem.remove(dpath)
+    end
+
     self.imgs = self.imgs + 1
   end,
 
 
   -- @method - TestMethod:exportImg()
   -- @desc - exports the given imgdata to the 'output/expected/' folder, to use when
-  --         writing new graphics tests to set the expected image output 
-  -- @NOTE - you should not leave this method in when you are finished this is 
+  --         writing new graphics tests to set the expected image output
+  -- @NOTE - you should not leave this method in when you are finished this is
   --         for test writing only
   -- @param {table} imgdata - imgdata to save as a png
   -- @param {integer} imgdata - index of the png, graphic tests are run sequentially
-  --                            and each test image is numbered in order that its 
+  --                            and each test image is numbered in order that its
   --                            compared to, so set the number here to match
   -- @return {nil}
   exportImg = function(self, imgdata, index)
@@ -386,6 +415,21 @@ TestMethod = {
     return false
   end,
 
+  -- @method - TestMethod:isLuaVersion()
+  -- @desc - checks for a specific Lua version (or list of versions)
+  -- @param {number} - the minimum Lua version to check against
+  -- @return {boolean} - returns true if the current Lua version is at least the given version
+  isAtLeastLuaVersion = function(self, version)
+    return love.test.lua_version >= version
+  end,
+
+  -- @method - TestMethod:isLuaJITEnabled()
+  -- @desc - checks if LuaJIT is enabled
+  -- @return {boolean} - returns true if LuaJIT is enabled
+  isLuaJITEnabled = function(self)
+    return love.test.has_lua_jit
+  end,
+
   -- @method - TestMethod:evaluateTest()
   -- @desc - evaluates the results of all assertions for a final restult
   -- @return {nil}
@@ -410,10 +454,10 @@ TestMethod = {
     if self.skipped then
       self.testmodule.skipped = self.testmodule.skipped + 1
       love.test.totals[3] = love.test.totals[3] + 1
-      self.result = { 
-        total = '', 
-        result = "SKIP", 
-        passed = false, 
+      self.result = {
+        total = '',
+        result = "SKIP",
+        passed = false,
         message = '(0/0) - method skipped [' .. self.skipreason .. ']',
         failures = {}
       }
@@ -424,10 +468,10 @@ TestMethod = {
         self.passed = true
         self.testmodule.passed = self.testmodule.passed + 1
         love.test.totals[1] = love.test.totals[1] + 1
-        self.result = { 
-          total = total, 
-          result = 'PASS', 
-          passed = true, 
+        self.result = {
+          total = total,
+          result = 'PASS',
+          passed = true,
           message = nil,
           failures = {}
         }
@@ -517,25 +561,25 @@ TestMethod = {
     local preview = ''
     if self.testmodule.module == 'graphics' then
       local filename = 'love.test.graphics.' .. self.method
-      if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-1.png', 'r') then
-        preview = '<div class="preview">' .. '<img src="expected/' .. filename .. '-1.png"/><p>Expected</p></div>' ..
-          '<div class="preview">' .. '<img src="actual/' .. filename .. '-1.png"/><p>Actual</p></div>'
-      end
-      if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-2.png', 'r') then
-        preview = preview .. '<div class="preview">' .. '<img src="expected/' .. filename .. '-2.png"/><p>Expected</p></div>' ..
-          '<div class="preview">' .. '<img src="actual/' .. filename .. '-2.png"/><p>Actual</p></div>'
-      end
-      if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-3.png', 'r') then
-        preview = preview .. '<div class="preview">' .. '<img src="expected/' .. filename .. '-3.png"/><p>Expected</p></div>' ..
-          '<div class="preview">' .. '<img src="actual/' .. filename .. '-3.png"/><p>Actual</p></div>'
+      for f=1,5 do
+        local fstr = tostring(f)
+        if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-' .. fstr .. '.png', 'r') then
+          preview = preview .. '<div class="preview-wrap">'
+          preview = preview .. '<div class="preview">' .. '<img src="expected/' .. filename .. '-' .. fstr .. '.png"/><p>Expected</p></div>' ..
+            '<div class="preview">' .. '<img src="actual/' .. filename .. '-' .. fstr .. '.png"/><p>Actual</p></div>'
+          if love.filesystem.openFile('tempoutput/difference/' .. filename .. '-' .. fstr .. '.png', 'r') then
+            preview = preview .. '<div class="preview">' .. '<img src="difference/' .. filename .. '-' .. fstr .. '.png"/><p>Difference</p></div>'
+          end
+          preview = preview .. '</div>'
+        end
       end
     end
 
-    -- append HTML for the test class result 
-    local status = '🔴'
+    -- append HTML for the test class result
+    local status = ''
     local cls = 'red'
-    if self.passed then status = '🟢'; cls = '' end
-    if self.skipped then status = '🟡'; cls = '' end
+    if self.passed then status = '<div class="icon pass"></div>'; cls = 'green' end
+    if self.skipped then status = ''; cls = 'yellow' end
     self.testmodule.html = self.testmodule.html ..
       '<tr class=" ' .. cls .. '">' ..
         '<td>' .. status .. '</td>' ..
@@ -565,7 +609,7 @@ TestMethod = {
       self.result.total .. msg
     )
 
-    -- if we failed on multiple asserts, list them here - makes it easier for 
+    -- if we failed on multiple asserts, list them here - makes it easier for
     -- debugging new methods added that are failing multiple asserts
     if #self.result.failures > 1 then
       for f=2,#self.result.failures do

+ 18 - 8
testing/classes/TestModule.lua

@@ -82,8 +82,8 @@ TestModule = {
   -- @return {nil}
   printResult = function(self)
     local finaltime = UtilTimeFormat(self.time)
-    local status = '🔴'
-    if self.failed == 0 then status = '🟢' end
+    local status = '<div class="icon fail"></div>'
+    if self.failed == 0 then status = '<div class="icon pass"></div>' end
     -- add md row to main output
     love.test.mdrows = love.test.mdrows .. '| ' .. status .. 
       ' ' .. self.module .. 
@@ -98,13 +98,23 @@ TestModule = {
       '" skipped="' .. tostring(self.skipped) ..
       '" time="' .. finaltime .. '">\n' .. self.xml .. '\t</testsuite>\n'
     -- add html to main output
-    love.test.html = love.test.html .. '<h2>' .. status .. '&nbsp;love.' .. self.module .. '</h2><ul class="summary">' ..
-      '<li>🟢&nbsp;' .. tostring(self.passed) .. ' Tests</li>' ..
-      '<li>🔴&nbsp;' .. tostring(self.failed) .. ' Failures</li>' ..
-      '<li>🟡&nbsp;' .. tostring(self.skipped) .. ' Skipped</li>' ..
-      '<li>' .. finaltime .. 's</li>' .. '<ul><br/><br/>' ..
+    local module_cls = 'toggle close'
+    local module_txt = '▶'
+    local wrap_cls = ''
+    if self.failed > 0 then
+      module_cls = 'toggle open'
+      module_txt = '▼'
+      wrap_cls = 'fail'
+    end
+    love.test.html = love.test.html .. '<div class="module ' .. wrap_cls .. '">' ..
+      '<div class="' .. module_cls .. '" onclick="toggle(this)">' .. module_txt .. '</div>' .. 
+      '<h2>' .. status .. '&nbsp;love.' .. self.module .. '</h2><ul class="summary">' ..
+      '<li class="l' .. tostring(self.passed) .. '">' .. tostring(self.passed) .. ' Passed</li>' ..
+      '<li class="l' .. tostring(self.failed) .. '">' .. tostring(self.failed) .. ' Failed</li>' ..
+      '<li class="l' .. tostring(self.skipped) .. '">' .. tostring(self.skipped) .. ' Skipped</li>' ..
+      '<li>' .. finaltime .. 's</li>' .. '</ul><br/><br/>' ..
       '<table><thead><tr><td width="20px"></td><td width="100px">Method</td><td width="60px">Time</td><td>Details</td></tr></thead><tbody>' ..
-      self.html .. '</tbody></table>'
+      self.html .. '</tbody></table></div>'
     -- print module results to console
     self:log('yellow', 'love.' .. self.module .. '.testmodule.end')
     local failedcol = '\27[31m'

+ 65 - 14
testing/classes/TestSuite.lua

@@ -24,6 +24,8 @@ TestSuite = {
       fakequit = false,
       windowmode = true,
       current_os = love._os,
+      lua_version = tonumber(_VERSION:match("%d%.%d")),
+      has_lua_jit = type(jit) == 'table',
 
       -- love modules to test
       audio = {},
@@ -98,7 +100,7 @@ TestSuite = {
 
               -- when wait finished (or no yields)
               if coroutine.status(self.test.co) == 'dead' then
-                -- now we're all done evaluate the test 
+                -- now we're all done evaluate the test
                 local ok, chunk, err = pcall(self.test.evaluateTest, self.test)
                 if ok == false then
                   self.test.passed = false
@@ -129,7 +131,7 @@ TestSuite = {
               self:printResult()
               love.event.quit(0)
             end
-  
+
           end
         end
       end
@@ -152,7 +154,7 @@ TestSuite = {
     if love.graphics then
       name, version, vendor, device = love.graphics.getRendererInfo()
     end
-    
+
     local md = '<!-- PASSED ' .. tostring(self.totals[1]) ..
       ' || FAILED ' .. tostring(self.totals[2]) ..
       ' || SKIPPED ' .. tostring(self.totals[3]) ..
@@ -161,25 +163,74 @@ TestSuite = {
       finaltime .. 's** with **' ..
       tostring(self.totals[1]) .. '** passed, **' ..
       tostring(self.totals[2]) .. '** failed, and **' ..
-      tostring(self.totals[3]) .. '** skipped\n\n' .. 
+      tostring(self.totals[3]) .. '** skipped\n\n' ..
       'Renderer: ' .. name .. ' | ' .. version .. ' | ' .. vendor .. ' | ' .. device .. '\n\n' ..
       '### Report\n' ..
       '| Module                | Pass | Fail | Skip | Time   |\n' ..
       '| --------------------- | ------ | ------ | ------- | ------ |\n' ..
       self.mdrows .. '\n### Failures\n' .. self.mdfailures
 
-    local xml = '<testsuites name="love.test" tests="' .. tostring(self.totals[1]) .. 
-      '" failures="' .. tostring(self.totals[2]) .. 
-      '" skipped="' .. tostring(self.totals[3]) .. 
+    local xml = '<testsuites name="love.test" tests="' .. tostring(self.totals[1]) ..
+      '" failures="' .. tostring(self.totals[2]) ..
+      '" skipped="' .. tostring(self.totals[3]) ..
       '" time="' .. finaltime .. '">\n'
 
-    local status = '🔴'
-    if self.totals[2] == 0 then status = '🟢' end
-    local html = '<html><head><style>* { font-family: monospace; margin: 0; font-size: 11px; padding: 0; } body { margin: 50px; } h1 { padding-bottom: 10px; font-size: 13px; } h2 { padding: 20px 0 10px 0; font-size: 12px; } .summary { list-style: none; margin: 0; padding: 0; } .summary li { float: left; background: #eee; padding: 5px; margin-right: 10px; } table { background: #eee; margin-top: 10px; width: 100%; max-width: 800px; border-collapse: collapse } table thead { background: #ddd; } table th, table td { padding: 2px; } tr.red { color: red } .wrap { max-width: 800px; margin: auto; } .preview { width: 64px; height: 80px; float: left; margin-right: 10px; } .preview img { width: 100% } .preview p { text-align: center; }</style></head><body><div class="wrap"><h1>' .. status .. '&nbsp;love.test</h1><ul class="summary">'
-    html = html .. 
-      '<li>🟢&nbsp;' .. tostring(self.totals[1]) .. ' Tests</li>' ..
-      '<li>🔴&nbsp;' .. tostring(self.totals[2]) .. ' Failures</li>' ..
-      '<li>🟡&nbsp;' .. tostring(self.totals[3]) .. ' Skipped</li>' ..
+    local status = '<div class="icon fail"></div>'
+    if self.totals[2] == 0 then status = '<div class="icon pass"></div>' end
+    local html = [[
+      <html>
+        <head>
+          <style>
+          * { font-family: monospace; margin: 0; font-size: 11px; padding: 0; }
+          body { margin: 40px 50px 50px 50px; overflow-y: scroll; background: #222; }
+          h1 { font-weight: normal; color: #eee; font-size: 12px; width: 140px; border-radius: 2px; padding: 5px 0; float: left; background: #333;  }
+          h2 { font-weight: normal; color: #eee; font-size: 12px; width: 140px; border-radius: 2px;  }
+          .summary { z-index: 10; position: relative; list-style: none; margin: 0; padding: 0; float: right; } 
+          .summary li { color: #111; float: left; border-radius: 2px; background: #eee; padding: 5px; margin-right: 10px; text-align: right; }
+          table { color: #eee; background: #444; margin: 5px 0 0 10px; width: calc(100% - 20px); max-width: 800px; border-collapse: collapse }
+          table thead { background: #333; }
+          table th, table td { padding: 2px 4px; font-size: 11px; }
+          tr.red { background: #d26666; color: #111; }
+          tr.yellow { background: slategrey; }
+          .wrap { max-width: 800px; padding-top: 30px; margin: auto; position: relative; }
+          .preview-wrap { display: inline-block; height: 80px; padding: 5px 0 0 5px; margin: 5px; background: rgba(0, 0, 0, 0.1); }
+          .preview { width: 64px; height: 80px; float: left; margin-right: 10px; }
+          .preview:nth-last-child(1) { margin-right: 5px; }
+          .preview img { width: 100%; image-rendering: pixelated; }
+          .preview p { text-align: center; }
+          .module { margin-top: 10px; position: relative; }
+          .module h2 { float: left; margin: 0; padding: 5px 0 0 35px; }
+          .module .toggle { background: #2d9966; color: #111; left: 10px; width: 14px; border-radius: 2px; padding: 6px; text-align: center; cursor: pointer; position: absolute; }
+          .module.fail .toggle { background: #d26666; }  
+          .module.fail h2 { color: #d26666; }
+          .toggle.close ~ table { display: none; }
+          .summary li:nth-child(1) { background: #2d9966; min-width: 70px; }
+          .summary li:nth-child(2) { background: #d26666; min-width: 70px; }
+          .summary li:nth-child(3) { background: slategrey; min-width: 70px; }
+          .summary li:nth-child(4) { background: #bbb; min-width: 60px; }
+          .summary li.l0 { opacity: 0.2; }
+          .renderer { position: absolute; top: 8px; right: 10px; color: #eee; }
+          h1 { width: 100%; top: 0; position: absolute; height: 50px; left: 0; }
+          table .icon.pass { position: relative; width: 8px; height: 8px; border-radius: 8px; margin-left: 6px; }
+          table .icon.pass:after { content: '✓'; top: -3px; position: absolute; color: #2d9966; font-size: 12px;  }
+          </style>
+          <script type="text/javascript">
+            function toggle(el) { 
+              el.className = el.className == 'toggle close' ? 'toggle open' : 'toggle close'; 
+              el.innerText = el.className == 'toggle close' ? '▶' : '▼';
+            }
+          </script>
+        </head>
+        <body>]]
+    local wrap_cls = ''
+    if self.totals[2] > 0 then wrap_cls = 'fail' end
+    html = html .. '<div class="wrap ' .. wrap_cls .. '"><h1>' .. status .. '&nbsp;love.test report</h1>' ..
+    '<p class="renderer">Renderer: ' .. name .. ' | ' .. version .. ' | ' .. vendor .. ' | ' .. device .. '</p>' ..
+    '<ul class="summary">'
+    html = html ..
+      '<li>' .. tostring(self.totals[1]) .. ' Passed</li>' ..
+      '<li>' .. tostring(self.totals[2]) .. ' Failed</li>' ..
+      '<li>' .. tostring(self.totals[3]) .. ' Skipped</li>' ..
       '<li>' .. finaltime .. 's</li></ul><br/><br/>'
 
     love.filesystem.write('tempoutput/' .. self.output .. '.xml', xml .. self.xml .. '</testsuites>')

File diff suppressed because it is too large
+ 0 - 0
testing/examples/lovetest_runAllTests.html


+ 31 - 23
testing/examples/lovetest_runAllTests.md

@@ -1,33 +1,41 @@
-<!-- PASSED 335 || FAILED 0 || SKIPPED 9 || TIME 14.817 -->
+<!-- PASSED 343 || FAILED 2 || SKIPPED 10 || TIME 14.567 -->
 
 ### Info
-**344** tests were completed in **14.817s** with **335** passed, **0** failed, and **9** skipped
+**355** tests were completed in **14.567s** with **343** passed, **2** failed, and **10** skipped
 
 Renderer: OpenGL | 4.1 Metal - 76.3 | Apple | Apple M1 Max
 
 ### Report
 | Module                | Pass | Fail | Skip | Time   |
 | --------------------- | ------ | ------ | ------- | ------ |
-| 🟢 audio | 28 | 0 | 0 | 0.886s |
-| 🟢 data | 12 | 0 | 0 | 0.212s |
-| 🟢 event | 4 | 0 | 2 | 0.103s |
-| 🟢 filesystem | 29 | 0 | 2 | 0.555s |
-| 🟢 font | 7 | 0 | 0 | 0.124s |
-| 🟢 graphics | 104 | 0 | 1 | 3.006s |
-| 🟢 image | 5 | 0 | 0 | 0.085s |
-| 🟢 joystick | 6 | 0 | 0 | 0.106s |
-| 🟢 keyboard | 9 | 0 | 0 | 0.150s |
-| 🟢 love | 6 | 0 | 0 | 0.098s |
-| 🟢 math | 20 | 0 | 0 | 0.337s |
-| 🟢 mouse | 18 | 0 | 0 | 0.302s |
-| 🟢 physics | 26 | 0 | 0 | 0.434s |
-| 🟢 sensor | 1 | 0 | 0 | 0.016s |
-| 🟢 sound | 4 | 0 | 0 | 0.072s |
-| 🟢 system | 6 | 0 | 2 | 0.135s |
-| 🟢 thread | 5 | 0 | 0 | 0.363s |
-| 🟢 timer | 6 | 0 | 0 | 2.074s |
-| 🟢 touch | 3 | 0 | 0 | 0.023s |
-| 🟢 video | 2 | 0 | 0 | 0.039s |
-| 🟢 window | 34 | 0 | 2 | 5.696s |
+| 🟢 audio | 31 | 0 | 0 | 1.328s |
+| 🟢 data | 12 | 0 | 0 | 0.197s |
+| 🟢 event | 4 | 0 | 2 | 0.100s |
+| 🟢 filesystem | 33 | 0 | 2 | 0.601s |
+| 🟢 font | 7 | 0 | 0 | 0.116s |
+| 🔴 graphics | 104 | 1 | 2 | 3.463s |
+| 🟢 image | 5 | 0 | 0 | 0.093s |
+| 🟢 joystick | 6 | 0 | 0 | 0.116s |
+| 🟢 keyboard | 10 | 0 | 0 | 0.170s |
+| 🟢 love | 6 | 0 | 0 | 0.100s |
+| 🟢 math | 20 | 0 | 0 | 0.334s |
+| 🔴 mouse | 17 | 1 | 0 | 0.301s |
+| 🟢 physics | 26 | 0 | 0 | 0.435s |
+| 🟢 sensor | 1 | 0 | 0 | 0.017s |
+| 🟢 sound | 4 | 0 | 0 | 0.075s |
+| 🟢 system | 7 | 0 | 2 | 0.150s |
+| 🟢 thread | 5 | 0 | 0 | 0.306s |
+| 🟢 timer | 6 | 0 | 0 | 0.298s |
+| 🟢 touch | 3 | 0 | 0 | 0.051s |
+| 🟢 video | 2 | 0 | 0 | 0.038s |
+| 🟢 window | 34 | 0 | 2 | 6.275s |
 
 ### Failures
+> 🔴 Shader  
+> assert 4 [check shader valid] expected '' got 'vertex shader:
+pixel shader:
+'  
+
+> 🔴 setGrabbed  
+> assert 2 [check now grabbed] expected 'true' got 'false'  
+

+ 328 - 299
testing/examples/lovetest_runAllTests.xml

@@ -1,137 +1,145 @@
-<testsuites name="love.test" tests="335" failures="0" skipped="9" time="14.817">
-	<testsuite name="love.audio" tests="28" failures="0" skipped="0" time="0.886">
-		<testcase classname="RecordingDevice" name="RecordingDevice" assertions="20" time="0.398">
+<testsuites name="love.test" tests="343" failures="2" skipped="10" time="14.567">
+	<testsuite name="love.audio" tests="31" failures="0" skipped="0" time="1.328">
+		<testcase classname="RecordingDevice" name="RecordingDevice" assertions="20" time="0.816">
 		</testcase>
-		<testcase classname="Source" name="Source" assertions="54" time="0.022">
+		<testcase classname="Source" name="Source" assertions="54" time="0.021">
 		</testcase>
-		<testcase classname="getActiveEffects" name="getActiveEffects" assertions="3" time="0.017">
+		<testcase classname="getActiveEffects" name="getActiveEffects" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="getActiveSourceCount" name="getActiveSourceCount" assertions="3" time="0.019">
+		<testcase classname="getActiveSourceCount" name="getActiveSourceCount" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="getDistanceModel" name="getDistanceModel" assertions="3" time="0.018">
+		<testcase classname="getDistanceModel" name="getDistanceModel" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="getDopplerScale" name="getDopplerScale" assertions="2" time="0.019">
+		<testcase classname="getDopplerScale" name="getDopplerScale" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getEffect" name="getEffect" assertions="4" time="0.017">
+		<testcase classname="getEffect" name="getEffect" assertions="4" time="0.016">
 		</testcase>
 		<testcase classname="getMaxSceneEffects" name="getMaxSceneEffects" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getMaxSourceEffects" name="getMaxSourceEffects" assertions="1" time="0.018">
+		<testcase classname="getMaxSourceEffects" name="getMaxSourceEffects" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getOrientation" name="getOrientation" assertions="6" time="0.018">
+		<testcase classname="getOrientation" name="getOrientation" assertions="6" time="0.017">
 		</testcase>
-		<testcase classname="getPosition" name="getPosition" assertions="3" time="0.018">
+		<testcase classname="getPlaybackDevice" name="getPlaybackDevice" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getRecordingDevices" name="getRecordingDevices" assertions="1" time="0.018">
+		<testcase classname="getPlaybackDevices" name="getPlaybackDevices" assertions="2" time="0.017">
+		</testcase>
+		<testcase classname="getPosition" name="getPosition" assertions="3" time="0.017">
+		</testcase>
+		<testcase classname="getRecordingDevices" name="getRecordingDevices" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="getVelocity" name="getVelocity" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="getVolume" name="getVolume" assertions="1" time="0.019">
+		<testcase classname="getVolume" name="getVolume" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isEffectsSupported" name="isEffectsSupported" assertions="1" time="0.018">
+		<testcase classname="isEffectsSupported" name="isEffectsSupported" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="newQueueableSource" name="newQueueableSource" assertions="3" time="0.018">
+		<testcase classname="newQueueableSource" name="newQueueableSource" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newSource" name="newSource" assertions="6" time="0.019">
+		<testcase classname="newSource" name="newSource" assertions="6" time="0.018">
 		</testcase>
-		<testcase classname="pause" name="pause" assertions="2" time="0.019">
+		<testcase classname="pause" name="pause" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="play" name="play" assertions="1" time="0.019">
+		<testcase classname="play" name="play" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="setDistanceModel" name="setDistanceModel" assertions="7" time="0.016">
+		<testcase classname="setDistanceModel" name="setDistanceModel" assertions="7" time="0.017">
 		</testcase>
 		<testcase classname="setDopplerScale" name="setDopplerScale" assertions="2" time="0.017">
 		</testcase>
 		<testcase classname="setEffect" name="setEffect" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="setMixWithSystem" name="setMixWithSystem" assertions="1" time="0.019">
+		<testcase classname="setMixWithSystem" name="setMixWithSystem" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="setOrientation" name="setOrientation" assertions="6" time="0.018">
+		<testcase classname="setOrientation" name="setOrientation" assertions="6" time="0.017">
 		</testcase>
-		<testcase classname="setPosition" name="setPosition" assertions="3" time="0.018">
+		<testcase classname="setPlaybackDevice" name="setPlaybackDevice" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="setVelocity" name="setVelocity" assertions="3" time="0.018">
+		<testcase classname="setPosition" name="setPosition" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="setVolume" name="setVolume" assertions="1" time="0.019">
+		<testcase classname="setVelocity" name="setVelocity" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="stop" name="stop" assertions="2" time="0.019">
+		<testcase classname="setVolume" name="setVolume" assertions="1" time="0.017">
+		</testcase>
+		<testcase classname="stop" name="stop" assertions="2" time="0.018">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.data" tests="12" failures="0" skipped="0" time="0.212">
-		<testcase classname="ByteData" name="ByteData" assertions="10" time="0.016">
+	<testsuite name="love.data" tests="12" failures="0" skipped="0" time="0.197">
+		<testcase classname="ByteData" name="ByteData" assertions="11" time="0.017">
 		</testcase>
-		<testcase classname="CompressedData" name="CompressedData" assertions="12" time="0.018">
+		<testcase classname="CompressedData" name="CompressedData" assertions="12" time="0.017">
 		</testcase>
-		<testcase classname="compress" name="compress" assertions="45" time="0.018">
+		<testcase classname="compress" name="compress" assertions="62" time="0.016">
 		</testcase>
-		<testcase classname="decode" name="decode" assertions="4" time="0.019">
+		<testcase classname="decode" name="decode" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="decompress" name="decompress" assertions="18" time="0.017">
+		<testcase classname="decompress" name="decompress" assertions="18" time="0.013">
 		</testcase>
-		<testcase classname="encode" name="encode" assertions="15" time="0.018">
+		<testcase classname="encode" name="encode" assertions="15" time="0.017">
 		</testcase>
-		<testcase classname="getPackedSize" name="getPackedSize" assertions="3" time="0.018">
+		<testcase classname="getPackedSize" name="getPackedSize" assertions="3" time="0.015">
 		</testcase>
-		<testcase classname="hash" name="hash" assertions="6" time="0.019">
+		<testcase classname="hash" name="hash" assertions="12" time="0.019">
 		</testcase>
-		<testcase classname="newByteData" name="newByteData" assertions="3" time="0.018">
+		<testcase classname="newByteData" name="newByteData" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newDataView" name="newDataView" assertions="3" time="0.018">
+		<testcase classname="newDataView" name="newDataView" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="pack" name="pack" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="unpack" name="unpack" assertions="3" time="0.017">
+		<testcase classname="unpack" name="unpack" assertions="3" time="0.018">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.event" tests="4" failures="0" skipped="2" time="0.103">
-		<testcase classname="clear" name="clear" assertions="1" time="0.016">
+	<testsuite name="love.event" tests="4" failures="0" skipped="2" time="0.100">
+		<testcase classname="clear" name="clear" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="poll" name="poll" assertions="1" time="0.018">
+		<testcase classname="poll" name="poll" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="pump" name="pump" assertions="0" time="0.017">
+		<testcase classname="pump" name="pump" assertions="0" time="0.016">
 			<skipped message="used internally" />
 		</testcase>
 		<testcase classname="push" name="push" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="quit" name="quit" assertions="1" time="0.017">
+		<testcase classname="quit" name="quit" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="wait" name="wait" assertions="0" time="0.018">
 			<skipped message="used internally" />
 		</testcase>
 	</testsuite>
-	<testsuite name="love.filesystem" tests="29" failures="0" skipped="2" time="0.555">
+	<testsuite name="love.filesystem" tests="33" failures="0" skipped="2" time="0.601">
 		<testcase classname="File" name="File" assertions="36" time="0.018">
 		</testcase>
 		<testcase classname="FileData" name="FileData" assertions="12" time="0.017">
 		</testcase>
-		<testcase classname="append" name="append" assertions="6" time="0.018">
+		<testcase classname="append" name="append" assertions="6" time="0.019">
 		</testcase>
-		<testcase classname="areSymlinksEnabled" name="areSymlinksEnabled" assertions="1" time="0.018">
+		<testcase classname="areSymlinksEnabled" name="areSymlinksEnabled" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="createDirectory" name="createDirectory" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="getAppdataDirectory" name="getAppdataDirectory" assertions="1" time="0.018">
+		<testcase classname="getAppdataDirectory" name="getAppdataDirectory" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getCRequirePath" name="getCRequirePath" assertions="1" time="0.019">
+		<testcase classname="getCRequirePath" name="getCRequirePath" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="getDirectoryItems" name="getDirectoryItems" assertions="2" time="0.019">
 		</testcase>
-		<testcase classname="getIdentity" name="getIdentity" assertions="1" time="0.018">
+		<testcase classname="getFullCommonPath" name="getFullCommonPath" assertions="7" time="0.017">
+		</testcase>
+		<testcase classname="getIdentity" name="getIdentity" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getInfo" name="getInfo" assertions="3" time="0.018">
+		<testcase classname="getInfo" name="getInfo" assertions="4" time="0.019">
 		</testcase>
-		<testcase classname="getRealDirectory" name="getRealDirectory" assertions="1" time="0.017">
+		<testcase classname="getRealDirectory" name="getRealDirectory" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="getRequirePath" name="getRequirePath" assertions="1" time="0.018">
+		<testcase classname="getRequirePath" name="getRequirePath" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="getSaveDirectory" name="getSaveDirectory" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="getSource" name="getSource" assertions="0" time="0.018">
 			<skipped message="used internally" />
 		</testcase>
-		<testcase classname="getSourceBaseDirectory" name="getSourceBaseDirectory" assertions="1" time="0.018">
+		<testcase classname="getSourceBaseDirectory" name="getSourceBaseDirectory" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getUserDirectory" name="getUserDirectory" assertions="1" time="0.017">
+		<testcase classname="getUserDirectory" name="getUserDirectory" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="getWorkingDirectory" name="getWorkingDirectory" assertions="1" time="0.018">
 		</testcase>
@@ -139,187 +147,203 @@
 		</testcase>
 		<testcase classname="lines" name="lines" assertions="6" time="0.017">
 		</testcase>
-		<testcase classname="load" name="load" assertions="4" time="0.017">
+		<testcase classname="load" name="load" assertions="6" time="0.018">
 		</testcase>
-		<testcase classname="mount" name="mount" assertions="5" time="0.019">
+		<testcase classname="mount" name="mount" assertions="5" time="0.017">
 		</testcase>
-		<testcase classname="newFileData" name="newFileData" assertions="1" time="0.017">
+		<testcase classname="mountCommonPath" name="mountCommonPath" assertions="7" time="0.017">
 		</testcase>
-		<testcase classname="openFile" name="openFile" assertions="4" time="0.019">
+		<testcase classname="mountFullPath" name="mountFullPath" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="read" name="read" assertions="6" time="0.018">
+		<testcase classname="newFileData" name="newFileData" assertions="1" time="0.016">
+		</testcase>
+		<testcase classname="openFile" name="openFile" assertions="4" time="0.017">
+		</testcase>
+		<testcase classname="read" name="read" assertions="6" time="0.017">
 		</testcase>
 		<testcase classname="remove" name="remove" assertions="5" time="0.019">
 		</testcase>
-		<testcase classname="setCRequirePath" name="setCRequirePath" assertions="1" time="0.018">
+		<testcase classname="setCRequirePath" name="setCRequirePath" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="setIdentity" name="setIdentity" assertions="1" time="0.018">
+		<testcase classname="setIdentity" name="setIdentity" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="setRequirePath" name="setRequirePath" assertions="1" time="0.018">
+		<testcase classname="setRequirePath" name="setRequirePath" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="setSource" name="setSource" assertions="0" time="0.018">
+		<testcase classname="setSource" name="setSource" assertions="0" time="0.016">
 			<skipped message="used internally" />
 		</testcase>
-		<testcase classname="unmount" name="unmount" assertions="2" time="0.019">
+		<testcase classname="unmount" name="unmount" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="write" name="write" assertions="3" time="0.017">
+		<testcase classname="unmountFullPath" name="unmountFullPath" assertions="2" time="0.016">
+		</testcase>
+		<testcase classname="write" name="write" assertions="3" time="0.018">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.font" tests="7" failures="0" skipped="0" time="0.124">
-		<testcase classname="GlyphData" name="GlyphData" assertions="17" time="0.017">
+	<testsuite name="love.font" tests="7" failures="0" skipped="0" time="0.116">
+		<testcase classname="GlyphData" name="GlyphData" assertions="17" time="0.016">
 		</testcase>
 		<testcase classname="Rasterizer" name="Rasterizer" assertions="13" time="0.018">
 		</testcase>
-		<testcase classname="newBMFontRasterizer" name="newBMFontRasterizer" assertions="3" time="0.018">
+		<testcase classname="newBMFontRasterizer" name="newBMFontRasterizer" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="newGlyphData" name="newGlyphData" assertions="3" time="0.018">
+		<testcase classname="newGlyphData" name="newGlyphData" assertions="3" time="0.016">
 		</testcase>
 		<testcase classname="newImageRasterizer" name="newImageRasterizer" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newRasterizer" name="newRasterizer" assertions="3" time="0.018">
+		<testcase classname="newRasterizer" name="newRasterizer" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newTrueTypeRasterizer" name="newTrueTypeRasterizer" assertions="6" time="0.019">
+		<testcase classname="newTrueTypeRasterizer" name="newTrueTypeRasterizer" assertions="6" time="0.016">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.graphics" tests="104" failures="0" skipped="1" time="3.006">
-		<testcase classname="Canvas" name="Canvas" assertions="18886" time="0.039">
+	<testsuite name="love.graphics" tests="104" failures="1" skipped="2" time="3.463">
+		<testcase classname="Buffer" name="Buffer" assertions="30" time="0.017">
+		</testcase>
+		<testcase classname="Canvas" name="Canvas" assertions="18857" time="0.086">
 		</testcase>
-		<testcase classname="Font" name="Font" assertions="428" time="0.011">
+		<testcase classname="Font" name="Font" assertions="356" time="0.021">
 		</testcase>
-		<testcase classname="Image" name="Image" assertions="3761" time="0.019">
+		<testcase classname="Image" name="Image" assertions="3763" time="0.041">
 		</testcase>
 		<testcase classname="Mesh" name="Mesh" assertions="49" time="0.018">
 		</testcase>
-		<testcase classname="ParticleSystem" name="ParticleSystem" assertions="3808" time="0.028">
+		<testcase classname="ParticleSystem" name="ParticleSystem" assertions="3808" time="0.040">
 		</testcase>
-		<testcase classname="Quad" name="Quad" assertions="3768" time="0.021">
+		<testcase classname="Quad" name="Quad" assertions="3728" time="0.025">
 		</testcase>
-		<testcase classname="Shader" name="Shader" assertions="208" time="0.028">
+		<testcase classname="Shader" name="Shader" assertions="177" time="0.028">
+			<failure message="assert 4 [check shader valid] expected '' got 'vertex shader:
+pixel shader:
+'">assert 4 [check shader valid] expected '' got 'vertex shader:
+pixel shader:
+'</failure>
 		</testcase>
-		<testcase classname="SpriteBatch" name="SpriteBatch" assertions="18808" time="0.037">
+		<testcase classname="ShaderStorageBuffer" name="ShaderStorageBuffer" assertions="0" time="0.017">
+			<skipped message="GLSL 4 and shader storage buffers are not supported on this system" />
 		</testcase>
-		<testcase classname="Text" name="Text" assertions="3811" time="0.014">
+		<testcase classname="SpriteBatch" name="SpriteBatch" assertions="18624" time="0.085">
 		</testcase>
-		<testcase classname="Video" name="Video" assertions="247057" time="0.770">
+		<testcase classname="Text" name="Text" assertions="3735" time="0.026">
 		</testcase>
-		<testcase classname="applyTransform" name="applyTransform" assertions="173" time="0.025">
+		<testcase classname="Video" name="Video" assertions="247033" time="0.885">
 		</testcase>
-		<testcase classname="arc" name="arc" assertions="2523" time="0.022">
+		<testcase classname="applyTransform" name="applyTransform" assertions="169" time="0.034">
 		</testcase>
-		<testcase classname="captureScreenshot" name="captureScreenshot" assertions="1" time="0.184">
+		<testcase classname="arc" name="arc" assertions="2523" time="0.021">
 		</testcase>
-		<testcase classname="circle" name="circle" assertions="1033" time="0.027">
+		<testcase classname="captureScreenshot" name="captureScreenshot" assertions="2" time="0.349">
 		</testcase>
-		<testcase classname="clear" name="clear" assertions="189" time="0.035">
+		<testcase classname="circle" name="circle" assertions="841" time="0.018">
 		</testcase>
-		<testcase classname="discard" name="discard" assertions="0" time="0.014">
+		<testcase classname="clear" name="clear" assertions="169" time="0.018">
+		</testcase>
+		<testcase classname="discard" name="discard" assertions="0" time="0.017">
 			<skipped message="cant test this worked" />
 		</testcase>
-		<testcase classname="draw" name="draw" assertions="949" time="0.020">
+		<testcase classname="draw" name="draw" assertions="841" time="0.032">
 		</testcase>
-		<testcase classname="drawInstanced" name="drawInstanced" assertions="3737" time="0.038">
+		<testcase classname="drawInstanced" name="drawInstanced" assertions="3721" time="0.034">
 		</testcase>
-		<testcase classname="drawLayer" name="drawLayer" assertions="3865" time="0.023">
+		<testcase classname="drawLayer" name="drawLayer" assertions="3721" time="0.031">
 		</testcase>
-		<testcase classname="ellipse" name="ellipse" assertions="921" time="0.016">
+		<testcase classname="ellipse" name="ellipse" assertions="841" time="0.019">
 		</testcase>
-		<testcase classname="flushBatch" name="flushBatch" assertions="1" time="0.016">
+		<testcase classname="flushBatch" name="flushBatch" assertions="1" time="0.018">
 		</testcase>
 		<testcase classname="getBackgroundColor" name="getBackgroundColor" assertions="8" time="0.017">
 		</testcase>
-		<testcase classname="getBlendMode" name="getBlendMode" assertions="4" time="0.018">
+		<testcase classname="getBlendMode" name="getBlendMode" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="getCanvas" name="getCanvas" assertions="4" time="0.018">
+		<testcase classname="getCanvas" name="getCanvas" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="getColor" name="getColor" assertions="8" time="0.018">
+		<testcase classname="getColor" name="getColor" assertions="8" time="0.017">
 		</testcase>
-		<testcase classname="getColorMask" name="getColorMask" assertions="8" time="0.018">
+		<testcase classname="getColorMask" name="getColorMask" assertions="8" time="0.017">
 		</testcase>
-		<testcase classname="getDPIScale" name="getDPIScale" assertions="1" time="0.018">
+		<testcase classname="getDPIScale" name="getDPIScale" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="getDefaultFilter" name="getDefaultFilter" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="getDepthMode" name="getDepthMode" assertions="2" time="0.017">
+		<testcase classname="getDepthMode" name="getDepthMode" assertions="2" time="0.016">
 		</testcase>
-		<testcase classname="getDimensions" name="getDimensions" assertions="2" time="0.018">
+		<testcase classname="getDimensions" name="getDimensions" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getFont" name="getFont" assertions="3" time="0.018">
+		<testcase classname="getFont" name="getFont" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="getFrontFaceWinding" name="getFrontFaceWinding" assertions="2" time="0.018">
+		<testcase classname="getFrontFaceWinding" name="getFrontFaceWinding" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getHeight" name="getHeight" assertions="1" time="0.018">
+		<testcase classname="getHeight" name="getHeight" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="getLineJoin" name="getLineJoin" assertions="2" time="0.019">
+		<testcase classname="getLineJoin" name="getLineJoin" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getLineStyle" name="getLineStyle" assertions="2" time="0.018">
+		<testcase classname="getLineStyle" name="getLineStyle" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getLineWidth" name="getLineWidth" assertions="2" time="0.018">
+		<testcase classname="getLineWidth" name="getLineWidth" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getMeshCullMode" name="getMeshCullMode" assertions="2" time="0.016">
+		<testcase classname="getMeshCullMode" name="getMeshCullMode" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getPixelDimensions" name="getPixelDimensions" assertions="2" time="0.018">
+		<testcase classname="getPixelDimensions" name="getPixelDimensions" assertions="2" time="0.017">
 		</testcase>
 		<testcase classname="getPixelHeight" name="getPixelHeight" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="getPixelWidth" name="getPixelWidth" assertions="1" time="0.018">
+		<testcase classname="getPixelWidth" name="getPixelWidth" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="getPointSize" name="getPointSize" assertions="2" time="0.018">
+		<testcase classname="getPointSize" name="getPointSize" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getRendererInfo" name="getRendererInfo" assertions="4" time="0.018">
+		<testcase classname="getRendererInfo" name="getRendererInfo" assertions="4" time="0.016">
 		</testcase>
-		<testcase classname="getScissor" name="getScissor" assertions="8" time="0.018">
+		<testcase classname="getScissor" name="getScissor" assertions="8" time="0.017">
 		</testcase>
-		<testcase classname="getShader" name="getShader" assertions="1" time="0.017">
+		<testcase classname="getShader" name="getShader" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="getStackDepth" name="getStackDepth" assertions="4" time="0.017">
+		<testcase classname="getStackDepth" name="getStackDepth" assertions="4" time="0.018">
 		</testcase>
 		<testcase classname="getStats" name="getStats" assertions="7" time="0.017">
 		</testcase>
-		<testcase classname="getStencilMode" name="getStencilMode" assertions="6" time="0.018">
+		<testcase classname="getStencilState" name="getStencilState" assertions="6" time="0.017">
 		</testcase>
-		<testcase classname="getSupported" name="getSupported" assertions="17" time="0.019">
+		<testcase classname="getSupported" name="getSupported" assertions="17" time="0.017">
 		</testcase>
-		<testcase classname="getSystemLimits" name="getSystemLimits" assertions="13" time="0.016">
+		<testcase classname="getSystemLimits" name="getSystemLimits" assertions="13" time="0.017">
 		</testcase>
-		<testcase classname="getTextureFormats" name="getTextureFormats" assertions="79" time="0.016">
+		<testcase classname="getTextureFormats" name="getTextureFormats" assertions="79" time="0.017">
 		</testcase>
-		<testcase classname="getTextureTypes" name="getTextureTypes" assertions="4" time="0.018">
+		<testcase classname="getTextureTypes" name="getTextureTypes" assertions="4" time="0.017">
 		</testcase>
 		<testcase classname="getWidth" name="getWidth" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="intersectScissor" name="intersectScissor" assertions="189" time="0.020">
+		<testcase classname="intersectScissor" name="intersectScissor" assertions="169" time="0.018">
 		</testcase>
-		<testcase classname="inverseTransformPoint" name="inverseTransformPoint" assertions="4" time="0.015">
+		<testcase classname="inverseTransformPoint" name="inverseTransformPoint" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="isActive" name="isActive" assertions="1" time="0.016">
+		<testcase classname="isActive" name="isActive" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isGammaCorrect" name="isGammaCorrect" assertions="1" time="0.016">
+		<testcase classname="isGammaCorrect" name="isGammaCorrect" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="isWireframe" name="isWireframe" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="line" name="line" assertions="233" time="0.034">
+		<testcase classname="line" name="line" assertions="169" time="0.018">
 		</testcase>
-		<testcase classname="newArrayImage" name="newArrayImage" assertions="3" time="0.014">
+		<testcase classname="newArrayImage" name="newArrayImage" assertions="3" time="0.018">
 		</testcase>
 		<testcase classname="newCanvas" name="newCanvas" assertions="6" time="0.017">
 		</testcase>
-		<testcase classname="newCubeImage" name="newCubeImage" assertions="3" time="0.019">
+		<testcase classname="newCubeImage" name="newCubeImage" assertions="3" time="0.020">
 		</testcase>
-		<testcase classname="newFont" name="newFont" assertions="6" time="0.017">
+		<testcase classname="newFont" name="newFont" assertions="6" time="0.018">
 		</testcase>
-		<testcase classname="newImage" name="newImage" assertions="3" time="0.017">
+		<testcase classname="newImage" name="newImage" assertions="3" time="0.016">
 		</testcase>
 		<testcase classname="newImageFont" name="newImageFont" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="newMesh" name="newMesh" assertions="3" time="0.016">
+		<testcase classname="newMesh" name="newMesh" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newParticleSystem" name="newParticleSystem" assertions="3" time="0.016">
+		<testcase classname="newParticleSystem" name="newParticleSystem" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="newQuad" name="newQuad" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newShader" name="newShader" assertions="3" time="0.023">
+		<testcase classname="newShader" name="newShader" assertions="3" time="0.028">
 		</testcase>
-		<testcase classname="newSpriteBatch" name="newSpriteBatch" assertions="3" time="0.019">
+		<testcase classname="newSpriteBatch" name="newSpriteBatch" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="newTextBatch" name="newTextBatch" assertions="3" time="0.018">
 		</testcase>
@@ -327,345 +351,352 @@
 		</testcase>
 		<testcase classname="newVolumeImage" name="newVolumeImage" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="origin" name="origin" assertions="173" time="0.018">
+		<testcase classname="origin" name="origin" assertions="169" time="0.019">
 		</testcase>
-		<testcase classname="points" name="points" assertions="169" time="0.026">
+		<testcase classname="points" name="points" assertions="169" time="0.022">
 		</testcase>
-		<testcase classname="polygon" name="polygon" assertions="225" time="0.018">
+		<testcase classname="polygon" name="polygon" assertions="169" time="0.017">
 		</testcase>
-		<testcase classname="pop" name="pop" assertions="173" time="0.017">
+		<testcase classname="pop" name="pop" assertions="169" time="0.017">
 		</testcase>
-		<testcase classname="print" name="print" assertions="317" time="0.022">
+		<testcase classname="print" name="print" assertions="169" time="0.028">
 		</testcase>
-		<testcase classname="printf" name="printf" assertions="1021" time="0.020">
+		<testcase classname="printf" name="printf" assertions="841" time="0.020">
 		</testcase>
-		<testcase classname="push" name="push" assertions="173" time="0.019">
+		<testcase classname="push" name="push" assertions="169" time="0.019">
 		</testcase>
-		<testcase classname="rectangle" name="rectangle" assertions="454" time="0.024">
+		<testcase classname="rectangle" name="rectangle" assertions="338" time="0.024">
 		</testcase>
-		<testcase classname="replaceTransform" name="replaceTransform" assertions="173" time="0.017">
+		<testcase classname="replaceTransform" name="replaceTransform" assertions="169" time="0.020">
 		</testcase>
-		<testcase classname="reset" name="reset" assertions="3" time="0.016">
+		<testcase classname="reset" name="reset" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="rotate" name="rotate" assertions="185" time="0.025">
+		<testcase classname="rotate" name="rotate" assertions="169" time="0.035">
 		</testcase>
-		<testcase classname="scale" name="scale" assertions="16" time="0.016">
+		<testcase classname="scale" name="scale" assertions="169" time="0.019">
 		</testcase>
 		<testcase classname="setBackgroundColor" name="setBackgroundColor" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="setBlendMode" name="setBlendMode" assertions="185" time="0.022">
+		<testcase classname="setBlendMode" name="setBlendMode" assertions="169" time="0.038">
 		</testcase>
-		<testcase classname="setCanvas" name="setCanvas" assertions="188" time="0.017">
+		<testcase classname="setCanvas" name="setCanvas" assertions="172" time="0.018">
 		</testcase>
-		<testcase classname="setColor" name="setColor" assertions="237" time="0.019">
+		<testcase classname="setColor" name="setColor" assertions="173" time="0.020">
 		</testcase>
-		<testcase classname="setColorMask" name="setColorMask" assertions="189" time="0.027">
+		<testcase classname="setColorMask" name="setColorMask" assertions="173" time="0.028">
 		</testcase>
-		<testcase classname="setDefaultFilter" name="setDefaultFilter" assertions="3" time="0.018">
+		<testcase classname="setDefaultFilter" name="setDefaultFilter" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="setDepthMode" name="setDepthMode" assertions="8" time="0.018">
+		<testcase classname="setDepthMode" name="setDepthMode" assertions="8" time="0.017">
 		</testcase>
-		<testcase classname="setFont" name="setFont" assertions="209" time="0.024">
+		<testcase classname="setFont" name="setFont" assertions="169" time="0.020">
 		</testcase>
 		<testcase classname="setFrontFaceWinding" name="setFrontFaceWinding" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="setLineJoin" name="setLineJoin" assertions="185" time="0.019">
+		<testcase classname="setLineJoin" name="setLineJoin" assertions="169" time="0.033">
 		</testcase>
-		<testcase classname="setLineStyle" name="setLineStyle" assertions="193" time="0.026">
+		<testcase classname="setLineStyle" name="setLineStyle" assertions="169" time="0.019">
 		</testcase>
-		<testcase classname="setLineWidth" name="setLineWidth" assertions="241" time="0.024">
+		<testcase classname="setLineWidth" name="setLineWidth" assertions="169" time="0.019">
 		</testcase>
 		<testcase classname="setMeshCullMode" name="setMeshCullMode" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="setScissor" name="setScissor" assertions="201" time="0.026">
+		<testcase classname="setScissor" name="setScissor" assertions="169" time="0.019">
 		</testcase>
-		<testcase classname="setShader" name="setShader" assertions="185" time="0.024">
+		<testcase classname="setShader" name="setShader" assertions="169" time="0.031">
 		</testcase>
-		<testcase classname="setStencilMode" name="setStencilMode" assertions="201" time="0.018">
+		<testcase classname="setStencilState" name="setStencilState" assertions="169" time="0.018">
 		</testcase>
-		<testcase classname="setWireframe" name="setWireframe" assertions="169" time="0.027">
+		<testcase classname="setWireframe" name="setWireframe" assertions="169" time="0.018">
 		</testcase>
-		<testcase classname="shear" name="shear" assertions="370" time="0.021">
+		<testcase classname="shear" name="shear" assertions="338" time="0.020">
 		</testcase>
 		<testcase classname="transformPoint" name="transformPoint" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="translate" name="translate" assertions="185" time="0.032">
+		<testcase classname="translate" name="translate" assertions="169" time="0.018">
 		</testcase>
-		<testcase classname="validateShader" name="validateShader" assertions="2" time="0.019">
+		<testcase classname="validateShader" name="validateShader" assertions="2" time="0.026">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.image" tests="5" failures="0" skipped="0" time="0.085">
-		<testcase classname="CompressedImageData" name="CompressedImageData" assertions="11" time="0.016">
+	<testsuite name="love.image" tests="5" failures="0" skipped="0" time="0.093">
+		<testcase classname="CompressedImageData" name="CompressedImageData" assertions="13" time="0.017">
 		</testcase>
-		<testcase classname="ImageData" name="ImageData" assertions="14" time="0.017">
+		<testcase classname="ImageData" name="ImageData" assertions="17" time="0.026">
 		</testcase>
-		<testcase classname="isCompressed" name="isCompressed" assertions="1" time="0.016">
+		<testcase classname="isCompressed" name="isCompressed" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="newCompressedData" name="newCompressedData" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newImageData" name="newImageData" assertions="6" time="0.018">
+		<testcase classname="newImageData" name="newImageData" assertions="6" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.joystick" tests="6" failures="0" skipped="0" time="0.106">
-		<testcase classname="getGamepadMappingString" name="getGamepadMappingString" assertions="1" time="0.016">
+	<testsuite name="love.joystick" tests="6" failures="0" skipped="0" time="0.116">
+		<testcase classname="getGamepadMappingString" name="getGamepadMappingString" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getJoystickCount" name="getJoystickCount" assertions="1" time="0.015">
+		<testcase classname="getJoystickCount" name="getJoystickCount" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getJoysticks" name="getJoysticks" assertions="1" time="0.016">
+		<testcase classname="getJoysticks" name="getJoysticks" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="loadGamepadMappings" name="loadGamepadMappings" assertions="1" time="0.021">
+		<testcase classname="loadGamepadMappings" name="loadGamepadMappings" assertions="1" time="0.023">
 		</testcase>
-		<testcase classname="saveGamepadMappings" name="saveGamepadMappings" assertions="1" time="0.021">
+		<testcase classname="saveGamepadMappings" name="saveGamepadMappings" assertions="1" time="0.024">
 		</testcase>
-		<testcase classname="setGamepadMapping" name="setGamepadMapping" assertions="24" time="0.017">
+		<testcase classname="setGamepadMapping" name="setGamepadMapping" assertions="24" time="0.018">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.keyboard" tests="9" failures="0" skipped="0" time="0.150">
+	<testsuite name="love.keyboard" tests="10" failures="0" skipped="0" time="0.170">
 		<testcase classname="getKeyFromScancode" name="getKeyFromScancode" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="getScancodeFromKey" name="getScancodeFromKey" assertions="1" time="0.018">
 		</testcase>
 		<testcase classname="hasKeyRepeat" name="hasKeyRepeat" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="hasScreenKeyboard" name="hasScreenKeyboard" assertions="1" time="0.018">
+		<testcase classname="hasScreenKeyboard" name="hasScreenKeyboard" assertions="1" time="0.017">
+		</testcase>
+		<testcase classname="hasTextInput" name="hasTextInput" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="hasTextInput" name="hasTextInput" assertions="1" time="0.016">
+		<testcase classname="isDown" name="isDown" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isDown" name="isDown" assertions="1" time="0.015">
+		<testcase classname="isModifierActive" name="isModifierActive" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="isScancodeDown" name="isScancodeDown" assertions="1" time="0.016">
+		<testcase classname="isScancodeDown" name="isScancodeDown" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="setKeyRepeat" name="setKeyRepeat" assertions="1" time="0.016">
+		<testcase classname="setKeyRepeat" name="setKeyRepeat" assertions="1" time="0.018">
 		</testcase>
 		<testcase classname="setTextInput" name="setTextInput" assertions="1" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.love" tests="6" failures="0" skipped="0" time="0.098">
-		<testcase classname="errhand" name="errhand" assertions="1" time="0.016">
+	<testsuite name="love.love" tests="6" failures="0" skipped="0" time="0.100">
+		<testcase classname="errhand" name="errhand" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getVersion" name="getVersion" assertions="4" time="0.018">
+		<testcase classname="getVersion" name="getVersion" assertions="4" time="0.016">
 		</testcase>
-		<testcase classname="hasDeprecationOutput" name="hasDeprecationOutput" assertions="1" time="0.016">
+		<testcase classname="hasDeprecationOutput" name="hasDeprecationOutput" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isVersionCompatible" name="isVersionCompatible" assertions="1" time="0.016">
+		<testcase classname="isVersionCompatible" name="isVersionCompatible" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="run" name="run" assertions="1" time="0.015">
+		<testcase classname="run" name="run" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="setDeprecationOutput" name="setDeprecationOutput" assertions="2" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.math" tests="20" failures="0" skipped="0" time="0.337">
-		<testcase classname="BezierCurve" name="BezierCurve" assertions="31" time="0.018">
+	<testsuite name="love.math" tests="20" failures="0" skipped="0" time="0.334">
+		<testcase classname="BezierCurve" name="BezierCurve" assertions="31" time="0.017">
 		</testcase>
-		<testcase classname="RandomGenerator" name="RandomGenerator" assertions="10" time="0.017">
+		<testcase classname="RandomGenerator" name="RandomGenerator" assertions="10" time="0.016">
 		</testcase>
-		<testcase classname="Transform" name="Transform" assertions="14" time="0.018">
+		<testcase classname="Transform" name="Transform" assertions="14" time="0.016">
 		</testcase>
 		<testcase classname="colorFromBytes" name="colorFromBytes" assertions="12" time="0.017">
 		</testcase>
-		<testcase classname="colorToBytes" name="colorToBytes" assertions="12" time="0.017">
+		<testcase classname="colorToBytes" name="colorToBytes" assertions="12" time="0.016">
 		</testcase>
-		<testcase classname="gammaToLinear" name="gammaToLinear" assertions="3" time="0.016">
+		<testcase classname="gammaToLinear" name="gammaToLinear" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="getRandomSeed" name="getRandomSeed" assertions="2" time="0.015">
+		<testcase classname="getRandomSeed" name="getRandomSeed" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="getRandomState" name="getRandomState" assertions="1" time="0.017">
+		<testcase classname="getRandomState" name="getRandomState" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="isConvex" name="isConvex" assertions="2" time="0.018">
+		<testcase classname="isConvex" name="isConvex" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="linearToGamma" name="linearToGamma" assertions="3" time="0.016">
+		<testcase classname="linearToGamma" name="linearToGamma" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="newBezierCurve" name="newBezierCurve" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="newRandomGenerator" name="newRandomGenerator" assertions="3" time="0.018">
+		<testcase classname="newRandomGenerator" name="newRandomGenerator" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newTransform" name="newTransform" assertions="3" time="0.017">
+		<testcase classname="newTransform" name="newTransform" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="perlinNoise" name="perlinNoise" assertions="4" time="0.015">
+		<testcase classname="perlinNoise" name="perlinNoise" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="random" name="random" assertions="10" time="0.016">
+		<testcase classname="random" name="random" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="randomNormal" name="randomNormal" assertions="1" time="0.016">
+		<testcase classname="randomNormal" name="randomNormal" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="setRandomSeed" name="setRandomSeed" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="setRandomState" name="setRandomState" assertions="1" time="0.016">
+		<testcase classname="setRandomState" name="setRandomState" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="simplexNoise" name="simplexNoise" assertions="4" time="0.018">
+		<testcase classname="simplexNoise" name="simplexNoise" assertions="4" time="0.017">
 		</testcase>
 		<testcase classname="triangulate" name="triangulate" assertions="2" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.mouse" tests="18" failures="0" skipped="0" time="0.302">
-		<testcase classname="getCursor" name="getCursor" assertions="4" time="0.018">
+	<testsuite name="love.mouse" tests="17" failures="1" skipped="0" time="0.301">
+		<testcase classname="getCursor" name="getCursor" assertions="4" time="0.016">
 		</testcase>
-		<testcase classname="getPosition" name="getPosition" assertions="2" time="0.018">
+		<testcase classname="getPosition" name="getPosition" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getRelativeMode" name="getRelativeMode" assertions="2" time="0.017">
+		<testcase classname="getRelativeMode" name="getRelativeMode" assertions="2" time="0.016">
 		</testcase>
-		<testcase classname="getSystemCursor" name="getSystemCursor" assertions="4" time="0.015">
+		<testcase classname="getSystemCursor" name="getSystemCursor" assertions="4" time="0.017">
 		</testcase>
 		<testcase classname="getX" name="getX" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getY" name="getY" assertions="2" time="0.017">
+		<testcase classname="getY" name="getY" assertions="2" time="0.016">
 		</testcase>
-		<testcase classname="isCursorSupported" name="isCursorSupported" assertions="1" time="0.016">
+		<testcase classname="isCursorSupported" name="isCursorSupported" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isDown" name="isDown" assertions="1" time="0.018">
+		<testcase classname="isDown" name="isDown" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="isGrabbed" name="isGrabbed" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isVisible" name="isVisible" assertions="2" time="0.018">
+		<testcase classname="isVisible" name="isVisible" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="newCursor" name="newCursor" assertions="3" time="0.017">
+		<testcase classname="newCursor" name="newCursor" assertions="3" time="0.016">
 		</testcase>
 		<testcase classname="setCursor" name="setCursor" assertions="4" time="0.017">
 		</testcase>
 		<testcase classname="setGrabbed" name="setGrabbed" assertions="2" time="0.016">
+			<failure message="assert 2 [check now grabbed] expected 'true' got 'false'">assert 2 [check now grabbed] expected 'true' got 'false'</failure>
 		</testcase>
-		<testcase classname="setPosition" name="setPosition" assertions="4" time="0.016">
+		<testcase classname="setPosition" name="setPosition" assertions="4" time="0.018">
 		</testcase>
-		<testcase classname="setRelativeMode" name="setRelativeMode" assertions="2" time="0.016">
+		<testcase classname="setRelativeMode" name="setRelativeMode" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="setVisible" name="setVisible" assertions="2" time="0.016">
+		<testcase classname="setVisible" name="setVisible" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="setX" name="setX" assertions="2" time="0.015">
+		<testcase classname="setX" name="setX" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="setY" name="setY" assertions="2" time="0.018">
+		<testcase classname="setY" name="setY" assertions="2" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.physics" tests="26" failures="0" skipped="0" time="0.434">
-		<testcase classname="Body" name="Body" assertions="85" time="0.017">
+	<testsuite name="love.physics" tests="26" failures="0" skipped="0" time="0.435">
+		<testcase classname="Body" name="Body" assertions="90" time="0.017">
 		</testcase>
 		<testcase classname="Contact" name="Contact" assertions="23" time="0.018">
 		</testcase>
 		<testcase classname="Joint" name="Joint" assertions="19" time="0.017">
 		</testcase>
-		<testcase classname="Shape" name="Shape" assertions="55" time="0.016">
+		<testcase classname="Shape" name="Shape" assertions="55" time="0.017">
 		</testcase>
-		<testcase classname="World" name="World" assertions="33" time="0.016">
+		<testcase classname="World" name="World" assertions="37" time="0.016">
 		</testcase>
-		<testcase classname="getDistance" name="getDistance" assertions="1" time="0.016">
+		<testcase classname="getDistance" name="getDistance" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getMeter" name="getMeter" assertions="1" time="0.015">
+		<testcase classname="getMeter" name="getMeter" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="newBody" name="newBody" assertions="3" time="0.018">
+		<testcase classname="newBody" name="newBody" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newChainShape" name="newChainShape" assertions="3" time="0.016">
+		<testcase classname="newChainShape" name="newChainShape" assertions="3" time="0.013">
 		</testcase>
-		<testcase classname="newCircleShape" name="newCircleShape" assertions="3" time="0.018">
+		<testcase classname="newCircleShape" name="newCircleShape" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newDistanceJoint" name="newDistanceJoint" assertions="3" time="0.016">
+		<testcase classname="newDistanceJoint" name="newDistanceJoint" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newEdgeShape" name="newEdgeShape" assertions="3" time="0.016">
+		<testcase classname="newEdgeShape" name="newEdgeShape" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newFrictionJoint" name="newFrictionJoint" assertions="3" time="0.018">
+		<testcase classname="newFrictionJoint" name="newFrictionJoint" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="newGearJoint" name="newGearJoint" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="newMotorJoint" name="newMotorJoint" assertions="3" time="0.016">
+		<testcase classname="newMotorJoint" name="newMotorJoint" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="newMouseJoint" name="newMouseJoint" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="newPolygonShape" name="newPolygonShape" assertions="3" time="0.016">
+		<testcase classname="newPolygonShape" name="newPolygonShape" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newPrismaticJoint" name="newPrismaticJoint" assertions="3" time="0.016">
+		<testcase classname="newPrismaticJoint" name="newPrismaticJoint" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newPulleyJoint" name="newPulleyJoint" assertions="3" time="0.018">
+		<testcase classname="newPulleyJoint" name="newPulleyJoint" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="newRectangleShape" name="newRectangleShape" assertions="6" time="0.017">
+		<testcase classname="newRectangleShape" name="newRectangleShape" assertions="6" time="0.018">
 		</testcase>
-		<testcase classname="newRevoluteJoint" name="newRevoluteJoint" assertions="3" time="0.018">
+		<testcase classname="newRevoluteJoint" name="newRevoluteJoint" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newRopeJoint" name="newRopeJoint" assertions="3" time="0.018">
+		<testcase classname="newRopeJoint" name="newRopeJoint" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newWeldJoint" name="newWeldJoint" assertions="3" time="0.015">
+		<testcase classname="newWeldJoint" name="newWeldJoint" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newWheelJoint" name="newWheelJoint" assertions="3" time="0.016">
+		<testcase classname="newWheelJoint" name="newWheelJoint" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="newWorld" name="newWorld" assertions="3" time="0.016">
+		<testcase classname="newWorld" name="newWorld" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="setMeter" name="setMeter" assertions="2" time="0.017">
+		<testcase classname="setMeter" name="setMeter" assertions="2" time="0.016">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.sensor" tests="1" failures="0" skipped="0" time="0.016">
-		<testcase classname="hasSensor" name="hasSensor" assertions="2" time="0.016">
+	<testsuite name="love.sensor" tests="1" failures="0" skipped="0" time="0.017">
+		<testcase classname="hasSensor" name="hasSensor" assertions="2" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.sound" tests="4" failures="0" skipped="0" time="0.072">
-		<testcase classname="Decoder" name="Decoder" assertions="14" time="0.019">
+	<testsuite name="love.sound" tests="4" failures="0" skipped="0" time="0.075">
+		<testcase classname="Decoder" name="Decoder" assertions="14" time="0.018">
 		</testcase>
-		<testcase classname="SoundData" name="SoundData" assertions="20" time="0.019">
+		<testcase classname="SoundData" name="SoundData" assertions="22" time="0.022">
 		</testcase>
 		<testcase classname="newDecoder" name="newDecoder" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newSoundData" name="newSoundData" assertions="6" time="0.017">
+		<testcase classname="newSoundData" name="newSoundData" assertions="6" time="0.019">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.system" tests="6" failures="0" skipped="2" time="0.135">
-		<testcase classname="getClipboardText" name="getClipboardText" assertions="1" time="0.018">
+	<testsuite name="love.system" tests="7" failures="0" skipped="2" time="0.150">
+		<testcase classname="getClipboardText" name="getClipboardText" assertions="1" time="0.016">
+		</testcase>
+		<testcase classname="getOS" name="getOS" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getOS" name="getOS" assertions="1" time="0.018">
+		<testcase classname="getPowerInfo" name="getPowerInfo" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getPowerInfo" name="getPowerInfo" assertions="1" time="0.016">
+		<testcase classname="getPreferredLocales" name="getPreferredLocales" assertions="2" time="0.017">
 		</testcase>
 		<testcase classname="getProcessorCount" name="getProcessorCount" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="hasBackgroundMusic" name="hasBackgroundMusic" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="openURL" name="openURL" assertions="0" time="0.016">
+		<testcase classname="openURL" name="openURL" assertions="0" time="0.017">
 			<skipped message="cant test this worked" />
 		</testcase>
-		<testcase classname="setClipboardText" name="setClipboardText" assertions="1" time="0.018">
+		<testcase classname="setClipboardText" name="setClipboardText" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="vibrate" name="vibrate" assertions="0" time="0.017">
+		<testcase classname="vibrate" name="vibrate" assertions="0" time="0.016">
 			<skipped message="cant test this worked" />
 		</testcase>
 	</testsuite>
-	<testsuite name="love.thread" tests="5" failures="0" skipped="0" time="0.363">
-		<testcase classname="Channel" name="Channel" assertions="10" time="0.237">
+	<testsuite name="love.thread" tests="5" failures="0" skipped="0" time="0.306">
+		<testcase classname="Channel" name="Channel" assertions="10" time="0.231">
 		</testcase>
-		<testcase classname="Thread" name="Thread" assertions="7" time="0.085">
+		<testcase classname="Thread" name="Thread" assertions="7" time="0.024">
 		</testcase>
-		<testcase classname="getChannel" name="getChannel" assertions="3" time="0.006">
+		<testcase classname="getChannel" name="getChannel" assertions="3" time="0.018">
 		</testcase>
-		<testcase classname="newChannel" name="newChannel" assertions="3" time="0.019">
+		<testcase classname="newChannel" name="newChannel" assertions="3" time="0.017">
 		</testcase>
-		<testcase classname="newThread" name="newThread" assertions="3" time="0.018">
+		<testcase classname="newThread" name="newThread" assertions="3" time="0.015">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.timer" tests="6" failures="0" skipped="0" time="2.074">
-		<testcase classname="getAverageDelta" name="getAverageDelta" assertions="1" time="0.015">
+	<testsuite name="love.timer" tests="6" failures="0" skipped="0" time="0.298">
+		<testcase classname="getAverageDelta" name="getAverageDelta" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getDelta" name="getDelta" assertions="1" time="0.018">
+		<testcase classname="getDelta" name="getDelta" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="getFPS" name="getFPS" assertions="1" time="0.017">
+		<testcase classname="getFPS" name="getFPS" assertions="1" time="0.015">
 		</testcase>
-		<testcase classname="getTime" name="getTime" assertions="1" time="1.017">
+		<testcase classname="getTime" name="getTime" assertions="1" time="0.118">
 		</testcase>
-		<testcase classname="sleep" name="sleep" assertions="1" time="1.003">
+		<testcase classname="sleep" name="sleep" assertions="1" time="0.117">
 		</testcase>
-		<testcase classname="step" name="step" assertions="1" time="0.003">
+		<testcase classname="step" name="step" assertions="1" time="0.016">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.touch" tests="3" failures="0" skipped="0" time="0.023">
-		<testcase classname="getPosition" name="getPosition" assertions="2" time="0.002">
+	<testsuite name="love.touch" tests="3" failures="0" skipped="0" time="0.051">
+		<testcase classname="getPosition" name="getPosition" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getPressure" name="getPressure" assertions="2" time="0.002">
+		<testcase classname="getPressure" name="getPressure" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="getTouches" name="getTouches" assertions="1" time="0.019">
+		<testcase classname="getTouches" name="getTouches" assertions="1" time="0.017">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.video" tests="2" failures="0" skipped="0" time="0.039">
-		<testcase classname="VideoStream" name="VideoStream" assertions="9" time="0.019">
+	<testsuite name="love.video" tests="2" failures="0" skipped="0" time="0.038">
+		<testcase classname="VideoStream" name="VideoStream" assertions="9" time="0.018">
 		</testcase>
 		<testcase classname="newVideoStream" name="newVideoStream" assertions="3" time="0.020">
 		</testcase>
 	</testsuite>
-	<testsuite name="love.window" tests="34" failures="0" skipped="2" time="5.696">
+	<testsuite name="love.window" tests="34" failures="0" skipped="2" time="6.275">
+		<testcase classname="focus" name="focus" assertions="1" time="0.017">
+		</testcase>
 		<testcase classname="fromPixels" name="fromPixels" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="getDPIScale" name="getDPIScale" assertions="1" time="0.018">
+		<testcase classname="getDPIScale" name="getDPIScale" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="getDesktopDimensions" name="getDesktopDimensions" assertions="2" time="0.016">
 		</testcase>
@@ -675,67 +706,65 @@
 		</testcase>
 		<testcase classname="getDisplayOrientation" name="getDisplayOrientation" assertions="1" time="0.016">
 		</testcase>
-		<testcase classname="getFullscreen" name="getFullscreen" assertions="2" time="1.109">
+		<testcase classname="getFullscreen" name="getFullscreen" assertions="2" time="1.351">
 		</testcase>
-		<testcase classname="getFullscreenModes" name="getFullscreenModes" assertions="1" time="0.005">
+		<testcase classname="getFullscreenModes" name="getFullscreenModes" assertions="1" time="0.013">
 		</testcase>
-		<testcase classname="getIcon" name="getIcon" assertions="2" time="0.021">
+		<testcase classname="getIcon" name="getIcon" assertions="2" time="0.019">
 		</testcase>
-		<testcase classname="getMode" name="getMode" assertions="3" time="0.016">
+		<testcase classname="getMode" name="getMode" assertions="3" time="0.017">
 		</testcase>
 		<testcase classname="getPosition" name="getPosition" assertions="2" time="0.017">
 		</testcase>
-		<testcase classname="getSafeArea" name="getSafeArea" assertions="4" time="0.018">
+		<testcase classname="getSafeArea" name="getSafeArea" assertions="4" time="0.017">
 		</testcase>
-		<testcase classname="getTitle" name="getTitle" assertions="1" time="0.017">
+		<testcase classname="getTitle" name="getTitle" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="getVSync" name="getVSync" assertions="1" time="0.017">
+		<testcase classname="getVSync" name="getVSync" assertions="1" time="0.016">
 		</testcase>
 		<testcase classname="hasFocus" name="hasFocus" assertions="1" time="0.017">
 		</testcase>
 		<testcase classname="hasMouseFocus" name="hasMouseFocus" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="isDisplaySleepEnabled" name="isDisplaySleepEnabled" assertions="3" time="0.018">
+		<testcase classname="isDisplaySleepEnabled" name="isDisplaySleepEnabled" assertions="3" time="0.016">
 		</testcase>
-		<testcase classname="isMaximized" name="isMaximized" assertions="2" time="0.185">
+		<testcase classname="isMaximized" name="isMaximized" assertions="2" time="0.186">
 		</testcase>
-		<testcase classname="isMinimized" name="isMinimized" assertions="2" time="0.726">
+		<testcase classname="isMinimized" name="isMinimized" assertions="2" time="0.816">
 		</testcase>
-		<testcase classname="isOpen" name="isOpen" assertions="1" time="0.002">
+		<testcase classname="isOpen" name="isOpen" assertions="1" time="0.014">
 		</testcase>
-		<testcase classname="isVisible" name="isVisible" assertions="1" time="0.002">
+		<testcase classname="isVisible" name="isVisible" assertions="1" time="0.017">
 		</testcase>
-		<testcase classname="maximize" name="maximize" assertions="2" time="0.159">
+		<testcase classname="maximize" name="maximize" assertions="2" time="0.186">
 		</testcase>
-		<testcase classname="minimize" name="minimize" assertions="2" time="0.727">
+		<testcase classname="minimize" name="minimize" assertions="2" time="0.807">
 		</testcase>
-		<testcase classname="requestAttention" name="requestAttention" assertions="0" time="0.015">
+		<testcase classname="requestAttention" name="requestAttention" assertions="0" time="0.016">
 			<skipped message="cant test this worked" />
 		</testcase>
-		<testcase classname="restore" name="restore" assertions="1" time="0.866">
+		<testcase classname="restore" name="restore" assertions="1" time="0.966">
 		</testcase>
-		<testcase classname="setDisplaySleepEnabled" name="setDisplaySleepEnabled" assertions="2" time="0.019">
+		<testcase classname="setDisplaySleepEnabled" name="setDisplaySleepEnabled" assertions="2" time="0.018">
 		</testcase>
-		<testcase classname="setFullscreen" name="setFullscreen" assertions="2" time="1.328">
+		<testcase classname="setFullscreen" name="setFullscreen" assertions="2" time="1.356">
 		</testcase>
 		<testcase classname="setIcon" name="setIcon" assertions="1" time="0.015">
 		</testcase>
 		<testcase classname="setMode" name="setMode" assertions="4" time="0.020">
 		</testcase>
-		<testcase classname="setPosition" name="setPosition" assertions="2" time="0.182">
+		<testcase classname="setPosition" name="setPosition" assertions="2" time="0.183">
 		</testcase>
-		<testcase classname="setTitle" name="setTitle" assertions="1" time="0.017">
+		<testcase classname="setTitle" name="setTitle" assertions="1" time="0.018">
 		</testcase>
-		<testcase classname="setVSync" name="setVSync" assertions="1" time="0.017">
+		<testcase classname="setVSync" name="setVSync" assertions="1" time="0.015">
 		</testcase>
-		<testcase classname="showMessageBox" name="showMessageBox" assertions="0" time="0.001">
+		<testcase classname="showMessageBox" name="showMessageBox" assertions="0" time="0.002">
 			<skipped message="cant test this worked" />
 		</testcase>
-		<testcase classname="toPixels" name="toPixels" assertions="1" time="0.001">
-		</testcase>
-		<testcase classname="updateMode" name="updateMode" assertions="4" time="0.009">
+		<testcase classname="toPixels" name="toPixels" assertions="1" time="0.002">
 		</testcase>
-		<testcase classname="z_close" name="z_close" assertions="4" time="0.034">
+		<testcase classname="updateMode" name="updateMode" assertions="4" time="0.010">
 		</testcase>
 	</testsuite>
 </testsuites>

+ 3 - 0
testing/output/difference/notes.txt

@@ -0,0 +1,3 @@
+# Graphic Differences
+If a graphics test fails then a "difference" image will be created to highlight 
+the differences between the actual + expected image, for use in the HTML report

+ 24 - 13
testing/tests/filesystem.lua

@@ -137,7 +137,7 @@ end
 
 -- love.filesystem.createDirectory
 love.test.filesystem.createDirectory = function(test)
-  -- try creating a dir + subdir and check both exist 
+  -- try creating a dir + subdir and check both exist
   local success = love.filesystem.createDirectory('foo/bar')
   test:assertNotEquals(false, success, 'check success')
   test:assertNotEquals(nil, love.filesystem.getInfo('foo', 'directory'), 'check directory created')
@@ -225,7 +225,7 @@ love.test.filesystem.getRealDirectory = function(test)
   love.filesystem.createDirectory('foo')
   love.filesystem.write('foo/test.txt', 'test')
   -- check save dir matches the real dir we just wrote to
-  test:assertEquals(love.filesystem.getSaveDirectory(), 
+  test:assertEquals(love.filesystem.getSaveDirectory(),
     love.filesystem.getRealDirectory('foo/test.txt'), 'check directory matches')
   -- cleanup
   love.filesystem.remove('foo/test.txt')
@@ -321,17 +321,28 @@ love.test.filesystem.load = function(test)
   -- setup some fake lua files
   love.filesystem.write('test1.lua', 'function test()\nreturn 1\nend\nreturn test()')
   love.filesystem.write('test2.lua', 'function test()\nreturn 1')
-  -- check file that doesn't exist
-  local chunk1, errormsg1 = love.filesystem.load('faker.lua', 'b')
-  test:assertEquals(nil, chunk1, 'check file doesnt exist')
-  -- check valid lua file (text load)
-  local chunk2, errormsg2 = love.filesystem.load('test1.lua', 't')
-  test:assertEquals(nil, errormsg2, 'check no error message')
-  test:assertEquals(1, chunk2(), 'check lua file runs')
+
+  if test:isAtLeastLuaVersion(5.2) or test:isLuaJITEnabled() then
+    -- check file that doesn't exist
+    local chunk1, errormsg1 = love.filesystem.load('faker.lua', 'b')
+    test:assertEquals(nil, chunk1, 'check file doesnt exist')
+    -- check valid lua file (text load)
+    local chunk2, errormsg2 = love.filesystem.load('test1.lua', 't')
+    test:assertEquals(nil, errormsg2, 'check no error message')
+    test:assertEquals(1, chunk2(), 'check lua file runs')
+  else
+    local _, errormsg3 = love.filesystem.load('test1.lua', 'b')
+    test:assertNotEquals(nil, errormsg3, 'check for an error message')
+
+    local _, errormsg4 = love.filesystem.load('test1.lua', 't')
+    test:assertNotEquals(nil, errormsg4, 'check for an error message')
+  end
+
   -- 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')
+  local chunk5, errormsg5 = love.filesystem.load('test1.lua', 'bt')
+  test:assertEquals(nil, errormsg5, 'check no error message')
+  test:assertEquals(1, chunk5(), 'check lua file runs')
+
   -- check invalid lua file
   local ok, chunk, err = pcall(love.filesystem.load, 'test2.lua')
   test:assertFalse(ok, 'check invalid lua file')
@@ -410,7 +421,7 @@ end
 
 -- love.filesystem.unmountCommonPath
 --love.test.filesystem.unmountCommonPath = function(test)
---  -- check unmounting invalid 
+--  -- check unmounting invalid
 --  local ok = pcall(love.filesystem.unmountCommonPath, 'fakepath')
 --  test:assertFalse(ok, 'check unmount invalid common path')
 --  -- check mounting valid paths

+ 0 - 2
testing/todo.md

@@ -23,8 +23,6 @@ These are all the outstanding methods that require test coverage, along with a f
 - love.graphics.drawIndirect()
 - love.graphics.getQuadIndexBuffer()
 - love.graphics.setBlendState()
-- love.graphics.setOrthoProjection()
-- love.graphics.setPerspectiveProjection()
 - love.graphics.resetProjection()
 - love.graphics.Mesh:getAttachedAttributes()
 - love.graphics.Shader:hasStage()

Some files were not shown because too many files changed in this diff