/**************************************************************************** * * Copyright (c) 2001 Novell, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * 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, contact Novell, Inc. * * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * ****************************************************************************/ #include /** \defgroup BongoCheck The Check Framework in the Bongo Project * \brief Provides unit testing for C code in the Bongo Project. * * The Bongo project uses the Check framework for testing C * code. For more information on Check consult its project website at * http://check.sourceforge.net/ . Many parts of the Check system are * wrapped up in macros found in the bongocheck.h header file. Specific * parts of the Check framework are to be used directly, and are listed * in the section \ref TheCheckFrameWork. * * Be sure to read the documentation for the \ref TheCheckFrameWork and * \ref CheckStyleAndMake modules before attempting to write unit tests. * * Here is an example of a basic test souce code file to get you started. * \code * #include * #ifdef BONGO_HAVE_CHECK * START_TEST(test1) * { * fail_unless(1==1); * fail_if(1 == 2); * if ( 1 == 2 ) { * fail("1 shouldn't equal 2"); * } * } * END_TEST * // pound-include other tests of your own here. * START_CHECK_SUITE_SETUP("My test suite description") * CREATE_CHECK_CASE (tc_core , "Core" ); * CHECK_SUITE_ADD_CASE(top_suite, tc_core ); * CHECK_CASE_ADD_TEST (tc_core , test1 ); * // register included tests here. * END_CHECK_SUITE_SETUP * #else * SKIP_CHECK_TESTS * #endif * \endcode * * @{ */ /** \file bongocheck.h * \brief Macros that help keep the use of the Check framework consistent. * * Even if you are adept at Check, please use these macros when * writing programmer tests for your code. If you want to access * a piece of Check's functionality that is not currently available * through these macros or listed in \link TheCheckFrameWork The Check * Framework\endlink, then please propose additional macros rather than * using Check directly. * */ #include #include #include #include /* Just for documentation */ #ifdef RUNNING_DOXYGEN /** Conditionally set by Autoconf in config.h. * The \p config.h file contains pound-defines that control the behavior * of the compilation process. Among them is the \c BONGO_HAVE_CHECK symbol, * which will be defined if and only if Check is installed and located * on the build system. * * When you use the Check framework then be sure to wrap it inside a * \code * #ifdef BONGO_HAVE_CHECK * // use Check here * #else * SKIP_CHECK_TESTS * #endif * \endcode * block. */ #define BONGO_HAVE_CHECK /** Set this symbol before including \c bongocheck.h in order to force tests * to return successfully. By default, the test program returns a failure * code if any of the tests fail. Defining the FORCE_CHECK_SUCCESS * symbol causes the test program to always return success. This prevents * a "make check" from stopping on test failures. * * The logging feature is not affected by this option. * */ #define FORCE_CHECK_SUCCESS #endif #ifdef _BONGO_BONGO_HAVE_CHECK #include #endif /** Creates a suite that can be used in a suite runner. * \hideinitializer * \param id regular C identifier. * \param description a string in double quotes. * * The suite is given the id \a id, and \a description is used when * printing a summary of how the test went. Programmers will normally * use \c top_suite provided by the #START_CHECK_SUITE_SETUP * macro. * */ #define CREATE_CHECK_SUITE( id, description ) \ Suite *id = suite_create( description ) /** Creates a test-case that can be added to a suite * (#CHECK_SUITE_ADD_CASE) and have tests added to it * (#CHECK_CASE_ADD_TEST). * \hideinitializer * \param id regular C identifier. * \param description a string in double quotes. * * It is given id \a id, and \a description is used in * reports to describe it. * */ #define CREATE_CHECK_CASE( id, description ) \ TCase *id = tcase_create( description ) /** Adds a test-case to a suite. * \hideinitializer * \param sid regular C identifier associated with a suite. * \param cid regular C identifier associated with a test-case. * * The test-case with id \a cid is added to the suite with * id \a sid. Normally, you will add all test-cases to the \c top_suite * which is automatically created by #START_CHECK_SUITE_SETUP. * */ #define CHECK_SUITE_ADD_CASE( sid, cid ) \ suite_add_tcase( sid , cid ) /** Adds a test to a test-case. * \hideinitializer * \param cid regular C identifier associated with a test-case. * \param tid regular C identifier associated with a test. * * The test with id \a tid is added to the test-case with * id \a cid. Tests must be previously defined in a \code * START_TEST () { * // ... * } END_TEST \endcode block. * Test-cases also must be previously defined (#CREATE_CHECK_CASE). * * Group similar tests into test-cases. Add all test-cases * to the \c top_suite. * */ #define CHECK_CASE_ADD_TEST( cid, tid ) \ tcase_add_test( cid, tid ) /** Creates the \c top_suite and opens the main function. * \hideinitializer * \param description a string in double quotes. * * \a description is used to describe the top suite in the results. * */ #define START_CHECK_SUITE_SETUP(description) \ int main (void) { \ int nf; \ CREATE_CHECK_SUITE(top_suite, description); /* Just for documentation */ #ifdef RUNNING_DOXYGEN /** \brief (For framework maintenance) Creates the proper exit code. * \param x number of tests failed. * * It may be desireable to force the "make check" target to return * success so that more tests can be run. In this case define the * #FORCE_CHECK_SUCCESS symbol. * * \attention This macro is only used in this header file. It is not * part of the public interface. * \hideinitializer * */ #define BONGO_CHECK_EXIT(x) #else /* executed when not running doxygen */ #ifdef FORCE_CHECK_SUCCESS #define BONGO_CHECK_EXIT(x) \ return EXIT_SUCCESS #else #define BONGO_CHECK_EXIT(x) \ return (x == 0) ? EXIT_SUCCESS : EXIT_FAILURE #endif /* */ #endif /** Finishes up the main function. * \hideinitializer * Call this macro after registering all of your tests and test-cases. It * runs the tests, outputs an xml log file, and cleans up before exiting. * */ #define END_CHECK_SUITE_SETUP \ SRunner *sr = srunner_create(top_suite); \ srunner_set_xml ( sr, "checklog.xml" ); \ srunner_run_all ( sr, CK_ENV); \ nf = srunner_ntests_failed(sr); \ srunner_free(sr); \ BONGO_CHECK_EXIT(nf); \ } /** Creates a simple program that informs the user no tests were run. * Should be used in the else block of \c #ifdef \c BONGO_HAVE_CHECK. * \hideinitializer * */ #define SKIP_CHECK_TESTS \ int main (void) { \ printf("#################################\n"); \ printf("Check not installed, no tests run\n"); \ printf("#################################\n"); \ return EXIT_SUCCESS; \ } /** \ingroup BongoCheck * \defgroup TheCheckFrameWork The Check Framework * \brief Listing of used bits of the Check framework (a consumed, * external project). * * The Bongo project uses the Check framework for programmer tests on C * code; however, developers for the project only access certain parts * of the Check framework directly. Other parts of the infrastructure * are supposed to be accessed through special macros implemented in * the bongocheck.h file. * * This section does not aim to document Check in full. Instead, it is a * quick reference for the pieces of Check that are meant to be accessed * directly in the Bongo project. For complete documentation of Check * itself refer to the site homepage at http://check.sourceforge.net/ . * * As you learn more about Check you may find pieces of it that you want * to use that are not listed here, nor are they accessbile through our * special macros. In that case, please discuss needed functionality * with the Bongo QA team. They will either add it to this list of * directly accessible bits, or write a macro for it. * * - Assertion-like functions: * - \c fail_unless( expr, msg ) * - \c fail_if( expr, msg) * - \c fail( msg ) * - Boilerplate Macros * - \c START_TEST( testname ) and \c END_TEST * * Of course, you are also free to set any environment variables that * Check honors, such as: * * - \c CK_VERBOSITY * - \c CK_FORK --- good for avoiding fork in the debugger * * Be sure to look at the example code in \ref BongoCheck to get started. */ /** \ingroup BongoCheck * \defgroup CheckStyleAndMake Style and Make * \brief Style guidlines, and instructions for Makefile.am relative to * using Check for unit testing. * * When writing unit tests please follow these style guidlines. * Please direct any suggestions concerning these style guidlines to * the Bongo QA team. * * \par Test all functionality * Try to follow the standard "If it isn't tested then it doesn't * exist." Writing good tests should take at least as long as writing * the code itself. * * \par Place tests in their own directory * If you are testing code in the \p foo directory, then place the tests * in the \c foo/tests directory. * * \par Follow the template for managing the suite * Have a file in your \c tests directory named \c checktest.c . In that file use the following template: * \code * #include * #ifdef BONGO_HAVE_CHECK * START_TEST(test1) * { * // TODO * // fail_unless(1==1); * // fail_if(1 == 2); * } * END_TEST * // TODO Write your tests above, and/or * // pound-include other tests of your own here. * START_CHECK_SUITE_SETUP("TODO Describe the unit you are testing") * CREATE_CHECK_CASE (tc_core , "Core" ); * CHECK_SUITE_ADD_CASE(top_suite, tc_core ); * CHECK_CASE_ADD_TEST (tc_core , test1 ); * // TODO register additional tests here * END_CHECK_SUITE_SETUP * #else * SKIP_CHECK_TESTS * #endif * \endcode * Use as many test cases as you want. Be sure to register each test with * exactly one test case, then register all test cases with the top_suite. * * \par Name your test files appropriately * If you are testing code in files \p big.c, \p bigger.c, and \p * biggest.c, then please put your corresponding test cases in files \p * big_test.c, \p bigger_test.c, and \p biggest_test.c, respectively. * * Remember to pound-include your test source code files in \p * checktest.c, and register the tests appropriately. * * \par Use the template Makefile.am * In your \c tests directory, create the file \c Makefile.am with the following contents: * \code * TESTS = checktest * check_PROGRAMS = $(TESTS) * checktest_SOURCES = checktest.c * checktest_LDADD = @CHECK_LIBS@ * checktest_CFLAGS = @CHECK_CFLAGS@ * \endcode * * \par Modify the parent's Makefile.am * Make sure that the parent directory (\c foo in the example above) * has a line in its Makefile.am similar to the following: * \code * SUBDIRS=tests * \endcode * If not, add it at the top. * * \par Add your tests directory to the top configure.in file * If the path to the code you are testing is \c bongo/src/apps/foo, * then your test code will be in directory \c bongo/src/apps/foo/tests. * You need to make sure its Makefile is in the list of makefiles * generated in \c configure.in (generally the one located in the \c * bongo directory). In this example, you would go to the end of \c * configure.in and look for the line * \code * src/apps/foo/tests/Makefile * \endcode * inside the \c AC_OUTPUT command. If the line is missing, then add it. * */ /** * @} */