Merge pull request #142 from fjoncourt/c_unit_testing

C unit testing - excellent, thank you Franck. I'll work on the relative path issue you mentioned as well.
This commit is contained in:
Michael Rash 2015-01-17 09:11:29 -05:00
commit e8cfeaf772
21 changed files with 737 additions and 27 deletions

View File

@ -8,11 +8,16 @@ if WANT_SERVER
SERVER_DIR = server
endif
if WANT_C_UNIT_TESTS
C_UNIT_TESTS_DIR = test/c-unit-tests
endif
SUBDIRS = \
lib \
common \
$(CLIENT_DIR) \
$(SERVER_DIR) \
$(C_UNIT_TESTS_DIR) \
doc
EXTRA_DIST = \

View File

@ -52,6 +52,10 @@
#define BITMASK_ARRAY_SIZE 2 /*!< Number of 32bits integer used to handle bitmask in the fko_var_bitmask_t structure */
#define LF_CHAR 0x0A /*!< Hexadecimal value associated to the LF char */
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(config_init, "Config init test suite");
#endif
/**
* Structure to handle long bitmask.
*
@ -2586,3 +2590,63 @@ usage(void)
return;
}
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE_INIT(config_init)
{
log_set_verbosity(LOG_VERBOSITY_ERROR);
return 0;
}
DECLARE_TEST_SUITE_CLEANUP(config_init)
{
return 0;
}
DECLARE_UTEST(critical_var, "Check critcial vars")
{
CU_ASSERT(var_is_critical(FWKNOP_CLI_ARG_KEY_RIJNDAEL) == 1);
CU_ASSERT(var_is_critical(FWKNOP_CLI_ARG_WGET_CMD) == 0);
}
DECLARE_UTEST(check_var_bitmask, "Check var_bitmask functions")
{
fko_var_bitmask_t var_bitmask;
memset(&var_bitmask, 0x00, sizeof(fko_var_bitmask_t));
add_var_to_bitmask(FWKNOP_CLI_FIRST_ARG, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_FIRST_ARG, &var_bitmask) == 1);
CU_ASSERT(var_bitmask.dw[0] == 1);
remove_var_from_bitmask(FWKNOP_CLI_FIRST_ARG, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_FIRST_ARG, &var_bitmask) == 0);
CU_ASSERT(var_bitmask.dw[0] == 0);
add_var_to_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_ARG_KEY_RIJNDAEL, &var_bitmask) == 1);
remove_var_from_bitmask(FWKNOP_CLI_ARG_KEY_RIJNDAEL, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_ARG_KEY_RIJNDAEL, &var_bitmask) == 0);
add_var_to_bitmask(FWKNOP_CLI_LAST_ARG, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_LAST_ARG, &var_bitmask) == 1);
remove_var_from_bitmask(FWKNOP_CLI_LAST_ARG, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_LAST_ARG, &var_bitmask) == 0);
add_var_to_bitmask(FWKNOP_CLI_LAST_ARG+32, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_LAST_ARG+32, &var_bitmask) == 0);
add_var_to_bitmask(FWKNOP_CLI_LAST_ARG+34, &var_bitmask);
CU_ASSERT(bitmask_has_var(FWKNOP_CLI_LAST_ARG+34, &var_bitmask) == 0);
}
int register_ts_config_init(void)
{
ts_init(&TEST_SUITE(config_init), TEST_SUITE_DESCR(config_init), TEST_SUITE_INIT(config_init), TEST_SUITE_CLEANUP(config_init));
ts_add_utest(&TEST_SUITE(config_init), UTEST_FCT(critical_var), UTEST_DESCR(critical_var));
ts_add_utest(&TEST_SUITE(config_init), UTEST_FCT(check_var_bitmask), UTEST_DESCR(check_var_bitmask));
return register_ts(&TEST_SUITE(config_init));
}
#endif /* HAVE_C_UNIT_TESTS */

View File

@ -43,6 +43,10 @@
void config_init(fko_cli_options_t *options, int argc, char **argv);
void usage(void);
#ifdef HAVE_C_UNIT_TESTS
int register_ts_config_init(void);
#endif
#endif /* CONFIG_INIT_H */
/***EOF***/

