See patch. Uwe. -- http://www.hermann-uwe.de | http://www.holsham-traders.de http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
Initial unit testing framework for LinuxBIOS using Check (http://check.sourceforge.net/).
To run the testsuite simply type 'make check' in the top-level LinuxBIOS
directory or in util/testsuite/unittests.
You need to have Check installed on your system for this to work.
On Debian systems this is done via 'apt-get install check', otherwise
you can compile the package from source.
You can check the current code coverage with tools such as ggcov.
Signed-off-by: Uwe Hermann <[EMAIL PROTECTED]>
Index: util/testsuite/unittests/check.h
===================================================================
--- util/testsuite/unittests/check.h (Revision 0)
+++ util/testsuite/unittests/check.h (Revision 0)
@@ -0,0 +1,375 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * It was taken from the Check project (src/check.h) and slightly modified
+ * for LinuxBIOS so that it doesn't need external headers anymore.
+ *
+ * Modifications are:
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ */
+
+/*-*- mode:C; -*- */
+/*
+ * Check: a unit test framework for C
+ * Copyright (C) 2001, 2002, Arien Malec
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CHECK_H
+#define CHECK_H
+
+// #include <stddef.h>
+typedef int pid_t;
+
+/* Check: a unit test framework for C
+
+ Check is a unit test framework for C. It features a simple
+ interface for defining unit tests, putting little in the way of the
+ developer. Tests are run in a separate address space, so Check can
+ catch both assertion failures and code errors that cause
+ segmentation faults or other signals. The output from unit tests
+ can be used within source code editors and IDEs.
+
+ Unit tests are created with the START_TEST/END_TEST macro
+ pair. The fail_unless and fail macros are used for creating
+ checks within unit tests; the mark_point macro is useful for
+ trapping the location of signals and/or early exits.
+
+
+ Test cases are created with tcase_create, unit tests are added
+ with tcase_add_test
+
+
+ Suites are created with suite_create; test cases are added
+ with suite_add_tcase
+
+ Suites are run through an SRunner, which is created with
+ srunner_create. Additional suites can be added to an SRunner with
+ srunner_add_suite. An SRunner is freed with srunner_free, which also
+ frees all suites added to the runner.
+
+ Use srunner_run_all to run a suite and print results.
+
+*/
+
+
+#ifdef __cplusplus
+#define CK_CPPSTART extern "C" {
+CK_CPPSTART
+#endif
+
+// #include <sys/types.h>
+
+/* check version numbers */
+
+#define CHECK_MAJOR_VERSION (0)
+#define CHECK_MINOR_VERSION (9)
+#define CHECK_MICRO_VERSION (5)
+
+extern int check_major_version;
+extern int check_minor_version;
+extern int check_micro_version;
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/* opaque type for a test case
+
+ A TCase represents a test case. Create with tcase_create, free
+ with tcase_free. For the moment, test cases can only be run
+ through a suite
+*/
+typedef struct TCase TCase;
+
+/* type for a test function */
+typedef void (*TFun) (int);
+
+/* type for a setup/teardown function */
+typedef void (*SFun) (void);
+
+/* Opaque type for a test suite */
+typedef struct Suite Suite;
+
+/* Creates a test suite with the given name */
+Suite *suite_create (const char *name);
+
+/* Add a test case to a suite */
+void suite_add_tcase (Suite *s, TCase *tc);
+
+/* Create a test case */
+TCase *tcase_create (const char *name);
+
+/* Add a test function to a test case (macro version) */
+#define tcase_add_test(tc,tf) tcase_add_test_raise_signal(tc,tf,0)
+
+/* Add a test function with signal handling to a test case (macro version) */
+#define tcase_add_test_raise_signal(tc,tf,signal) \
+ _tcase_add_test((tc),(tf),"" # tf "",(signal), 0, 1)
+
+/* Add a looping test function to a test case (macro version)
+
+ The test will be called in a for(i = s; i < e; i++) loop with each
+ iteration being executed in a new context. The loop variable 'i' is
+ available in the test.
+ */
+#define tcase_add_loop_test(tc,tf,s,e) \
+ _tcase_add_test((tc),(tf),"" # tf "",0,(s),(e))
+
+/* Signal version of loop test.
+ FIXME: add a test case; this is untested as part of Check's tests.
+ */
+#define tcase_add_loop_test_raise_signal(tc,tf,signal,s,e) \
+ _tcase_add_test((tc),(tf),"" # tf "",(signal),(s),(e))
+
+/* Add a test function to a test case
+ (function version -- use this when the macro won't work
+*/
+void _tcase_add_test (TCase *tc, TFun tf, const char *fname, int signal, int start, int end);
+
+/* Add unchecked fixture setup/teardown functions to a test case
+
+ If unchecked fixture functions are run at the start and end of the
+ test case, and not before and after unit tests. Note that unchecked
+ setup/teardown functions are not run in a separate address space,
+ like test functions, and so must not exit or signal (e.g.,
+ segfault)
+
+ Also, when run in CK_NOFORK mode, unchecked fixture functions may
+ lead to different unit test behavior IF unit tests change data
+ setup by the fixture functions.
+*/
+void tcase_add_unchecked_fixture (TCase *tc, SFun setup, SFun teardown);
+
+/* Add fixture setup/teardown functions to a test case
+
+ Checked fixture functions are run before and after unit
+ tests. Unlike unchecked fixture functions, checked fixture
+ functions are run in the same separate address space as the test
+ program, and thus the test function will survive signals or
+ unexpected exits in the fixture function. Also, IF the setup
+ function is idempotent, unit test behavior will be the same in
+ CK_FORK and CK_NOFORK modes.
+
+ However, since fixture functions are run before and after each unit
+ test, they should not be expensive code.
+
+*/
+void tcase_add_checked_fixture (TCase *tc, SFun setup, SFun teardown);
+
+/* Set the timeout for all tests in a test case. A test that lasts longer
+ than the timeout (in seconds) will be killed and thus fail with an error.
+ The timeout can also be set globaly with the environment variable
+ CK_DEFAULT_TIMEOUT, the specific setting always takes precedence.
+*/
+void tcase_set_timeout (TCase *tc, int timeout);
+
+/* Internal function to mark the start of a test function */
+void tcase_fn_start (const char *fname, const char *file, int line);
+
+/* Start a unit test with START_TEST(unit_name), end with END_TEST
+ One must use braces within a START_/END_ pair to declare new variables
+*/
+#define START_TEST(__testname)\
+static void __testname (int _i __attribute__((unused)))\
+{\
+ tcase_fn_start (""# __testname, __FILE__, __LINE__);
+
+/* End a unit test */
+#define END_TEST }
+
+/* Fail the test case unless expr is true */
+/* The space before the comma sign before ## is essential to be compatible
+ with gcc 2.95.3 and earlier.
+*/
+#define fail_unless(expr, ...)\
+ _fail_unless(expr, __FILE__, __LINE__,\
+ "Assertion '"#expr"' failed" , ## __VA_ARGS__, NULL)
+
+/* Fail the test case if expr is true */
+/* The space before the comma sign before ## is essential to be compatible
+ with gcc 2.95.3 and earlier.
+*/
+
+/* FIXME: these macros may conflict with C89 if expr is
+ FIXME: strcmp (str1, str2) due to excessive string length. */
+#define fail_if(expr, ...)\
+ _fail_unless(!(expr), __FILE__, __LINE__,\
+ "Failure '"#expr"' occured" , ## __VA_ARGS__, NULL)
+
+/* Always fail */
+#define fail(...) _fail_unless(0, __FILE__, __LINE__, "Failed" , ## __VA_ARGS__, NULL)
+
+/* Non macro version of #fail_unless, with more complicated interface */
+void _fail_unless (int result, const char *file,
+ int line, const char *expr, ...);
+
+/* Mark the last point reached in a unit test
+ (useful for tracking down where a segfault, etc. occurs)
+*/
+#define mark_point() _mark_point(__FILE__,__LINE__)
+
+/* Non macro version of #mark_point */
+void _mark_point (const char *file, int line);
+
+/* Result of a test */
+enum test_result {
+ CK_PASS, /* Test passed*/
+ CK_FAILURE, /* Test completed but failed */
+ CK_ERROR /* Test failed to complete
+ (unexpected signal or non-zero early exit) */
+};
+
+/* Specifies the how much output an SRunner should produce */
+enum print_output {
+ CK_SILENT, /* No output */
+ CK_MINIMAL, /* Only summary output */
+ CK_NORMAL, /* All failed tests */
+ CK_VERBOSE, /* All tests */
+ CK_ENV, /* Look at environment var */
+ CK_LAST
+};
+
+/* Holds state for a running of a test suite */
+typedef struct SRunner SRunner;
+
+/* Opaque type for a test failure */
+typedef struct TestResult TestResult;
+
+/* accessors for tr fields */
+ enum ck_result_ctx {
+ CK_CTX_SETUP,
+ CK_CTX_TEST,
+ CK_CTX_TEARDOWN
+};
+
+/* Type of result */
+int tr_rtype (TestResult *tr);
+/* Context in which the result occurred */
+enum ck_result_ctx tr_ctx (TestResult *tr);
+/* Failure message */
+const char *tr_msg (TestResult *tr);
+/* Line number at which failure occured */
+int tr_lno (TestResult *tr);
+/* File name at which failure occured */
+const char *tr_lfile (TestResult *tr);
+/* Test case in which unit test was run */
+const char *tr_tcname (TestResult *tr);
+
+/* Creates an SRunner for the given suite */
+SRunner *srunner_create (Suite *s);
+
+/* Adds a Suite to an SRunner */
+void srunner_add_suite (SRunner *sr, Suite *s);
+
+/* Frees an SRunner, all suites added to it and all contained test cases */
+void srunner_free (SRunner *sr);
+
+
+/* Test running */
+
+/* Runs an SRunner, printing results as specified (see enum print_output) */
+void srunner_run_all (SRunner *sr, enum print_output print_mode);
+
+
+/* Next functions are valid only after the suite has been
+ completely run, of course */
+
+/* Number of failed tests in a run suite. Includes failures + errors */
+int srunner_ntests_failed (SRunner *sr);
+
+/* Total number of tests run in a run suite */
+int srunner_ntests_run (SRunner *sr);
+
+/* Return an array of results for all failures
+
+ Number of failures is equal to srunner_nfailed_tests. Memory for
+ the array is malloc'ed and must be freed, but individual TestResults
+ must not
+*/
+TestResult **srunner_failures (SRunner *sr);
+
+/* Return an array of results for all run tests
+
+ Number of results is equal to srunner_ntests_run, and excludes
+ failures due to setup function failure.
+
+ Memory is malloc'ed and must be freed, but individual TestResults
+ must not
+*/
+TestResult **srunner_results (SRunner *sr);
+
+
+/* Printing */
+
+/* Print the results contained in an SRunner */
+void srunner_print (SRunner *sr, enum print_output print_mode);
+
+
+/* Set a log file to which to write during test running.
+
+ Log file setting is an initialize only operation -- it should be
+ done immediatly after SRunner creation, and the log file can't be
+ changed after being set.
+*/
+void srunner_set_log (SRunner *sr, const char *fname);
+
+/* Does the SRunner have a log file? */
+int srunner_has_log (SRunner *sr);
+
+/* Return the name of the log file, or NULL if none */
+const char *srunner_log_fname (SRunner *sr);
+
+/* Set a xml file to which to write during test running.
+
+ XML file setting is an initialize only operation -- it should be
+ done immediatly after SRunner creation, and the XML file can't be
+ changed after being set.
+*/
+void srunner_set_xml (SRunner *sr, const char *fname);
+
+/* Does the SRunner have an XML log file? */
+int srunner_has_xml (SRunner *sr);
+
+/* Return the name of the XML file, or NULL if none */
+const char *srunner_xml_fname (SRunner *sr);
+
+
+/* Control forking */
+enum fork_status {
+ CK_FORK,
+ CK_NOFORK
+};
+
+/* Get the current fork status */
+enum fork_status srunner_fork_status (SRunner *sr);
+
+/* Set the current fork status */
+void srunner_set_fork_status (SRunner *sr, enum fork_status fstat);
+
+/* Fork in a test and make sure messaging and tests work. */
+pid_t check_fork(void);
+
+/* Wait for the pid and exit. If pid is zero, just exit. */
+void check_waitpid_and_exit(pid_t pid);
+
+#ifdef __cplusplus
+#define CK_CPPEND }
+CK_CPPEND
+#endif
+
+#endif /* CHECK_H */
Index: util/testsuite/unittests/check_clog2.c
===================================================================
--- util/testsuite/unittests/check_clog2.c (Revision 0)
+++ util/testsuite/unittests/check_clog2.c (Revision 0)
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lib.h>
+#include "check.h"
+
+START_TEST(test_log2)
+{
+ fail_unless(log2(0) == 0, NULL);
+ fail_unless(log2(1) == 0, NULL);
+ fail_unless(log2(4) == 2, NULL);
+ fail_unless(log2(8) == 3, NULL);
+ fail_unless(log2(1024) == 10, NULL);
+ fail_unless(log2(1024 * 1024) == 20, NULL);
+}
+END_TEST
+
+TCase *test_clog2_create_tests(void)
+{
+ TCase *tc;
+ tc = tcase_create("clog2");
+ tcase_add_test(tc, test_log2);
+ return tc;
+}
Index: util/testsuite/unittests/check_string.c
===================================================================
--- util/testsuite/unittests/check_string.c (Revision 0)
+++ util/testsuite/unittests/check_string.c (Revision 0)
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include "check.h"
+
+START_TEST(test_strlen)
+{
+ fail_unless(strlen("Hello") == 5, NULL);
+ fail_unless(strlen("Hello\nWorld!") == 12, NULL);
+ fail_unless(strlen("") == 0, NULL);
+ fail_unless(strlen("\n") == 1, NULL);
+ fail_unless(strlen("\r") == 1, NULL);
+ fail_unless(strlen("\r\n") == 2, NULL);
+ fail_unless(strlen("\0") == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_strnlen)
+{
+ fail_unless(strnlen("Hello", 10) == 5, NULL);
+ fail_unless(strnlen("Hello", 5) == 5, NULL);
+ fail_unless(strnlen("Hello", 3) == 3, NULL);
+ fail_unless(strnlen("Hello", 0) == 0, NULL);
+ fail_unless(strnlen("Hello\nWorld!", 7) == 7, NULL);
+ fail_unless(strnlen("", 10) == 0, NULL);
+ fail_unless(strnlen("\n", 10) == 1, NULL);
+ fail_unless(strnlen("\r", 10) == 1, NULL);
+ fail_unless(strnlen("\r\n", 10) == 2, NULL);
+ fail_unless(strnlen("\0", 0) == 0, NULL);
+ fail_unless(strnlen("\0", 10) == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_strcmp)
+{
+ fail_unless(strcmp("Hello", "Hello") == 0, NULL);
+ fail_unless(strcmp("123", "124") < 0, NULL);
+ fail_unless(strcmp("124", "123") > 0, NULL);
+ fail_unless(strcmp("abcd", "abc") > 0, NULL);
+ fail_unless(strcmp("abc", "abcd") < 0, NULL);
+ fail_unless(strcmp("", "") == 0, NULL);
+ fail_unless(strcmp("\0", "") == 0, NULL);
+ fail_unless(strcmp("", "\0") == 0, NULL);
+ fail_unless(strcmp("\0", "\0") == 0, NULL);
+}
+END_TEST
+
+TCase *test_string_create_tests(void)
+{
+ TCase *tc;
+ tc = tcase_create("string");
+ tcase_add_test(tc, test_strlen);
+ tcase_add_test(tc, test_strnlen);
+ tcase_add_test(tc, test_strcmp);
+ return tc;
+}
Index: util/testsuite/unittests/runtests.c
===================================================================
--- util/testsuite/unittests/runtests.c (Revision 0)
+++ util/testsuite/unittests/runtests.c (Revision 0)
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "runtests.h"
+#include "check.h"
+
+int main(void)
+{
+ SRunner *runner;
+ Suite *lbsuite;
+ TCase *tc;
+ int failed;
+
+ lbsuite = suite_create("LinuxBIOS");
+
+ tc = test_clog2_create_tests();
+ suite_add_tcase(lbsuite, tc);
+
+ tc = test_string_create_tests();
+ suite_add_tcase(lbsuite, tc);
+
+ tc = test_device_util_create_tests();
+ suite_add_tcase(lbsuite, tc);
+
+ runner = srunner_create(lbsuite);
+ srunner_run_all(runner, CK_VERBOSE);
+ failed = srunner_ntests_failed(runner);
+
+ srunner_free(runner);
+
+ /* Return 0 upon success, -1 if some test cases failed. */
+ return (failed == 0) ? 0 : -1;
+}
Index: util/testsuite/unittests/check_device_util.c
===================================================================
--- util/testsuite/unittests/check_device_util.c (Revision 0)
+++ util/testsuite/unittests/check_device_util.c (Revision 0)
@@ -0,0 +1,148 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include <string.h> // FIXME! The unit tests rely on _our_ strcmp() to work!
+#include "check.h"
+
+/* Stubs */
+// TODO: Better stubs?
+struct device dev_root;
+struct device *all_devices = &dev_root;
+struct constructor *all_constructors[] = { NULL };
+struct device *alloc_dev(struct bus *parent, struct device_path *path,
+ struct device_id *devid) { return NULL; }
+void printk(int msg_level, const char *fmt, ...) {}
+void die(void) {}
+void post_code(void) {}
+
+/* Function prototypes */
+extern resource_t align_up(resource_t val, unsigned long gran);
+extern resource_t align_down(resource_t val, unsigned long gran);
+
+START_TEST(test_id_eq_pci)
+{
+ struct device_id id1 = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0x2000,.device = 0x4000}}};
+ struct device_id id2 = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0x2000,.device = 0x4000}}};
+ struct device_id id3 = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0x9999,.device = 0x4000}}};
+ struct device_id id4 = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0x2000,.device = 0x9999}}};
+ struct device_id id_i2c = {.type = DEVICE_ID_I2C,
+ .u = {.pci = {.vendor = 0x2000,.device = 0x4000}}};
+ /* This id_i2c is deliberately a "broken" PCI device! */
+ struct device_id id_zero = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0x0000,.device = 0x0000}}};
+ struct device_id id_ffff = {.type = DEVICE_ID_PCI,
+ .u = {.pci = {.vendor = 0xffff,.device = 0xffff}}};
+ struct device_id id_root = {.type = DEVICE_ID_ROOT};
+
+ fail_unless(id_eq(&id_root, &id1) == 0, NULL);
+ fail_unless(id_eq(&id1, &id_root) == 0, NULL);
+ fail_unless(id_eq(&id1, &id2) == 1, NULL);
+ fail_unless(id_eq(&id1, &id3) == 0, NULL);
+ fail_unless(id_eq(&id1, &id4) == 0, NULL);
+ fail_unless(id_eq(&id_zero, &id1) == 0, NULL);
+ fail_unless(id_eq(&id1, &id_zero) == 0, NULL);
+ fail_unless(id_eq(&id_zero, &id_zero) == 1, NULL);
+ fail_unless(id_eq(&id_ffff, &id1) == 0, NULL);
+ fail_unless(id_eq(&id1, &id_ffff) == 0, NULL);
+ fail_unless(id_eq(&id_ffff, &id_ffff) == 1, NULL);
+ // fail_unless(id_eq(NULL, NULL) == 1, NULL); // FIXME: Bug?
+
+ /* Comparing a PCI ID to an I2C ID should fail. */
+ fail_unless(id_eq(&id1, &id_i2c) == 0, NULL);
+ fail_unless(id_eq(&id_i2c, &id1) == 0, NULL);
+ fail_unless(id_eq(&id_zero, &id_i2c) == 0, NULL);
+ fail_unless(id_eq(&id_i2c, &id_zero) == 0, NULL);
+ fail_unless(id_eq(&id_ffff, &id_i2c) == 0, NULL);
+ fail_unless(id_eq(&id_i2c, &id_ffff) == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_dev_path)
+{
+ struct device dev_root = {.path = {.type = DEVICE_PATH_ROOT}};
+ struct device dev_pnp = {.path = {.type = DEVICE_PATH_PNP,
+ .u = {.pnp = {.port = 0x1111, .device = 0x2222}}}};
+
+ fail_unless(strcmp(dev_path(NULL), "<null>") == 0, NULL);
+ fail_unless(strcmp(dev_path(&dev_root), "Root Device") == 0, NULL);
+ fail_unless(strcmp(dev_path(&dev_pnp), "PNP: 1111.2222") == 0, NULL);
+ // ...
+}
+END_TEST
+
+START_TEST(test_align_up)
+{
+ fail_unless(align_up(0, 0) == 0, NULL);
+ fail_unless(align_up(0, 1) == 0, NULL);
+ fail_unless(align_up(0, 2) == 0, NULL);
+ fail_unless(align_up(0, 19) == 0, NULL);
+
+ fail_unless(align_up(1, 0) == 1, NULL);
+ fail_unless(align_up(1, 1) == 2, NULL);
+ fail_unless(align_up(1, 2) == 4, NULL);
+ fail_unless(align_up(1, 3) == 8, NULL);
+
+ fail_unless(align_up(2, 0) == 2, NULL); // ...
+ fail_unless(align_up(2, 1) == 2, NULL);
+ fail_unless(align_up(2, 2) == 4, NULL);
+ fail_unless(align_up(2, 3) == 8, NULL);
+
+ fail_unless(align_up(0, 5) == 0, NULL);
+ fail_unless(align_up(1, 5) == 32, NULL);
+ fail_unless(align_up(2, 5) == 32, NULL);
+ fail_unless(align_up(3, 5) == 32, NULL);
+ fail_unless(align_up(18, 5) == 32, NULL);
+ fail_unless(align_up(31, 5) == 32, NULL);
+ fail_unless(align_up(32, 5) == 32, NULL);
+ fail_unless(align_up(33, 5) == 64, NULL);
+ // ...
+}
+END_TEST
+
+START_TEST(test_align_down)
+{
+ fail_unless(align_down(0, 5) == 0, NULL);
+
+ fail_unless(align_down(31, 5) == 0, NULL);
+ fail_unless(align_down(32, 5) == 32, NULL);
+ fail_unless(align_down(33, 5) == 32, NULL);
+ fail_unless(align_down(63, 5) == 32, NULL);
+ fail_unless(align_down(64, 5) == 64, NULL);
+ fail_unless(align_down(65, 5) == 64, NULL);
+ fail_unless(align_down(99, 5) == 96, NULL);
+ // ...
+}
+END_TEST
+
+TCase *test_device_util_create_tests(void)
+{
+ TCase *tc;
+ tc = tcase_create("device_util");
+ tcase_add_test(tc, test_id_eq_pci);
+ tcase_add_test(tc, test_dev_path);
+ tcase_add_test(tc, test_align_up);
+ tcase_add_test(tc, test_align_down);
+ return tc;
+}
Index: util/testsuite/unittests/Makefile
===================================================================
--- util/testsuite/unittests/Makefile (Revision 0)
+++ util/testsuite/unittests/Makefile (Revision 0)
@@ -0,0 +1,83 @@
+##
+## This file is part of the LinuxBIOS project.
+##
+## Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+##
+## 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; either version 2 of the License, or
+## (at your option) any later version.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+src := $(shell pwd)/../../..
+obj := $(shell pwd)/../../../build
+export src obj
+
+# If $(Q) is not set (e.g. because make was invoked in
+# util/testsuite/unittests and not at the top-level), we default to
+# silent mode.
+ifeq ($(Q),)
+V := 0;
+endif
+
+# Make is silent per default, but 'make V=1' will show all compiler calls.
+ifneq ($(V),1)
+Q := @
+endif
+
+# FIXME?
+ARCH := x86
+
+HOSTCC := gcc
+
+HOSTCFLAGS := -Wall -g -std=c99 -Wundef -Wstrict-prototypes -Wno-trigraphs \
+ -fomit-frame-pointer -Werror-implicit-function-declaration \
+ -Wno-unused -Wno-sign-compare -fno-builtin \
+ -Wstrict-aliasing -fno-common -ffreestanding -pedantic \
+ -I$(src) -Iinclude -I$(src)/include -nostdinc \
+ -I$(src)/include/arch/$(ARCH) \
+ -fprofile-arcs -ftest-coverage \
+ -DLINUXBIOS_UNITTEST
+
+# TODO: Check if gcov is available, and only use it if that's the case.
+LDFLAGS := -L/usr/local/lib -lcheck -lgcov
+
+OBJS := check_clog2.o clog2.o \
+ check_string.o \
+ check_device_util.o device_util.o \
+ runtests.o
+
+SRCOBJS := $(src)/lib/clog2.o \
+ $(src)/device/device_util.o
+
+all: runtests
+
+check: runtests
+ $(Q)./runtests
+
+runtests: $(SRCOBJS) $(OBJS)
+ $(Q)printf " LD runtests\n"
+ $(Q)$(HOSTCC) $(HOSTCFLAGS) -o $@ $(OBJS) $(LDFLAGS)
+
+.c.o:
+ $(Q)printf " HOSTCC $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(HOSTCC) $(HOSTCFLAGS) -c $<
+
+clean:
+ $(Q)printf " CLEAN $(subst $(realpath $(src))/,,$(realpath $(shell pwd)))\n"
+ $(Q)rm -f core $(OBJS) *.gcda *.gcno
+
+distclean: clean
+ $(Q)rm -f runtests
+
+.PHONY: clean distclean
+
Index: util/testsuite/unittests/runtests.h
===================================================================
--- util/testsuite/unittests/runtests.h (Revision 0)
+++ util/testsuite/unittests/runtests.h (Revision 0)
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <[EMAIL PROTECTED]>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RUNTESTS_H
+#define RUNTESTS_H
+
+#include "check.h"
+
+TCase *test_clog2_create_tests(void);
+TCase *test_string_create_tests(void);
+TCase *test_device_util_create_tests(void);
+
+#endif
Index: util/testsuite/unittests/README
===================================================================
--- util/testsuite/unittests/README (Revision 0)
+++ util/testsuite/unittests/README (Revision 0)
@@ -0,0 +1,50 @@
+-------------------------------------------------------------------------------
+README
+-------------------------------------------------------------------------------
+
+This is a testsuite of unit tests for the LinuxBIOSv3 code.
+
+
+Requirements
+------------
+
+ - Check, a unit testing framework for C, needs to be installed.
+ You can download it from http://check.sourceforge.net/.
+ On Debian systems 'apt-get install check' is sufficient.
+
+
+Running all tests
+-----------------
+
+In the LinuxBIOS top-level directory type:
+
+ $ make check
+
+This will run the complete testsuite of unit tests. If all tests passed, the
+result will look like this:
+
+ 100%: Checks: 8, Failures: 0, Errors: 0
+
+Alternatively, you can also run the testsuite from util/testsuite/unittests
+directly by typing:
+
+ $ cd util/testsuite/unittests
+ $ make check
+
+
+Code Coverage
+-------------
+
+In order to estimate the amount of code which is tested ("covered") by the
+current unit tests you can use any coverage tools which can process the
+files *.gcda and *.gcno, which are automatically generated when running the
+testsuite.
+
+One such tool (ggcov) is available from http://ggcov.sourceforge.net/.
+On Debian system you can install ggcov via 'apt-get install ggcov'.
+
+To start the ggcov GUI type:
+
+ $ cd util/testsuite/unittests
+ $ ggcov
+
Index: HACKING
===================================================================
--- HACKING (Revision 358)
+++ HACKING (Arbeitskopie)
@@ -102,3 +102,7 @@
Source: Linux kernel, lib/vsprintf.c
Current version we use: ?
+* util/testsuite/unittests/check.h: LGPLv2.1 or later
+ Source: http://check.sourceforge.net/ (src/check.h)
+ Current version we use: 0.9.5
+
Index: Makefile
===================================================================
--- Makefile (Revision 358)
+++ Makefile (Arbeitskopie)
@@ -124,6 +124,9 @@
doxygen:
$(Q)$(DOXYGEN) util/doxygen/Doxyfile.LinuxBIOS
+check:
+ $(Q)Q=$(Q) $(MAKE) -C util/testsuite/unittests check
+
prepare:
$(Q)mkdir -p $(obj)
@@ -152,6 +155,7 @@
$(Q)rm -rf $(DOXYGEN_OUTPUT_DIR)
$(Q)printf " CLEAN doc/design/newboot.pdf\n"
$(Q)rm -f doc/design/newboot.pdf
+ $(Q)Q=$(Q) $(MAKE) -C util/testsuite/unittests clean
distclean: clean
$(Q)printf " CLEAN .kconfig.d .config .tmpconfig.h .config.old .xcompile\n"
@@ -161,5 +165,5 @@
$(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n"
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
-.PHONY: doc doxygen depends prepare prepare2 clean distclean
+.PHONY: doc doxygen depends check prepare prepare2 clean distclean
Index: device/device_util.c
===================================================================
--- device/device_util.c (Revision 358)
+++ device/device_util.c (Arbeitskopie)
@@ -496,7 +496,7 @@
* @param gran Granularity we are aligning the number to.
* @returns The aligned value.
*/
-static resource_t align_up(resource_t val, unsigned long gran)
+resource_t align_up(resource_t val, unsigned long gran)
{
resource_t mask;
mask = (1ULL << gran) - 1ULL;
@@ -512,7 +512,7 @@
* @param gran Granularity we are aligning the number to.
* @returns The aligned value.
*/
-static resource_t align_down(resource_t val, unsigned long gran)
+resource_t align_down(resource_t val, unsigned long gran)
{
resource_t mask;
mask = (1ULL << gran) - 1ULL;
signature.asc
Description: Digital signature
-- linuxbios mailing list [email protected] http://www.linuxbios.org/mailman/listinfo/linuxbios
