summaryrefslogtreecommitdiff
path: root/README.md
blob: 0e6692a7301d3cf0656b1e8d9b3f60a74abdd431 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
lily
====

**lily** is a testing library for C. It provides both basic assertions as well as mocking.

To incorporate lily into a project, just copy `lily-test.h` and `lily-test.c` into your
source code.


usage
-----

Tests are any function with the signature `void (void)`, and are run with the macro `lily_run_test(test)`.
Tests are intended to be run inside of suite functions, which have the same signature as a test.
To add suite setup or teardown operations, just do them inside the suite function.
Suites are run with the `lily_run_suite(suite)` macro.

Tests can contain assertions! You should not try to use these assertions outside of tests run with
`lily_run_test()` because you'll probably just crash your program. Tests, if they fail, generate
error messages that detail the mismatch between their expected and actual results and also indicate
the file and line of the failed assertion. On some compilers `__FILE__` is the complete path of the 
file (i.e. all the way from root), so lily lets you trim N characters from the front of it by 
defining a `SOURCE_PATH_SIZE` macro whose value is N. (I usually define this from within my build tool
so that it'll still work if other people download the software).

The following assertions are available:

* `lily_assert_true(bool)`
* `lily_assert_false(bool)`
* `lily_assert_not_null(void *)`
* `lily_assert_null(void *)`
* `lily_assert_ptr_equal(void *, void *)`
* `lily_assert_ptr_not_equal(void *, void *)`
* `lily_assert_int_equal(int, int)`
* `lily_assert_int_not_equal(int, int)`
* `lily_assert_float_equal(float, float, float epsilon)`
* `lily_assert_float_not_equal(float, float, float epsilon)`
* `lily_assert_string_equal(char *, char *)`
* `lily_assert_string_not_equal(char *, char *)`
* `lily_assert_memory_equal(void *, void *, size_t size)`
* `lily_assert_memory_not_equal(void *, void *, size_t size)`

lily also provides some features to make mocking functions a little nicer. First,
there is the `lily_queue_t` object, which contains a FIFO queue for arbitrary data.
They support the following operations:

* `lily_queue_t * lily_queue_create()` - create a new queue
* `lily_queue_destroy(lily_queue_t *)` - destroy a queue
* `lily_enqueue(lily_queue_t*, TYPE, value)` - enqueue some value. Any type can be queued; just be careful to dequeue the same data types in the same order!
* `lily_dequeue(lily_queue_t*, TYPE, ptr)` - pops a value from the queue into a pointer of **an appropriate type**. Be careful not to dequeue data types in the same order you queued them!

This system is intended to allow you to control the behavior/return types of mock functions
by queueing things before a call that the mock will dequeue.

lily also provides the `lily_mock_t` object, which uses these queues to easily store the arguments
of a call to a function.

* `lily_mock_t * lily_mock_create()` - create a new mock object
* `lily_mock_destroy(lily_mock_t *)` - destroy a mock object
* `lily_mock_call(lily_mock_t*, struct lily_mock_arg_t*)` - store arguments (see below)
* `lily_get_call(lily_mock_t*, struct lily_mock_arg_t*, int)` - store arguments (see below)

Each `struct lily_mock_arg_t` contains a size and void pointer, so storing a set of arguments
looks something like this:

```
lily_mock_t *m; // initialized somewhere
void some_func(int a, const char *b)
{
	struct lily_mock_arg_t args[] = {
		{ sizeof(int), &a },
		{ sizeof(const char *), &b },
	};
	lily_mock_call(m, args);
	/* ... */
}
```

Retrieving calls looks much the same, except the pointers in the array are to destinations
and not sources. (You also need to specify the zero-indexed number of the call -- that's the `int` argument).



~ the future ~
--------------

Some features I'd like to add:

A `prepare-tests.sh` script that will automatically scan
the given source root for all files matching `*.test.c` and qenerate a header file,
main function, and Makefile to run all of the functions matching `void ()` in those
test files. (If you want a utility function or something, just make it `static`).

It might be nice to switch to an stb-style header-only library, where the contents of
`lily-test.c` are put inside of a macro gate, and the user just has to `#define LILY_IMPLEMENTATION`
in some file that includes `lily-test.h`.