* Removed duplicated entry in Makefile.am for libfko

* Added c unit tests for fko (draft)
* Updated c unit test README file.
This commit is contained in:
Franck Joncourt 2014-12-29 18:47:17 +01:00
parent cb13d84d48
commit 620d31364e
6 changed files with 291 additions and 152 deletions

View File

@ -7,7 +7,7 @@ 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 \
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

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,10 @@
#define FIELD_PARSERS 9
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(fko_decode, "FKO decode test suite");
#endif
static int
num_fields(char *str)
{
@ -590,4 +594,23 @@ 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")
{
CU_ASSERT(num_fields("abcdef") == 0);
CU_ASSERT(num_fields("abcdef:gh") == 1);
}
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));
return register_ts(&TEST_SUITE(fko_decode));
}
#endif /* HAVE_C_UNIT_TESTS */
/***EOF***/

View File

@ -1,4 +1,4 @@
bin_PROGRAMS = fwknop_utests fwknopd_utests
bin_PROGRAMS = fwknop_utests fwknopd_utests fko_utests
fwknop_utests_SOURCES = fwknop_utests.c \
../../client/config_init.c \
@ -14,6 +14,9 @@ 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 \
@ -38,3 +41,37 @@ fwknopd_utests_CPPFLAGS = -I ../../lib -I ../../common -I ../../server -DSYSCONF
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
fko_utests_CPPFLAGS = -I ../../lib -I ../../common
fko_utests_LDFLAGS = -lcunit

View File

@ -1,150 +1,191 @@
##Build
~~~
$ ./autogen.sh
$ ./configure --enable-c-unit-tests --prefix=/usr --sysconfdir=/etc --enable-profile-coverage
$ make
~~~
~~~
$ ./test-fwknop.pl --enable-profile-coverage-check --loopback lo
~~~
The HAVE_C_UNIT_TESTS constant is used in source files to define c-unit test code.
Source code is built against libcunit.
##Run test suites
Once the build is complete, two 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
~~~
$ test/c-unit-tests/fwknopd_utests
CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
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
CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
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
~~~
##Manage C unit tests
C unit tests are implemented in source files directly and registered in a test suite.
All test suites are then added to fwknopd or fwknop test programs
In order to add new tests, the user must follow the below steps:
* Declare the tests suite
* Create one or more unit tests
* Create a function to register new tests
###Declare the tests suite
In access.c 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
###Create unit tests
In access.c 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); /* 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 */
}
#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
In access.c file:
~~~
#ifdef HAVE_C_UNIT_TESTS
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 */
~~~
In access.h file:
~~~
#ifdef HAVE_C_UNIT_TESTS
int register_ts_access(void);
#endif
~~~
In fwknopd_utests.c file:
~~~
static void register_test_suites(void)
{
register_ts_access();
}
~~~
The register_ts_access function create the new test suite and add unit test to it.
###Check gcov coverage
# Build
~~~
$ ./autogen.sh
$ ./configure --enable-c-unit-tests --prefix=/usr --sysconfdir=/etc --enable-profile-coverage
$ make
~~~
~~~
$ ./test-fwknop.pl --enable-profile-coverage-check --loopback lo
~~~
The HAVE_C_UNIT_TESTS constant is used in source files to define c-unit test code.
Source code is built against libcunit.
# Run test suites
Once the build is complete, two 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
~~~
$ test/c-unit-tests/fwknopd_utests
CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
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
CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
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
~~~
# Manage C unit tests
C unit tests are implemented in source files directly and registered in a test suite.
All test suites are then added to fwknopd or fwknop test programs
In order to add new tests, the user must follow the below steps:
* Declare the tests suite
* Declare an initialization function
* Declare a cleanup function
* Create one or more unit tests
* Create a function to register new tests
## Declare the tests suite
In access.c 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
To declare an init function to execute before runnning the test suite to initiize the context use the DECLARE_TEST_SUITE_INIT macro as follow:
DECLARE_TEST_SUITE_INIT(filename)
~~~
DECLARE_TEST_SUITE_INIT(access)
{
log_set_verbosity(LOG_VERBOSITY_ERROR);
return 0;
}
~~~
In the above example, the log message verbosity is decreeased to error to only display error messages since debug messages are useless.
## Declare a cleanup function
To declare a cleanup function to execute at the end of the test suite to cleanup the context use the DECLARE_TEST_SUITE_CLEANUP macro as follow:
DECLARE_TEST_SUITE_CLEANUP(filename)
~~~
DECLARE_TEST_SUITE_CLEANUP(access)
{
return 0;
}
~~~
In the above example, the cleanup function returns 0 and does strictly nothing. There is no need to declare such function and
thus could be replaced by a NULL pointer at test suite initialization
## Create unit tests
In access.c 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); /* 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 */
}
#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
In access.c 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.
In access.h file:
~~~
#ifdef HAVE_C_UNIT_TESTS
int register_ts_access(void);
#endif
~~~
In fwknopd_utests.c file:
~~~
static void register_test_suites(void)
{
register_ts_access();
}
~~~
The register_ts_access function create the new test suite and add unit test to it.
## 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();
}