2 * virmock.h: helper for mocking C functions
4 * Copyright (C) 2014 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
30 #define VIR_MOCK_COUNT_ARGS(...) VIR_MOCK_ARG21(__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
31 #define VIR_MOCK_ARG21(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, ...) _21
32 #define VIR_MOCK_ARG_PASTE(a, b, ...) a##b(__VA_ARGS__)
34 #define VIR_MOCK_ARGNAME(a, b) b
35 #define VIR_MOCK_ARGTYPE(a, b) a
36 #define VIR_MOCK_ARGTYPENAME(a, b) a b
37 #define VIR_MOCK_ARGTYPENAME_UNUSED(a, b) a b ATTRIBUTE_UNUSED
39 #define VIR_MOCK_GET_ARG2(z, a, b) z(a, b)
40 #define VIR_MOCK_GET_ARG3(z, a, b, c) z(a, b)
41 #define VIR_MOCK_GET_ARG4(z, a, b, c, d) z(a, b), z(c, d)
42 #define VIR_MOCK_GET_ARG5(z, a, b, c, d, e) z(a, b), z(c, d)
43 #define VIR_MOCK_GET_ARG6(z, a, b, c, d, e, f) z(a, b), z(c, d), z(e, f)
44 #define VIR_MOCK_GET_ARG7(z, a, b, c, d, e, f, g) z(a, b), z(c, d), z(e, f)
45 #define VIR_MOCK_GET_ARG8(z, a, b, c, d, e, f, g, h) z(a, b), z(c, d), z(e, f), z(g, h)
46 #define VIR_MOCK_GET_ARG9(z, a, b, c, d, e, f, g, h, i) z(a, b), z(c, d), z(e, f), z(g, h)
47 #define VIR_MOCK_GET_ARG10(z, a, b, c, d, e, f, g, h, i, j) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j)
48 #define VIR_MOCK_GET_ARG11(z, a, b, c, d, e, f, g, h, i, j, k) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j)
49 #define VIR_MOCK_GET_ARG12(z, a, b, c, d, e, f, g, h, i, j, k, l) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l)
50 #define VIR_MOCK_GET_ARG13(z, a, b, c, d, e, f, g, h, i, j, k, l, m) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l)
51 #define VIR_MOCK_GET_ARG14(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n)
52 #define VIR_MOCK_GET_ARG15(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n)
53 #define VIR_MOCK_GET_ARG16(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p)
54 #define VIR_MOCK_GET_ARG17(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p)
55 #define VIR_MOCK_GET_ARG18(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p), z(q, r)
56 #define VIR_MOCK_GET_ARG19(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p), z(q, r)
57 #define VIR_MOCK_GET_ARG20(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p), z(q, r), z(s, t)
58 #define VIR_MOCK_GET_ARG21(z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) z(a, b), z(c, d), z(e, f), z(g, h), z(i, j), z(k, l), z(m, n), z(o, p), z(q, r), z(s, t)
61 #define VIR_MOCK_ARGNAMES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
62 #define VIR_MOCK_ARGNAMES(...) \
63 VIR_MOCK_ARGNAMES_EXPAND(VIR_MOCK_GET_ARG, VIR_MOCK_COUNT_ARGS(__VA_ARGS__), VIR_MOCK_ARGNAME, __VA_ARGS__)
65 #define VIR_MOCK_ARGTYPES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
66 #define VIR_MOCK_ARGTYPES(...) \
67 VIR_MOCK_ARGTYPES_EXPAND(VIR_MOCK_GET_ARG, VIR_MOCK_COUNT_ARGS(__VA_ARGS__), VIR_MOCK_ARGTYPE, __VA_ARGS__)
69 #define VIR_MOCK_ARGTYPENAMES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
70 #define VIR_MOCK_ARGTYPENAMES(...) \
71 VIR_MOCK_ARGTYPENAMES_EXPAND(VIR_MOCK_GET_ARG, VIR_MOCK_COUNT_ARGS(__VA_ARGS__), VIR_MOCK_ARGTYPENAME, __VA_ARGS__)
73 #define VIR_MOCK_ARGTYPENAMES_UNUSED_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
74 #define VIR_MOCK_ARGTYPENAMES_UNUSED(...) \
75 VIR_MOCK_ARGTYPENAMES_UNUSED_EXPAND(VIR_MOCK_GET_ARG, VIR_MOCK_COUNT_ARGS(__VA_ARGS__), VIR_MOCK_ARGTYPENAME_UNUSED, __VA_ARGS__)
79 * The VIR_MOCK_LINK_NNN_MMM() macros are intended for use in
80 * LD_PRELOAD based wrappers. They provide a replacement for
81 * for an existing shared library symbol export. They will
82 * then lookup the same symbol name but with 'wrap_' prefixed
83 * on it, and call that.
85 * The actual test suite should provide the implementation of
86 * the wrap_XXXX symbol, using the VIR_MOCK_WRAP_NNN_MMM
92 * VIR_MOCK_LINK_RET_ARGS:
93 * @name: the symbol name to replace
94 * @rettype: the return type
95 * @...: pairs of parameter type and parameter name
97 * Define a replacement for @name which invokes wrap_@name
98 * forwarding on all args, and passing back the return value.
100 #define VIR_MOCK_LINK_RET_ARGS(name, rettype, ...) \
101 rettype name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)) \
103 static rettype (*wrap_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
104 if (wrap_##name == NULL && \
105 !(wrap_##name = dlsym(RTLD_DEFAULT, \
107 fprintf(stderr, "Missing symbol 'wrap_" #name "'\n"); \
111 return wrap_##name(VIR_MOCK_ARGNAMES(__VA_ARGS__)); \
115 * VIR_MOCK_LINK_RET_VOID:
116 * @name: the symbol name to replace
117 * @rettype: the return type
119 * Define a replacement for @name which invokes wrap_@name
120 * with no arguments, and passing back the return value.
122 #define VIR_MOCK_LINK_RET_VOID(name, rettype) \
125 static rettype (*wrap_##name)(void); \
126 if (wrap_##name == NULL && \
127 !(wrap_##name = dlsym(RTLD_DEFAULT, \
129 fprintf(stderr, "Missing symbol 'wrap_" #name "'\n"); \
133 return wrap_##name(); \
137 * VIR_MOCK_LINK_VOID_ARGS:
138 * @name: the symbol name to replace
139 * @...: pairs of parameter type and parameter name
141 * Define a replacement for @name which invokes wrap_@name
142 * forwarding on all args, but with no return value.
144 #define VIR_MOCK_LINK_VOID_ARGS(name, ...) \
145 void name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)) \
147 static void (*wrap_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
148 if (wrap_##name == NULL && \
149 !(wrap_##name = dlsym(RTLD_DEFAULT, \
151 fprintf(stderr, "Missing symbol 'wrap_" #name "'\n"); \
155 wrap_##name(VIR_MOCK_ARGNAMES(__VA_ARGS__)); \
161 * The VIR_MOCK_STUB_NNN_MMM() macros are intended for use in
162 * LD_PRELOAD based wrappers. They provide a replacement for
163 * for an existing shared library symbol export. They will
164 * be a pure no-op, optionally returning a dummy value.
169 * VIR_MOCK_STUB_RET_ARGS:
170 * @name: the symbol name to replace
171 * @rettype: the return type
172 * @retval: the return value
173 * @...: pairs of parameter type and parameter name
175 * Define a replacement for @name which doesn't invoke anything, just
178 #define VIR_MOCK_STUB_RET_ARGS(name, rettype, retval, ...) \
179 rettype name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) \
185 * VIR_MOCK_STUB_RET_VOID:
186 * @name: the symbol name to replace
187 * @rettype: the return type
188 * @retval: value to return
190 * Define a replacement for @name which doesn't invoke anything, just
193 #define VIR_MOCK_STUB_RET_VOID(name, rettype, retval) \
200 * VIR_MOCK_STUB_VOID_ARGS:
201 * @name: the symbol name to replace
202 * @...: pairs of parameter type and parameter name
204 * Define a replacement for @name which doesn't invoke or return
207 #define VIR_MOCK_STUB_VOID_ARGS(name, ...) \
208 void name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) \
215 * VIR_MOCK_STUB_VOID_VOID:
216 * @name: the symbol name to replace
218 * Define a replacement for @name which doesn't invoke or return
221 #define VIR_MOCK_STUB_VOID_VOID(name) \
228 * The VIR_MOCK_IMPL_NNN_MMM() macros are intended for use in the
229 * individual test suites. The define a stub implementation of
230 * the wrapped method and insert the caller provided code snippet
231 * as the body of the method.
234 #define VIR_MOCK_IMPL_RET_ARGS(name, rettype, ...) \
235 rettype name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \
236 static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
237 rettype name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__))
239 #define VIR_MOCK_IMPL_RET_VOID(name, rettype) \
240 rettype name(void); \
241 static rettype (*real_##name)(void); \
244 #define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \
245 void name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \
246 static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
247 void name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__))
249 #define VIR_MOCK_IMPL_VOID_VOID(name) \
251 static void (*real_##name)(void); \
255 * The VIR_MOCK_WRAP_NNN_MMM() macros are intended for use in the
256 * individual test suites. The define a stub implementation of
257 * the wrapped method and insert the caller provided code snippet
258 * as the body of the method.
261 #define VIR_MOCK_WRAP_RET_ARGS(name, rettype, ...) \
262 rettype wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \
263 static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
264 rettype wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__))
266 #define VIR_MOCK_WRAP_RET_VOID(name, rettype) \
267 rettype wrap_##name(void); \
268 static rettype (*real_##name)(void); \
269 rettype wrap_##name(void)
271 #define VIR_MOCK_WRAP_VOID_ARGS(name, ...) \
272 void wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \
273 static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \
274 void wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__))
276 #define VIR_MOCK_WRAP_VOID_VOID(name) \
277 void wrap_##name(void); \
278 static void (*real_##name)(void); \
279 void wrap_##name(void)
282 #define VIR_MOCK_REAL_INIT(name) \
284 if (real_##name == NULL && \
285 !(real_##name = dlsym(RTLD_NEXT, \
287 fprintf(stderr, "Missing symbol '" #name "'\n"); \