Skip to content

Commit

Permalink
Add unit test framework
Browse files Browse the repository at this point in the history
  • Loading branch information
roblabla committed Feb 17, 2024
1 parent a5bcc33 commit 79b4e52
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "3rdparty/munit"]
path = 3rdparty/munit
url = https://github.com/roblabla/munit
branch = msvc2002
1 change: 1 addition & 0 deletions 3rdparty/munit
Submodule munit added at 4ea671
4 changes: 3 additions & 1 deletion scripts/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def build(build_type, verbose=False):
def main():
parser = argparse.ArgumentParser("th06-build")
parser.add_argument(
"--build-type", choices=["normal", "diffbuild"], default="normal"
"--build-type", choices=["normal", "diffbuild", "tests"], default="normal"
)
args = parser.parse_args()

Expand All @@ -37,6 +37,8 @@ def main():
build_type = BuildType.NORMAL
elif args.build_type == "diffbuild":
build_type = BuildType.DIFFBUILD
elif args.build_type == "tests":
build_type = BuildType.TESTS

build(build_type, args.verbose)

Expand Down
54 changes: 50 additions & 4 deletions scripts/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class BuildType(Enum):
NORMAL = 1
DIFFBUILD = 2
TESTS = 3


def configure(build_type):
Expand All @@ -21,7 +22,7 @@ def configure(build_type):
writer.variable("cl", "cl.exe")
writer.variable(
"cl_common_flags",
"/nologo /MT /EHsc /G5 /Gs /GS /DNDEBUG /Zi /I $builddir/autogenerated /I src /I src/pbg3",
"/nologo /MT /EHsc /G5 /Gs /GS /DNDEBUG /Zi /I $builddir/autogenerated /I src /I src/pbg3 /I 3rdparty/munit",
)
writer.variable("cl_flags", "$cl_common_flags /Od /Oi /Ob1 /Op")
writer.variable("cl_flags_pbg3", "$cl_common_flags /O2")
Expand Down Expand Up @@ -64,9 +65,9 @@ def configure(build_type):
"""python -c "import sys; open(sys.argv[2], 'wb').write(open(sys.argv[1], 'rb').read().decode('utf8').encode('shift_jis'))" $in $out""",
)

main_sources = ["main"]
cxx_sources = [
"AsciiManager",
"main",
"Chain",
"FileSystem",
"Supervisor",
Expand All @@ -89,7 +90,14 @@ def configure(build_type):
"FileAbstraction",
]

for rule in cxx_sources:
munit_sources = ["munit"]

test_sources = [
"tests",
"test_Pbg3Archive",
]

for rule in main_sources + cxx_sources:
writer.build(
"$builddir/" + rule + ".obj",
"cc",
Expand All @@ -105,6 +113,20 @@ def configure(build_type):
implicit=["$builddir/autogenerated/i18n.hpp"],
)

for rule in munit_sources:
writer.build(
"$builddir/" + rule + ".obj",
"cc",
"3rdparty/munit/" + rule + ".c",
)

for rule in test_sources:
writer.build(
"$builddir/" + rule + ".obj",
"cc",
"tests/" + rule + ".cpp",
)

writer.build("$builddir/globals.obj", "as", inputs="src/globals.asm")
writer.build("$builddir/autogenerated/i18n.hpp", "geni18n", "src/i18n.tpl")
writer.build("$builddir/icon.ico", "copyicon", "resources/placeholder.ico")
Expand All @@ -115,13 +137,37 @@ def configure(build_type):
implicit="$builddir/icon.ico",
)
objfiles = (
["$builddir/" + src + ".obj" for src in cxx_sources]
["$builddir/" + src + ".obj" for src in main_sources]
+ ["$builddir/" + src + ".obj" for src in cxx_sources]
+ ["$builddir/" + src + ".obj" for src in pbg3_sources]
+ ["$builddir/th06.res"]
)
if build_type == BuildType.DIFFBUILD:
objfiles += ["$builddir/globals.obj"]
writer.build("$builddir/th06e.exe", "link", inputs=objfiles)

test_objfiles = (
["$builddir/" + src + ".obj" for src in cxx_sources]
+ ["$builddir/" + src + ".obj" for src in pbg3_sources]
+ ["$builddir/" + src + ".obj" for src in test_sources]
)
writer.build(
"$builddir/th06e-tests.exe",
"link",
inputs=test_objfiles + ["$builddir/munit.lib"],
variables={
"link_libs": "$link_libs $builddir/munit.lib",
"link_flags": "/debug /pdb:$builddir/th06e.pdb",
},
)

