Name of user not set #1002873 has uploaded this change for review.

View Change

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);
+}

To view, visit change 40538. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ibf5554d1e99a393721a66bdd35af0122c2e412c4
Gerrit-Change-Number: 40538
Gerrit-PatchSet: 1
Gerrit-Owner: Name of user not set #1002873
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange