nissy-nx

A Rubik's cube optimal solver
git clone https://git.tronto.net/nissy-nx
Download | Log | Files | Refs | README | LICENSE

commit 092270834eac54ed33e634494f9f38ba7fd38fd4
parent 9daff8c1625d4cbb5500a50fbfe83b7ecba06f8f
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Sat,  4 Feb 2023 17:26:32 +0100

Some improvements to test suite, ready to go

Diffstat:
MMakefile | 2+-
MTODO/testing.md | 5-----
Dtest.sh | 20--------------------
Mtests/fst_tests.c | 10+++++++---
Mtests/fst_tests.h | 2++
Mtests/test.c | 43++++++++++++++++++++++++++++++++++++-------
Dtests/test.h | 7-------
Mtests/test_common.h | 34++++++++++++++++++++++++++++------
8 files changed, 74 insertions(+), 49 deletions(-)

diff --git a/Makefile b/Makefile @@ -25,7 +25,7 @@ debug: ${CC} ${DBGFLAGS} -o nissy src/*.c test: - ${CC} ${DBGFLAGS} -DTEST -o tests/nissy_test src/*.c tests/*.c + ${CC} ${DBGFLAGS} -DTEST -o test src/*.c tests/*.c clean: rm -rf nissy nissy*.exe nissy*.tar.gz doc/nissy.html doc/nissy.pdf diff --git a/TODO/testing.md b/TODO/testing.md @@ -1,10 +1,5 @@ # Testing -## Architecture - -* write makefile -* how to build everything except nissy.c? - ## Write tests * Pretty much all are missing, except fst. diff --git a/test.sh b/test.sh @@ -1,20 +0,0 @@ -#!/bin/sh - -# Warning: tests should be in the correct order! -# Every testing module assumes that modules it depends on pass their tests. -all_modules=fst - -test_module() { - modules=$@ - for m in modules; do - ./tests/nissy_test $m - done -} - -make test -if [ -n "$@" ]; then - test_module $@ -else - test_module $all_modules -fi -rm tests/nissy_test diff --git a/tests/fst_tests.c b/tests/fst_tests.c @@ -3,9 +3,7 @@ static bool testmethod_fst_is_consistent(void *); static bool testmethod_cube_to_fst_to_cube(void *); static bool testmethod_fst_move(void *); -static bool testmethod_fst_inverse(void *); - -static bool check_equal_and_log(Cube *, Cube *); +static bool testmethod_fst_inverse(void *); static bool check_equal_and_log(Cube *, Cube *); static void void_to_cube(void *, Cube *); char *algs[] = { @@ -66,6 +64,12 @@ TestSuite fst_post_init_suite = { .teardown = NULL, }; +TestSuite *fst_testsuites[] = { + &fst_pre_init_suite, + &fst_post_init_suite, + NULL +}; + static bool check_equal_and_log(Cube *c, Cube *d) { diff --git a/tests/fst_tests.h b/tests/fst_tests.h @@ -14,4 +14,6 @@ extern Test test_fst_inverse; extern TestSuite fst_pre_init_suite; extern TestSuite fst_post_init_suite; +extern TestSuite *fst_testsuites[]; + #endif diff --git a/tests/test.c b/tests/test.c @@ -1,4 +1,6 @@ -#include "test.h" +#include <stdio.h> + +#include "fst_tests.h" static bool run_test(Test *); static bool run_suite(TestSuite *); @@ -36,15 +38,42 @@ run_suite(TestSuite *suite) return true; } -int main() { +static bool +module_in_args(char *module, int argc, char *argv[]) +{ + for (int i = 0; i < argc; i++) + if (!strcmp(module, argv[i])) + return true; + return false; +} + +int main(int argc, char *argv[]) { + /* TODO: init should be in testsuites */ init_env(); init_trans(); + /**************************************/ - if (!run_suite(&fst_pre_init_suite)) - return 1; - if (!run_suite(&fst_post_init_suite)) - return 1; + TestModule fst = { .name = "fst", .suites = fst_testsuites }; + TestModule *modules[999] = { + &fst, + NULL + }; + + + bool all = argc == 1 || module_in_args("all", argc, argv); + int count = 0; + for (int i = 0; modules[i] != NULL; i++) { + if (all || module_in_args(modules[i]->name, argc, argv)) { + for (int j = 0; modules[i]->suites[j] != NULL; j++) { + if (!run_suite(modules[i]->suites[j])) { + return 1; + } else { + count++; + } + } + } + } - printf("All tests passed.\n"); + printf("All tests passed (%d test suites).\n", count); return 0; } diff --git a/tests/test.h b/tests/test.h @@ -1,7 +0,0 @@ -#ifndef TEST_H -#define TEST_H - -#include <stdio.h> -#include "fst_tests.h" - -#endif diff --git a/tests/test_common.h b/tests/test_common.h @@ -1,19 +1,41 @@ #ifndef TEST_COMMON_H #define TEST_COMMON_H +/* + * Common utilities for testing. + * A VoidMethod can be used as a setup or teardown method for testing, see + * the TestSuite struct. A TestMethod takes a void pointer (usually cast + * to some data to be used for testing, but can also be ignored) and returns + * a bool: true for pass, false for fail. + * A Test consists of a name (string), a TestMethod and an array of void + * pointers that describe the test cases. Each element of this array is + * passed to the test method sequentially, and the test session stops on + * the first failure. + * A test suite is just a list of tests with a setup and a teardown method. + * The setup method is run once and for all before the first test, and the + * teardown is run at the end of the testsuite. + * Finally, a TestModule roughly corresponds to a test file. This type is + * only used in test.c to collect multiple test modules. + */ + typedef void (*VoidMethod)(void); typedef bool (*TestMethod)(void *); typedef struct { - char * name; - TestMethod t; - void ** cases; + char * name; + TestMethod t; + void ** cases; } Test; typedef struct { - VoidMethod setup; - Test ** tests; - VoidMethod teardown; + VoidMethod setup; + Test ** tests; + VoidMethod teardown; } TestSuite; +typedef struct { + char * name; + TestSuite ** suites; +} TestModule; + #endif