writer.build(
"$builddir/munit.lib",
"link",
inputs=["$builddir/" + s + ".obj" for s in munit_sources],
variables={"link_flags": "/lib"},
)

writer.close()


Expand Down
21 changes: 21 additions & 0 deletions scripts/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pathlib import Path

from build import BuildType, build
from winhelpers import run_windows_program

SCRIPTS_DIR = Path(__file__).parent


def main():
# Run the build for tests
build(BuildType.TESTS)

# Then, run the tests
run_windows_program(
[SCRIPTS_DIR.parent / "build" / "th06e-tests.exe"],
cwd=str(SCRIPTS_DIR.parent),
)


if __name__ == "__main__":
main()
86 changes: 86 additions & 0 deletions tests/test_Pbg3Archive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <fstream>
#include <vector>

#include "munit.h"
#include <Pbg3Archive.hpp>

static MunitResult test_read_raw(const MunitParameter params[], void *user_data)
{
Pbg3Archive archive;
munit_assert_int(archive.Load("resources/KOUMAKYO_IN.dat"), !=, 0);

// Read from PBG3
i32 entryIdx = archive.FindEntry("th06logo.jpg");
munit_assert_int(entryIdx, !=, -1);

u32 size;
u32 expectedCsum;
u8 *entry = archive.ReadEntryRaw(&size, &expectedCsum, entryIdx);
munit_assert_not_null(entry);

return MUNIT_OK;
}

static MunitResult test_read_decompress(const MunitParameter params[], void *user_data)
{
Pbg3Archive archive;
munit_assert_int(archive.Load("resources/KOUMAKYO_IN.dat"), !=, 0);

// Read from PBG3
i32 entryIdx = archive.FindEntry("th06logo.jpg");
munit_assert_int(entryIdx, !=, -1);
u8 *entry = archive.ReadDecompressEntry(entryIdx, "th06logo.jpg");
munit_assert_not_null(entry);
u32 entrySize = archive.GetEntrySize(entryIdx);
munit_assert_int(entrySize, !=, 0);

// Write decompressed file to disk.
std::ofstream outfile("resources/th06logo2.jpg.expected", std::ios::out | std::ios::binary);
outfile.write((char *)entry, entrySize);

// Read file on disk
std::ifstream infile("resources/th06logo.jpg", std::ios::binary);
std::vector<char> buffer(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>());
u8 *reference = (u8 *)&buffer[0];
u32 referenceSize = buffer.size();

munit_assert_int(entrySize, ==, referenceSize);
munit_assert_memory_equal(entrySize, entry, reference);
return MUNIT_OK;
}

static MunitResult test_read_decompress_anm(const MunitParameter params[], void *user_data)
{
Pbg3Archive archive;
munit_assert_int(archive.Load("resources/KOUMAKYO_IN.dat"), !=, 0);

// Read from PBG3
i32 entryIdx = archive.FindEntry("text.anm");
munit_assert_int(entryIdx, !=, -1);
u8 *entry = archive.ReadDecompressEntry(entryIdx, "text.anm");
munit_assert_not_null(entry);
u32 entrySize = archive.GetEntrySize(entryIdx);
munit_assert_int(entrySize, !=, 0);

// Write decompressed file to disk.
std::ofstream outfile("resources/text.anm.expected", std::ios::out | std::ios::binary);
outfile.write((char *)entry, entrySize);

// Read file on disk
std::ifstream infile("resources/text.anm", std::ios::binary);
std::vector<char> buffer(std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>());
u8 *reference = (u8 *)&buffer[0];
u32 referenceSize = buffer.size();

munit_assert_int(entrySize, ==, referenceSize);
munit_assert_memory_equal(entrySize, entry, reference);
return MUNIT_OK;
}

static MunitTest pbg3archives_test_suite_tests[] = {
{"/read_decompress_anm", test_read_decompress_anm, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/read_decompress", test_read_decompress, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"/read_raw", test_read_raw, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
/* Mark the end of the array with an entry where the test
* function is NULL */
{NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL}};
16 changes: 16 additions & 0 deletions tests/tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "munit.h"

#include "test_Pbg3Archive.cpp"

static MunitSuite root_test_suites[] = {
{"/Pbg3Archives", pbg3archives_test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE},
{NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE}};
static const MunitSuite test_suite = {"", NULL, root_test_suites, 1, MUNIT_SUITE_OPTION_NONE};

int main(int argc, char **argv)
{
/* Finally, we'll actually run our test suite! That second argument
* is the user_data parameter which will be passed either to the
* test or (if provided) the fixture setup function. */
return munit_suite_main(&test_suite, NULL, argc, argv);
}

0 comments on commit 79b4e52

Please sign in to comment.