View File

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = subdir-objects
noinst_LIBRARIES = libfko_util.a
libfko_util_source_files = ../lib/strlcpy.c ../lib/strlcat.c ../lib/fko_util.c ../lib/fko_util.h
libfko_util_source_files = ../lib/cunit_common.c cunit_common.h ../lib/strlcpy.c ../lib/strlcat.c ../lib/fko_util.c ../lib/fko_util.h
libfko_util_a_SOURCES = $(libfko_util_source_files)

View File

@ -42,6 +42,12 @@
#include <fiu-control.h>
#endif
/* Include cunit header if c unit testing support is enabled. */
#ifdef HAVE_C_UNIT_TESTS
#include "CUnit/Basic.h"
#include "cunit_common.h"
#endif
#include <stdio.h>
#if HAVE_SYS_TYPES_H

37
common/cunit_common.h Executable file
View File

@ -0,0 +1,37 @@
#ifndef CUNIT_COMMON_H
#define CUNIT_COMMON_H
typedef struct c_unit_test
{
char description[128];
void (*func)(void);
} c_unit_test_t;
typedef struct c_unit_test_suite
{
char description[128];
int (*init_func)(void);
int (*cleanup_func)(void);
c_unit_test_t test_array[12];
int nb_c_unit_test;
} c_unit_test_suite_t;
#define UTEST_DESCR(name) ut_descr_##name
#define UTEST_FCT(name) ut_##name
#define TEST_SUITE(name) ts_##name
#define TEST_SUITE_DESCR(name) ts_descr_##name
#define TEST_SUITE_INIT(name) _ts_init_##name
#define TEST_SUITE_CLEANUP(name) _ts_cleanup_##name
#define DECLARE_TEST_SUITE(name, description) static const char ts_descr_##name[] = description; \
static c_unit_test_suite_t ts_##name;
#define DECLARE_TEST_SUITE_INIT(name) int _ts_init_##name(void)
#define DECLARE_TEST_SUITE_CLEANUP(name) int _ts_cleanup_##name(void)
#define DECLARE_UTEST(name, description) static const char ut_descr_##name[] = description; \
static void ut_##name(void)
void ts_init(c_unit_test_suite_t* ts, const char* description, int (*init)(void), int (*cleanup)(void));
void ts_add_utest(c_unit_test_suite_t* ts, void (*utest_func)(void), const char* utest_description);
int register_ts(c_unit_test_suite_t *ts);
#endif // CUNIT_COMMON_H

View File

@ -21,7 +21,7 @@ AC_CONFIG_AUX_DIR(config)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE
AM_INIT_AUTOMAKE([subdir-objects])
dnl AM_MAINTAINER_MODE
@ -153,6 +153,23 @@ if test "x$want_libfiu_support" = "xyes"; then
FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-lfiu])
fi
dnl Decide whether or not to enable C unit testing
dnl
want_c_unit_tests=no
AC_ARG_ENABLE([c-unit-tests],
[AS_HELP_STRING([--enable-c-unit-tests],
[Enable C unit testing with libcunit support @<:@default is to disable@:>@])],
[want_c_unit_tests=$enableval],
[])
if test "x$want_c_unit_tests" = "xyes"; then
AC_DEFINE([HAVE_C_UNIT_TESTS], [1], [Define for C unit testing support])
FKO_CHECK_COMPILER_ARG([-DHAVE_C_UNIT_TESTS])
FKO_CHECK_COMPILER_ARG_LDFLAGS_ONLY([-lcunit])
fi
AM_CONDITIONAL([WANT_C_UNIT_TESTS], [test "$want_c_unit_tests" = yes])
dnl Decide whether or not to compile in certain features that enable fuzzing
dnl of fwknop code - this is for testing purposes only.
dnl
@ -693,6 +710,7 @@ AC_CONFIG_FILES([Makefile
client/Makefile
server/Makefile
common/Makefile
test/c-unit-tests/Makefile
doc/Makefile])
AC_OUTPUT

View File

