From 97255eb813405007174d9572bfcc70519f3fdb94 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Fri, 29 Nov 2024 09:41:02 -0500 Subject: [PATCH] First coverage reports. Tests don't get near enough coverage but running the program does. --- Makefile | 5 +- combat.hpp | 2 + meson.build | 4 +- scripts/coverage_reset.ps1 | 7 +++ scripts/reset_build.sh | 2 +- status.txt | 7 ++- tests/components.cpp | 105 +++++++++++++++++++++++++++++++++++++ 7 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 scripts/coverage_reset.ps1 create mode 100644 tests/components.cpp diff --git a/Makefile b/Makefile index ff8c808..bc3ef5a 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ ragel: ragel -o .\ansi_parser.cpp .\ansi_parser.rl build: ansi_parser.cpp - meson compile -j 4 -C builddir + meson compile -j 10 -C builddir test: build ./builddir/runtests @@ -28,3 +28,6 @@ clean: debug: gdb --nx -x .gdbinit builddir/roguish.exe + +cover: + gcovr --html coverage/coverage_report.html --gcov-ignore-errors=no_working_dir_found --exclude "scratchpad.*" --exclude "subprojects.*" --html-nested coverage/ diff --git a/combat.hpp b/combat.hpp index a7c48f9..fa8f887 100644 --- a/combat.hpp +++ b/combat.hpp @@ -4,6 +4,8 @@ namespace components { struct Combat { int hp; int damage; + + /* NOTE: This is used to _mark_ entities as dead, to detect ones that have just died. Don't make attack automatically set it.*/ bool dead; int attack(Combat &target); diff --git a/meson.build b/meson.build index 550684f..75ab421 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,7 @@ runtests = executable('runtests', [ 'map.cpp', 'rand.cpp', 'sound.cpp', + 'combat.cpp', 'collider.cpp', 'ansi_parser.cpp', 'config.cpp', @@ -27,6 +28,7 @@ runtests = executable('runtests', [ 'tests/dbc.cpp', 'tests/map.cpp', 'tests/collider.cpp', + 'tests/components.cpp', 'tests/sound.cpp', 'tests/dinkyecs.cpp', 'tests/ansi_parser.cpp', @@ -53,7 +55,7 @@ roguish = executable('roguish', [ ], dependencies: dependencies) -roguish = executable('img2ansi', [ +img2ansi = executable('img2ansi', [ 'dbc.cpp', 'panel.cpp', 'ansi_parser.cpp', diff --git a/scripts/coverage_reset.ps1 b/scripts/coverage_reset.ps1 new file mode 100644 index 0000000..4799ae6 --- /dev/null +++ b/scripts/coverage_reset.ps1 @@ -0,0 +1,7 @@ +mv .\subprojects\packagecache . +rm -recurse -force .\subprojects\,.\builddir\ +mkdir subprojects +mv .\packagecache .\subprojects\ +mkdir builddir +cp wraps\*.wrap subprojects\ +meson setup --default-library=static --prefer-static -Db_coverage=true builddir diff --git a/scripts/reset_build.sh b/scripts/reset_build.sh index 9d56a7f..9970738 100755 --- a/scripts/reset_build.sh +++ b/scripts/reset_build.sh @@ -8,4 +8,4 @@ mv packagecache ./subprojects/ mkdir builddir cp wraps/*.wrap subprojects/ # on OSX you can't do this with static -meson setup builddir +meson setup -Db_coverage=true builddir diff --git a/status.txt b/status.txt index a61ac38..4ac69b2 100644 --- a/status.txt +++ b/status.txt @@ -1,11 +1,14 @@ TODAY'S GOAL: * Neighbors needs a rewrite * Neighbors algo isn't using greater parameter -* Think up an enemy system. -* Revisit map generation. * How do we do coverage reports in C++? +* Better tests and more coverage. +* Clean up and document as much code as possible. +* Doxygen? Other docs tool? TODO: +* Think up an enemy system. +* Revisit map generation. * Write a method for renderer that can translate coordinates. * Can std::any be defaulted to a noop in the events? * Save file isn't saving gold. diff --git a/tests/components.cpp b/tests/components.cpp new file mode 100644 index 0000000..dd90449 --- /dev/null +++ b/tests/components.cpp @@ -0,0 +1,105 @@ +#include +#include "components.hpp" +#include "dinkyecs.hpp" + +using namespace components; +using namespace DinkyECS; + +TEST_CASE("all components can work in the world", "[components]") { + World world; + auto ent1 = world.entity(); + + world.set(ent1, {ent1}); + world.set(ent1, {{10,1}}); + world.set(ent1, {1,0}); + world.set(ent1, {100}); + world.set(ent1, {0}); + world.set(ent1, {"Z"}); + world.set(ent1, {4}); + + auto player = world.get(ent1); + REQUIRE(player.entity == ent1); + + auto position = world.get(ent1); + REQUIRE(position.location.x == 10); + REQUIRE(position.location.y == 1); + + auto motion = world.get(ent1); + REQUIRE(motion.dx == 1); + REQUIRE(motion.dy == 0); + + auto loot = world.get(ent1); + REQUIRE(loot.amount == 100); + + auto inv = world.get(ent1); + REQUIRE(inv.gold == 0); + + auto tile = world.get(ent1); + REQUIRE(tile.chr == "Z"); + + auto enemy = world.get(ent1); + REQUIRE(enemy.HEARING_DISTANCE == 4); +} + +TEST_CASE("all components can be facts", "[components]") { + World world; + auto ent1 = world.entity(); + + world.set_the({ent1}); + world.set_the({{10,1}}); + world.set_the({1,0}); + world.set_the({100}); + world.set_the({0}); + world.set_the({"Z"}); + world.set_the({4}); + + auto player = world.get_the(); + REQUIRE(player.entity == ent1); + + auto position = world.get_the(); + REQUIRE(position.location.x == 10); + REQUIRE(position.location.y == 1); + + auto motion = world.get_the(); + REQUIRE(motion.dx == 1); + REQUIRE(motion.dy == 0); + + auto loot = world.get_the(); + REQUIRE(loot.amount == 100); + + auto inv = world.get_the(); + REQUIRE(inv.gold == 0); + + auto tile = world.get_the(); + REQUIRE(tile.chr == "Z"); + + auto enemy = world.get_the(); + REQUIRE(enemy.HEARING_DISTANCE == 4); +} + +TEST_CASE("confirm combat works", "[components]") { + World world; + auto player = world.entity(); + auto enemy = world.entity(); + + world.set(player, {100, 10}); + world.set(enemy, {20, 10}); + + auto p_fight = world.get(player); + REQUIRE(p_fight.hp == 100); + REQUIRE(p_fight.damage == 10); + REQUIRE(p_fight.dead == false); + + auto e_fight = world.get(enemy); + REQUIRE(e_fight.hp == 20); + REQUIRE(e_fight.damage == 10); + REQUIRE(e_fight.dead == false); + + for(int i = 0; e_fight.hp > 0 && i < 100; i++) { + p_fight.attack(e_fight); + } +} + +TEST_CASE("MapConfig loads from JSON", "[components]") { + +}