Name of user not set #1002873 has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/40538 )
Change subject: tests: Add lib/string-test test case ......................................................................
tests: Add lib/string-test test case
This commit's purpose is to show basic example of how unit testing may be applied for coreboot project. It adds test harness for lib/string.c module.
In order to run this example, one need to install (beside general coreboot dependencies) cmocka package: sudo apt-get install -y libcmocka-dev sudo emerge dev-util/cmocka yum install libcmocka-devel
After invoking: make unit-tests report from unit test will be created and shown on the screen
This test harness definitely isn't complete, as it only checks for some functions within module. Purpose of this code is only an example and a starting point for a discussion about implementation.
Signed-off-by: Jan Dabros jsd@semihalf.com Change-Id: Ibf5554d1e99a393721a66bdd35af0122c2e412c4 --- A tests/include/mocks/assert.h A tests/lib/Makefile.inc A tests/lib/string-test.c 3 files changed, 152 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/38/40538/1
diff --git a/tests/include/mocks/assert.h b/tests/include/mocks/assert.h new file mode 100644 index 0000000..0b0499b --- /dev/null +++ b/tests/include/mocks/assert.h @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASSERT_H__ +#define __ASSERT_H__ + +#include <arch/hlt.h> +#include <console/console.h> + +/* TODO: Fix vendorcode headers to not define macros coreboot uses or to be more + properly isolated. */ +#ifdef ASSERT +#undef ASSERT +#endif + +/* GCC and CAR versions */ +#define ASSERT(x) { \ + if (!(x)) { \ + printk(BIOS_EMERG, "ASSERTION ERROR: file '%s'" \ + ", line %d\n", __FILE__, __LINE__); \ + if (CONFIG(FATAL_ASSERTS)) \ + hlt(); \ + } \ +} + +#define ASSERT_MSG(x, msg) { \ + if (!(x)) { \ + printk(BIOS_EMERG, "ASSERTION ERROR: file '%s'" \ + ", line %d\n", __FILE__, __LINE__); \ + printk(BIOS_EMERG, "%s", msg); \ + if (CONFIG(FATAL_ASSERTS)) \ + hlt(); \ + } \ +} + +/* Compile-out BUG() macro, since checkpatch is not happy with it, + * to be revised later. + */ +/* #define BUG() { \ + printk(BIOS_EMERG, "ERROR: BUG ENCOUNTERED at file '%s'"\ + ", line %d\n", __FILE__, __LINE__); \ + if (CONFIG(FATAL_ASSERTS)) \ + hlt(); \ +} */ + +#define assert(statement) ASSERT(statement) + +/* + * Original dead_code() from src/include/assert.h breaks compilation when + * non-intended code is compiled in. This is not suitable for unit testing, + * thus we are changing this macro to be run-time assert. mock_assert() allows + * Cmocka to expect such assert and pass test, when dead_code() is correctly + * called. + */ + +extern void mock_assert(const int result, const char * const expression, + const char * const file, const int line); + +#define dead_code() \ + mock_assert(0, "dead_code", __FILE__, __LINE__) + +#undef assert +#define assert(expression) \ + mock_assert((int)(expression), #expression, __FILE__, __LINE__) + +/* This can be used in the context of an expression of type 'type'. */ +#define dead_code_t(type) ({ \ + dead_code(); \ + *(type *)(uintptr_t)0; \ +}) + +#endif // __ASSERT_H__ diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc new file mode 100644 index 0000000..5f73446 --- /dev/null +++ b/tests/lib/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +# object filest should be under build/tests/ build/test/src/ build/test/run/ +# two examples - first should be simply string.c, second should use -wrap + +tests += string-test + +string-test-srcs += tests/lib/string-test.c +string-test-srcs += src/lib/string.c diff --git a/tests/lib/string-test.c b/tests/lib/string-test.c new file mode 100644 index 0000000..3ce0563 --- /dev/null +++ b/tests/lib/string-test.c @@ -0,0 +1,49 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <string.h> + +struct strings_t { + char *str; + size_t size; +} strings[] = { + {"coreboot", 8}, + {"is\0very", 2}, /* strlen should be 2 because of the embedded \0 */ + {"nice\n", 5} +}; + +static void test_strlen_strings(void **state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(strings); i++) + assert_int_equal(strings[i].size, strlen(strings[i].str)); +} + +/* Since strdup() requires malloc() it may only be invoked during ramstage + * phase. Expect dead_code/assert invocation otherwise. + */ +static void test_strdup(void **state) +{ +#ifdef __RAMSTAGE__ + char str[] = "Hello coreboot\n"; + char *duplicate; + + duplicate = strdup(str); + assert_int_equal(0, memcmp(str, duplicate, strlen(str))); +#else + expect_assert_failure(strdup(NULL)); +#endif +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_strlen_strings), + cmocka_unit_test(test_strdup), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}