aboutsummaryrefslogtreecommitdiff
path: root/src/common/testsupport.h
blob: 4a4f50b69b39ec609020fa19cbc4d1dadbdcfd00 (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
/* Copyright (c) 2013, The Tor Project, Inc. */
/* See LICENSE for licensing information */

#ifndef TOR_TESTSUPPORT_H
#define TOR_TESTSUPPORT_H

#ifdef TOR_UNIT_TESTS
#define STATIC
#else
#define STATIC static
#endif

/** Quick and dirty macros to implement test mocking.
 *
 * To use them, suppose that you have a function you'd like to mock
 * with the signature "void writebuf(size_t n, char *buf)".  You can then
 * declare the function as:
 *
 *     MOCK_DECL(void, writebuf, (size_t n, char *buf));
 *
 * and implement it as:
 *
 *     MOCK_IMPL(void
 *     writebuf,(size_t n, char *buf)
 *     {
 *          ...
 *     }
 *
 * For the non-testing build, this will expand simply into:
 *
 *     void writebuf(size_t n, char *buf);
 *     void
 *     writebuf(size_t n, char *buf)
 *     {
 *         ...
 *     }
 *
 * But for the testing case, it will expand into:
 *
 *     void writebuf__real(size_t n, char *buf);
 *     extern void (*writebuf)(size_t n, char *buf);
 *
 *     void (*writebuf)(size_t n, char *buf) = writebuf__real;
 *     void
 *     writebuf__real(size_t n, char *buf)
 *     {
 *         ...
 *     }
 *
 * This is not a great mocking system!  It is deliberately "the simplest
 * thing that could work", and pays for its simplicity in its lack of
 * features, and in its uglification of the Tor code.  Replacing it with
 * something clever would be a fine thing.
 *
 * @{ */
#ifdef TOR_UNIT_TESTS
#define MOCK_DECL(rv, funcname, arglist)     \
  rv funcname ##__real arglist;              \
  extern rv(*funcname) arglist
#define MOCK_IMPL(rv, funcname, arglist)     \
  rv(*funcname) arglist = funcname ##__real; \
  rv funcname ##__real arglist
#define MOCK(func, replacement)                 \
  do {                                          \
    (func) = (replacement);                     \
  } while (0)
#define UNMOCK(func)                            \
  do {                                          \
    func = func ##__real;                       \
  } while (0)
#else
#define MOCK_DECL(rv, funcname, arglist) \
  rv funcname arglist
#define MOCK_IMPL(rv, funcname, arglist) \
  rv funcname arglist
#endif
/** @} */

#endif