Home | History | Annotate | Download | only in doc
      1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
      2 <html><head>
      3 <title>Cmockery</title>
      4 </head>
      5 <body>
      6 <h1>Cmockery Unit Testing Framework</h1>
      7 <p>Cmockery is a lightweight library that is used to author C unit tests.</p>
      8 
      9 <ul>Contents
     10   <li><a href="#Motivation">Motivation</a></li>
     11   <li><a href="#Overview">Overview</a></li>
     12   <li><a href="#TestExecution">Test Execution</a>
     13   <li><a href="#ExceptionHandling">Exception Handling</a></li>
     14   <li><a href="#FailureConditions">Failure Conditions</a></li>
     15   <li><a href="#Assertions">Assertions</a></li>
     16   <ul>
     17     <li><a href="#AssertMacros">Assert Macros</a></li>
     18   </ul>
     19   <li><a href="#MemoryAllocation">Dynamic Memory Allocation</a></li>
     20   <li><a href="#MockFunctions">Mock functions</a></li>
     21   <ul>
     22     <li><a href="#MockFunctionsReturnValues">Return Values</a></li>
     23     <li><a href="#MockFunctionsCheckingParameters">Checking Parameters</a></li>
     24   </ul>
     25   <li><a href="#TestState">Test State</a></li>
     26   <li><a href="#Example">Example</a></li>
     27 </ul>
     28 
     29 <a name="Motivation"><h2>Motivation</h2></a>
     30 <p>There are a variety of C unit testing frameworks available however many of
     31 them are fairly complex and require the latest compiler technology.  Some
     32 development requires the use of old compilers which makes it difficult to
     33 use some unit testing frameworks.  In addition many unit testing frameworks
     34 assume the code being tested is an application or module that is targeted to
     35 the same platform that will ultimately execute the test.  Because of this
     36 assumption many frameworks require the inclusion of standard C library headers
     37 in the code module being tested which may collide with the custom or
     38 incomplete implementation of the C library utilized by the code under test.</p>
     39 
     40 <p>Cmockery only requires a test application is linked with the standard C
     41 library which minimizes conflicts with standard C library headers.  Also,
     42 Cmockery tries avoid the use of some of the newer features of C compilers.</p>
     43 
     44 <p>This results in Cmockery being a relatively small library that can be used
     45 to test a variety of exotic code.  If a developer wishes to simply test an
     46 application with the latest compiler then other unit testing frameworks maybe
     47 preferable.</p>
     48 
     49 <a name="Overview"><h2>Overview</h2></a>
     50 <p>Cmockery tests are compiled into stand-alone executables and linked with
     51 the Cmockery library, the standard C library and module being tested.  Any
     52 symbols external to the module being tested should be mocked - replaced with 
     53 functions that return values determined by the test - within the test
     54 application.  Even though significant differences may exist between the target
     55 execution environment of a code module and the environment used to test the
     56 code the unit testing is still valid since its goal is to test the logic of a
     57 code modules at a functional level and not necessarily all of its interactions
     58 with the target execution environment.</p>
     59 
     60 <p>It may not be possible to compile a module into a test application without
     61 some modification, therefore the preprocessor symbol <b>UNIT_TESTING</b> should
     62 be defined when Cmockery unit test applications are compiled so code within the
     63 module can be conditionally compiled for tests.</p>
     64 
     65 <a name="TestExecution"><h2>Test Execution</h2></a>
     66 <p>Cmockery unit test cases are functions with the signature
     67 <b>void function(void **state)</b>.  Cmockery test applications initialize a
     68 table with test case function pointers using <b>unit_test*()</b> macros.  This
     69 table is then passed to the <b>run_tests()</b> macro to execute the tests.
     70 
     71 <b>run_tests()</b> sets up the appropriate exception / signal handlers and
     72 other data structures prior to running each test function.   When a unit test
     73 is complete <b>run_tests()</b> performs various checks to determine whether
     74 the test succeeded.</p>
     75 
     76 <h4>Using run_tests()</h4>
     77 <listing>
     78 <a href="../src/example/run_tests.c">run_tests.c</a>
     79 -------------------------------------------------------------------------------
     80 #include &lt;stdarg.h&gt;
     81 #include &lt;stddef.h&gt;
     82 #include &lt;setjmp.h&gt;
     83 #include &lt;cmockery.h&gt;
     84 
     85 // A test case that does nothing and succeeds.
     86 void null_test_success(void **state) {
     87 }
     88 
     89 int main(int argc, char* argv[]) {
     90     const UnitTest tests[] = {
     91         unit_test(null_test_success),
     92     };
     93     return run_tests(tests);
     94 }
     95 </listing>
     96 
     97 <a name="ExceptionHandling"><h2>Exception Handling</h2></a>
     98 <p>Before a test function is executed by <b>run_tests()</b>,
     99 exception / signal handlers are overridden with a handler that simply
    100 displays an error and exits a test function if an exception occurs.  If an
    101 exception occurs outside of a test function, for example in Cmockery itself,
    102 the application aborts execution and returns an error code.</p>
    103 
    104 <a name="FailureConditions"><h2>Failure Conditions</h2></a>
    105 <p>If a failure occurs during a test function that's executed via
    106 <b>run_tests()</b>, the test function is aborted and the application's
    107 execution resumes with the next test function.
    108 
    109 Test failures are ultimately signalled via the Cmockery function <b>fail()</b>.
    110 The following events will result in the Cmockery library signalling a test
    111 failure...
    112 
    113 <ul>
    114   <li><a href="#Assertions">Assertions</a></li>
    115   <li><a href="#ExceptionHandling">Exceptions</a></li>
    116   <li><a href="#MemoryAllocation">Memory leaks</a></li>
    117   <li><a href="#TestState">Mismatched setup and tear down functions</a></li>
    118   <li><a href="#MockFunctionsReturnValues">Missing mock return values</a></li>
    119   <li><a href="#MockFunctionsReturnValues">Unused mock return values</a></li>
    120   <li><a href="#MockFunctionsCheckingParameters">Missing expected parameter
    121                                                  values</a></li>
    122   <li><a href="#MockFunctionsCheckingParameters">Unused expected parameter
    123                                                  values</a></li>
    124 </ul>
    125 </p>
    126 
    127 <a name="Assertions"><h2>Assertions</h2></a>
    128 <p>Runtime assert macros like the standard C library's <b>assert()</b> should
    129 be redefined in modules being tested to use Cmockery's <b>mock_assert()</b>
    130 function.  Normally <b>mock_assert()</b> signals a
    131 <a href="#FailureConditions">test failure</a>.  If a function is called using
    132 the <b>expect_assert_failure()</b> macro, any calls to <b>mock_assert()</b>
    133 within the function will result in the execution of the test.  If no
    134 calls to <b>mock_assert()</b> occur during the function called via
    135 <b>expect_assert_failure()</b> a test failure is signalled.</p>
    136 
    137 <h4>Using mock_assert()</h4>
    138 <listing>
    139 <a href="../src/example/assert_module.c">assert_module.c</a>
    140 -------------------------------------------------------------------------------
    141 #include &lt;assert.h&gt;
    142 
    143 // If unit testing is enabled override assert with mock_assert().
    144 #if UNIT_TESTING
    145 extern void mock_assert(const int result, const char* const expression, 
    146                         const char * const file, const int line);
    147 #undef assert
    148 #define assert(expression) \
    149     mock_assert((int)(expression), #expression, __FILE__, __LINE__);
    150 #endif // UNIT_TESTING
    151 
    152 void increment_value(int * const value) {
    153     assert(value);
    154     (*value) ++;
    155 }
    156 
    157 void decrement_value(int * const value) {
    158     if (value) {
    159         *value --;
    160     }
    161 }
    162 
    163 <a href="../src/example/assert_module_test.c">assert_module_test.c</a>
    164 -------------------------------------------------------------------------------
    165 #include &lt;stdarg.h&gt;
    166 #include &lt;stddef.h&gt;
    167 #include &lt;setjmp.h&gt;
    168 #include &lt;cmockery.h&gt;
    169 
    170 extern void increment_value(int * const value);
    171 
    172 /* This test case will fail but the assert is caught by run_tests() and the
    173  * next test is executed. */
    174 void increment_value_fail(void **state) {
    175     increment_value(NULL);
    176 }
    177 
    178 // This test case succeeds since increment_value() asserts on the NULL pointer.
    179 void increment_value_assert(void **state) {
    180     expect_assert_failure(increment_value(NULL));
    181 }
    182 
    183 /* This test case fails since decrement_value() doesn't assert on a NULL
    184  * pointer. */
    185 void decrement_value_fail(void **state) {
    186     expect_assert_failure(decrement_value(NULL));
    187 }
    188 
    189 int main(int argc, char *argv[]) {
    190     const UnitTest tests[] = {
    191         unit_test(increment_value_fail),
    192         unit_test(increment_value_assert),
    193         unit_test(decrement_value_fail),
    194     };
    195     return run_tests(tests);
    196 }
    197 </listing>
    198 
    199 <h3><a name="AssertMacros">Assert Macros</a></h3>
    200 
    201 <p>Cmockery provides an assortment of assert macros that tests applications
    202 should use use in preference to the C standard library's assert macro.  On an
    203 assertion failure a Cmockery assert macro will write the failure to the
    204 standard error stream and signal a test failure.  Due to limitations of the
    205 C language the general C standard library assert() and Cmockery's
    206 assert_true() and assert_false() macros can only display the expression that
    207 caused the assert failure.  Cmockery's type specific assert macros,
    208 assert_{type}_equal() and assert_{type}_not_equal(), display the data that
    209 caused the assertion failure which increases data visibility aiding
    210 debugging of failing test cases.</p>
    211 
    212 <h4>Using assert_{type}_equal() macros</h4>
    213 <listing>
    214 <a href="../src/example/assert_macro.c">assert_macro.c</a>
    215 -------------------------------------------------------------------------------
    216 #include &lt;string.h&gt;
    217 
    218 static const char* status_code_strings[] = {
    219     "Address not found",
    220     "Connection dropped",
    221     "Connection timed out",
    222 };
    223 
    224 const char* get_status_code_string(const unsigned int status_code) {
    225     return status_code_strings[status_code];
    226 };
    227 
    228 unsigned int string_to_status_code(const char* const status_code_string) {
    229     unsigned int i;
    230     for (i = 0; i < sizeof(status_code_string) / sizeof(status_code_string[0]);
    231          i++) {
    232         if (strcmp(status_code_strings[i], status_code_string) == 0) {
    233             return i;
    234         }
    235     }
    236     return ~0U;
    237 }
    238 
    239 <a href="../src/example/assert_macro_test.c">assert_macro_test.c</a>
    240 -------------------------------------------------------------------------------
    241 #include &lt;stdarg.h&gt;
    242 #include &lt;stddef.h&gt;
    243 #include &lt;setjmp.h&gt;
    244 #include &lt;cmockery.h&gt;
    245 
    246 extern const char* get_status_code_string(const unsigned int status_code);
    247 extern unsigned int string_to_status_code(
    248     const char* const status_code_string);
    249 
    250 /* This test will fail since the string returned by get_status_code_string(0)
    251  * doesn't match "Connection timed out". */
    252 void get_status_code_string_test(void **state) {
    253     assert_string_equal(get_status_code_string(0), "Address not found");
    254     assert_string_equal(get_status_code_string(1), "Connection timed out");
    255 }
    256 
    257 // This test will fail since the status code of "Connection timed out" isn't 1
    258 void string_to_status_code_test(void **state) {
    259     assert_int_equal(string_to_status_code("Address not found"), 0);
    260     assert_int_equal(string_to_status_code("Connection timed out"), 1);
    261 }
    262 
    263 int main(int argc, char *argv[]) {
    264     const UnitTest tests[] = {
    265         unit_test(get_status_code_string_test),
    266         unit_test(string_to_status_code_test),
    267     };
    268     return run_tests(tests);
    269 }
    270 </listing>
    271 
    272 <a name="MemoryAllocation"><h2>Dynamic Memory Allocation</h2></a>
    273 
    274 <p>To test for memory leaks, buffer overflows and underflows a module being
    275 tested by Cmockery should replace calls to <b>malloc()</b>, <b>calloc()</b> and
    276 <b>free()</b> to <b>test_malloc()</b>, <b>test_calloc()</b> and
    277 <b>test_free()</b> respectively.  Each time a block is deallocated using
    278 <b>test_free()</b> it is checked for corruption, if a corrupt block is found
    279 a <a href="#FailureConditions">test failure</a> is signalled.  All blocks
    280 allocated using the <b>test_*()</b> allocation functions are tracked by the
    281 Cmockery library.  When a test completes if any allocated blocks (memory leaks)
    282 remain they are reported and a test failure is signalled.</p>
    283 <p>For simplicity Cmockery currently executes all tests in one process.
    284 Therefore all test cases in a test application share a single address space
    285 which means memory corruption from a single test case could potentially cause
    286 the test application to exit prematurely.</p>
    287 
    288 <h4>Using Cmockery's Allocators</h4>
    289 <listing>
    290 <a href="../src/example/allocate_module.c">allocate_module.c</a>
    291 -------------------------------------------------------------------------------
    292 #include &lt;malloc.h&gt;
    293 
    294 #if UNIT_TESTING
    295 extern void* _test_malloc(const size_t size, const char* file, const int line);
    296 extern void* _test_calloc(const size_t number_of_elements, const size_t size, 
    297                           const char* file, const int line);
    298 extern void _test_free(void* const ptr, const char* file, const int line);
    299 
    300 #define malloc(size) _test_malloc(size, __FILE__, __LINE__)
    301 #define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
    302 #define free(ptr) _test_free(ptr, __FILE__, __LINE__)
    303 #endif // UNIT_TESTING
    304 
    305 void leak_memory() {
    306     int * const temporary = (int*)malloc(sizeof(int));
    307     *temporary = 0;
    308 }
    309 
    310 void buffer_overflow() {
    311     char * const memory = (char*)malloc(sizeof(int));
    312     memory[sizeof(int)] = '!';
    313     free(memory);
    314 }
    315 
    316 void buffer_underflow() {
    317     char * const memory = (char*)malloc(sizeof(int));
    318     memory[-1] = '!';
    319     free(memory);
    320 }
    321 
    322 
    323 <a href="../src/example/allocate_module_test.c">allocate_module_test.c</a>
    324 -------------------------------------------------------------------------------
    325 #include &lt;stdarg.h&gt;
    326 #include &lt;stddef.h&gt;
    327 #include &lt;setjmp.h&gt;
    328 #include &lt;cmockery.h&gt;
    329 
    330 extern void leak_memory();
    331 extern void buffer_overflow();
    332 extern void buffer_underflow();
    333 
    334 // Test case that fails as leak_memory() leaks a dynamically allocated block.
    335 void leak_memory_test(void **state) {
    336     leak_memory();
    337 }
    338 
    339 // Test case that fails as buffer_overflow() corrupts an allocated block.
    340 void buffer_overflow_test(void **state) {
    341     buffer_overflow();
    342 }
    343 
    344 // Test case that fails as buffer_underflow() corrupts an allocated block.
    345 void buffer_underflow_test(void **state) {
    346     buffer_underflow();
    347 }
    348 
    349 int main(int argc, char* argv[]) {
    350     const UnitTest tests[] = {
    351         unit_test(leak_memory_test),
    352         unit_test(buffer_overflow_test),
    353         unit_test(buffer_underflow_test),
    354     };
    355     return run_tests(tests);
    356 }
    357 </listing>
    358 
    359 <a name="MockFunctions"><h2>Mock Functions</h2></a>
    360 
    361 <p>A unit test should ideally isolate the function or module being tested
    362 from any external dependencies.  This can be performed using mock functions
    363 that are either statically or dynamically linked with the module being tested.
    364 Mock functions must be statically linked when the code being tested directly 
    365 references external functions.  Dynamic linking is simply the process of 
    366 setting a function pointer in a table used by the tested module to reference 
    367 a mock function defined in the unit test.</p>
    368 
    369 <a name="MockFunctionsReturnValues"><h3>Return Values</h3></a>
    370 
    371 <p>In order to simplify the implementation of mock functions Cmockery provides
    372 functionality which stores return values for mock functions in each test
    373 case using <b>will_return()</b>.  These values are then returned by each mock 
    374 function using calls to <b>mock()</b>.
    375 
    376 Values passed to <b>will_return()</b> are added to a queue for each function 
    377 specified.  Each successive call to <b>mock()</b> from a function removes a
    378 return value from the queue.  This makes it possible for a mock function to use
    379 multiple calls to <b>mock()</b> to return output parameters in addition to a
    380 return value.  In addition this allows the specification of return values for 
    381 multiple calls to a mock function.</p>
    382 
    383 <h4>Using will_return()</h4>
    384 <listing>
    385 <a name="../src/example/database.h" href="database.h">database.h</a>
    386 -------------------------------------------------------------------------------
    387 typedef struct DatabaseConnection DatabaseConnection;
    388 
    389 /* Function that takes an SQL query string and sets results to an array of
    390  * pointers with the result of the query.  The value returned specifies the
    391  * number of items in the returned array of results.  The returned array of
    392  * results are statically allocated and should not be deallocated using free()
    393  */
    394 typedef unsigned int (*QueryDatabase)(
    395     DatabaseConnection* const connection, const char * const query_string,
    396     void *** const results);
    397 
    398 // Connection to a database.
    399 struct DatabaseConnection {
    400     const char *url;
    401     unsigned int port;
    402     QueryDatabase query_database;
    403 };
    404 
    405 // Connect to a database.
    406 DatabaseConnection* connect_to_database(const char * const url,
    407                                         const unsigned int port);
    408 
    409 
    410 <a href="../src/example/customer_database.c">customer_database.c</a>
    411 -------------------------------------------------------------------------------
    412 #include &lt;stddef.h&gt;
    413 #include &lt;stdio.h&gt;
    414 #include <a href="#database.h">&lt;database.h&gt;</a>
    415 #ifdef _WIN32
    416 #define snprintf _snprintf
    417 #endif // _WIN32
    418 
    419 // Connect to the database containing customer information.
    420 DatabaseConnection* connect_to_customer_database() {
    421     return connect_to_database("customers.abcd.org", 321);
    422 }
    423 
    424 /* Find the ID of a customer by his/her name returning a value > 0 if
    425  * successful, 0 otherwise. */
    426 unsigned int get_customer_id_by_name(
    427         DatabaseConnection * const connection,
    428         const char * const customer_name) {
    429     char query_string[256];
    430     int number_of_results;
    431     void **results;
    432     snprintf(query_string, sizeof(query_string),
    433              "SELECT ID FROM CUSTOMERS WHERE NAME = %s", customer_name);
    434     number_of_results = connection->query_database(connection, query_string,
    435                                                    &results);
    436     if (number_of_results != 1) {
    437         return -1;
    438     }
    439     return (unsigned int)results[0];
    440 }
    441 
    442 
    443 <a href="../src/example/customer_database_test.c">customer_database_test.c</a>
    444 -------------------------------------------------------------------------------
    445 #include &lt;stdarg.h&gt;
    446 #include &lt;stddef.h&gt;
    447 #include &lt;setjmp.h&gt;
    448 #include &lt;cmockery.h&gt;
    449 #include <a href="#database.h">&lt;database.h&gt;</a>
    450 
    451 
    452 extern DatabaseConnection* connect_to_customer_database();
    453 extern unsigned int get_customer_id_by_name(
    454     DatabaseConnection * const connection, const char * const customer_name);
    455 
    456 // Mock query database function.
    457 unsigned int mock_query_database(
    458         DatabaseConnection* const connection, const char * const query_string,
    459         void *** const results) {
    460     *results = (void**)mock();
    461     return (unsigned int)mock();
    462 }
    463 
    464 // Mock of the connect to database function.
    465 DatabaseConnection* connect_to_database(const char * const database_url,
    466                                         const unsigned int port) {
    467     return (DatabaseConnection*)mock();
    468 }
    469 
    470 void test_connect_to_customer_database(void **state) {
    471     will_return(connect_to_database, 0x0DA7ABA53);
    472     assert_true(connect_to_customer_database() ==
    473                 (DatabaseConnection*)0x0DA7ABA53);
    474 }
    475 
    476 /* This test fails as the mock function connect_to_database() will have no
    477  * value to return. */
    478 void fail_connect_to_customer_database(void **state) {
    479     will_return(connect_to_database, 0x0DA7ABA53);
    480     assert_true(connect_to_customer_database() ==
    481                 (DatabaseConnection*)0x0DA7ABA53);
    482 }
    483 
    484 void test_get_customer_id_by_name(void **state) {
    485     DatabaseConnection connection = {
    486         "somedatabase.somewhere.com", 12345678, mock_query_database
    487     };
    488     // Return a single customer ID when mock_query_database() is called.
    489     int customer_ids = 543;
    490     will_return(mock_query_database, &customer_ids);
    491     will_return(mock_query_database, 1);
    492     assert_int_equal(get_customer_id_by_name(&connection, "john doe"), 543);
    493 }
    494 
    495 int main(int argc, char* argv[]) {
    496     const UnitTest tests[] = {
    497         unit_test(test_connect_to_customer_database),
    498         unit_test(fail_connect_to_customer_database),
    499         unit_test(test_get_customer_id_by_name),
    500     };
    501     return run_tests(tests);
    502 }
    503 </listing>
    504 
    505 <a name="MockFunctionsCheckingParameters"><h3>Checking Parameters</h3></a>
    506 <p>In addition to storing the return values of mock functions, Cmockery
    507 provides functionality to store expected values for mock function parameters
    508 using the expect_*() functions provided.  A mock function parameter can then
    509 be validated using the check_expected() macro.
    510 
    511 <p>Successive calls to expect_*() macros for a parameter queues values to
    512 check the specified parameter.  check_expected() checks a function parameter
    513 against the next value queued using expect_*(), if the parameter check fails a
    514 test failure is signalled.  In addition if check_expected() is called and
    515 no more parameter values are queued a test failure occurs.</p>
    516 
    517 <h4>Using expect_*()</h4>
    518 <listing>
    519 <a href="../src/example/product_database.c">product_database.c</a>
    520 -------------------------------------------------------------------------------
    521 #include <a href="#database.h">&lt;database.h&gt;</a>
    522 
    523 // Connect to the database containing customer information.
    524 DatabaseConnection* connect_to_product_database() {
    525     return connect_to_database("products.abcd.org", 322);
    526 }
    527 
    528 <a href="../src/example/product_database_test.c">product_database_test.c</a>
    529 -------------------------------------------------------------------------------
    530 #include &lt;stdarg.h&gt;
    531 #include &lt;stddef.h&gt;
    532 #include &lt;setjmp.h&gt;
    533 #include &lt;cmockery.h&gt;
    534 #include <a href="#database.h">&lt;database.h&gt;</a>
    535 
    536 extern DatabaseConnection* connect_to_product_database();
    537 
    538 /* Mock connect to database function.
    539  * NOTE: This mock function is very general could be shared between tests
    540  * that use the imaginary database.h module. */
    541 DatabaseConnection* connect_to_database(const char * const url,
    542                                         const unsigned int port) {
    543     check_expected(url);
    544     check_expected(port);
    545     return (DatabaseConnection*)mock();
    546 }
    547 
    548 void test_connect_to_product_database(void **state) {
    549     expect_string(connect_to_database, url, "products.abcd.org");
    550     expect_value(connect_to_database, port, 322);
    551     will_return(connect_to_database, 0xDA7ABA53);
    552     assert_int_equal(connect_to_product_database(), 0xDA7ABA53);
    553 }
    554 
    555 /* This test will fail since the expected URL is different to the URL that is
    556  * passed to connect_to_database() by connect_to_product_database(). */
    557 void test_connect_to_product_database_bad_url(void **state) {
    558     expect_string(connect_to_database, url, "products.abcd.com");
    559     expect_value(connect_to_database, port, 322);
    560     will_return(connect_to_database, 0xDA7ABA53);
    561     assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
    562 }
    563 
    564 /* This test will fail since the mock connect_to_database() will attempt to
    565  * retrieve a value for the parameter port which isn't specified by this
    566  * test function. */
    567 void test_connect_to_product_database_missing_parameter(void **state) {
    568     expect_string(connect_to_database, url, "products.abcd.org");
    569     will_return(connect_to_database, 0xDA7ABA53);
    570     assert_int_equal((int)connect_to_product_database(), 0xDA7ABA53);
    571 }
    572 
    573 int main(int argc, char* argv[]) {
    574     const UnitTest tests[] = {
    575         unit_test(test_connect_to_product_database),
    576         unit_test(test_connect_to_product_database_bad_url),
    577         unit_test(test_connect_to_product_database_missing_parameter),
    578     };
    579     return run_tests(tests);
    580 }
    581 </listing>
    582 
    583 <a name="TestState"><h2>Test State</h2></a>
    584 
    585 <p>Cmockery allows the specification of multiple setup and tear down functions
    586 for each test case.  Setup functions, specified by the <b>unit_test_setup()</b>
    587 or <b>unit_test_setup_teardown()</b> macros allow common initialization to be
    588 shared between multiple test cases.  In addition, tear down functions,
    589 specified by the <b>unit_test_teardown()</b> or
    590 <b>unit_test_setup_teardown()</b> macros provide a code path that is always
    591 executed for a test case even when it fails.</p>
    592 
    593 <h4>Using unit_test_setup_teardown()</h4>
    594 <listing>
    595 <a href="../src/example/key_value.c">key_value.c</a>
    596 -------------------------------------------------------------------------------
    597 #include &lt;stddef.h&gt;
    598 #include &lt;stdlib.h&gt;
    599 #include &lt;string.h&gt;
    600 
    601 typedef struct KeyValue {
    602     unsigned int key;
    603     const char* value;
    604 } KeyValue;
    605 
    606 static KeyValue *key_values = NULL;
    607 static unsigned int number_of_key_values = 0;
    608 
    609 void set_key_values(KeyValue * const new_key_values,
    610                     const unsigned int new_number_of_key_values) {
    611     key_values = new_key_values;
    612     number_of_key_values = new_number_of_key_values;
    613 }
    614 
    615 // Compare two key members of KeyValue structures.
    616 int key_value_compare_keys(const void *a, const void *b) {
    617     return (int)((KeyValue*)a)->key - (int)((KeyValue*)b)->key;
    618 }
    619 
    620 // Search an array of key value pairs for the item with the specified value.
    621 KeyValue* find_item_by_value(const char * const value) {
    622   unsigned int i;
    623     for (i = 0; i < number_of_key_values; i++) {
    624         if (strcmp(key_values[i].value, value) == 0) {
    625             return &key_values[i];
    626         }
    627     }
    628     return NULL;
    629 }
    630 
    631 // Sort an array of key value pairs by key.
    632 void sort_items_by_key() {
    633     qsort(key_values, number_of_key_values, sizeof(*key_values),
    634           key_value_compare_keys);
    635 }
    636 
    637 <a href="../src/example/key_value_test.c">key_value_test.c</a>
    638 -------------------------------------------------------------------------------
    639 #include &lt;stdarg.h&gt;
    640 #include &lt;stddef.h&gt;
    641 #include &lt;setjmp.h&gt;
    642 #include &lt;string.h&gt;
    643 #include &lt;cmockery.h&gt;
    644 
    645 /* This is duplicated here from the module setup_teardown.c to reduce the
    646  * number of files used in this test. */
    647 typedef struct KeyValue {
    648     unsigned int key;
    649     const char* value;
    650 } KeyValue;
    651 
    652 void set_key_values(KeyValue * const new_key_values,
    653                     const unsigned int new_number_of_key_values);
    654 extern KeyValue* find_item_by_value(const char * const value);
    655 extern void sort_items_by_key();
    656 
    657 static KeyValue key_values[] = {
    658     { 10, "this" },
    659     { 52, "test" },
    660     { 20, "a" },
    661     { 13, "is" },
    662 };
    663 
    664 void create_key_values(void **state) {
    665     KeyValue * const items = (KeyValue*)test_malloc(sizeof(key_values));
    666     memcpy(items, key_values, sizeof(key_values));
    667     *state = (void*)items;
    668     set_key_values(items, sizeof(key_values) / sizeof(key_values[0]));
    669 }
    670 
    671 void destroy_key_values(void **state) {
    672     test_free(*state);
    673     set_key_values(NULL, 0);
    674 }
    675 
    676 void test_find_item_by_value(void **state) {
    677     unsigned int i;
    678     for (i = 0; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
    679         KeyValue * const found  = find_item_by_value(key_values[i].value);
    680         assert_true(found);
    681         assert_int_equal(found->key, key_values[i].key);
    682         assert_string_equal(found->value, key_values[i].value);
    683     }
    684 }
    685 
    686 void test_sort_items_by_key(void **state) {
    687     unsigned int i;
    688     KeyValue * const kv = *state;
    689     sort_items_by_key();
    690     for (i = 1; i < sizeof(key_values) / sizeof(key_values[0]); i++) {
    691         assert_true(kv[i - 1].key < kv[i].key);
    692     }
    693 }
    694 
    695 int main(int argc, char* argv[]) {
    696     const UnitTest tests[] = {
    697         unit_test_setup_teardown(test_find_item_by_value, create_key_values,
    698                                  destroy_key_values),
    699         unit_test_setup_teardown(test_sort_items_by_key, create_key_values,
    700                                  destroy_key_values),
    701     };
    702     return run_tests(tests);
    703 }
    704 </listing>
    705 
    706 <a name="Example"><h2>Example</h2></a>
    707 
    708 <p>A small command line calculator
    709 <a href="../src/example/calculator.c">calculator.c</a> application
    710 and test application that full exercises the calculator application
    711 <a href="../src/example/calculator_test.c">calculator_test.c</a>
    712 are provided as an example of Cmockery's features discussed in this document.
    713 </p>
    714 
    715 <hr>
    716 <address></address>
    717 <!-- hhmts start --> Last modified: Tue Aug 26 09:33:31 PDT 2008 <!-- hhmts end -->
    718 </body> </html>
    719