blob: cb9130c8cfd3802fa0afa5575722223f4c8aeced [file] [log] [blame]
#ifndef CHECK_H
#define CHECK_H
/*
Check: a unit test framework for C
Copyright (C) 2001, Arien Malec
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Comments are in Doxygen format: see http://www.stack.nl/~dimitri/doxygen/ */
/*! \mainpage Check: a unit test framework for C
\section overview
Overview 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.
\section quickref Quick Reference
\subsection creating Creating
\par
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.
\subsection managing Managing test cases and suites
\par
Test cases are created with #tcase_create, unit tests are added
with #tcase_add_test
\par
Suites are created with #suite_create, freed with #suite_free; test
cases are added with #suite_add_tcase
\subsection running Running suites
\par
Suites are run through an SRunner, which is created with
#srunner_create, freed with #srunner_free. Additional suites can be
added to an SRunner with #srunner_add_suite.
\par
Use #srunner_run_all to run a suite and print results.
*/
/*! \file check.h */
#ifdef __cplusplus
extern "C" {
#endif
/*! Magic values */
enum {
CMAXMSG = 100 /*!< maximum length of a message, including terminating nul */
};
/*! \defgroup check_core Check Core
Core suite/test case types and functions
@{
*/
/*! \brief opaque type for a test suite */
typedef struct Suite Suite;
/*! \brief 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);
/*! Create a test suite */
Suite *suite_create (const char *name);
/*! Free a test suite
(For the moment, this also frees all contained test cases) */
void suite_free (Suite *s);
/*! Create a test case */
TCase *tcase_create (const char *name);
/*! Free a test case
(Note that as it stands, one will normally free the contaning suite) */
void tcase_free (TCase *tc);
/*! Add a test case to a suite */
void suite_add_tcase (Suite *s, TCase *tc);
/*! Add a test function to a test case
(macro version) */
#define tcase_add_test(tc,tf) tcase_add_test_(tc,tf,"" # tf "")
/*! 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);
/*!
Add fixture setup/teardown functions to a test case Note that
setup/teardown functions are not run in a separate address space, like
test functions, and so must not exit or signal (e.g., segfault)
*/
void tcase_set_fixture(TCase *tc, SFun setup, SFun teardown);
/*! Internal function to mark the start of a test function */
void tcase_fn_start (int msqid, 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 msqid__)\
{\
tcase_fn_start (msqid__,""# testname__, __FILE__, __LINE__);
/*! End a unit test */
#define END_TEST }
/*! Fail the test case unless result is true */
#define fail_unless(result,msg) \
if(fail_unless_(msqid__,result,__FILE__,__LINE__,msg)) return;
/*! Non macro version of #fail_unless, with more complicated interface */
int fail_unless_ (int msqid, int result, const char *file, int line,
const char *msg);
/*! Always fail */
#define fail(msg) fail_unless_(msqid__,0,__FILE__,__LINE__,msg)
/*! Mark the last point reached in a unit test
(useful for tracking down where a segfault, etc. occurs */
#define mark_point() mark_point_(msqid__,__FILE__,__LINE__)
/*! Non macro version of #mark_point */
void mark_point_ (int msqid, char *file, int line);
/*! @} */
/*! \defgroup check_run Suite running functions
@{
*/
/*! Result of a test */
enum test_result {
CRPASS, /*!< Test passed*/
CRFAILURE, /*!< Test completed but failed */
CRERROR /*!< Test failed to complete (signal or non-zero early exit) */
};
/*! Specifies the verbosity of srunner printing */
enum print_verbosity {
CRSILENT, /*!< No output */
CRMINIMAL, /*!< Only summary output */
CRNORMAL, /*!< All failed tests */
CRVERBOSE, /*!< All tests */
CRLAST
};
/*! 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 */
/*! Type of result */
int tr_rtype (TestResult *tr);
/*! Failure message */
char *tr_msg (TestResult *tr);
/*! Line number at which failure occured */
int tr_lno (TestResult *tr);
/*! File name at which failure occured */
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 */
void srunner_free (SRunner *sr);
/* Test running */
/*! Runs an SRunner, printing results as specified
(see enum #print_verbosity)*/
void srunner_run_all (SRunner *sr, int 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);
/*! \brief Return an array of results for all failures
Number of failures is equal to #srunner_nfailed_tests. Memory is
alloc'ed and must be freed, but individual TestResults must not */
TestResult **srunner_failures (SRunner *sr);
/*! \brief Return an array of results for all run tests
Number of failrues is equal to #srunner_ntests_run Memory is alloc'ed
and must be freed, but individual TestResults must not */
TestResult **srunner_results (SRunner *sr);
/* Printing */
/*! Print the results contained in an SRunner
\param sr SRunner for which results are printed
\param print_mode Specification of print verbosity, constrainted to
enum #print_verbosity
*/
void srunner_print (SRunner *sr, int print_mode);
/*! @} */
/*! \defgroup check_log Logging functions
@{
*/
/*! 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.
\param sr The SRunner for which to enable logging
\param fname The file name to which to write the log
*/
void srunner_set_log (SRunner *sr, char *fname);
/*! Does the SRunner have a log file?
\param sr The SRunner to test
\return True if logging, False otherwise
*/
int srunner_has_log (SRunner *sr);
/*! Return the name of the log file, or NULL if none
\param sr The SRunner to query
\return The current log file, or NULL if not logging
*/
char *srunner_log_fname (SRunner *sr);
/*! @} */
#ifdef __cplusplus
}
#endif
#endif /* CHECK_H */