@ -7,8 +7,9 @@ libfko_source_files = \
fko_message.h fko_nat_access.c fko_rand_value.c fko_server_auth.c \
fko.h fko_limits.h fko_timestamp.c fko_hmac.c hmac.c hmac.h \
fko_user.c fko_user.h md5.c md5.h rijndael.c rijndael.h sha1.c \
sha1.h sha2.c sha2.h fko_context.h fko_state.h fko_context.h \
gpgme_funcs.c gpgme_funcs.h strlcpy.c strlcat.c fko_util.c fko_util.h
sha1.h sha2.c sha2.h fko_context.h fko_state.h \
gpgme_funcs.c gpgme_funcs.h strlcpy.c strlcat.c fko_util.c fko_util.h \
cunit_common.c cunit_common.h
libfko_la_SOURCES = $(libfko_source_files)
libfko_la_LDFLAGS = -version-info 2:3:0 $(GPGME_LIBS) -export-symbols-regex '^fko_'

51
lib/cunit_common.c Normal file
View File

@ -0,0 +1,51 @@
#ifdef HAVE_C_UNIT_TESTS
#include "cunit_common.h"
#include "stdlib.h"
#include "stdio.h"
#include "CUnit/Basic.h"
void ts_init(c_unit_test_suite_t* ts, const char* description, int (*init)(void), int (*cleanup)(void))
{
memset(ts, 0x00, sizeof(c_unit_test_suite_t));
strcpy(ts->description, description);
ts->init_func = init;
ts->cleanup_func = cleanup;
}
void ts_add_utest(c_unit_test_suite_t* ts, void (*utest_func)(void), const char* utest_description)
{
c_unit_test_t* utest = &(ts->test_array[ts->nb_c_unit_test]);
utest->func = utest_func;
strcpy(utest->description, utest_description);
(ts->nb_c_unit_test)++;
}
int register_ts(c_unit_test_suite_t *ts)
{
CU_pSuite pSuite = NULL;
int ix_utest;
pSuite = CU_add_suite(ts->description, ts->init_func, ts->cleanup_func);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* add the tests to the suite */
for (ix_utest=0 ; ix_utest<ts->nb_c_unit_test ; ix_utest++)
{
c_unit_test_t* utest = &(ts->test_array[ix_utest]);
if (NULL == CU_add_test(pSuite, utest->description, utest->func))
{
CU_cleanup_registry();
return CU_get_error();
}
}
return 0;
}
#endif /* HAVE_C_UNIT_TESTS */

View File

@ -448,6 +448,10 @@ DLL_API int fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char * const fpr,
}
#endif
#ifdef HAVE_C_UNIT_TESTS
int register_ts_fko_decode(void);
#endif
#endif /* FKO_H */
/***EOF***/

View File

@ -36,6 +36,13 @@
#define FIELD_PARSERS 9
/* Char used to separate SPA fields in an SPA packet */
#define SPA_FIELD_SEPARATOR ":"
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(fko_decode, "FKO decode test suite");
#endif
static int
num_fields(char *str)
{
@ -590,4 +597,65 @@ fko_decode_spa_data(fko_ctx_t ctx)
return(FKO_SUCCESS);
}
#ifdef HAVE_C_UNIT_TESTS
DECLARE_UTEST(num_fields, "Count the number of SPA fields in a SPA packet")
{
int ix_field=0;
char spa_packet[(MAX_SPA_FIELDS+1)*3];
/* Zeroing the spa packet */
memset(spa_packet, 0, sizeof(spa_packet));
/* Check we are able to count the number of SPA fields */
for(ix_field=0 ; ix_field<=MAX_SPA_FIELDS+2 ; ix_field++)
{
strcat(spa_packet, "x");
CU_ASSERT(num_fields(spa_packet) == ix_field);
strcat(spa_packet, SPA_FIELD_SEPARATOR);
}
/* Check for possible overflow */
strcat(spa_packet, "x");
CU_ASSERT(num_fields(spa_packet) == MAX_SPA_FIELDS + 2);
strcat(spa_packet, "x");
strcat(spa_packet, SPA_FIELD_SEPARATOR);
CU_ASSERT(num_fields(spa_packet) == MAX_SPA_FIELDS + 2);
}
DECLARE_UTEST(last_field, "Count the number of bytes to the last :")
{
int ix_field;
char spa_packet[(MAX_SPA_FIELDS+1)*3];
/* Zeroing the spa packet */
memset(spa_packet, 0, sizeof(spa_packet));
/* Check for a valid count when the number of field is less than MAX_SPA_FIELDS */
CU_ASSERT(last_field("a:") == 2);
CU_ASSERT(last_field("ab:abc:") == 7);
CU_ASSERT(last_field("abc:abcd:") == 9);
CU_ASSERT(last_field("abc:abcd:abc") == 9);
/* */
for(ix_field=0 ; ix_field<=MAX_SPA_FIELDS+2 ; ix_field++)
{
strcat(spa_packet, "x");
strcat(spa_packet, SPA_FIELD_SEPARATOR);
}
CU_ASSERT(last_field(spa_packet) == ((MAX_SPA_FIELDS+2)*2));
}
int register_ts_fko_decode(void)
{
ts_init(&TEST_SUITE(fko_decode), TEST_SUITE_DESCR(fko_decode), NULL, NULL);
ts_add_utest(&TEST_SUITE(fko_decode), UTEST_FCT(num_fields), UTEST_DESCR(num_fields));
ts_add_utest(&TEST_SUITE(fko_decode), UTEST_FCT(last_field), UTEST_DESCR(last_field));
return register_ts(&TEST_SUITE(fko_decode));
}
#endif /* HAVE_C_UNIT_TESTS */
/***EOF***/

