diff --git a/.gitignore b/.gitignore index 0741829..b8772e8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /output/*.xml /output/*.html /output/*.md -/output/actual/*.png \ No newline at end of file +/output/actual/*.png +resources/.DS_Store diff --git a/examples/lovetest_runAllTests.html b/examples/lovetest_runAllTests.html index 5a0be83..4146220 100644 --- a/examples/lovetest_runAllTests.html +++ b/examples/lovetest_runAllTests.html @@ -1 +1 @@ -

πŸ”΄ love.test



πŸ”΄ love.audio

\ No newline at end of file +

πŸ”΄ love.test



🟒 love.audio

\ No newline at end of file diff --git a/examples/lovetest_runAllTests.md b/examples/lovetest_runAllTests.md index c69865b..d309282 100644 --- a/examples/lovetest_runAllTests.md +++ b/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/examples/lovetest_runAllTests.xml b/examples/lovetest_runAllTests.xml index deb2d42..dc3bb5e 100644 --- a/examples/lovetest_runAllTests.xml +++ b/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/output/expected/love.test.graphics.Font-1.png b/output/expected/love.test.graphics.Font-1.png new file mode 100644 index 0000000..cb2f21a Binary files /dev/null and b/output/expected/love.test.graphics.Font-1.png differ diff --git a/output/expected/love.test.graphics.Font-2.png b/output/expected/love.test.graphics.Font-2.png new file mode 100644 index 0000000..d12d684 Binary files /dev/null and b/output/expected/love.test.graphics.Font-2.png differ diff --git a/output/expected/love.test.graphics.Image-1.png b/output/expected/love.test.graphics.Image-1.png new file mode 100644 index 0000000..5f45cf9 Binary files /dev/null and b/output/expected/love.test.graphics.Image-1.png differ diff --git a/output/expected/love.test.graphics.Quad-1.png b/output/expected/love.test.graphics.Quad-1.png new file mode 100644 index 0000000..22ab17e Binary files /dev/null and b/output/expected/love.test.graphics.Quad-1.png differ diff --git a/output/expected/love.test.graphics.Shader-1.png b/output/expected/love.test.graphics.Shader-1.png new file mode 100644 index 0000000..6742f63 Binary files /dev/null and b/output/expected/love.test.graphics.Shader-1.png differ diff --git a/output/expected/love.test.graphics.Text-1.png b/output/expected/love.test.graphics.Text-1.png new file mode 100644 index 0000000..4f15348 Binary files /dev/null and b/output/expected/love.test.graphics.Text-1.png differ diff --git a/output/expected/love.test.graphics.setColorMask-1.png b/output/expected/love.test.graphics.setColorMask-1.png index 254f834..315c7a9 100644 Binary files a/output/expected/love.test.graphics.setColorMask-1.png and b/output/expected/love.test.graphics.setColorMask-1.png differ diff --git a/readme.md b/readme.md index 52bedda..81b9f5a 100644 --- a/readme.md +++ b/readme.md @@ -1,136 +1,109 @@ -# LΓΆvetest -Basic testing suite for the [LΓΆve](https://github.com/love2d/love) APIs, based off of [this issue](https://github.com/love2d/love/issues/1745). - -Currently written for [LΓΆve 12](https://github.com/love2d/love/tree/12.0-development), which is still in development. - ---- - -## Features -- [x] Simple pass/fail tests in Lua with minimal setup -- [x] Ability to run all tests with a simple command -- [x] Ability to see how many tests are passing/failing -- [x] Ability to run a subset of tests -- [x] Ability to easily run an individual test -- [x] Ability to see all visual results at a glance -- [x] Automatic testing that happens after every commit -- [x] No platform-specific dependencies / scripts - ---- - -## Coverage -This is the status of all module tests currently. -| Module | Done | Todo | Skip | -| ----------------- | ---- | ---- | ---- | -| 🟒 audio | 28 | 0 | 0 | -| 🟒 data | 12 | 0 | 0 | -| 🟑 event | 4 | 1 | 1 | -| 🟒 filesystem | 28 | 0 | 2 | -| 🟒 font | 7 | 0 | 0 | -| 🟑 graphics | 93 | 14 | 1 | -| 🟒 image | 5 | 0 | 0 | -| 🟒 math | 20 | 0 | 0 | -| 🟑 physics | 22 | 6 | 0 | -| 🟒 sound | 4 | 0 | 0 | -| 🟒 system | 6 | 0 | 2 | -| 🟒 thread | 5 | 0 | 0 | -| 🟒 timer | 6 | 0 | 0 | -| 🟒 video | 2 | 0 | 0 | -| 🟒 window | 34 | 0 | 2 | - -> The following modules are not covered as we can't really emulate input nicely: -> `joystick`, `keyboard`, `mouse`, and `touch` - ---- - -## Running Tests -The testsuite aims to keep things as simple as possible, and just runs all the tests inside LΓΆve to match how they'd be used by developers in-engine. -To run the tests, download the repo and then run the main.lua as you would a LΓΆve game, i.e: - -WINDOWS: `& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER --console` -MACOS: `/Applications/love.app/Contents/MacOS/love PATH_TO_TESTING_FOLDER` -LINUX: `./love.AppImage PATH_TO_TESTING_FOLDER` - -By default all tests will be run for all modules. -If you want to specify a module/s you can use: -`--runSpecificModules filesystem,audio` -If you want to specify only 1 specific method only you can use: -`--runSpecificMethod filesystem write` - -All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. - -When finished, the following files will be generated in the `/output` directory with a summary of the test results: -- an `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) -- a `HTML` file that shows any visual test results -- a `Markdown` file for use with [this github action](https://github.com/ellraiser/love-test-report) -> An example of all types of output can be found in the `/examples` -> The visual results of any graphic tests can be found in `/output/actual` - ---- - -## Architecture -Each method and object has it's own test method written in `/tests` under the matching module name. - -When you run the tests, a single TestSuite object is created which handles the progress + totals for all the tests. -Each module has a TestModule object created, and each test method has a TestMethod object created which keeps track of assertions for that method. You can currently do the following assertions: -- **assertNotNil**(value) -- **assertEquals**(expected, actual, label) -- **assertNotEquals**(expected, actual, label) -- **assertRange**(actual, min, max, label) -- **assertMatch**({option1, option2, option3 ...}, actual, label) -- **assertGreaterEqual**(expected, actual, label) -- **assertLessEqual**(expected, actual, label) -- **assertObject**(table) -- **assertPixels**(imgdata, pixeltable, label) -- **assertCoords**(expected, actual, label) - -Example test method: -```lua --- love.filesystem.read test method --- all methods should be put under love.test.MODULE.METHOD, matching the API -love.test.filesystem.read = function(test) - -- setup any data needed then run any asserts using the passed test object - local content, size = love.filesystem.read('resources/test.txt') - test:assertNotNil(content) - test:assertEquals('helloworld', content, 'check content match') - test:assertEquals(10, size, 'check size match') - content, size = love.filesystem.read('resources/test.txt', 5) - test:assertNotNil(content) - test:assertEquals('hello', content, 'check content match') - test:assertEquals(5, size, 'check size match') - -- no need to return anything or cleanup, GCC is called after each method -end -``` - -Each test is run inside it's own coroutine - you can use `test:waitFrames(frames)` to pause the test for a small period if you need to check things that won't happen for a few seconds. - -After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any) - -For sanity-checking, if it's currently not covered or it's not possible to test the method we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the test output without it affected the pass/fail totals - ---- - -## Todo -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 - ---- - -## Future Goals -- [ ] Tests can compare visual results to a reference image (partially done) -- [ ] Ability to test loading different combinations of modules -- [ ] Performance tests +LΓ–VE is an *awesome* framework you can use to make 2D games in Lua. It's free, open-source, and works on Windows, macOS, Linux, Android, and iOS. + +[![Build Status: Github CI](https://github.com/love2d/love/workflows/continuous-integration/badge.svg)](https://github.com/love2d/love/actions?query=workflow%3Acontinuous-integration) + +Documentation +------------- + +We use our [wiki][wiki] for documentation. +If you need further help, feel free to ask on our [forums][forums], our [Discord server][discord], or our [subreddit][subreddit]. + +Repository +---------- + +We use the 'main' branch for patch development of the current major release, and therefore it should not be considered stable. +There may also be a branch for the next major version in development, which is named after that version. + +We tag all our releases (since we started using mercurial and git), and have binary downloads available for them. + +Experimental changes are developed in a separate [love-experiments][love-experiments] repository. + +Builds +------ + +Files for releases are in the [releases][releases] section on GitHub. [The site][site] has links to files and additional platform content for the latest release. + +There are also unstable/nightly builds: + +- Builds for some platforms are automatically created after each commit and are available through GitHub's CI interfaces. +- For ubuntu linux they are in [ppa:bartbes/love-unstable][unstableppa] +- For arch linux there's [love-git][aur] in the AUR. + +Contributing +------------ + +The best places to contribute are through the issue tracker and the official Discord server or IRC channel. + +For code contributions, pull requests and patches are welcome. Be sure to read the [source code style guide][codestyle]. +Changes and new features typically get discussed in the issue tracker or on Discord or the forums before a pull request is made. + +Compilation +----------- + +### Windows +Follow the instructions at the [megasource][megasource] repository page. + +### *nix +Run `platform/unix/automagic` from the repository root, then run ./configure and make. + + $ platform/unix/automagic + $ ./configure + $ make + +When using a source release, automagic has already been run, and the first step can be skipped. + +### macOS +Download or clone [this repository][dependencies-apple] and copy, move, or symlink the `macOS/Frameworks` subfolder into love's `platform/xcode/macosx` folder. + +Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the `love-macosx` target. + +### iOS +Building for iOS requires macOS and Xcode. + +#### LΓ–VE 11.4 and newer +Download the `love-apple-dependencies` zip file corresponding to the LΓ–VE version being used from the [Releases page][dependencies-ios], +unzip it, and place the `iOS/libraries` subfolder into love's `platform/xcode/ios` folder. + +Or, download or clone [this repository][dependencies-apple] and copy, move, or symlink the `iOS/libraries` subfolder into love's `platform/xcode/ios` folder. + +Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the `love-ios` target. + +See `readme-iOS.rtf` for more information. + +#### LΓ–VE 11.3 and older +Download the `ios-libraries` zip file corresponding to the LΓ–VE version being used from the [Releases page][dependencies-ios], +unzip it, and place the `include` and `libraries` subfolders into love's `platform/xcode/ios` folder. + +Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the `love-ios` target. + +See `readme-iOS.rtf` for more information. + +### Android +Visit the [Android build repository][android-repository] for build instructions. + +Dependencies +------------ + +- SDL2 +- OpenGL 2.1+ / OpenGL ES 2+ +- OpenAL +- Lua / LuaJIT / LLVM-lua +- FreeType +- ModPlug +- Vorbisfile +- Theora + +[site]: https://love2d.org +[wiki]: https://love2d.org/wiki +[forums]: https://love2d.org/forums +[discord]: https://discord.gg/rhUets9 +[subreddit]: https://www.reddit.com/r/love2d +[dependencies-apple]: https://github.com/love2d/love-apple-dependencies +[dependencies-ios]: https://github.com/love2d/love/releases +[megasource]: https://github.com/love2d/megasource +[unstableppa]: https://launchpad.net/~bartbes/+archive/love-unstable +[aur]: https://aur.archlinux.org/packages/love-git +[love-experiments]: https://github.com/slime73/love-experiments +[codestyle]: https://love2d.org/wiki/Code_Style +[android-repository]: https://github.com/love2d/love-android +[releases]: https://github.com/love2d/love/releases diff --git a/resources/.DS_Store b/resources/.DS_Store index 7abf222..39c7c62 100644 Binary files a/resources/.DS_Store and b/resources/.DS_Store differ diff --git a/resources/font-letters-ab.png b/resources/font-letters-ab.png new file mode 100644 index 0000000..3ec8aec Binary files /dev/null and b/resources/font-letters-ab.png differ diff --git a/resources/font-letters-cd.png b/resources/font-letters-cd.png new file mode 100644 index 0000000..51190f6 Binary files /dev/null and b/resources/font-letters-cd.png differ diff --git a/resources/love_test_graphics_rectangle_expected.png b/resources/love_test_graphics_rectangle_expected.png deleted file mode 100644 index bbbaf6e..0000000 Binary files a/resources/love_test_graphics_rectangle_expected.png and /dev/null differ diff --git a/tests/audio.lua b/tests/audio.lua index 4645629..bf36b11 100644 --- a/tests/audio.lua +++ b/tests/audio.lua @@ -10,6 +10,9 @@ -- RecordingDevice (love.audio.getRecordingDevices) love.test.audio.RecordingDevice = function(test) + if GITHUB_RUNNER == true then + return test:skipTest('cant emulate recording devices in CI') + end -- check devices first local devices = love.audio.getRecordingDevices() if #devices == 0 then diff --git a/tests/event.lua b/tests/event.lua index 9e43f8b..00b49f3 100644 --- a/tests/event.lua +++ b/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/tests/graphics.lua b/tests/graphics.lua index 43b389f..1b06b0d 100644 --- a/tests/graphics.lua +++ b/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