#ifndef PK_PKTST_H #define PK_PKTST_H #include "pkmacros.h" /* deleteme */ typedef int (pk_test_func)(); struct pk_test_group; typedef struct pk_test_group *(pk_test_group_get)(); typedef void (pk_test_group_setup)(); typedef void (pk_test_group_teardown)(); typedef void (pk_test_setup)(); typedef void (pk_test_teardown)(); struct pk_test { const char *title; pk_test_func *func; int expected_result; }; struct pk_test_group { const char *title; pk_test_group_setup *group_setup; pk_test_group_teardown *group_teardown; pk_test_setup *test_setup; pk_test_teardown *test_teardown; struct pk_test *tests; unsigned char n_tests; }; void pk_test_run_test_groups(pk_test_group_get **group_get_fns, unsigned long n_groups); #if defined(__cplusplus) #include #define PK_TEST_ASSERT_BODY(expected, value, comp) \ std::cerr << "[pk-test] "; \ std::cerr << "(" << __FILE__ << ":" << __LINE__ << ")"; \ std::cerr << PK_CLR_FG_RED " Failed " PK_CLR_RESET; \ std::cerr << #comp " , Condition: \""; \ std::cerr << PK_CLR_FG_BRIGHT_BLUE << #value << PK_CLR_RESET; \ std::cerr << "\", Expected: \""; \ std::cerr << PK_CLR_FG_GREEN << (expected) << PK_CLR_RESET; \ std::cerr << "\", Got: \""; \ std::cerr << PK_CLR_FG_RED << (value) << PK_CLR_RESET; \ std::cerr << "\"." << std::endl; template inline bool flt_equal(T a, T b, T epsilon) { return abs(a - b) < epsilon; } #else /* __cplusplus */ #include #define PK_TEST_ASSERT_BODY(expected, value, comp) \ fprintf(stderr,"[pk-test] (%s:%i) ", __FILE__, __LINE__); \ fprintf(stderr,"%s ", PK_CLR_FG_RED "Failed" PK_CLR_RESET); \ fprintf(stderr,#comp " : Test condition \""); \ fprintf(stderr,"%s\"\n",PK_CLR_FG_BRIGHT_BLUE #value PK_CLR_RESET); #endif /* __cplusplus */ #define PK_TEST_ASSERT_EQ(expected, value) { \ if ((value) != (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, ==) \ } \ } #define PK_TEST_ASSERT_EQ_RET(expected, value) { \ if ((value) != (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, ==) \ return -1; \ } \ } #define PK_TEST_ASSERT_EQ_EXIT(expected, value) { \ if ((value) != (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, ==) \ exit(1); \ } \ } #define PK_TEST_ASSERT_NEQ(expected, value) { \ if ((value) == (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, !=) \ } \ } #define PK_TEST_ASSERT_NEQ_RET(expected, value) { \ if ((value) == (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, !=) \ return -1; \ } \ } #define PK_TEST_ASSERT_NEQ_EXIT(expected, value) { \ if ((value) == (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, !=) \ exit(1); \ } \ } #define PK_TEST_ASSERT_GT(expected, value) { \ if ((value) <= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >) \ } \ } #define PK_TEST_ASSERT_GT_RET(expected, value) { \ if ((value) <= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >) \ return -1; \ } \ } #define PK_TEST_ASSERT_GT_EXIT(expected, value) { \ if ((value) <= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >) \ exit(1); \ } \ } #define PK_TEST_ASSERT_LT(expected, value) { \ if ((value) >= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <) \ } \ } #define PK_TEST_ASSERT_LT_RET(expected, value) { \ if ((value) >= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <) \ return -1; \ } \ } #define PK_TEST_ASSERT_LT_EXIT(expected, value) { \ if ((value) <= (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <) \ exit(1); \ } \ } #define PK_TEST_ASSERT_GTE(expected, value) { \ if ((value) < (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >=) \ } \ } #define PK_TEST_ASSERT_GTE_RET(expected, value) { \ if ((value) < (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >=) \ return -1; \ } \ } #define PK_TEST_ASSERT_GTE_EXIT(expected, value) { \ if ((value) < (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, >=) \ exit(1); \ } \ } #define PK_TEST_ASSERT_LTE(expected, value) { \ if ((value) > (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <=) \ } \ } #define PK_TEST_ASSERT_LTE_RET(expected, value) { \ if ((value) > (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <=) \ return -1; \ } \ } #define PK_TEST_ASSERT_LTE_EXIT(expected, value) { \ if ((value) > (expected)) { \ PK_TEST_ASSERT_BODY(expected, value, <=) \ exit(1); \ } \ } #ifdef PK_IMPL_TST #include "./pktmr.h" /* deleteme */ void pk_test_run_test_groups(pk_test_group_get **group_get_fns, unsigned long n_groups) { int result; unsigned long i; unsigned int k, pass_count, total_test_count, total_test_pass_count, test_group_count, test_group_pass_count; double elapsed_ms, group_ms, total_ms; struct pk_tmr func_tmr, total_tmr; struct pk_test_group *group; fprintf(stdout, "\r\n"); fprintf(stdout, "[pk-test] Begin..\n"); fprintf(stdout, "[pk-test] Running %04ld tests..\n", n_groups); i = 0; total_ms = 0; total_test_count = 0; total_test_pass_count = 0; test_group_count = 0; test_group_pass_count = 0; pk_tmr_start(total_tmr); fprintf(stdout, "\r\n"); for (i = 0; i < n_groups; ++i) { test_group_count += 1; pass_count = 0; group_ms = 0; group = group_get_fns[i](); fprintf(stdout, "[pk-test][%s] Begin..\n", group->title); if (group->group_setup != NULL) (group->group_setup)(); for (k = 0; k < group->n_tests; ++k) { total_test_count += 1; fprintf(stdout, "[pk-test][%s][%s] Begin..\n", group->title, group->tests[k].title); if (group->test_setup != NULL) (group->test_setup)(); pk_tmr_start(func_tmr); result = (group->tests[k].func)(); pk_tmr_stop(func_tmr); elapsed_ms = pk_tmr_duration_dbl_mili(func_tmr); fprintf(stdout, "[pk-test][%s][%s] End.\n", group->title, group->tests[k].title); group_ms += elapsed_ms; total_ms += elapsed_ms; fprintf(stdout, "[pk-test][%s][%s] Elapsed ms: '%f'.\n", group->title, group->tests[k].title, elapsed_ms); if (result == group->tests[k].expected_result){ total_test_pass_count += 1; pass_count += 1; fprintf(stdout, "[pk-test][%s][%s] %sPassed.%s\n", group->title, group->tests[k].title, PK_CLR_FG_GREEN, PK_CLR_RESET); } else { fprintf(stdout, "[pk-test][%s][%s] %sFailed.%s\n", group->title, group->tests[k].title, PK_CLR_FG_RED, PK_CLR_RESET); fprintf(stdout, "[pk-test][%s][%s] Expected: '" PK_CLR_FG_GREEN "%i" PK_CLR_RESET "', Got: '" PK_CLR_FG_RED "%i" PK_CLR_RESET "'.\n", group->title, group->tests[k].title, group->tests[k].expected_result, result); } if (group->test_teardown != NULL) (group->test_teardown)(); } if (group->group_teardown != NULL) (group->group_teardown)(); fprintf(stdout, "[pk-test][%s] End.\n", group->title); fprintf(stdout, "[pk-test][%s] Tests completed: ( %s%04d%s / %04d ).\n", group->title, pass_count == group->n_tests ? PK_CLR_FG_GREEN : PK_CLR_FG_RED, pass_count, PK_CLR_RESET, group->n_tests); fprintf(stdout, "[pk-test][%s] Elapsed ms: '%f'.\n\n", group->title, group_ms); if (pass_count == group->n_tests) { test_group_pass_count += 1; } } pk_tmr_stop(total_tmr); fprintf(stdout, "[pk-test] End.\n"); fprintf(stdout, "[pk-test] Tests completed: ( %s%04d%s / %04d ).\n", total_test_count == total_test_pass_count ? PK_CLR_FG_GREEN : PK_CLR_FG_RED, total_test_pass_count, PK_CLR_RESET, total_test_count); fprintf(stdout, "[pk-test] Test groups completed: ( %s%04d%s / %04d ).\n", test_group_count == test_group_pass_count ? PK_CLR_FG_GREEN : PK_CLR_FG_RED, test_group_pass_count, PK_CLR_RESET, test_group_count); fprintf(stdout, "[pk-test] Elapsed ms: '%f' (test fn sum).\n", total_ms); fprintf(stdout, "[pk-test] Elapsed ms: '%f' (actual).\n\n", pk_tmr_duration_dbl_mili(total_tmr)); } #endif /* PK_IMPL_TST */ #endif /* PK_PKTST_H */