diff --git a/src/include/ipxe/test.h b/src/include/ipxe/test.h new file mode 100644 index 00000000..8c361d28 --- /dev/null +++ b/src/include/ipxe/test.h @@ -0,0 +1,45 @@ +#ifndef _IPXE_TEST_H +#define _IPXE_TEST_H + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Self-test infrastructure + * + */ + +#include + +/** A self-test set */ +struct self_test { + /** Test set name */ + const char *name; + /** Run self-tests */ + void ( * exec ) ( void ); + /** Number of tests run */ + unsigned int total; + /** Number of test failures */ + unsigned int failures; + /** Number of assertion failures */ + unsigned int assertion_failures; +}; + +/** Self-test table */ +#define SELF_TESTS __table ( struct self_test, "self_tests" ) + +/** Declare a self-test */ +#define __self_test __table_entry ( SELF_TESTS, 01 ) + +extern void test_ok ( int success, const char *file, unsigned int line ); + +/** + * Report test result + * + * @v success Test succeeded + */ +#define ok( success ) do { \ + test_ok ( (success), __FILE__, __LINE__ ); \ + } while ( 0 ) + +#endif /* _IPXE_TEST_H */ diff --git a/src/tests/test.c b/src/tests/test.c new file mode 100644 index 00000000..fa9f5797 --- /dev/null +++ b/src/tests/test.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 Michael Brown . + * + * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Self-test infrastructure + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include +#include + +/** Current self-test set */ +static struct self_test *current_tests; + +/** + * Report test result + * + * @v success Test succeeded + * @v file Test code file + * @v line Test code line + */ +void test_ok ( int success, const char *file, unsigned int line ) { + + /* Sanity check */ + assert ( current_tests != NULL ); + + /* Increment test counter */ + current_tests->total++; + + /* Report failure if applicable */ + if ( ! success ) { + current_tests->failures++; + printf ( "FAILURE: \"%s\" test failed at %s line %d\n", + current_tests->name, file, line ); + } +} + +/** + * Run self-test set + * + */ +static void run_tests ( struct self_test *tests ) { + unsigned int old_assertion_failures = assertion_failures; + + /* Sanity check */ + assert ( current_tests == NULL ); + + /* Record current test set */ + current_tests = tests; + + /* Run tests */ + tests->exec(); + + /* Clear current test set */ + current_tests = NULL; + + /* Record number of assertion failures */ + tests->assertion_failures = + ( assertion_failures - old_assertion_failures ); + + /* Print test set summary */ + if ( tests->failures || tests->assertion_failures ) { + printf ( "FAILURE: \"%s\" %d of %d tests failed", + tests->name, tests->failures, tests->total ); + if ( tests->assertion_failures ) { + printf ( " with %d assertion failures", + tests->assertion_failures ); + } + printf ( "\n" ); + } else { + printf ( "OK: \"%s\" %d tests passed\n", + tests->name, tests->total ); + } +} + +/** + * Run all self-tests + * + */ +static void test_init ( void ) { + struct self_test *tests; + unsigned int failures = 0; + unsigned int assertions = 0; + unsigned int total = 0; + + /* Run all compiled-in self-tests */ + printf ( "Starting self-tests\n" ); + for_each_table_entry ( tests, SELF_TESTS ) + run_tests ( tests ); + + /* Print overall summary */ + for_each_table_entry ( tests, SELF_TESTS ) { + total += tests->total; + failures += tests->failures; + assertions += tests->assertion_failures; + } + if ( failures || assertions ) { + printf ( "FAILURE: %d of %d tests failed", + failures, total ); + if ( assertions ) { + printf ( " with %d assertion failures", assertions ); + } + printf ( "\n" ); + } else { + printf ( "OK: all %d tests passed\n", total ); + } + + /* Lock system */ + while ( 1 ) {} +} + +/** Self-test initialisation function */ +struct init_fn test_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = test_init, +};