index.html revision bdd62c531bbdea115a3a7e71bba91c19dd319cc4
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
31them are fairly complex and require the latest compiler technology.  Some
32development requires the use of old compilers which makes it difficult to
33use some unit testing frameworks.  In addition many unit testing frameworks
34assume the code being tested is an application or module that is targeted to
35the same platform that will ultimately execute the test.  Because of this
36assumption many frameworks require the inclusion of standard C library headers
37in the code module being tested which may collide with the custom or
38incomplete 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
41library which minimizes conflicts with standard C library headers.  Also,
42Cmockery 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
45to test a variety of exotic code.  If a developer wishes to simply test an
46application with the latest compiler then other unit testing frameworks maybe
47preferable.</p>
48
49<a name="Overview"><h2>Overview</h2></a>
50<p>Cmockery tests are compiled into stand-alone executables and linked with
51the Cmockery library, the standard C library and module being tested.  Any
52symbols external to the module being tested should be mocked - replaced with 
53functions that return values determined by the test - within the test
54application.  Even though significant differences may exist between the target
55execution environment of a code module and the environment used to test the
56code the unit testing is still valid since its goal is to test the logic of a
57code modules at a functional level and not necessarily all of its interactions
58with the target execution environment.</p>
59
60<p>It may not be possible to compile a module into a test application without
61some modification, therefore the preprocessor symbol <b>UNIT_TESTING</b> should
62be defined when Cmockery unit test applications are compiled so code within the
63module 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
68table with test case function pointers using <b>unit_test*()</b> macros.  This
69table 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
72other data structures prior to running each test function.   When a unit test
73is complete <b>run_tests()</b> performs various checks to determine whether
74the 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.
86void null_test_success(void **state) {
87}
88
89int 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>,
99exception / signal handlers are overridden with a handler that simply
100displays an error and exits a test function if an exception occurs.  If an
101exception occurs outside of a test function, for example in Cmockery itself,
102the 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
107execution resumes with the next test function.
108
109Test failures are ultimately signalled via the Cmockery function <b>fail()</b>.
110The following events will result in the Cmockery library signalling a test
111failure...
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
129be redefined in modules being tested to use Cmockery's <b>mock_assert()</b>
130function.  Normally <b>mock_assert()</b> signals a
131<a href="#FailureConditions">test failure</a>.  If a function is called using
132the <b>expect_assert_failure()</b> macro, any calls to <b>mock_assert()</b>
133within the function will result in the execution of the test.  If no
134calls 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
145extern 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
152void increment_value(int * const value) {
153    assert(value);
154    (*value) ++;
155}
156
157void 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
170extern 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. */
174void increment_value_fail(void **state) {
175    increment_value(NULL);
176}
177
178// This test case succeeds since increment_value() asserts on the NULL pointer.
179void 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. */
185void decrement_value_fail(void **state) {
186    expect_assert_failure(decrement_value(NULL));
187}
188
189int 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
202should use use in preference to the C standard library's assert macro.  On an
203assertion failure a Cmockery assert macro will write the failure to the
204standard error stream and signal a test failure.  Due to limitations of the
205C language the general C standard library assert() and Cmockery's
206assert_true() and assert_false() macros can only display the expression that
207caused the assert failure.  Cmockery's type specific assert macros,
208assert_{type}_equal() and assert_{type}_not_equal(), display the data that
209caused the assertion failure which increases data visibility aiding
210debugging 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
218static const char* status_code_strings[] = {
219    "Address not found",
220    "Connection dropped",
221    "Connection timed out",
222};
223
224const char* get_status_code_string(const unsigned int status_code) {
225    return status_code_strings[status_code];
226};
227
228unsigned 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
246extern const char* get_status_code_string(const unsigned int status_code);
247extern 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". */
252void 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
258void 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
263int 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
275tested 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
279a <a href="#FailureConditions">test failure</a> is signalled.  All blocks
280allocated using the <b>test_*()</b> allocation functions are tracked by the
281Cmockery library.  When a test completes if any allocated blocks (memory leaks)
282remain they are reported and a test failure is signalled.</p>
283<p>For simplicity Cmockery currently executes all tests in one process.
284Therefore all test cases in a test application share a single address space
285which means memory corruption from a single test case could potentially cause
286the 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
295extern void* _test_malloc(const size_t size, const char* file, const int line);
296extern void* _test_calloc(const size_t number_of_elements, const size_t size, 
297                          const char* file, const int line);
298extern 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
305void leak_memory() {
306    int * const temporary = (int*)malloc(sizeof(int));
307    *temporary = 0;
308}
309
310void buffer_overflow() {
311    char * const memory = (char*)malloc(sizeof(int));
312    memory[sizeof(int)] = '!';
313    free(memory);
314}
315
316void 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
330extern void leak_memory();
331extern void buffer_overflow();
332extern void buffer_underflow();
333
334// Test case that fails as leak_memory() leaks a dynamically allocated block.
335void leak_memory_test(void **state) {
336    leak_memory();
337}
338
339// Test case that fails as buffer_overflow() corrupts an allocated block.
340void buffer_overflow_test(void **state) {
341    buffer_overflow();
342}
343
344// Test case that fails as buffer_underflow() corrupts an allocated block.
345void buffer_underflow_test(void **state) {
346    buffer_underflow();
347}
348
349int 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
362from any external dependencies.  This can be performed using mock functions
363that are either statically or dynamically linked with the module being tested.
364Mock functions must be statically linked when the code being tested directly 
365references external functions.  Dynamic linking is simply the process of 
366setting a function pointer in a table used by the tested module to reference 
367a 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
372functionality which stores return values for mock functions in each test
373case using <b>will_return()</b>.  These values are then returned by each mock 
374function using calls to <b>mock()</b>.
375
376Values passed to <b>will_return()</b> are added to a queue for each function 
377specified.  Each successive call to <b>mock()</b> from a function removes a
378return value from the queue.  This makes it possible for a mock function to use
379multiple calls to <b>mock()</b> to return output parameters in addition to a
380return value.  In addition this allows the specification of return values for 
381multiple 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-------------------------------------------------------------------------------
387typedef 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 */
394typedef unsigned int (*QueryDatabase)(
395    DatabaseConnection* const connection, const char * const query_string,
396    void *** const results);
397
398// Connection to a database.
399struct DatabaseConnection {
400    const char *url;
401    unsigned int port;
402    QueryDatabase query_database;
403};
404
405// Connect to a database.
406DatabaseConnection* 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.
420DatabaseConnection* 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. */
426unsigned 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
452extern DatabaseConnection* connect_to_customer_database();
453extern unsigned int get_customer_id_by_name(
454    DatabaseConnection * const connection, const char * const customer_name);
455
456// Mock query database function.
457unsigned 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.
465DatabaseConnection* connect_to_database(const char * const database_url,
466                                        const unsigned int port) {
467    return (DatabaseConnection*)mock();
468}
469
470void 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. */
478void 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
484void 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
495int 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
507provides functionality to store expected values for mock function parameters
508using the expect_*() functions provided.  A mock function parameter can then
509be validated using the check_expected() macro.
510
511<p>Successive calls to expect_*() macros for a parameter queues values to
512check the specified parameter.  check_expected() checks a function parameter
513against the next value queued using expect_*(), if the parameter check fails a
514test failure is signalled.  In addition if check_expected() is called and
515no 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.
524DatabaseConnection* 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
536extern 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. */
541DatabaseConnection* 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
548void 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(). */
557void 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. */
567void 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
573int 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
586for each test case.  Setup functions, specified by the <b>unit_test_setup()</b>
587or <b>unit_test_setup_teardown()</b> macros allow common initialization to be
588shared between multiple test cases.  In addition, tear down functions,
589specified by the <b>unit_test_teardown()</b> or
590<b>unit_test_setup_teardown()</b> macros provide a code path that is always
591executed 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
601typedef struct KeyValue {
602    unsigned int key;
603    const char* value;
604} KeyValue;
605
606static KeyValue *key_values = NULL;
607static unsigned int number_of_key_values = 0;
608
609void 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.
616int 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.
621KeyValue* 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.
632void 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. */
647typedef struct KeyValue {
648    unsigned int key;
649    const char* value;
650} KeyValue;
651
652void set_key_values(KeyValue * const new_key_values,
653                    const unsigned int new_number_of_key_values);
654extern KeyValue* find_item_by_value(const char * const value);
655extern void sort_items_by_key();
656
657static KeyValue key_values[] = {
658    { 10, "this" },
659    { 52, "test" },
660    { 20, "a" },
661    { 13, "is" },
662};
663
664void 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
671void destroy_key_values(void **state) {
672    test_free(*state);
673    set_key_values(NULL, 0);
674}
675
676void 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
686void 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
695int 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
710and test application that full exercises the calculator application
711<a href="/src/example/calculator_test.c">calculator_test.c</a>
712are 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