View File

@ -12,7 +12,8 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
fw_util_iptables.c fw_util_iptables.h \
fw_util_ipfw.c fw_util_ipfw.h \
fw_util_pf.c fw_util_pf.h cmd_opts.h \
extcmd.c extcmd.h
extcmd.c extcmd.h \
common.h
fwknopd_LDADD = $(top_builddir)/lib/libfko.la $(top_builddir)/common/libfko_util.a

View File

@ -40,6 +40,7 @@
#include "access.h"
#include "utils.h"
#include "log_msg.h"
#include "common.h"
#define FATAL_ERR -1
@ -47,6 +48,10 @@
#define SUCCESS 1
#endif
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(access, "Access test suite");
#endif
/* Add an access string entry
*/
static int
@ -2004,5 +2009,35 @@ dump_access_list(const fko_srv_options_t *opts)
fprintf(stdout, "\n");
fflush(stdout);
}
#ifdef HAVE_C_UNIT_TESTS
DECLARE_UTEST(compare_port_list, "check compare_port_list function")
{
acc_port_list_t *in1_pl = NULL;
acc_port_list_t *in2_pl = NULL;
acc_port_list_t *acc_pl = NULL;
/* Match any test */
free_acc_port_list(in1_pl);
free_acc_port_list(acc_pl);
add_port_list_ent(&in1_pl, "udp/6002");
add_port_list_ent(&in2_pl, "udp/6002, udp/6003");
add_port_list_ent(&acc_pl, "udp/6002, udp/6003");
CU_ASSERT(compare_port_list(in1_pl, acc_pl, 1) == 1); /* Only one match is needed from access port list - 1 */
CU_ASSERT(compare_port_list(in2_pl, acc_pl, 1) == 1); /* Only match is needed from access port list - 2 */
CU_ASSERT(compare_port_list(in1_pl, acc_pl, 0) == 1); /* All ports must match access port list - 1 */
CU_ASSERT(compare_port_list(in2_pl, acc_pl, 0) == 1); /* All ports must match access port list - 2 */
CU_ASSERT(compare_port_list(acc_pl, in1_pl, 0) == 0); /* All ports must match in1 port list - 1 */
CU_ASSERT(compare_port_list(acc_pl, in2_pl, 0) == 1); /* All ports must match in2 port list - 2 */
}
int register_ts_access(void)
{
ts_init(&TEST_SUITE(access), TEST_SUITE_DESCR(access), NULL, NULL);
ts_add_utest(&TEST_SUITE(access), UTEST_FCT(compare_port_list), UTEST_DESCR(compare_port_list));
return register_ts(&TEST_SUITE(access));
}
#endif /* HAVE_C_UNIT_TESTS */
/***EOF***/

View File

@ -48,6 +48,10 @@ int expand_acc_port_list(acc_port_list_t **plist, char *plist_str);
void free_acc_stanzas(fko_srv_options_t *opts);
void free_acc_port_list(acc_port_list_t *plist);
#ifdef HAVE_C_UNIT_TESTS
int register_ts_access(void);
#endif
#endif /* ACCESS_H */
/***EOF***/

