diff --git a/testing/examples/lovetest_runAllTests.html b/testing/examples/lovetest_runAllTests.html
index 5a0be8304..41462203f 100644
--- a/testing/examples/lovetest_runAllTests.html
+++ b/testing/examples/lovetest_runAllTests.html
@@ -1 +1 @@
-
🔴 love.test
- 🟢 275 Tests
- 🔴 2 Failures
- 🟡 28 Skipped
- 16.781s
🔴 love.audio
- 🟢 27 Tests
- 🔴 1 Failures
- 🟡 0 Skipped
- 4.898s
| Method | Time | Details |
| 🟢 | RecordingDevice | 4.419s | |
| 🔴 | Source | 0.019s | assert 53 [check effect was applied] expected 'true' got 'false' |
| 🟢 | getActiveEffects | 0.013s | |
| 🟢 | getActiveSourceCount | 0.018s | |
| 🟢 | getDistanceModel | 0.018s | |
| 🟢 | getDopplerScale | 0.019s | |
| 🟢 | getEffect | 0.018s | |
| 🟢 | getMaxSceneEffects | 0.017s | |
| 🟢 | getMaxSourceEffects | 0.016s | |
| 🟢 | getOrientation | 0.018s | |
| 🟢 | getPosition | 0.017s | |
| 🟢 | getRecordingDevices | 0.017s | |
| 🟢 | getVelocity | 0.018s | |
| 🟢 | getVolume | 0.018s | |
| 🟢 | isEffectsSupported | 0.017s | |
| 🟢 | newQueueableSource | 0.016s | |
| 🟢 | newSource | 0.019s | |
| 🟢 | pause | 0.019s | |
| 🟢 | play | 0.019s | |
| 🟢 | setDistanceModel | 0.019s | |
| 🟢 | setDopplerScale | 0.018s | |
| 🟢 | setEffect | 0.017s | |
| 🟢 | setMixWithSystem | 0.017s | |
| 🟢 | setOrientation | 0.019s | |
| 🟢 | setPosition | 0.019s | |
| 🟢 | setVelocity | 0.018s | |
| 🟢 | setVolume | 0.017s | |
| 🟢 | stop | 0.019s | |
🟢 love.data
- 🟢 12 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.213s
| Method | Time | Details |
| 🟢 | ByteData | 0.017s | |
| 🟢 | CompressedData | 0.017s | |
| 🟢 | compress | 0.018s | |
| 🟢 | decode | 0.018s | |
| 🟢 | decompress | 0.018s | |
| 🟢 | encode | 0.018s | |
| 🟢 | getPackedSize | 0.018s | |
| 🟢 | hash | 0.019s | |
| 🟢 | newByteData | 0.017s | |
| 🟢 | newDataView | 0.017s | |
| 🟢 | pack | 0.017s | |
| 🟢 | unpack | 0.018s | |
🟢 love.event
- 🟢 4 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.103s
| Method | Time | Details |
| 🟢 | clear | 0.015s | |
| 🟢 | poll | 0.017s | |
| 🟡 | pump | 0.018s | used internally |
| 🟢 | push | 0.018s | |
| 🟢 | quit | 0.018s | |
| 🟡 | wait | 0.017s | test class needs writing |
🟢 love.filesystem
- 🟢 29 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.561s
| Method | Time | Details |
| 🟢 | File | 0.018s | |
| 🟢 | FileData | 0.019s | |
| 🟢 | append | 0.020s | |
| 🟢 | areSymlinksEnabled | 0.017s | |
| 🟢 | createDirectory | 0.019s | |
| 🟢 | getAppdataDirectory | 0.018s | |
| 🟢 | getCRequirePath | 0.017s | |
| 🟢 | getDirectoryItems | 0.018s | |
| 🟢 | getIdentity | 0.018s | |
| 🟢 | getInfo | 0.019s | |
| 🟢 | getRealDirectory | 0.018s | |
| 🟢 | getRequirePath | 0.017s | |
| 🟢 | getSaveDirectory | 0.017s | |
| 🟡 | getSource | 0.016s | used internally |
| 🟢 | getSourceBaseDirectory | 0.018s | |
| 🟢 | getUserDirectory | 0.017s | |
| 🟢 | getWorkingDirectory | 0.018s | |
| 🟢 | isFused | 0.018s | |
| 🟢 | lines | 0.022s | |
| 🟢 | load | 0.017s | |
| 🟢 | mount | 0.018s | |
| 🟢 | newFileData | 0.018s | |
| 🟢 | openFile | 0.018s | |
| 🟢 | read | 0.018s | |
| 🟢 | remove | 0.018s | |
| 🟢 | setCRequirePath | 0.018s | |
| 🟢 | setIdentity | 0.019s | |
| 🟢 | setRequirePath | 0.019s | |
| 🟡 | setSource | 0.017s | used internally |
| 🟢 | unmount | 0.018s | |
| 🟢 | write | 0.019s | |
🔴 love.font
- 🟢 6 Tests
- 🔴 1 Failures
- 🟡 0 Skipped
- 0.123s
| Method | Time | Details |
| 🔴 | GlyphData | 0.017s | assert 8 [check glyph number] expected '97' got '0' |
| 🟢 | Rasterizer | 0.018s | |
| 🟢 | newBMFontRasterizer | 0.018s | |
| 🟢 | newGlyphData | 0.018s | |
| 🟢 | newImageRasterizer | 0.018s | |
| 🟢 | newRasterizer | 0.017s | |
| 🟢 | newTrueTypeRasterizer | 0.019s | |
🟢 love.graphics
- 🟢 93 Tests
- 🔴 0 Failures
- 🟡 14 Skipped
- 2.106s
| Method | Time | Details |
| 🟡 | Canvas | 0.017s | test class needs writing |
| 🟡 | Font | 0.018s | test class needs writing |
| 🟡 | Image | 0.017s | test class needs writing |
| 🟡 | Mesh | 0.017s | test class needs writing |
| 🟡 | ParticleSystem | 0.017s | test class needs writing |
| 🟡 | Quad | 0.017s | test class needs writing |
| 🟡 | Shader | 0.018s | test class needs writing |
| 🟡 | SpriteBatch | 0.018s | test class needs writing |
| 🟡 | Text | 0.018s | test class needs writing |
| 🟡 | Texture | 0.018s | test class needs writing |
| 🟡 | Video | 0.007s | test class needs writing |
| 🟢 | applyTransform | 0.019s |  Expected  Actual |
| 🟢 | arc | 0.024s |  Expected  Actual  Expected  Actual  Expected  Actual |
| 🟢 | captureScreenshot | 0.184s | |
| 🟢 | circle | 0.021s |  Expected  Actual |
| 🟢 | clear | 0.018s |  Expected  Actual |
| 🟡 | discard | 0.016s | cant test this worked |
| 🟢 | draw | 0.018s |  Expected  Actual |
| 🟡 | drawInstanced | 0.018s | test class needs writing |
| 🟢 | drawLayer | 0.020s |  Expected  Actual |
| 🟢 | ellipse | 0.018s |  Expected  Actual |
| 🟢 | flushBatch | 0.017s | |
| 🟢 | getBackgroundColor | 0.018s | |
| 🟢 | getBlendMode | 0.018s | |
| 🟢 | getCanvas | 0.019s | |
| 🟢 | getColor | 0.017s | |
| 🟢 | getColorMask | 0.018s | |
| 🟢 | getDPIScale | 0.017s | |
| 🟢 | getDefaultFilter | 0.018s | |
| 🟢 | getDepthMode | 0.017s | |
| 🟢 | getDimensions | 0.018s | |
| 🟢 | getFont | 0.019s | |
| 🟢 | getFrontFaceWinding | 0.017s | |
| 🟢 | getHeight | 0.017s | |
| 🟢 | getLineJoin | 0.017s | |
| 🟢 | getLineStyle | 0.020s | |
| 🟢 | getLineWidth | 0.016s | |
| 🟢 | getMeshCullMode | 0.016s | |
| 🟢 | getPixelDimensions | 0.018s | |
| 🟢 | getPixelHeight | 0.018s | |
| 🟢 | getPixelWidth | 0.018s | |
| 🟢 | getPointSize | 0.016s | |
| 🟢 | getRendererInfo | 0.019s | |
| 🟢 | getScissor | 0.017s | |
| 🟢 | getShader | 0.019s | |
| 🟢 | getStackDepth | 0.018s | |
| 🟢 | getStats | 0.018s | |
| 🟢 | getStencilMode | 0.017s | |
| 🟢 | getSupported | 0.018s | |
| 🟢 | getSystemLimits | 0.018s | |
| 🟢 | getTextureFormats | 0.019s | |
| 🟢 | getTextureTypes | 0.018s | |
| 🟢 | getWidth | 0.017s | |
| 🟢 | intersectScissor | 0.019s |  Expected  Actual |
| 🟢 | inverseTransformPoint | 0.017s | |
| 🟢 | isActive | 0.017s | |
| 🟢 | isGammaCorrect | 0.018s | |
| 🟢 | isWireframe | 0.018s | |
| 🟢 | line | 0.019s |  Expected  Actual |
| 🟢 | newArrayImage | 0.019s | |
| 🟢 | newCanvas | 0.015s | |
| 🟢 | newCubeImage | 0.020s | |
| 🟢 | newFont | 0.018s | |
| 🟢 | newImage | 0.017s | |
| 🟢 | newImageFont | 0.019s | |
| 🟢 | newMesh | 0.018s | |
| 🟢 | newParticleSystem | 0.018s | |
| 🟢 | newQuad | 0.017s | |
| 🟢 | newShader | 0.022s | |
| 🟢 | newSpriteBatch | 0.019s | |
| 🟢 | newTextBatch | 0.016s | |
| 🟢 | newVideo | 0.021s | |
| 🟢 | newVolumeImage | 0.019s | |
| 🟢 | origin | 0.018s |  Expected  Actual |
| 🟢 | points | 0.019s |  Expected  Actual |
| 🟢 | polygon | 0.016s |  Expected  Actual |
| 🟢 | pop | 0.019s |  Expected  Actual |
| 🟡 | present | 0.018s | test class needs writing |
| 🟢 | print | 0.019s |  Expected  Actual |
| 🟢 | printf | 0.019s |  Expected  Actual |
| 🟢 | push | 0.021s |  Expected  Actual |
| 🟢 | rectangle | 0.018s |  Expected  Actual  Expected  Actual |
| 🟢 | replaceTransform | 0.017s |  Expected  Actual |
| 🟢 | reset | 0.017s | |
| 🟢 | rotate | 0.020s |  Expected  Actual |
| 🟢 | scale | 0.020s | |
| 🟢 | setBackgroundColor | 0.017s | |
| 🟢 | setBlendMode | 0.020s |  Expected  Actual |
| 🟢 | setCanvas | 0.019s |  Expected  Actual |
| 🟢 | setColor | 0.018s |  Expected  Actual |
| 🟢 | setColorMask | 0.019s |  Expected  Actual |
| 🟢 | setDefaultFilter | 0.018s | |
| 🟢 | setDepthMode | 0.018s | |
| 🟢 | setFont | 0.018s |  Expected  Actual |
| 🟢 | setFrontFaceWinding | 0.018s | |
| 🟢 | setLineJoin | 0.020s |  Expected  Actual |
| 🟢 | setLineStyle | 0.017s |  Expected  Actual |
| 🟢 | setLineWidth | 0.018s |  Expected  Actual |
| 🟢 | setMeshCullMode | 0.018s | |
| 🟢 | setScissor | 0.018s |  Expected  Actual |
| 🟢 | setShader | 0.024s |  Expected  Actual |
| 🟢 | setStencilTest | 0.018s |  Expected  Actual |
| 🟢 | setWireframe | 0.019s |  Expected  Actual |
| 🟢 | shear | 0.021s |  Expected  Actual  Expected  Actual |
| 🟢 | transformPoint | 0.016s | |
| 🟢 | translate | 0.020s |  Expected  Actual |
| 🟢 | validateShader | 0.021s | |
🟢 love.image
- 🟢 5 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.088s
| Method | Time | Details |
| 🟢 | CompressedImageData | 0.018s | |
| 🟢 | ImageData | 0.018s | |
| 🟢 | isCompressed | 0.017s | |
| 🟢 | newCompressedData | 0.018s | |
| 🟢 | newImageData | 0.018s | |
🟢 love.math
- 🟢 20 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.284s
| Method | Time | Details |
| 🟢 | BezierCurve | 0.016s | |
| 🟢 | RandomGenerator | 0.017s | |
| 🟢 | Transform | 0.017s | |
| 🟢 | colorFromBytes | 0.018s | |
| 🟢 | colorToBytes | 0.018s | |
| 🟢 | gammaToLinear | 0.017s | |
| 🟢 | getRandomSeed | 0.017s | |
| 🟢 | getRandomState | 0.018s | |
| 🟢 | isConvex | 0.018s | |
| 🟢 | linearToGamma | 0.018s | |
| 🟢 | newBezierCurve | 0.018s | |
| 🟢 | newRandomGenerator | 0.018s | |
| 🟢 | newTransform | 0.017s | |
| 🟢 | perlinNoise | 0.019s | |
| 🟢 | random | 0.012s | |
| 🟢 | randomNormal | 0.017s | |
| 🟢 | setRandomSeed | 0.002s | |
| 🟢 | setRandomState | 0.002s | |
| 🟢 | simplexNoise | 0.002s | |
| 🟢 | triangulate | 0.003s | |
🟢 love.physics
- 🟢 22 Tests
- 🔴 0 Failures
- 🟡 6 Skipped
- 0.059s
| Method | Time | Details |
| 🟡 | Body | 0.002s | test class needs writing |
| 🟡 | Contact | 0.002s | test class needs writing |
| 🟡 | Fixture | 0.002s | test class needs writing |
| 🟡 | Joint | 0.002s | test class needs writing |
| 🟡 | Shape | 0.002s | test class needs writing |
| 🟡 | World | 0.002s | test class needs writing |
| 🟢 | getDistance | 0.002s | |
| 🟢 | getMeter | 0.002s | |
| 🟢 | newBody | 0.002s | |
| 🟢 | newChainShape | 0.002s | |
| 🟢 | newCircleShape | 0.005s | |
| 🟢 | newDistanceJoint | 0.002s | |
| 🟢 | newEdgeShape | 0.002s | |
| 🟢 | newFixture | 0.002s | |
| 🟢 | newFrictionJoint | 0.002s | |
| 🟢 | newGearJoint | 0.002s | |
| 🟢 | newMotorJoint | 0.002s | |
| 🟢 | newMouseJoint | 0.002s | |
| 🟢 | newPolygonShape | 0.002s | |
| 🟢 | newPrismaticJoint | 0.002s | |
| 🟢 | newPulleyJoint | 0.002s | |
| 🟢 | newRectangleShape | 0.002s | |
| 🟢 | newRevoluteJoint | 0.002s | |
| 🟢 | newRopeJoint | 0.002s | |
| 🟢 | newWeldJoint | 0.002s | |
| 🟢 | newWheelJoint | 0.002s | |
| 🟢 | newWorld | 0.002s | |
| 🟢 | setMeter | 0.002s | |
🟢 love.sound
- 🟢 4 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.015s
| Method | Time | Details |
| 🟢 | Decoder | 0.007s | |
| 🟢 | SoundData | 0.003s | |
| 🟢 | newDecoder | 0.002s | |
| 🟢 | newSoundData | 0.003s | |
🟢 love.system
- 🟢 6 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.023s
| Method | Time | Details |
| 🟢 | getClipboardText | 0.004s | |
| 🟢 | getOS | 0.007s | |
| 🟢 | getPowerInfo | 0.002s | |
| 🟢 | getProcessorCount | 0.002s | |
| 🟢 | hasBackgroundMusic | 0.002s | |
| 🟡 | openURL | 0.002s | cant test this worked |
| 🟢 | setClipboardText | 0.003s | |
| 🟡 | vibrate | 0.002s | cant test this worked |
🟢 love.thread
- 🟢 5 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.318s
| Method | Time | Details |
| 🟢 | Channel | 0.220s | |
| 🟢 | Thread | 0.092s | |
| 🟢 | getChannel | 0.002s | |
| 🟢 | newChannel | 0.002s | |
| 🟢 | newThread | 0.002s | |
🟢 love.timer
- 🟢 6 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 2.020s
| Method | Time | Details |
| 🟢 | getAverageDelta | 0.002s | |
| 🟢 | getDelta | 0.002s | |
| 🟢 | getFPS | 0.002s | |
| 🟢 | getTime | 1.003s | |
| 🟢 | sleep | 1.006s | |
| 🟢 | step | 0.004s | |
🟢 love.video
- 🟢 2 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.016s
| Method | Time | Details |
| 🟢 | VideoStream | 0.009s | |
| 🟢 | newVideoStream | 0.007s | |
🟢 love.window
- 🟢 34 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 5.954s
| Method | Time | Details |
| 🟢 | close | 0.054s | |
| 🟢 | fromPixels | 0.002s | |
| 🟢 | getDPIScale | 0.002s | |
| 🟢 | getDesktopDimensions | 0.002s | |
| 🟢 | getDisplayCount | 0.002s | |
| 🟢 | getDisplayName | 0.015s | |
| 🟢 | getDisplayOrientation | 0.017s | |
| 🟢 | getFullscreen | 1.340s | |
| 🟢 | getFullscreenModes | 0.009s | |
| 🟢 | getIcon | 0.019s | |
| 🟢 | getMode | 0.014s | |
| 🟢 | getPosition | 0.017s | |
| 🟢 | getSafeArea | 0.017s | |
| 🟢 | getTitle | 0.018s | |
| 🟢 | getVSync | 0.017s | |
| 🟢 | hasFocus | 0.018s | |
| 🟢 | hasMouseFocus | 0.018s | |
| 🟢 | isDisplaySleepEnabled | 0.017s | |
| 🟢 | isMaximized | 0.186s | |
| 🟢 | isMinimized | 0.744s | |
| 🟢 | isOpen | 0.054s | |
| 🟢 | isVisible | 0.031s | |
| 🟢 | maximize | 0.173s | |
| 🟢 | minimize | 0.740s | |
| 🟡 | requestAttention | 0.003s | cant test this worked |
| 🟢 | restore | 0.840s | |
| 🟢 | setDisplaySleepEnabled | 0.016s | |
| 🟢 | setFullscreen | 1.335s | |
| 🟢 | setIcon | 0.013s | |
| 🟢 | setMode | 0.021s | |
| 🟢 | setPosition | 0.178s | |
| 🟢 | setTitle | 0.003s | |
| 🟢 | setVSync | 0.002s | |
| 🟡 | showMessageBox | 0.002s | cant test this worked |
| 🟢 | toPixels | 0.002s | |
| 🟢 | updateMode | 0.014s | |
\ No newline at end of file
+🔴 love.test
- 🟢 281 Tests
- 🔴 2 Failures
- 🟡 20 Skipped
- 13.278s
🟢 love.audio
- 🟢 28 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.851s
| Method | Time | Details |
| 🟢 | RecordingDevice | 0.397s | |
| 🟢 | Source | 0.021s | |
| 🟢 | getActiveEffects | 0.017s | |
| 🟢 | getActiveSourceCount | 0.018s | |
| 🟢 | getDistanceModel | 0.017s | |
| 🟢 | getDopplerScale | 0.017s | |
| 🟢 | getEffect | 0.017s | |
| 🟢 | getMaxSceneEffects | 0.017s | |
| 🟢 | getMaxSourceEffects | 0.017s | |
| 🟢 | getOrientation | 0.017s | |
| 🟢 | getPosition | 0.016s | |
| 🟢 | getRecordingDevices | 0.017s | |
| 🟢 | getVelocity | 0.014s | |
| 🟢 | getVolume | 0.017s | |
| 🟢 | isEffectsSupported | 0.017s | |
| 🟢 | newQueueableSource | 0.017s | |
| 🟢 | newSource | 0.017s | |
| 🟢 | pause | 0.017s | |
| 🟢 | play | 0.017s | |
| 🟢 | setDistanceModel | 0.018s | |
| 🟢 | setDopplerScale | 0.016s | |
| 🟢 | setEffect | 0.017s | |
| 🟢 | setMixWithSystem | 0.017s | |
| 🟢 | setOrientation | 0.016s | |
| 🟢 | setPosition | 0.016s | |
| 🟢 | setVelocity | 0.016s | |
| 🟢 | setVolume | 0.016s | |
| 🟢 | stop | 0.017s | |
🟢 love.data
- 🟢 12 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.197s
| Method | Time | Details |
| 🟢 | ByteData | 0.016s | |
| 🟢 | CompressedData | 0.016s | |
| 🟢 | compress | 0.016s | |
| 🟢 | decode | 0.018s | |
| 🟢 | decompress | 0.017s | |
| 🟢 | encode | 0.017s | |
| 🟢 | getPackedSize | 0.016s | |
| 🟢 | hash | 0.015s | |
| 🟢 | newByteData | 0.016s | |
| 🟢 | newDataView | 0.015s | |
| 🟢 | pack | 0.018s | |
| 🟢 | unpack | 0.016s | |
🟢 love.event
- 🟢 4 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.096s
| Method | Time | Details |
| 🟢 | clear | 0.016s | |
| 🟢 | poll | 0.016s | |
| 🟡 | pump | 0.016s | used internally |
| 🟢 | push | 0.016s | |
| 🟢 | quit | 0.016s | |
| 🟡 | wait | 0.016s | used internally |
🟢 love.filesystem
- 🟢 29 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.539s
| Method | Time | Details |
| 🟢 | File | 0.020s | |
| 🟢 | FileData | 0.016s | |
| 🟢 | append | 0.022s | |
| 🟢 | areSymlinksEnabled | 0.017s | |
| 🟢 | createDirectory | 0.017s | |
| 🟢 | getAppdataDirectory | 0.016s | |
| 🟢 | getCRequirePath | 0.017s | |
| 🟢 | getDirectoryItems | 0.019s | |
| 🟢 | getIdentity | 0.017s | |
| 🟢 | getInfo | 0.018s | |
| 🟢 | getRealDirectory | 0.017s | |
| 🟢 | getRequirePath | 0.017s | |
| 🟢 | getSaveDirectory | 0.017s | |
| 🟡 | getSource | 0.017s | used internally |
| 🟢 | getSourceBaseDirectory | 0.017s | |
| 🟢 | getUserDirectory | 0.018s | |
| 🟢 | getWorkingDirectory | 0.021s | |
| 🟢 | isFused | 0.014s | |
| 🟢 | lines | 0.017s | |
| 🟢 | load | 0.018s | |
| 🟢 | mount | 0.018s | |
| 🟢 | newFileData | 0.018s | |
| 🟢 | openFile | 0.016s | |
| 🟢 | read | 0.016s | |
| 🟢 | remove | 0.017s | |
| 🟢 | setCRequirePath | 0.016s | |
| 🟢 | setIdentity | 0.016s | |
| 🟢 | setRequirePath | 0.015s | |
| 🟡 | setSource | 0.017s | used internally |
| 🟢 | unmount | 0.018s | |
| 🟢 | write | 0.019s | |
🔴 love.font
- 🟢 6 Tests
- 🔴 1 Failures
- 🟡 0 Skipped
- 0.121s
| Method | Time | Details |
| 🔴 | GlyphData | 0.016s | assert 8 [check glyph number] expected '97' got '0' |
| 🟢 | Rasterizer | 0.016s | |
| 🟢 | newBMFontRasterizer | 0.017s | |
| 🟢 | newGlyphData | 0.018s | |
| 🟢 | newImageRasterizer | 0.018s | |
| 🟢 | newRasterizer | 0.018s | |
| 🟢 | newTrueTypeRasterizer | 0.018s | |
🔴 love.graphics
- 🟢 98 Tests
- 🔴 1 Failures
- 🟡 6 Skipped
- 2.029s
| Method | Time | Details |
| 🔴 | Canvas | 0.018s | assert 44 [check depth sample mode set] expected 'equal' got 'nil' |
| 🟢 | Font | 0.023s |  Expected  Actual  Expected  Actual |
| 🟢 | Image | 0.020s |  Expected  Actual |
| 🟡 | Mesh | 0.018s | test class needs writing |
| 🟡 | ParticleSystem | 0.017s | test class needs writing |
| 🟢 | Quad | 0.020s |  Expected  Actual |
| 🟢 | Shader | 0.029s |  Expected  Actual |
| 🟡 | SpriteBatch | 0.016s | test class needs writing |
| 🟢 | Text | 0.014s |  Expected  Actual |
| 🟡 | Video | 0.015s | test class needs writing |
| 🟢 | applyTransform | 0.018s |  Expected  Actual |
| 🟢 | arc | 0.026s |  Expected  Actual  Expected  Actual  Expected  Actual |
| 🟢 | captureScreenshot | 0.183s | |
| 🟢 | circle | 0.023s |  Expected  Actual |
| 🟢 | clear | 0.018s |  Expected  Actual |
| 🟡 | discard | 0.017s | cant test this worked |
| 🟢 | draw | 0.034s |  Expected  Actual |
| 🟡 | drawInstanced | 0.014s | test class needs writing |
| 🟢 | drawLayer | 0.017s |  Expected  Actual |
| 🟢 | ellipse | 0.018s |  Expected  Actual |
| 🟢 | flushBatch | 0.016s | |
| 🟢 | getBackgroundColor | 0.016s | |
| 🟢 | getBlendMode | 0.016s | |
| 🟢 | getCanvas | 0.016s | |
| 🟢 | getColor | 0.016s | |
| 🟢 | getColorMask | 0.015s | |
| 🟢 | getDPIScale | 0.016s | |
| 🟢 | getDefaultFilter | 0.016s | |
| 🟢 | getDepthMode | 0.016s | |
| 🟢 | getDimensions | 0.016s | |
| 🟢 | getFont | 0.016s | |
| 🟢 | getFrontFaceWinding | 0.016s | |
| 🟢 | getHeight | 0.015s | |
| 🟢 | getLineJoin | 0.016s | |
| 🟢 | getLineStyle | 0.025s | |
| 🟢 | getLineWidth | 0.018s | |
| 🟢 | getMeshCullMode | 0.016s | |
| 🟢 | getPixelDimensions | 0.016s | |
| 🟢 | getPixelHeight | 0.024s | |
| 🟢 | getPixelWidth | 0.013s | |
| 🟢 | getPointSize | 0.016s | |
| 🟢 | getRendererInfo | 0.016s | |
| 🟢 | getScissor | 0.016s | |
| 🟢 | getShader | 0.017s | |
| 🟢 | getStackDepth | 0.016s | |
| 🟢 | getStats | 0.015s | |
| 🟢 | getStencilMode | 0.016s | |
| 🟢 | getSupported | 0.015s | |
| 🟢 | getSystemLimits | 0.015s | |
| 🟢 | getTextureFormats | 0.017s | |
| 🟢 | getTextureTypes | 0.016s | |
| 🟢 | getWidth | 0.015s | |
| 🟢 | intersectScissor | 0.017s |  Expected  Actual |
| 🟢 | inverseTransformPoint | 0.016s | |
| 🟢 | isActive | 0.016s | |
| 🟢 | isGammaCorrect | 0.015s | |
| 🟢 | isWireframe | 0.015s | |
| 🟢 | line | 0.017s |  Expected  Actual |
| 🟢 | newArrayImage | 0.016s | |
| 🟢 | newCanvas | 0.015s | |
| 🟢 | newCubeImage | 0.017s | |
| 🟢 | newFont | 0.017s | |
| 🟢 | newImage | 0.017s | |
| 🟢 | newImageFont | 0.016s | |
| 🟢 | newMesh | 0.016s | |
| 🟢 | newParticleSystem | 0.017s | |
| 🟢 | newQuad | 0.016s | |
| 🟢 | newShader | 0.022s | |
| 🟢 | newSpriteBatch | 0.017s | |
| 🟢 | newTextBatch | 0.011s | |
| 🟢 | newVideo | 0.019s | |
| 🟢 | newVolumeImage | 0.018s | |
| 🟢 | origin | 0.018s |  Expected  Actual |
| 🟢 | points | 0.020s |  Expected  Actual |
| 🟢 | polygon | 0.021s |  Expected  Actual |
| 🟢 | pop | 0.018s |  Expected  Actual |
| 🟢 | print | 0.020s |  Expected  Actual |
| 🟢 | printf | 0.020s |  Expected  Actual |
| 🟢 | push | 0.018s |  Expected  Actual |
| 🟢 | rectangle | 0.020s |  Expected  Actual  Expected  Actual |
| 🟢 | replaceTransform | 0.018s |  Expected  Actual |
| 🟢 | reset | 0.018s | |
| 🟢 | rotate | 0.018s |  Expected  Actual |
| 🟢 | scale | 0.017s | |
| 🟢 | setBackgroundColor | 0.017s | |
| 🟢 | setBlendMode | 0.019s |  Expected  Actual |
| 🟢 | setCanvas | 0.018s |  Expected  Actual |
| 🟢 | setColor | 0.018s |  Expected  Actual |
| 🟢 | setColorMask | 0.019s |  Expected  Actual |
| 🟢 | setDefaultFilter | 0.017s | |
| 🟢 | setDepthMode | 0.017s | |
| 🟢 | setFont | 0.019s |  Expected  Actual |
| 🟢 | setFrontFaceWinding | 0.017s | |
| 🟢 | setLineJoin | 0.018s |  Expected  Actual |
| 🟢 | setLineStyle | 0.018s |  Expected  Actual |
| 🟢 | setLineWidth | 0.019s |  Expected  Actual |
| 🟢 | setMeshCullMode | 0.018s | |
| 🟢 | setScissor | 0.020s |  Expected  Actual |
| 🟢 | setShader | 0.023s |  Expected  Actual |
| 🟢 | setStencilTest | 0.019s |  Expected  Actual |
| 🟢 | setWireframe | 0.018s |  Expected  Actual |
| 🟢 | shear | 0.019s |  Expected  Actual  Expected  Actual |
| 🟢 | transformPoint | 0.018s | |
| 🟢 | translate | 0.025s |  Expected  Actual |
| 🟢 | validateShader | 0.016s | |
🟢 love.image
- 🟢 5 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.087s
| Method | Time | Details |
| 🟢 | CompressedImageData | 0.018s | |
| 🟢 | ImageData | 0.017s | |
| 🟢 | isCompressed | 0.017s | |
| 🟢 | newCompressedData | 0.019s | |
| 🟢 | newImageData | 0.017s | |
🟢 love.math
- 🟢 20 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.321s
| Method | Time | Details |
| 🟢 | BezierCurve | 0.018s | |
| 🟢 | RandomGenerator | 0.017s | |
| 🟢 | Transform | 0.017s | |
| 🟢 | colorFromBytes | 0.017s | |
| 🟢 | colorToBytes | 0.016s | |
| 🟢 | gammaToLinear | 0.016s | |
| 🟢 | getRandomSeed | 0.016s | |
| 🟢 | getRandomState | 0.016s | |
| 🟢 | isConvex | 0.016s | |
| 🟢 | linearToGamma | 0.017s | |
| 🟢 | newBezierCurve | 0.016s | |
| 🟢 | newRandomGenerator | 0.016s | |
| 🟢 | newTransform | 0.016s | |
| 🟢 | perlinNoise | 0.015s | |
| 🟢 | random | 0.016s | |
| 🟢 | randomNormal | 0.014s | |
| 🟢 | setRandomSeed | 0.015s | |
| 🟢 | setRandomState | 0.015s | |
| 🟢 | simplexNoise | 0.016s | |
| 🟢 | triangulate | 0.016s | |
🟢 love.physics
- 🟢 22 Tests
- 🔴 0 Failures
- 🟡 6 Skipped
- 0.468s
| Method | Time | Details |
| 🟡 | Body | 0.018s | test class needs writing |
| 🟡 | Contact | 0.017s | test class needs writing |
| 🟡 | Fixture | 0.026s | test class needs writing |
| 🟡 | Joint | 0.017s | test class needs writing |
| 🟡 | Shape | 0.017s | test class needs writing |
| 🟡 | World | 0.017s | test class needs writing |
| 🟢 | getDistance | 0.017s | |
| 🟢 | getMeter | 0.015s | |
| 🟢 | newBody | 0.016s | |
| 🟢 | newChainShape | 0.016s | |
| 🟢 | newCircleShape | 0.017s | |
| 🟢 | newDistanceJoint | 0.016s | |
| 🟢 | newEdgeShape | 0.017s | |
| 🟢 | newFixture | 0.016s | |
| 🟢 | newFrictionJoint | 0.016s | |
| 🟢 | newGearJoint | 0.016s | |
| 🟢 | newMotorJoint | 0.016s | |
| 🟢 | newMouseJoint | 0.018s | |
| 🟢 | newPolygonShape | 0.016s | |
| 🟢 | newPrismaticJoint | 0.017s | |
| 🟢 | newPulleyJoint | 0.016s | |
| 🟢 | newRectangleShape | 0.017s | |
| 🟢 | newRevoluteJoint | 0.015s | |
| 🟢 | newRopeJoint | 0.016s | |
| 🟢 | newWeldJoint | 0.015s | |
| 🟢 | newWheelJoint | 0.016s | |
| 🟢 | newWorld | 0.014s | |
| 🟢 | setMeter | 0.015s | |
🟢 love.sound
- 🟢 4 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.068s
| Method | Time | Details |
| 🟢 | Decoder | 0.018s | |
| 🟢 | SoundData | 0.017s | |
| 🟢 | newDecoder | 0.016s | |
| 🟢 | newSoundData | 0.017s | |
🟢 love.system
- 🟢 6 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 0.148s
| Method | Time | Details |
| 🟢 | getClipboardText | 0.019s | |
| 🟢 | getOS | 0.017s | |
| 🟢 | getPowerInfo | 0.017s | |
| 🟢 | getProcessorCount | 0.016s | |
| 🟢 | hasBackgroundMusic | 0.029s | |
| 🟡 | openURL | 0.016s | cant test this worked |
| 🟢 | setClipboardText | 0.017s | |
| 🟡 | vibrate | 0.016s | cant test this worked |
🟢 love.thread
- 🟢 5 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.376s
| Method | Time | Details |
| 🟢 | Channel | 0.230s | |
| 🟢 | Thread | 0.093s | |
| 🟢 | getChannel | 0.018s | |
| 🟢 | newChannel | 0.017s | |
| 🟢 | newThread | 0.018s | |
🟢 love.timer
- 🟢 6 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 2.082s
| Method | Time | Details |
| 🟢 | getAverageDelta | 0.017s | |
| 🟢 | getDelta | 0.016s | |
| 🟢 | getFPS | 0.016s | |
| 🟢 | getTime | 1.017s | |
| 🟢 | sleep | 1.009s | |
| 🟢 | step | 0.005s | |
🟢 love.video
- 🟢 2 Tests
- 🔴 0 Failures
- 🟡 0 Skipped
- 0.039s
| Method | Time | Details |
| 🟢 | VideoStream | 0.020s | |
| 🟢 | newVideoStream | 0.020s | |
🟢 love.window
- 🟢 34 Tests
- 🔴 0 Failures
- 🟡 2 Skipped
- 5.855s
| Method | Time | Details |
| 🟢 | close | 0.052s | |
| 🟢 | fromPixels | 0.002s | |
| 🟢 | getDPIScale | 0.017s | |
| 🟢 | getDesktopDimensions | 0.018s | |
| 🟢 | getDisplayCount | 0.017s | |
| 🟢 | getDisplayName | 0.018s | |
| 🟢 | getDisplayOrientation | 0.018s | |
| 🟢 | getFullscreen | 1.357s | |
| 🟢 | getFullscreenModes | 0.010s | |
| 🟢 | getIcon | 0.019s | |
| 🟢 | getMode | 0.015s | |
| 🟢 | getPosition | 0.017s | |
| 🟢 | getSafeArea | 0.016s | |
| 🟢 | getTitle | 0.017s | |
| 🟢 | getVSync | 0.016s | |
| 🟢 | hasFocus | 0.016s | |
| 🟢 | hasMouseFocus | 0.015s | |
| 🟢 | isDisplaySleepEnabled | 0.017s | |
| 🟢 | isMaximized | 0.185s | |
| 🟢 | isMinimized | 0.749s | |
| 🟢 | isOpen | 0.037s | |
| 🟢 | isVisible | 0.024s | |
| 🟢 | maximize | 0.156s | |
| 🟢 | minimize | 0.733s | |
| 🟡 | requestAttention | 0.003s | cant test this worked |
| 🟢 | restore | 0.880s | |
| 🟢 | setDisplaySleepEnabled | 0.020s | |
| 🟢 | setFullscreen | 1.151s | |
| 🟢 | setIcon | 0.007s | |
| 🟢 | setMode | 0.023s | |
| 🟢 | setPosition | 0.181s | |
| 🟢 | setTitle | 0.018s | |
| 🟢 | setVSync | 0.015s | |
| 🟡 | showMessageBox | 0.003s | cant test this worked |
| 🟢 | toPixels | 0.002s | |
| 🟢 | updateMode | 0.011s | |
\ No newline at end of file
diff --git a/testing/examples/lovetest_runAllTests.md b/testing/examples/lovetest_runAllTests.md
index c69865ba7..d309282ee 100644
--- a/testing/examples/lovetest_runAllTests.md
+++ b/testing/examples/lovetest_runAllTests.md
@@ -1,31 +1,31 @@
-
+
-**305** tests were completed in **16.781s** with **275** passed, **2** failed, and **28** skipped
+**303** tests were completed in **13.278s** with **281** passed, **2** failed, and **20** skipped
### Report
| Module | Pass | Fail | Skip | Time |
| --------------------- | ------ | ------ | ------- | ------ |
-| 🔴 audio | 27 | 1 | 0 | 4.898s |
-| 🟢 data | 12 | 0 | 0 | 0.213s |
-| 🟢 event | 4 | 0 | 2 | 0.103s |
-| 🟢 filesystem | 29 | 0 | 2 | 0.561s |
-| 🔴 font | 6 | 1 | 0 | 0.123s |
-| 🟢 graphics | 93 | 0 | 14 | 2.106s |
-| 🟢 image | 5 | 0 | 0 | 0.088s |
-| 🟢 math | 20 | 0 | 0 | 0.284s |
-| 🟢 physics | 22 | 0 | 6 | 0.059s |
-| 🟢 sound | 4 | 0 | 0 | 0.015s |
-| 🟢 system | 6 | 0 | 2 | 0.023s |
-| 🟢 thread | 5 | 0 | 0 | 0.318s |
-| 🟢 timer | 6 | 0 | 0 | 2.020s |
-| 🟢 video | 2 | 0 | 0 | 0.016s |
-| 🟢 window | 34 | 0 | 2 | 5.954s |
+| 🟢 audio | 28 | 0 | 0 | 0.851s |
+| 🟢 data | 12 | 0 | 0 | 0.197s |
+| 🟢 event | 4 | 0 | 2 | 0.096s |
+| 🟢 filesystem | 29 | 0 | 2 | 0.539s |
+| 🔴 font | 6 | 1 | 0 | 0.121s |
+| 🔴 graphics | 98 | 1 | 6 | 2.029s |
+| 🟢 image | 5 | 0 | 0 | 0.087s |
+| 🟢 math | 20 | 0 | 0 | 0.321s |
+| 🟢 physics | 22 | 0 | 6 | 0.468s |
+| 🟢 sound | 4 | 0 | 0 | 0.068s |
+| 🟢 system | 6 | 0 | 2 | 0.148s |
+| 🟢 thread | 5 | 0 | 0 | 0.376s |
+| 🟢 timer | 6 | 0 | 0 | 2.082s |
+| 🟢 video | 2 | 0 | 0 | 0.039s |
+| 🟢 window | 34 | 0 | 2 | 5.855s |
### Failures
-> 🔴 Source
-> assert 53 [check effect was applied] expected 'true' got 'false'
-
> 🔴 GlyphData
> assert 8 [check glyph number] expected '97' got '0'
+> 🔴 Canvas
+> assert 44 [check depth sample mode set] expected 'equal' got 'nil'
+
diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml
index deb2d4201..dc3bb5e04 100644
--- a/testing/examples/lovetest_runAllTests.xml
+++ b/testing/examples/lovetest_runAllTests.xml
@@ -1,162 +1,161 @@
-
-
-
+
+
+
-
- assert 53 [check effect was applied] expected 'true' got 'false'
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -166,507 +165,496 @@
-
-
+
+
assert 8 [check glyph number] expected '97' got '0'
-
+
-
+
-
+
-
+
-
-
-
+
+
+ assert 44 [check depth sample mode set] expected 'equal' got 'nil'
-
-
+
-
-
+
-
+
-
+
+
+
+
+
-
+
+
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/testing/output/expected/love.test.graphics.Font-1.png b/testing/output/expected/love.test.graphics.Font-1.png
new file mode 100644
index 000000000..cb2f21a1e
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Font-1.png differ
diff --git a/testing/output/expected/love.test.graphics.Font-2.png b/testing/output/expected/love.test.graphics.Font-2.png
new file mode 100644
index 000000000..d12d68425
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Font-2.png differ
diff --git a/testing/output/expected/love.test.graphics.Image-1.png b/testing/output/expected/love.test.graphics.Image-1.png
new file mode 100644
index 000000000..5f45cf9e7
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Image-1.png differ
diff --git a/testing/output/expected/love.test.graphics.Quad-1.png b/testing/output/expected/love.test.graphics.Quad-1.png
new file mode 100644
index 000000000..22ab17e3e
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Quad-1.png differ
diff --git a/testing/output/expected/love.test.graphics.Shader-1.png b/testing/output/expected/love.test.graphics.Shader-1.png
new file mode 100644
index 000000000..6742f6386
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Shader-1.png differ
diff --git a/testing/output/expected/love.test.graphics.Text-1.png b/testing/output/expected/love.test.graphics.Text-1.png
new file mode 100644
index 000000000..4f15348cd
Binary files /dev/null and b/testing/output/expected/love.test.graphics.Text-1.png differ
diff --git a/testing/output/expected/love.test.graphics.setColorMask-1.png b/testing/output/expected/love.test.graphics.setColorMask-1.png
index 254f834f8..315c7a936 100644
Binary files a/testing/output/expected/love.test.graphics.setColorMask-1.png and b/testing/output/expected/love.test.graphics.setColorMask-1.png differ
diff --git a/testing/readme.md b/testing/readme.md
index 2f6f8bb42..9a56fe471 100644
--- a/testing/readme.md
+++ b/testing/readme.md
@@ -23,10 +23,10 @@ This is the status of all module tests currently.
| ----------------- | ---- | ---- | ---- |
| 🟢 audio | 28 | 0 | 0 |
| 🟢 data | 12 | 0 | 0 |
-| 🟡 event | 4 | 1 | 1 |
-| 🟢 filesystem | 28 | 0 | 2 |
+| 🟢 event | 4 | 0 | 2 |
+| 🟢 filesystem | 29 | 0 | 2 |
| 🟢 font | 7 | 0 | 0 |
-| 🟡 graphics | 93 | 14 | 1 |
+| 🟡 graphics | 99 | 5 | 1 |
| 🟢 image | 5 | 0 | 0 |
| 🟢 math | 20 | 0 | 0 |
| 🟡 physics | 22 | 6 | 0 |
@@ -113,24 +113,20 @@ For sanity-checking, if it's currently not covered or it's not possible to test
Things still left to do:
- [ ] physics.Body, physics.Contact, physics.Fixture,
physics.Joint, physics.Shape, physics.World
-- [ ] graphics.Canvas, graphics.Font, graphics.Image, graphics.Mesh,
- graphics.ParticleSystem, graphics.Quad, graphics.Shader,
- graphics.SpriteBatch, graphics.Text, graphics.Texture, graphics.Video
-- [ ] event.wait
-- [ ] graphics.present
-- [ ] graphics.drawInstanced
-- [ ] graphics.setDepthMode (needs actual graphical comparison if possible)
-- [ ] graphics.setFrontFaceWinding (needs actual graphical comparison if possible)
-- [ ] graphics.setMeshCullMode (needs actual graphical comparison if possible)
-- [ ] @deprecated setStencilTest (use setStencilMode)
- [ ] @deprecated physics methods (sasha changes)
-- [ ] check 12.0 wiki page for new methods
-- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported)
-- [ ] ideally graphics.isCompressed should have an example of all compressed files love can take
+- [ ] graphics.Mesh, graphics.ParticleSystem
+ graphics.SpriteBatch, graphics.Video
+- [ ] graphics.drawInstanced
+- [ ] @deprecated love.graphics.stencil (replaced by love.graphics.setStencilMode)
+- [ ] @deprecated love.graphics.setStencilTest (replaced by love.graphics.setStencilMode)
---
## Future Goals
-- [ ] Tests can compare visual results to a reference image (partially done)
+- [ ] graphics.isCompressed should have an example of all compressed files love can take
+- [ ] Tests can compare visual results to a reference image
+ This is partially done as we already save actual images for graphics tests to
+ use in the report output comparisons, so we just need to add a helper method
+ to the test class to let you just do assertMatching on the imgdata
- [ ] Ability to test loading different combinations of modules
- [ ] Performance tests
diff --git a/testing/resources/font-letters-ab.png b/testing/resources/font-letters-ab.png
new file mode 100644
index 000000000..3ec8aeca3
Binary files /dev/null and b/testing/resources/font-letters-ab.png differ
diff --git a/testing/resources/font-letters-cd.png b/testing/resources/font-letters-cd.png
new file mode 100644
index 000000000..51190f648
Binary files /dev/null and b/testing/resources/font-letters-cd.png differ
diff --git a/testing/resources/love_test_graphics_rectangle_expected.png b/testing/resources/love_test_graphics_rectangle_expected.png
deleted file mode 100644
index bbbaf6edc..000000000
Binary files a/testing/resources/love_test_graphics_rectangle_expected.png and /dev/null differ
diff --git a/testing/tests/event.lua b/testing/tests/event.lua
index 9e43f8b82..00b49f3a3 100644
--- a/testing/tests/event.lua
+++ b/testing/tests/event.lua
@@ -76,5 +76,5 @@ end
-- love.event.wait
-- @NOTE not sure best way to test this one
love.test.event.wait = function(test)
- test:skipTest('test class needs writing')
+ test:skipTest('used internally')
end
diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua
index 43b389fa4..1b06b0dcc 100644
--- a/testing/tests/graphics.lua
+++ b/testing/tests/graphics.lua
@@ -10,19 +10,221 @@
-- Canvas (love.graphics.newCanvas)
love.test.graphics.Canvas = function(test)
- test:skipTest('test class needs writing')
+ -- create canvas with defaults
+ local canvas = love.graphics.newCanvas(100, 100, {
+ type = '2d',
+ format = 'normal',
+ readable = true,
+ msaa = 0,
+ dpiscale = love.graphics.getDPIScale(),
+ mipmaps = 'auto'
+ })
+ test:assertObject(canvas)
+ -- check texture settings
+ test:assertEquals(love.graphics.getDPIScale(), canvas:getDPIScale(), 'check dpi scale')
+ test:assertEquals(1, canvas:getDepth(), 'check depth is 2d')
+ test:assertEquals(nil, canvas:getDepthSampleMode(), 'check depth sample nil')
+ local min, mag, ani = canvas:getFilter()
+ test:assertEquals('nearest', min, 'check filter def min')
+ test:assertEquals('nearest', mag, 'check filter def mag')
+ test:assertEquals(1, ani, 'check filter def ani')
+ canvas:setFilter('linear', 'linear', 2)
+ min, mag, ani = canvas:getFilter()
+ test:assertEquals('linear', min, 'check filter changed min')
+ test:assertEquals('linear', mag, 'check filter changed mag')
+ test:assertEquals(2, ani, 'check filter changed ani')
+ test:assertEquals(1, canvas:getLayerCount(), 'check 1 layer for 2d')
+ test:assertEquals('2d', canvas:getTextureType(), 'check 2d')
+ local horiz, vert = canvas:getWrap()
+ test:assertEquals('clamp', horiz, 'check def wrap h')
+ test:assertEquals('clamp', vert, 'check def wrap v')
+ canvas:setWrap('repeat', 'repeat')
+ horiz, vert = canvas:getWrap()
+ test:assertEquals('repeat', horiz, 'check changed wrap h')
+ test:assertEquals('repeat', vert, 'check changed wrap v')
+ test:assertEquals(true, canvas:isReadable(), 'check canvas readable')
+ test:assertEquals(1, canvas:getMSAA(), 'check samples match')
+ -- check dimensions
+ local cw, ch = canvas:getDimensions()
+ test:assertEquals(100, cw, 'check canvas dim w')
+ test:assertEquals(100, ch, 'check canvas dim h')
+ test:assertEquals(cw, canvas:getWidth(), 'check canvas w matches dim')
+ test:assertEquals(ch, canvas:getHeight(), 'check canvas h matches dim')
+ local pw, ph = canvas:getPixelDimensions()
+ test:assertEquals(100*love.graphics.getDPIScale(), pw, 'check pixel dim w')
+ test:assertEquals(100*love.graphics.getDPIScale(), ph, 'check pixel dim h')
+ test:assertEquals(pw, canvas:getPixelWidth(), 'check pixel w matches dim')
+ test:assertEquals(ph, canvas:getPixelHeight(), 'check pixel h matches dim')
+ -- check mipmaps
+ local mode, sharpness = canvas:getMipmapFilter()
+ test:assertEquals('linear', mode, 'check def minmap filter mode')
+ test:assertEquals(0, sharpness, 'check def minmap filter sharpness')
+ canvas:setMipmapFilter('nearest', 1)
+ mode, sharpness = canvas:getMipmapFilter()
+ test:assertEquals('nearest', mode, 'check changed minmap filter mode')
+ test:assertEquals(1, sharpness, 'check changed minmap filter sharpness')
+ test:assertGreaterEqual(2, canvas:getMipmapCount()) -- docs say no mipmaps should return 1
+ test:assertEquals('auto', canvas:getMipmapMode())
+ -- check rendering
+ canvas:renderTo(function()
+ love.graphics.setColor(1, 0, 0)
+ love.graphics.rectangle('fill', 0, 0, 200, 200)
+ love.graphics.setColor(1, 1, 1, 1)
+ end)
+ local data = love.graphics.readbackTexture(canvas, {100, 0, 0, 0, 100, 100})
+ local r, g, b, a = data:getPixel(2, 2)
+ test:assertEquals(1, r, 'check canvas draw r')
+ test:assertEquals(0, g, 'check canvas draw g')
+ test:assertEquals(0, b, 'check canvas draw b')
+ test:assertEquals(1, a, 'check canvas draw a')
+ -- check using canvas in love.graphics.draw()
+ local xcanvas = love.graphics.newCanvas()
+ love.graphics.setCanvas(xcanvas)
+ love.graphics.draw(canvas, 0, 0)
+ love.graphics.setCanvas()
+ data = love.graphics.readbackTexture(canvas, {100, 0, 0, 0, 100, 100})
+ r, g, b, a = data:getPixel(2, 2)
+ test:assertEquals(1, r, 'check canvas draw r')
+ test:assertEquals(0, g, 'check canvas draw g')
+ test:assertEquals(0, b, 'check canvas draw b')
+ test:assertEquals(1, a, 'check canvas draw a')
+ -- check depth samples
+ local dcanvas = love.graphics.newCanvas(100, 100, {
+ type = '2d',
+ format = 'depth16'
+ })
+ test:assertEquals(nil, dcanvas:getDepthSampleMode(), 'check depth sample mode nil by def')
+ dcanvas:setDepthSampleMode('equal')
+ test:assertEquals('equal', dcanvas:getDepthSampleMode(), 'check depth sample mode set')
end
-- Font (love.graphics.newFont)
love.test.graphics.Font = function(test)
- test:skipTest('test class needs writing')
+ -- create obj
+ local font = love.graphics.newFont('resources/font.ttf', 8)
+ test:assertObject(font)
+ -- check properties match expected
+ test:assertEquals(6, font:getAscent(), 'check ascent')
+ test:assertEquals(6, font:getBaseline(), 'check baseline')
+ test:assertEquals(1, font:getDPIScale(), 'check dpi')
+ test:assertEquals(-2, font:getDescent(), 'check descent')
+ test:assertEquals('nearest', font:getFilter(), 'check filter def')
+ font:setFilter('linear', 'linear')
+ test:assertEquals('linear', font:getFilter(), 'check filter change')
+ font:setFilter('nearest', 'nearest')
+ test:assertEquals(8, font:getHeight(), 'check height')
+ test:assertEquals(0, font:getKerning('a', 'b'), 'check kerning')
+ test:assertEquals(1, font:getLineHeight(), 'check line height')
+ font:setLineHeight(2)
+ test:assertEquals(2, font:getLineHeight(), 'check changed line height')
+ font:setLineHeight(1) -- reset for drawing + wrap later
+ test:assertEquals(24, font:getWidth('test'), 'check data size')
+ test:assertEquals(true, font:hasGlyphs('test'), 'check data size')
+ -- check font wrapping
+ local width, wrappedtext = font:getWrap('LÖVE is an *awesome* framework you can use to make 2D games in Lua.', 50)
+ test:assertEquals(48, width, 'check actual wrap width')
+ test:assertEquals(8, #wrappedtext, 'check wrapped lines')
+ test:assertEquals('LÖVE is an ', wrappedtext[1], 'check wrapped line')
+ -- check drawing font
+ local canvas = love.graphics.newCanvas(16, 16)
+ love.graphics.setCanvas(canvas)
+ love.graphics.setFont(font)
+ love.graphics.print('Aa', 0, 5)
+ love.graphics.setCanvas()
+ local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
+ test:assertPixels(imgdata, {
+ white = {{0,3},{4,3},{7,4},{9,4},{10,5},{0,8},{4,8},{10,8}},
+ }, 'font draw check')
+ test:exportImg(imgdata)
+ -- check font substitution
+ local fontab = love.graphics.newImageFont('resources/font-letters-ab.png', 'AB')
+ local fontcd = love.graphics.newImageFont('resources/font-letters-cd.png', 'CD')
+ fontab:setFallbacks(fontcd)
+ love.graphics.setCanvas(canvas)
+ love.graphics.clear(0, 0, 0, 0)
+ love.graphics.setFont(fontab)
+ love.graphics.print('AB', 0, 0)
+ love.graphics.print('CD', 0, 9)
+ love.graphics.setCanvas()
+ local imgdata2 = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
+ test:assertPixels(imgdata2, {
+ green = {{1,8},{6,8},{2,10},{5,10},{9,10}},
+ black = {{9,9},{14,8},{14,10},{14,1},{1,10}}
+ }, 'font draw check')
+ test:exportImg(imgdata2)
end
-- Image (love.graphics.newImage)
love.test.graphics.Image = function(test)
- test:skipTest('test class needs writing')
+ -- create object
+ local image = love.graphics.newImage('resources/love.png', {
+ dpiscale = 1,
+ mipmaps = true
+ })
+ test:assertObject(image)
+ -- check texture props
+ test:assertEquals(love.graphics.getDPIScale(), image:getDPIScale(), 'check dpi scale')
+ test:assertEquals(1, image:getDepth(), 'check depth is 2d')
+ test:assertEquals(nil, image:getDepthSampleMode(), 'check depth sample nil')
+ local min, mag, ani = image:getFilter()
+ test:assertEquals('nearest', min, 'check filter def min')
+ test:assertEquals('nearest', mag, 'check filter def mag')
+ test:assertEquals(1, ani, 'check filter def ani')
+ image:setFilter('linear', 'linear', 2)
+ min, mag, ani = image:getFilter()
+ test:assertEquals('linear', min, 'check filter changed min')
+ test:assertEquals('linear', mag, 'check filter changed mag')
+ test:assertEquals(2, ani, 'check filter changed ani')
+ test:assertEquals(1, image:getLayerCount(), 'check 1 layer for 2d')
+ test:assertEquals('2d', image:getTextureType(), 'check 2d')
+ local horiz, vert = image:getWrap()
+ test:assertEquals('clamp', horiz, 'check def wrap h')
+ test:assertEquals('clamp', vert, 'check def wrap v')
+ image:setWrap('repeat', 'repeat')
+ horiz, vert = image:getWrap()
+ test:assertEquals('repeat', horiz, 'check changed wrap h')
+ test:assertEquals('repeat', vert, 'check changed wrap v')
+ test:assertEquals(true, image:isReadable(), 'check canvas readable')
+ test:assertEquals(1, image:getMSAA(), 'check samples match')
+ -- check dimensions
+ local cw, ch = image:getDimensions()
+ test:assertEquals(64, cw, 'check canvas dim w')
+ test:assertEquals(64, ch, 'check canvas dim h')
+ test:assertEquals(cw, image:getWidth(), 'check canvas w matches dim')
+ test:assertEquals(ch, image:getHeight(), 'check canvas h matches dim')
+ local pw, ph = image:getPixelDimensions()
+ test:assertEquals(64*love.graphics.getDPIScale(), pw, 'check pixel dim w')
+ test:assertEquals(64*love.graphics.getDPIScale(), ph, 'check pixel dim h')
+ test:assertEquals(pw, image:getPixelWidth(), 'check pixel w matches dim')
+ test:assertEquals(ph, image:getPixelHeight(), 'check pixel h matches dim')
+ -- check mipmaps
+ local mode, sharpness = image:getMipmapFilter()
+ test:assertEquals('linear', mode, 'check def minmap filter mode')
+ test:assertEquals(0, sharpness, 'check def minmap filter sharpness')
+ image:setMipmapFilter('nearest', 1)
+ mode, sharpness = image:getMipmapFilter()
+ test:assertEquals('nearest', mode, 'check changed minmap filter mode')
+ test:assertEquals(1, sharpness, 'check changed minmap filter sharpness')
+ test:assertGreaterEqual(2, image:getMipmapCount()) -- docs say no mipmaps should return 1
+ -- check image properties
+ test:assertEquals(false, image:isCompressed(), 'check not compressed')
+ test:assertEquals(false, image:isFormatLinear(), 'check not linear')
+ local cimage = love.graphics.newImage('resources/love.dxt1')
+ test:assertObject(cimage)
+ test:assertEquals(true, cimage:isCompressed(), 'check is compressed')
+ -- check pixel replacement
+ local rimage = love.image.newImageData('resources/loveinv.png')
+ image:replacePixels(rimage)
+ local canvas = love.graphics.newCanvas(64, 64)
+ love.graphics.setCanvas(canvas)
+ love.graphics.draw(image, 0, 0)
+ love.graphics.setCanvas()
+ local imgdata = love.graphics.readbackTexture(canvas, {64, 0, 0, 0, 64, 64})
+ local r1, g1, b1 = imgdata:getPixel(25, 25)
+ test:assertEquals(3, r1+g1+b1, 'check back to white')
+ test:exportImg(imgdata)
end
@@ -40,13 +242,102 @@ end
-- Quad (love.graphics.newQuad)
love.test.graphics.Quad = function(test)
- test:skipTest('test class needs writing')
+ local texture = love.graphics.newImage('resources/love.png')
+ local quad = love.graphics.newQuad(0, 0, 32, 32, texture)
+ test:assertObject(quad)
+ -- check properties
+ test:assertEquals(1, quad:getLayer(), 'check default layer')
+ quad:setLayer(2)
+ test:assertEquals(2, quad:getLayer(), 'check changed layer')
+ local sw, sh = quad:getTextureDimensions()
+ test:assertEquals(64, sw, 'check texture w')
+ test:assertEquals(64, sh, 'check texture h')
+ -- check drawing and viewport changes
+ local canvas = love.graphics.newCanvas(64, 64)
+ love.graphics.setCanvas(canvas)
+ love.graphics.draw(texture, quad, 0, 0)
+ quad:setViewport(32, 32, 32, 32, 64, 64)
+ love.graphics.draw(texture, quad, 32, 32)
+ love.graphics.setCanvas()
+ local imgdata = love.graphics.readbackTexture(canvas, {64, 0, 0, 0, 64, 64})
+ test:assertPixels(imgdata, {
+ white = {{17,31},{31,31},{31,24},{32,32},{46,32},{32,46}},
+ lovepink = {{2,31},{31,2}},
+ loveblue = {{32,61},{61,32}}
+ }, 'check quad drawing')
+ test:exportImg(imgdata)
end
-- Shader (love.graphics.newShader)
love.test.graphics.Shader = function(test)
- test:skipTest('test class needs writing')
+ -- check valid shader
+ local pixelcode1 = [[
+ extern Image tex2;
+ vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
+ vec4 texturecolor = Texel(tex2, texture_coords);
+ return texturecolor * color;
+ }
+ ]]
+ local vertexcode1 = [[
+ vec4 position(mat4 transform_projection, vec4 vertex_position) {
+ return transform_projection * vertex_position;
+ }
+ ]]
+ local shader1 = love.graphics.newShader(pixelcode1, vertexcode1)
+ test:assertObject(shader1)
+ test:assertEquals('vertex shader:\npixel shader:\n', shader1:getWarnings(), 'check shader valid')
+ test:assertEquals(false, shader1:hasUniform('tex1'), 'check invalid uniform')
+ test:assertEquals(true, shader1:hasUniform('tex2'), 'check valid uniform')
+ -- check invalid shader
+ local pixelcode2 = [[
+ extern float ww;
+ vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
+ vec4 texturecolor = Texel(tex, texture_coords);
+ float unused = ww * 3 * color;
+ return texturecolor * color;
+ }
+ ]]
+ local res, err = pcall(love.graphics.newShader, pixelcode2, vertexcode1)
+ test:assertNotEquals(nil, err, 'check shader compile fails')
+ -- check using a shader to draw + sending uniforms
+ -- shader will return a given color if overwrite set to 1, otherwise def. draw
+ local pixelcode3 = [[
+ extern vec4 col;
+ extern float overwrite;
+ vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) {
+ vec4 texcol = Texel(tex, texture_coords);
+ if (overwrite == 1) {
+ return col;
+ } else {
+ return texcol * color;
+ }
+ }
+ ]]
+ local shader3 = love.graphics.newShader(pixelcode3, vertexcode1)
+ local canvas = love.graphics.newCanvas(16, 16)
+ love.graphics.setCanvas(canvas)
+ -- set color to yellow
+ love.graphics.setColor(1, 1, 0, 1)
+ -- turn shader 'on' and use red to draw
+ shader3:send('overwrite', 1)
+ shader3:sendColor('col', {1, 0, 0, 1})
+ love.graphics.setShader(shader3)
+ love.graphics.rectangle('fill', 0, 0, 8, 8)
+ love.graphics.setShader()
+ -- turn shader 'off' and draw again
+ shader3:send('overwrite', 0)
+ love.graphics.setShader(shader3)
+ love.graphics.rectangle('fill', 8, 8, 8, 8)
+ love.graphics.setShader()
+ love.graphics.setColor(1, 1, 1, 1)
+ love.graphics.setCanvas()
+ local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
+ test:assertPixels(imgdata, {
+ red = {{1,1},{1,7},{7,7},{7,1}},
+ yellow = {{8,8},{8,15},{15,15},{15,8}}
+ }, 'shader draw check')
+ test:exportImg(imgdata)
end
@@ -58,13 +349,40 @@ end
-- Text (love.graphics.newTextBatch)
love.test.graphics.Text = function(test)
- test:skipTest('test class needs writing')
-end
-
-
--- Texture (love.graphics.newTexture)
-love.test.graphics.Texture = function(test)
- test:skipTest('test class needs writing')
+ local font = love.graphics.newFont('resources/font.ttf', 8)
+ local plaintext = love.graphics.newTextBatch(font, 'test')
+ -- check text properties
+ test:assertObject(plaintext)
+ test:assertEquals(font:getHeight(), plaintext:getFont():getHeight(), 'check font matches')
+ local tw, th = plaintext:getDimensions()
+ test:assertEquals(24, tw, 'check initial dim w')
+ test:assertEquals(8, th, 'check initial dim h')
+ test:assertEquals(tw, plaintext:getWidth(), 'check initial dim w')
+ test:assertEquals(th, plaintext:getHeight(), 'check initial dim h')
+ -- check changing text
+ plaintext:add('more text', 100, 0, 0)
+ test:assertEquals(49, plaintext:getDimensions(), 'check adding text')
+ plaintext:set('test')
+ test:assertEquals(24, plaintext:getDimensions(), 'check resetting text')
+ plaintext:clear()
+ test:assertEquals(0, plaintext:getDimensions(), 'check clearing text')
+ -- check drawing + setting more complex text
+ local colortext = love.graphics.newTextBatch(font, {{1, 0, 0, 1}, 'test'})
+ test:assertObject(colortext)
+ colortext:setf('LÖVE is an *awesome* framework you can use to make 2D games in Lua', 60, 'right')
+ colortext:addf({{1, 1, 0}, 'overlap'}, 1000, 'left')
+ local font2 = love.graphics.newFont('resources/font.ttf', 8)
+ colortext:setFont(font2)
+ local canvas = love.graphics.newCanvas(64, 64)
+ love.graphics.setCanvas(canvas)
+ love.graphics.draw(colortext, 0, 10)
+ love.graphics.setCanvas()
+ local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16})
+ test:assertPixels(imgdata, {
+ yellow = {{1,9},{8,13},{16,11},{22,10},{25,7},{29,9},{32,13},{34,15}},
+ white = {{17,13},{30,12},{38,9},{44,13},{58,13},{8,29},{58,29},{57,37},{5,39},{57,45},{1,55}}
+ }, 'text draw check')
+ test:exportImg(imgdata)
end
@@ -196,15 +514,8 @@ end
-- love.graphics.discard
love.test.graphics.discard = function(test)
+ -- from the docs: "on some desktops this may do nothing"
test:skipTest('cant test this worked')
- -- wrote all this before seeing "on some desktops this may do nothing"
- -- leaving in case we need it in future
- --local canvas = love.graphics.newCanvas(32, 32)
- --love.graphics.setCanvas(canvas)
- -- love.graphics.clear(0, 0, 0, 1)
- -- love.graphics.draw(Logo.texture, Logo.img, 0, 0)
- -- love.graphics.discard(true, true)
- --love.graphics.setCanvas()
end
@@ -369,12 +680,6 @@ love.test.graphics.polygon = function(test)
end
--- love.graphics.present
-love.test.graphics.present = function(test)
- test:skipTest('test class needs writing')
-end
-
-
-- love.graphics.print
love.test.graphics.print = function(test)
love.graphics.setFont(Font)
@@ -939,9 +1244,7 @@ end
-- love.graphics.isGammaCorrect
love.test.graphics.isGammaCorrect = function(test)
-- we know the config so know this is false
- print('gammaCorrect #1')
test:assertNotNil(love.graphics.isGammaCorrect())
- print('gammaCorrect #2')
end