Bump copyright date to 2019
[tor.git] / src / lib / testsupport / testsupport.h
blob9363a9ba661c8d295a841256335473f472eb7f6a
1 /* Copyright (c) 2013-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file testsupport.h
7 * \brief Macros to implement mocking and selective exposure for the test code.
9 * Each Tor source file is built twice: once with TOR_UNIT_TESTS defined, and
10 * once with it undefined. The only difference between these configurations
11 * should be that when building for the tests, more functions are exposed as
12 * non-static, and a number of functions are declared as mockable.
13 **/
15 #ifndef TOR_TESTSUPPORT_H
16 #define TOR_TESTSUPPORT_H
18 #ifdef TOR_UNIT_TESTS
19 /** The "STATIC" macro marks a function or variable that is static when
20 * building Tor for production, but non-static when building the unit
21 * tests. */
22 #define STATIC
23 #define EXTERN(type, name) extern type name;
24 #else
25 #define STATIC static
26 #define EXTERN(type, name)
27 #endif /* defined(TOR_UNIT_TESTS) */
29 /** Quick and dirty macros to implement test mocking.
31 * To use them, suppose that you have a function you'd like to mock
32 * with the signature "void writebuf(size_t n, char *buf)". You can then
33 * declare the function as:
35 * MOCK_DECL(void, writebuf, (size_t n, char *buf));
37 * and implement it as:
39 * MOCK_IMPL(void,
40 * writebuf,(size_t n, char *buf))
41 * {
42 * ...
43 * }
45 * For the non-testing build, this will expand simply into:
47 * void writebuf(size_t n, char *buf);
48 * void
49 * writebuf(size_t n, char *buf)
50 * {
51 * ...
52 * }
54 * But for the testing case, it will expand into:
56 * void writebuf__real(size_t n, char *buf);
57 * extern void (*writebuf)(size_t n, char *buf);
59 * void (*writebuf)(size_t n, char *buf) = writebuf__real;
60 * void
61 * writebuf__real(size_t n, char *buf)
62 * {
63 * ...
64 * }
66 * This is not a great mocking system! It is deliberately "the simplest
67 * thing that could work", and pays for its simplicity in its lack of
68 * features, and in its uglification of the Tor code. Replacing it with
69 * something clever would be a fine thing.
71 * @{ */
72 #ifdef TOR_UNIT_TESTS
73 #define MOCK_DECL(rv, funcname, arglist) \
74 rv funcname ##__real arglist; \
75 extern rv(*funcname) arglist
76 #define MOCK_IMPL(rv, funcname, arglist) \
77 rv(*funcname) arglist = funcname ##__real; \
78 rv funcname ##__real arglist
79 #define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
80 rv funcname ##__real arglist attr; \
81 extern rv(*funcname) arglist
82 #define MOCK_IMPL(rv, funcname, arglist) \
83 rv(*funcname) arglist = funcname ##__real; \
84 rv funcname ##__real arglist
85 #define MOCK(func, replacement) \
86 do { \
87 (func) = (replacement); \
88 } while (0)
89 #define UNMOCK(func) \
90 do { \
91 func = func ##__real; \
92 } while (0)
93 #else /* !(defined(TOR_UNIT_TESTS)) */
94 #define MOCK_DECL(rv, funcname, arglist) \
95 rv funcname arglist
96 #define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
97 rv funcname arglist attr
98 #define MOCK_IMPL(rv, funcname, arglist) \
99 rv funcname arglist
100 #endif /* defined(TOR_UNIT_TESTS) */
101 /** @} */
103 #endif /* !defined(TOR_TESTSUPPORT_H) */