View File

@ -1014,26 +1014,4 @@ enable_fault_injections(fko_srv_options_t * const opts)
}
#endif
void
clean_exit(fko_srv_options_t *opts, unsigned int fw_cleanup_flag, unsigned int exit_status)
{
#if HAVE_LIBFIU
if(opts->config[CONF_FAULT_INJECTION_TAG] != NULL)
{
fiu_disable(opts->config[CONF_FAULT_INJECTION_TAG]);
}
#endif
if(!opts->test && (fw_cleanup_flag == FW_CLEANUP))
fw_cleanup(opts);
#if USE_FILE_CACHE
free_replay_list(opts);
#endif
free_logging();
free_configs(opts);
exit(exit_status);
}
/***EOF***/

View File

@ -28,6 +28,10 @@
#include "fwknopd_common.h"
#include "utils.h"
#include "log_msg.h"
#include "replay_cache.h"
#include "config_init.h"
#include "fw_util.h"
#include <stdarg.h>
#define ASCII_LEN 16
@ -252,4 +256,26 @@ free_argv(char **argv_new, int *argc_new)
return;
}
void
clean_exit(fko_srv_options_t *opts, unsigned int fw_cleanup_flag, unsigned int exit_status)
{
#if HAVE_LIBFIU
if(opts->config[CONF_FAULT_INJECTION_TAG] != NULL)
{
fiu_disable(opts->config[CONF_FAULT_INJECTION_TAG]);
}
#endif
if(!opts->test && (fw_cleanup_flag == FW_CLEANUP))
fw_cleanup(opts);
#if USE_FILE_CACHE
free_replay_list(opts);
#endif
free_logging();
free_configs(opts);
exit(exit_status);
}
/***EOF***/

78
test/c-unit-tests/Makefile.am Executable file
View File

@ -0,0 +1,78 @@
bin_PROGRAMS = fwknop_utests fwknopd_utests fko_utests
fwknop_utests_SOURCES = fwknop_utests.c \
../../client/config_init.c \
../../client/spa_comm.c \
../../client/utils.c \
../../client/http_resolve_host.c \
../../client/getpasswd.c \
../../client/log_msg.c
fwknop_utests_CPPFLAGS = -I ../../lib -I ../../common -I ../../client
fwknop_utests_LDADD = ../../lib/libfko.la ../../common/libfko_util.a
fwknop_utests_LDFLAGS = -lcunit
fwknopd_utests_SOURCES = fwknopd_utests.c \
../../server/config_init.c \
../../server/incoming_spa.c \
../../server/pcap_capture.c \
../../server/process_packet.c \
../../server/log_msg.c \
../../server/utils.c \
../../server/sig_handler.c \
../../server/replay_cache.c \
../../server/access.c\
../../server/fwknopd_errors.c \
../../server/tcp_server.c \
../../server/extcmd.c \
../../server/fw_util.c \
../../server/fw_util_ipf.c \
../../server/fw_util_iptables.c \
../../server/fw_util_ipfw.c \
../../server/fw_util_pf.c
fwknopd_utests_CPPFLAGS = -I ../../lib -I ../../common -I ../../server -DSYSCONFDIR=\"$(sysconfdir)\" -DSYSRUNDIR=\"$(localstatedir)\"
fwknopd_utests_LDADD = $(top_builddir)/lib/libfko.la $(top_builddir)/common/libfko_util.a
fwknopd_utests_LDFLAGS = -lcunit -lpcap
fko_utests_SOURCES = fko_utests.c \
../../lib/base64.c \
../../lib/cipher_funcs.c \
../../lib/digest.c \
../../lib/fko_client_timeout.c \
../../lib/fko_digest.c \
../../lib/fko_encode.c \
../../lib/fko_decode.c \
../../lib/fko_encryption.c \
../../lib/fko_error.c \
../../lib/fko_funcs.c \
../../lib/fko_message.c \
../../lib/fko_nat_access.c \
../../lib/fko_rand_value.c \
../../lib/fko_server_auth.c \
../../lib/fko_timestamp.c \
../../lib/fko_hmac.c \
../../lib/hmac.c \
../../lib/fko_user.c \
../../lib/md5.c \
../../lib/rijndael.c \
../../lib/sha1.c \
../../lib/sha2.c \
../../lib/strlcpy.c \
../../lib/strlcat.c \
../../lib/fko_util.c \
../../lib/cunit_common.c \
../../lib/gpgme_funcs.c
fko_utests_CPPFLAGS = -I ../../lib -I ../../common $(GPGME_CFLAGS)
fko_utests_LDFLAGS = -lcunit $(GPGME_LIBS)

