Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
find_package(Threads REQUIRED)
enable_testing()

# Usage: add_test(NAME src1.c src2.c ...
# [EXTRA_LIBS lib1 lib2]
# [EXTRA_INCLUDES dir1 dir2]
# [ENV "VAR=val;VAR2=val2"])
function(add_test TEST_NAME)
message("Adding test: ${TEST_NAME} -> ${ARGN}")
add_executable(${TEST_NAME} ${ARGN})
target_include_directories(${TEST_NAME} PRIVATE ${INCLUDE_DIRS})
target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARY} ${SDL_LIBRARY})
cmake_parse_arguments(ARG "" "" "EXTRA_LIBS;EXTRA_INCLUDES;ENV" ${ARGN})
message("Adding test: ${TEST_NAME} -> ${ARG_UNPARSED_ARGUMENTS}")
add_executable(${TEST_NAME} ${ARG_UNPARSED_ARGUMENTS})
target_include_directories(${TEST_NAME} PRIVATE ${INCLUDE_DIRS} ${ARG_EXTRA_INCLUDES})
target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARY} ${SDL_LIBRARY} ${ARG_EXTRA_LIBS})
_add_test(${TEST_NAME} ${TEST_NAME})
if(ARG_ENV)
set_tests_properties(${TEST_NAME} PROPERTIES ENVIRONMENT "${ARG_ENV}")
endif()
endfunction()

add_test(test_util test_util.c ../src/util.c)
Expand All @@ -17,10 +25,15 @@ add_test(test_input test_input.c ../src/input.c ../src/keyboard.c)
add_test(test_position test_position.c ../src/position.c)
add_test(test_collisions test_collisions.c ../src/collisions.c)

add_test(test_random test_random.c ../src/random.c ../src/util.c
EXTRA_INCLUDES ${CMAKE_SOURCE_DIR}/lib/bh_random/src
EXTRA_LIBS bh_random
)

# roommatrix needs a real SDL renderer (lightmap texture), so it uses the
# offscreen video driver. Extra libs: SDL_image + SDL_ttf (pulled in by
# texture.c) and physfs (pulled in by io_util.c / physfsrwops.c).
add_executable(test_roommatrix
add_test(test_roommatrix
test_roommatrix.c
../src/roommatrix.c
../src/texture.c
Expand All @@ -29,16 +42,6 @@ add_executable(test_roommatrix
../src/position.c
../src/io_util.c
../src/physfsrwops.c
)
target_include_directories(test_roommatrix PRIVATE ${INCLUDE_DIRS})
target_link_libraries(test_roommatrix
${CMOCKA_LIBRARY}
${SDL_LIBRARY}
${SDL_IMAGE_LIBRARY}
${SDL_TTF_LIBRARY}
${PHYSFS_LIBRARY}
)
_add_test(test_roommatrix test_roommatrix)
set_tests_properties(test_roommatrix PROPERTIES
ENVIRONMENT "SDL_VIDEODRIVER=offscreen;SDL_RENDER_DRIVER=software"
)
EXTRA_LIBS ${SDL_IMAGE_LIBRARY} ${SDL_TTF_LIBRARY} ${PHYSFS_LIBRARY}
ENV "SDL_VIDEODRIVER=offscreen;SDL_RENDER_DRIVER=software"
)
128 changes: 128 additions & 0 deletions test/test_random.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2026 Linus Probert <linus.probert@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "cmocka_include.h"
#include "../src/random.h"

/* set_random_seed / get_random_seed round-trip */
static void
test_seed_roundtrip(void **state)
{
(void)state;

set_random_seed(42);
assert_int_equal(get_random_seed(), 42);

set_random_seed(0xDEADBEEF);
assert_int_equal(get_random_seed(), 0xDEADBEEF);
}

/* Same seed must produce identical map seeds for all 20 levels */
static void
test_map_seeds_are_deterministic(void **state)
{
(void)state;

unsigned int first[20], second[20];

set_random_seed(12345);
for (int i = 0; i < 20; ++i)
first[i] = get_random_map_seed(i + 1);

set_random_seed(12345);
for (int i = 0; i < 20; ++i)
second[i] = get_random_map_seed(i + 1);

for (int i = 0; i < 20; ++i)
assert_int_equal(first[i], second[i]);
}

/* Two different seeds must not produce the same map seed sequence */
static void
test_different_seeds_differ(void **state)
{
(void)state;

unsigned int a[20], b[20];

set_random_seed(11111);
for (int i = 0; i < 20; ++i)
a[i] = get_random_map_seed(i + 1);

set_random_seed(22222);
for (int i = 0; i < 20; ++i)
b[i] = get_random_map_seed(i + 1);

/* At least one level must differ — all matching would be a collision */
int any_differ = 0;
for (int i = 0; i < 20; ++i) {
if (a[i] != b[i]) {
any_differ = 1;
break;
}
}
assert_true(any_differ);
}

/* get_random(max) must always return a value in [0, max] */
static void
test_get_random_bounds(void **state)
{
(void)state;

set_random_seed(99999);

for (unsigned int max = 0; max <= 100; ++max) {
for (int trial = 0; trial < 50; ++trial) {
unsigned int r = get_random(max);
assert_true(r <= max);
}
}
}

/*
* Seed 0 is the "uninitialised" sentinel in init_seed().
* set_random_seed(0) works fine, but get_random_seed() will subsequently
* re-init with time(NULL) because init_seed() sees seed==0 as unset.
* Verify that the code doesn't crash and that get_random_seed returns
* something non-zero after that lazy re-init.
*/
static void
test_seed_zero_reinit(void **state)
{
(void)state;

set_random_seed(0);
/* get_random_seed() triggers init_seed() which replaces 0 with time(NULL) */
assert_int_not_equal(get_random_seed(), 0);
/* map seeds are now populated from the time-based seed — must not crash */
(void)get_random_map_seed(1);
(void)get_random_map_seed(20);
}

int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_seed_roundtrip), cmocka_unit_test(test_map_seeds_are_deterministic),
cmocka_unit_test(test_different_seeds_differ), cmocka_unit_test(test_get_random_bounds),
cmocka_unit_test(test_seed_zero_reinit),
};

return cmocka_run_group_tests(tests, NULL, NULL);
}
5 changes: 2 additions & 3 deletions test/test_roommatrix.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* BreakHack - A dungeone crawler RPG
* Copyright (C) 2025 Linus Probert <linus.probert@gmail.com>
* Copyright (C) 2026 Linus Probert <linus.probert@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <SDL3/SDL.h>
#include "cmocka_include.h"
#include "../src/roommatrix.h"
Expand Down Expand Up @@ -141,4 +140,4 @@ main(void)
};

return cmocka_run_group_tests(tests, NULL, NULL);
}
}
Loading