aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/1.lua13
-rw-r--r--test/2.lua13
-rw-r--r--test/defines.s11
-rw-r--r--test/run.sh44
-rw-r--r--test/utils.lua80
5 files changed, 161 insertions, 0 deletions
diff --git a/test/1.lua b/test/1.lua
new file mode 100644
index 0000000..b51f21e
--- /dev/null
+++ b/test/1.lua
@@ -0,0 +1,13 @@
+utils = require "utils"
+
+utils.StartRun("1")
+
+utils.MemTest("@test", {{0x08, "D6"}, {0x09, "A9"}})
+
+-- The test appears to be done in a few frames. Let's run this several times
+-- just in case.
+for i = 0, 20, 1 do
+ emu.frameadvance();
+end
+
+utils.EndRun()
diff --git a/test/2.lua b/test/2.lua
new file mode 100644
index 0000000..7cb8f40
--- /dev/null
+++ b/test/2.lua
@@ -0,0 +1,13 @@
+utils = require "utils"
+
+utils.StartRun("2")
+
+utils.MemTest("@test", {{0x0B, "00"}, {0x0C, "01"}, {0x0D, "0F"}, {0x0E, "FD"}})
+
+-- The test appears to be done in a few frames. Let's run this several times
+-- just in case.
+for i = 0, 20, 1 do
+ emu.frameadvance();
+end
+
+utils.EndRun()
diff --git a/test/defines.s b/test/defines.s
new file mode 100644
index 0000000..17c0221
--- /dev/null
+++ b/test/defines.s
@@ -0,0 +1,11 @@
+RUN_TESTS = 0
+
+.macro CALL_TESTS_ON_DONE
+ .ifdef RUN_TESTS
+ bit Globals::m_flags
+ bvc :+
+ @test:
+ nop
+ :
+ .endif
+.endmacro
diff --git a/test/run.sh b/test/run.sh
new file mode 100644
index 0000000..2142ad1
--- /dev/null
+++ b/test/run.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+set -e
+
+ROOT="$( cd "$( dirname "$0" )/.." && pwd )"
+cd "$ROOT"
+
+# Clean previous builds and prepare the test environment.
+rm -f "$ROOT/out/test-results.txt"
+make clean
+sed -i 's/RUN_TESTS = 0/RUN_TESTS = 1/g' $ROOT/test/defines.s
+
+# Github Actions do not allow GUI programs to be run. This means that the code
+# below will always fail (fceux won't be able to run). There is a way to emulate
+# an X server with tools like xvfb-run or xvncserver, but so far I've had no
+# luck on this front.
+if [ -n "${GITHUB_ACTION}" ]; then
+ exit 0
+fi
+
+# Run all the tests that we have on Lua.
+for name in $(seq 2); do
+ DEBUG=1 make out/$name.nes
+ fceux --loadlua "$ROOT/test/$name.lua" "$ROOT/out/$name.nes"
+done
+
+# Show the results.
+cat "$ROOT/out/test-results.txt"
+n=$(cat "$ROOT/out/test-results.txt" | grep FAIL | wc -l)
+echo ""
+case $n in
+ 0)
+ echo "All tests passed!"
+ exit 0
+ ;;
+ 1)
+ echo "1 test failed!"
+ exit 1
+ ;;
+ *)
+ echo "$n tests failed!"
+ exit 1
+ ;;
+esac
diff --git a/test/utils.lua b/test/utils.lua
new file mode 100644
index 0000000..c5ecd94
--- /dev/null
+++ b/test/utils.lua
@@ -0,0 +1,80 @@
+utils = {}
+
+-- Returns the root path for the project.
+function utils.RootPath()
+ local fullpath = debug.getinfo(1,"S").source:sub(2)
+ fullpath = io.popen("realpath '"..fullpath.."'", 'r'):read()
+ fullpath = fullpath:gsub('[\n\r]*$','')
+
+ local dirname, filename = fullpath:match('^(.*/)([^/]-)$')
+ dirname = dirname or ''
+ if dirname == '' then
+ return ''
+ end
+
+ return io.popen("realpath '"..dirname.."/..'", 'r'):read()
+end
+
+-- At a `label` that exists on the assembly code grab the values for the given
+-- addresses and write it all into the `test-results.txt` file. The `addresses`
+-- array is made up of two-sized arrays, where the first element contains the
+-- memory you are trying to test, and the second element is the value that we
+-- are expecting.
+function utils.MemTest(label, addresses)
+ local cmd = "cat ".. utils.RootPath() .. "/out/labels.txt | grep .".. label .." | awk '{ print $2; }' | cut -c3-"
+ local file = assert(io.popen(cmd, 'r'))
+ local result = file:read("*a")
+
+ -- Double check that the address that we grabbed has at least a good format.
+ if string.len(result) ~= 5 then
+ error("Error on '" .. label .. "': got a bad address! (".. result ..")")
+ end
+
+ -- Register a function to execute on the given test address. The function will
+ -- simply iterate over the given `addresses` and compare them with the
+ -- expected result. Everything will be saved into the `test-results.txt` file.
+ memory.registerexecute(tonumber(result, 16), function()
+ local expected = ""
+ local got = ""
+
+ for _, vals in ipairs(addresses) do
+ expected = expected .. "$" .. string.format("%04X", vals[1]) .. " -> " .. vals[2] .. "; "
+ got = got .. "$" .. string.format("%04X", vals[1]) .. " -> " .. string.format("%02X", memory.readbyte(vals[1])) .. "; "
+ end
+
+ file = io.open(utils.RootPath() .. "/out/test-results.txt", "a")
+ io.output(file)
+
+ if expected == got then
+ io.write("OK\n")
+ else
+ io.write("\n-> Test '".. label .."': FAIL\n")
+ io.write("Expected: ".. expected .. "\n")
+ io.write("Got: ".. got .. "\n")
+ io.write("\n")
+ end
+ io.close(file)
+ end)
+end
+
+function utils.StartRun(title)
+ file = io.open(utils.RootPath() .. "/out/test-results.txt", "a")
+ io.output(file)
+ io.write(title .. ": ")
+ io.close(file)
+end
+
+-- Ends the given test run. That is, it will exit from the emulator so we can
+-- turn back to the runner.
+function utils.EndRun()
+ -- I'm not entirely sure why this is needed, but if we don't advance for
+ -- several frames fceux won't exit. Thus, let's advance for some frames and
+ -- then quit.
+ for i = 0, 10, 1 do
+ emu.frameadvance();
+ end
+
+ emu.exit()
+end
+
+return utils