226
test/c-unit-tests/README.md Normal file
View File

@ -0,0 +1,226 @@
# Build
C unit library is used to perform c unit testing. Source code associated to those tests
must be started with
~~~
#ifdef HAVE_C_UNIT_TESTS
~~~
and closed with:
~~~
#endif /* HAVE_C_UNIT_TESTS */
~~~
In order to build the test suite use the following commands with the **--enable-c-unit-tests**
switch
~~~
$ ./autogen.sh
$ ./configure --enable-c-unit-tests --prefix=/usr --sysconfdir=/etc --enable-profile-coverage
$ make
~~~
~~~
$ ./test-fwknop.pl --enable-profile-coverage-check --loopback lo --client-only-mode
~~~
# Run test suites
Once the build is complete, three test programs allow the user to run the tests suites:
* fwknopd_utests: program to run fwknopd c unit test suites
* fwknop_utests: program to run fwknop c unit test suites
* fko_utests: program to run fko c unit test suites
~~~
$ test/c-unit-tests/fwknopd_utests
Suite: Access test suite
Test: check compare_port_list function ...FAILED
1. ../../server/access.c:2017 - compare_port_list(acc_pl, in1_pl, 0) == 0
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 1 1 0 1 0
asserts 6 6 5 1 n/a
Elapsed time = 0.000 seconds
~~~
~~~
$ test/c-unit-tests/fwknop_utests
Suite: Config init test suite
Test: Check critcial vars ...passed
Test: Check var_bitmask functions ...passed
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 2 2 2 0 0
asserts 12 12 12 0 n/a
Elapsed time = 0.000 seconds
~~~
~~~
$ test/c-unit-tests/fko_utests
Suite: FKO decode test suite
Test: Count the number of SPA fields in a SPA packet ...passed
Test: Count the number of bytes to the last : ...passed
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 2 2 2 0 0
asserts 19 19 19 0 n/a
Elapsed time = 0.000 seconds
~~~
# Manage C unit tests
C unit tests are implemented in source files and registered in a test suite.
All test suites are then added to fwknopd, fwknop or fko test programs
In order to add new tests, the user must follow the below steps:
* Declare a test suite
* Declare an initialization function
* Declare a clean up function
* Create one or more unit tests
* Create a function to register new tests
## Declare a test suite
In *source* file:
~~~
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(access, "Access test suite");
#endif
~~~
In the above example, we create a test suite using the **DECLARE_TEST_SUITE** macro:
* the test suite is named "access".
* the test suite description is "Access test suite" and is displayed on the console
when the test program is executed
## Declare an initialization function
Before running the test suite, an init function can be used to initialize the test suite context.
To declare such a function use the **DECLARE_TEST_SUITE_INIT** macro.
In *source* file:
~~~
DECLARE_TEST_SUITE_INIT(access)
{
log_set_verbosity(LOG_VERBOSITY_ERROR);
return 0;
}
~~~
In the above example, the log message verbosity is decreased to error level to only display error
messages since debug messages are too verbose.
In some cases, there is no need for such a function and thus this declaration is not mandatory.
## Declare a clean-up function
In order to clean up the context at the end of the test suite, it is possible to declare a clean up
function with the **DECLARE_TEST_SUITE_CLEANUP** macro
In *source* file:
~~~
DECLARE_TEST_SUITE_CLEANUP(access)
{
return 0;
}
~~~
In the above example, the clean up function returns 0 and does strictly nothing.
In some cases, there is no need for such function and thus this declaration is not mandatory.
## Create unit tests
In *source* file:
~~~
#ifdef HAVE_C_UNIT_TESTS
DECLARE_UTEST(compare_port_list, "check compare_port_list function")
{
acc_port_list_t *in1_pl = NULL;
acc_port_list_t *in2_pl = NULL;
acc_port_list_t *acc_pl = NULL;
/* Match any test */
free_acc_port_list(in1_pl);
free_acc_port_list(acc_pl);
add_port_list_ent(&in1_pl, "udp/6002");
add_port_list_ent(&in2_pl, "udp/6002, udp/6003");
add_port_list_ent(&acc_pl, "udp/6002, udp/6003");
CU_ASSERT(compare_port_list(in1_pl, acc_pl, 1) == 1);
CU_ASSERT(compare_port_list(in2_pl, acc_pl, 1) == 1);
CU_ASSERT(compare_port_list(in1_pl, acc_pl, 0) == 1);
CU_ASSERT(compare_port_list(in2_pl, acc_pl, 0) == 1);
CU_ASSERT(compare_port_list(acc_pl, in1_pl, 0) == 0);
CU_ASSERT(compare_port_list(acc_pl, in2_pl, 0) == 1);
}
#endif /* HAVE_C_UNIT_TESTS */
~~~
In the above example, we create a c-unit test using the **DECLARE_UTEST** macro:
* The unit test is named "compare_port_list" ; This id must be unique
* The unit test description is "check compare_port_list function" and is displayed on the console
when the test program is executed
## Create a function to register new tests
We have previously declared unit tests, but they have to be registered to a test suite
to be executed.
In *source* file:
~~~
#ifdef HAVE_C_UNIT_TESTS
int register_ts_access(void)
{
ts_init(&TEST_SUITE(access), TEST_SUITE_DESCR(access), TEST_SUITE_INIT(access), TEST_SUITE_CLEANUP(access));
ts_add_utest(&TEST_SUITE(access), UTEST_FCT(compare_port_list), UTEST_DESCR(compare_port_list));
return register_ts(&TEST_SUITE(access));
}
#endif /* HAVE_C_UNIT_TESTS */
~~~
If no init or cleanup function is defined, they have to be replaced by a NULL pointer
at test suite initialization : **ts_init**
Each unit test must be added using **ts_add_utest** function.
In *header* file, add the register function prototype as follows:
~~~
#ifdef HAVE_C_UNIT_TESTS
int register_ts_access(void);
#endif
~~~
In the unit test program, add the test suite to the current list of existing
test suite.
~~~
static void register_test_suites(void)
{
register_ts_access();
}
~~~
## Check gcov coverage

