add new feature for testing
This commit is contained in:
parent
0bb51750ef
commit
cdc22d158f
@ -16,9 +16,6 @@ include(tool/meta.cmake)
|
||||
# ---- thirdparty import
|
||||
add_subdirectory(thirdparty EXCLUDE_FROM_ALL)
|
||||
|
||||
# ---- generation
|
||||
include(tool/meta.cmake)
|
||||
|
||||
# ---- common config
|
||||
add_library(nf7config INTERFACE)
|
||||
target_include_directories(nf7config
|
||||
@ -42,6 +39,9 @@ target_compile_options(nf7config INTERFACE
|
||||
>
|
||||
)
|
||||
|
||||
# ---- test library
|
||||
add_subdirectory(test EXCLUDE_FROM_ALL)
|
||||
|
||||
# ---- util library
|
||||
add_subdirectory(util)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
# ---- basic modules
|
||||
set(MODS
|
||||
sdl2
|
||||
test
|
||||
)
|
||||
|
||||
# ---- core library
|
||||
|
14
core/test/CMakeLists.txt
Normal file
14
core/test/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
add_library(nf7core_test)
|
||||
target_sources(nf7core_test
|
||||
PRIVATE
|
||||
mod.c
|
||||
run.h
|
||||
PUBLIC
|
||||
mod.h
|
||||
)
|
||||
target_link_libraries(nf7core_test
|
||||
PRIVATE
|
||||
nf7if
|
||||
nf7util
|
||||
nf7test
|
||||
)
|
51
core/test/mod.c
Normal file
51
core/test/mod.c
Normal file
@ -0,0 +1,51 @@
|
||||
// No copyright
|
||||
#include "core/test/mod.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "nf7.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/malloc.h"
|
||||
|
||||
#include "core/test/run.h"
|
||||
|
||||
|
||||
static void del_(struct nf7_mod*);
|
||||
|
||||
|
||||
struct nf7_mod* nf7_core_test_new(struct nf7* nf7) {
|
||||
assert(nullptr != nf7);
|
||||
|
||||
struct nf7_core_test* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate instance");
|
||||
return nullptr;
|
||||
}
|
||||
*this = (struct nf7_core_test) {
|
||||
.meta = &nf7_core_test,
|
||||
.nf7 = nf7,
|
||||
.malloc = nf7->malloc,
|
||||
.uv = nf7->uv,
|
||||
};
|
||||
|
||||
if (!run_trigger_setup_(this)) {
|
||||
nf7_util_log_error("failed to setup runner");
|
||||
return nullptr;
|
||||
}
|
||||
return (struct nf7_mod*) this;
|
||||
}
|
||||
|
||||
static void del_(struct nf7_mod* mod) {
|
||||
struct nf7_core_test* this = (struct nf7_core_test*) mod;
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
|
||||
const struct nf7_mod_meta nf7_core_test = {
|
||||
.name = (const uint8_t*) "nf7core_test",
|
||||
.desc = (const uint8_t*) "executes tests after the initialization",
|
||||
.ver = 0,
|
||||
|
||||
.delete = del_,
|
||||
};
|
22
core/test/mod.h
Normal file
22
core/test/mod.h
Normal file
@ -0,0 +1,22 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
struct nf7_core_test;
|
||||
struct nf7_core_test_run;
|
||||
|
||||
struct nf7_core_test {
|
||||
const struct nf7_mod_meta* meta;
|
||||
|
||||
struct nf7* nf7;
|
||||
struct nf7_util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
struct nf7_core_test_run* run;
|
||||
};
|
||||
|
||||
extern const struct nf7_mod_meta nf7_core_test;
|
143
core/test/run.h
Normal file
143
core/test/run.h
Normal file
@ -0,0 +1,143 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "test/run.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/malloc.h"
|
||||
|
||||
#include "core/test/mod.h"
|
||||
|
||||
|
||||
static bool run_trigger_setup_(struct nf7_core_test*);
|
||||
static void run_cancel_(struct nf7_core_test_run*);
|
||||
static void run_cancel_close_(uv_handle_t*);
|
||||
static void run_trigger_(uv_idle_t*);
|
||||
|
||||
static void run_single_test_(struct nf7_test*, const char*, nf7_test_func);
|
||||
static void run_expect_(struct nf7_test*, bool, const char*);
|
||||
static void run_finalize_(struct nf7_test*);
|
||||
|
||||
|
||||
struct nf7_core_test_run {
|
||||
struct nf7_core_test* mod;
|
||||
struct nf7_util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
uv_idle_t idle;
|
||||
struct nf7_test test;
|
||||
|
||||
uint64_t run_tests;
|
||||
uint64_t succeeded_tests;
|
||||
|
||||
const char* running_test_name;
|
||||
};
|
||||
|
||||
|
||||
static bool run_trigger_setup_(struct nf7_core_test* mod) {
|
||||
assert(nullptr != mod);
|
||||
|
||||
struct nf7_core_test_run* this = nf7_util_malloc_new(mod->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate an test context");
|
||||
return false;
|
||||
}
|
||||
*this = (struct nf7_core_test_run) {
|
||||
.mod = mod,
|
||||
.malloc = mod->malloc,
|
||||
.uv = mod->uv,
|
||||
.test = {
|
||||
.nf7 = mod->nf7,
|
||||
.data = this,
|
||||
.run = run_single_test_,
|
||||
.expect = run_expect_,
|
||||
.finalize = run_finalize_,
|
||||
},
|
||||
};
|
||||
nf7_test_ref(&this->test);
|
||||
|
||||
nf7_util_log_uv_assert(uv_idle_init(this->uv, &this->idle));
|
||||
this->idle.data = this;
|
||||
nf7_util_log_uv_assert(uv_idle_start(&this->idle, run_trigger_));
|
||||
|
||||
mod->run = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void run_cancel_(struct nf7_core_test_run* this) {
|
||||
if (nullptr != this) {
|
||||
if (nullptr != this->mod) {
|
||||
this->mod->run = nullptr;
|
||||
}
|
||||
uv_idle_stop(&this->idle);
|
||||
uv_close((uv_handle_t*) &this->idle, run_cancel_close_);
|
||||
}
|
||||
}
|
||||
static void run_cancel_close_(uv_handle_t* handle) {
|
||||
struct nf7_core_test_run* this = handle->data;
|
||||
nf7_test_unref(&this->test);
|
||||
}
|
||||
|
||||
static void run_trigger_(uv_idle_t* idle) {
|
||||
struct nf7_core_test_run* this = idle->data;
|
||||
|
||||
nf7_util_log_info("triggering tests...");
|
||||
nf7_test_run(&this->test);
|
||||
nf7_util_log_info("all tests are triggered");
|
||||
|
||||
run_cancel_(this);
|
||||
}
|
||||
|
||||
|
||||
static void run_single_test_(
|
||||
struct nf7_test* test, const char* name, nf7_test_func func) {
|
||||
assert(nullptr != test);
|
||||
assert(nullptr != name);
|
||||
assert(nullptr != func);
|
||||
|
||||
struct nf7_core_test_run* this = test->data;
|
||||
|
||||
this->running_test_name = name;
|
||||
const bool result = func(&this->test);
|
||||
this->running_test_name = nullptr;
|
||||
|
||||
++this->run_tests;
|
||||
if (result) {
|
||||
++this->succeeded_tests;
|
||||
nf7_util_log_info("test succeeded: %s", name);
|
||||
} else {
|
||||
nf7_util_log_error("TEST FAILED: %s", name);
|
||||
}
|
||||
}
|
||||
static void run_expect_(struct nf7_test* test, bool val, const char* expr) {
|
||||
assert(nullptr != test);
|
||||
assert(nullptr != expr);
|
||||
|
||||
if (val) {
|
||||
nf7_util_log_debug("expectation is met: %s", expr);
|
||||
} else {
|
||||
nf7_util_log_error("expectation is NOT met: %s", expr);
|
||||
}
|
||||
}
|
||||
static void run_finalize_(struct nf7_test* test) {
|
||||
assert(nullptr != test);
|
||||
|
||||
struct nf7_core_test_run* this = test->data;
|
||||
if (0 < this->run_tests) {
|
||||
if (this->succeeded_tests == this->run_tests) {
|
||||
nf7_util_log_info(
|
||||
"all tests (%" PRIu64 ") has passed! :)",
|
||||
this->run_tests);
|
||||
} else {
|
||||
nf7_util_log_warn(
|
||||
"%" PRIu64 "/%" PRIu64 " tests have FAILED! X(",
|
||||
this->run_tests - this->succeeded_tests,
|
||||
this->run_tests);
|
||||
}
|
||||
}
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
}
|
32
test/CMakeLists.txt
Normal file
32
test/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
# ---- test interfae library
|
||||
add_library(nf7test_if INTERFACE)
|
||||
target_link_libraries(nf7test_if INTERFACE nf7config)
|
||||
target_sources(nf7test_if INTERFACE common.h)
|
||||
|
||||
# ---- test library
|
||||
add_library(nf7test)
|
||||
target_link_libraries(nf7test
|
||||
PUBLIC
|
||||
nf7config
|
||||
nf7test_if
|
||||
)
|
||||
target_meta_source(nf7test
|
||||
PRIVATE run.c.sh
|
||||
ARGS $<TARGET_PROPERTY:nf7test_src,SOURCES>
|
||||
DEPENDS $<TARGET_PROPERTY:nf7test_src,SOURCES>
|
||||
)
|
||||
|
||||
# ---- a custom target to keep source files of tests
|
||||
add_custom_target(nf7test_src)
|
||||
|
||||
function(target_tests target)
|
||||
if (NOT TARGET "${target}")
|
||||
message(FATAL_ERROR "unknown target: ${target}")
|
||||
endif()
|
||||
|
||||
target_sources(${target} PRIVATE ${ARGN})
|
||||
target_link_libraries(${target} PRIVATE nf7test_if)
|
||||
|
||||
target_sources(nf7test_src PRIVATE ${ARGN})
|
||||
target_link_libraries(nf7test PRIVATE ${target})
|
||||
endfunction()
|
40
test/common.h
Normal file
40
test/common.h
Normal file
@ -0,0 +1,40 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define NF7_TEST(name) bool name([[maybe_unused]] struct nf7_test*)
|
||||
|
||||
struct nf7;
|
||||
struct nf7_test;
|
||||
|
||||
typedef bool (*nf7_test_func)(struct nf7_test*);
|
||||
|
||||
struct nf7_test {
|
||||
struct nf7* nf7;
|
||||
void* data;
|
||||
|
||||
uint64_t refcnt;
|
||||
|
||||
void (*run)(struct nf7_test*, const char* name, nf7_test_func);
|
||||
void (*expect)(struct nf7_test*, bool val, const char* expr);
|
||||
void (*finalize)(struct nf7_test*);
|
||||
};
|
||||
|
||||
|
||||
static inline void nf7_test_ref(struct nf7_test* test) {
|
||||
++test->refcnt;
|
||||
}
|
||||
static inline void nf7_test_unref(struct nf7_test* test) {
|
||||
if (--test->refcnt == 0) {
|
||||
test->finalize(test);
|
||||
}
|
||||
}
|
||||
|
||||
#define nf7_test_expect(test, expr) nf7_test_expect_(test, (expr), #expr)
|
||||
static inline bool nf7_test_expect_(
|
||||
struct nf7_test* test, bool val, const char* expr) {
|
||||
test->expect(test, val, expr);
|
||||
return val;
|
||||
}
|
17
test/run.c.sh
Executable file
17
test/run.c.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
tests=$(cat $@ | sed -e '/^NF7_TEST(/!d; s|^NF7_TEST(\([^)]*\)).*$|\1|' | xargs echo)
|
||||
|
||||
echo "#include \"test/common.h\""
|
||||
echo "#include \"test/run.h\""
|
||||
echo
|
||||
echo
|
||||
echo "bool nf7_test_run(struct nf7_test* test) {"
|
||||
echo " // $tests"
|
||||
for test in $tests; do
|
||||
echo " extern bool $test(struct nf7_test*);"
|
||||
echo " test->run(test, \"$test\", $test);"
|
||||
done
|
||||
echo " return true;"
|
||||
echo "}"
|
||||
|
7
test/run.h
Normal file
7
test/run.h
Normal file
@ -0,0 +1,7 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
bool nf7_test_run(struct nf7_test*);
|
@ -10,7 +10,7 @@ function(target_meta_source args_target args_scope args_src)
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "^${PROJECT_SOURCE_DIR}/" "" CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
file(RELATIVE_PATH CURRENT_DIR "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GENERATED_DIR "${PROJECT_BINARY_DIR}/generated")
|
||||
set(GENERATED_CURRENT_DIR "${GENERATED_DIR}/${CURRENT_DIR}")
|
||||
|
||||
|
9
tool/testset.c.sh
Normal file
9
tool/testset.c.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
cat $@ | sed -e ''
|
||||
|
||||
echo "bool nf7_test_run(void) {"
|
||||
echo " // $@"
|
||||
echo " return true;"
|
||||
echo "}"
|
||||
|
@ -8,4 +8,11 @@ target_sources(nf7util
|
||||
malloc.h
|
||||
signal.h
|
||||
)
|
||||
target_link_libraries(nf7util PRIVATE nf7config)
|
||||
target_tests(nf7util
|
||||
array.test.c
|
||||
)
|
||||
target_link_libraries(nf7util
|
||||
PRIVATE
|
||||
nf7config
|
||||
uv
|
||||
)
|
||||
|
12
util/array.test.c
Normal file
12
util/array.test.c
Normal file
@ -0,0 +1,12 @@
|
||||
// No copyright
|
||||
#include "util/array.h"
|
||||
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
NF7_TEST(nf7_util_array_test) {
|
||||
return true;
|
||||
}
|
||||
NF7_TEST(nf7_util_array_test2) {
|
||||
return true;
|
||||
}
|
13
util/log.h
13
util/log.h
@ -1,10 +1,12 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define NF7_UTIL_LOG_CURRENT_FILE \
|
||||
((const char*) __FILE__ + NF7_PROJECT_DIR_LEN)
|
||||
|
||||
@ -27,6 +29,8 @@
|
||||
#define nf7_util_log_error(...) \
|
||||
nf7_util_log_sugar("ERR", __VA_ARGS__)
|
||||
|
||||
|
||||
// ---- libuv utils
|
||||
#define nf7_util_log_uv(ret) \
|
||||
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7_util_log_uv_(
|
||||
@ -36,3 +40,12 @@ static inline int nf7_util_log_uv_(
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define nf7_util_log_uv_assert(ret) \
|
||||
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7_util_log_uv_assert_(
|
||||
int ret, const char* file, uint64_t line, const char* func) {
|
||||
nf7_util_log_uv_(ret, file, line, func);
|
||||
assert(0 == ret);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user