34
test/c-unit-tests/fko_utests.c Executable file
View File

@ -0,0 +1,34 @@
#include "CUnit/Basic.h"
#include "fko.h"
/**
* Register test suites from FKO files.
*
* The module should fetch functions according to used modules. All of them follow the same
* naming convention.
*/
static void register_test_suites(void)
{
register_ts_fko_decode();
}
/* The main() function for setting up and running the tests.
* Returns a CUE_SUCCESS on successful running, another
* CUnit error code on failure.
*/
int main()
{
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* Register test suites from fko files */
register_test_suites();
/* RUN ALL TESTS USING THE CUNIT BASIC INTERFACE */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}

View File

@ -0,0 +1,35 @@
#include "CUnit/Basic.h"
#include "fwknop_common.h"
#include "config_init.h"
/**
* Register test suites from FKO files.
*
* The module should fetch functions according to used modules. All of them follow the same
* naming convention.
*/
static void register_test_suites(void)
{
register_ts_config_init();
}
/* The main() function for setting up and running the tests.
* Returns a CUE_SUCCESS on successful running, another
* CUnit error code on failure.
*/
int main()
{
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* Register test suites from fko files */
register_test_suites();
/* RUN ALL TESTS USING THE CUNIT BASIC INTERFACE */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}

View File

@ -0,0 +1,35 @@
#include "CUnit/Basic.h"
#include "fwknopd_common.h"
#include "access.h"
/**
* Register test suites from FKO files.
*
* The module should fetch functions according to used modules. All of them follow the same
* naming convention.
*/
static void register_test_suites(void)
{
register_ts_access();
}
/* The main() function for setting up and running the tests.
* Returns a CUE_SUCCESS on successful running, another
* CUnit error code on failure.
*/
int main()
{
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* Register test suites from fko files */
register_test_suites();
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}