2014-03-11 21:48:10 +04:00
/*
* virmock . h : helper for mocking C functions
*
* Copyright ( C ) 2014 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*
*/
# ifndef __VIR_MOCK_H__
# define __VIR_MOCK_H__
2014-04-25 18:48:30 +04:00
# if HAVE_DLFCN_H
# include <dlfcn.h>
# endif
2014-03-11 21:48:10 +04:00
# include "internal.h"
# 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)
# 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
# define VIR_MOCK_ARG_PASTE(a, b, ...) a##b(__VA_ARGS__)
# define VIR_MOCK_ARGNAME(a, b) b
# define VIR_MOCK_ARGTYPE(a, b) a
# define VIR_MOCK_ARGTYPENAME(a, b) a b
# define VIR_MOCK_ARGTYPENAME_UNUSED(a, b) a b ATTRIBUTE_UNUSED
# define VIR_MOCK_GET_ARG2(z, a, b) z(a, b)
# define VIR_MOCK_GET_ARG3(z, a, b, c) z(a, b)
# define VIR_MOCK_GET_ARG4(z, a, b, c, d) z(a, b), z(c, d)
# define VIR_MOCK_GET_ARG5(z, a, b, c, d, e) z(a, b), z(c, d)
# define VIR_MOCK_GET_ARG6(z, a, b, c, d, e, f) z(a, b), z(c, d), z(e, f)
# define VIR_MOCK_GET_ARG7(z, a, b, c, d, e, f, g) z(a, b), z(c, d), z(e, f)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# 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)
# define VIR_MOCK_ARGNAMES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_ARGNAMES(...) \
2014-03-11 21:48:10 +04:00
VIR_MOCK_ARGNAMES_EXPAND ( VIR_MOCK_GET_ARG , VIR_MOCK_COUNT_ARGS ( __VA_ARGS__ ) , VIR_MOCK_ARGNAME , __VA_ARGS__ )
# define VIR_MOCK_ARGTYPES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_ARGTYPES(...) \
2014-03-11 21:48:10 +04:00
VIR_MOCK_ARGTYPES_EXPAND ( VIR_MOCK_GET_ARG , VIR_MOCK_COUNT_ARGS ( __VA_ARGS__ ) , VIR_MOCK_ARGTYPE , __VA_ARGS__ )
# define VIR_MOCK_ARGTYPENAMES_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_ARGTYPENAMES(...) \
2014-03-11 21:48:10 +04:00
VIR_MOCK_ARGTYPENAMES_EXPAND ( VIR_MOCK_GET_ARG , VIR_MOCK_COUNT_ARGS ( __VA_ARGS__ ) , VIR_MOCK_ARGTYPENAME , __VA_ARGS__ )
# define VIR_MOCK_ARGTYPENAMES_UNUSED_EXPAND(a, b, ...) VIR_MOCK_ARG_PASTE(a, b, __VA_ARGS__)
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_ARGTYPENAMES_UNUSED(...) \
2014-03-11 21:48:10 +04:00
VIR_MOCK_ARGTYPENAMES_UNUSED_EXPAND ( VIR_MOCK_GET_ARG , VIR_MOCK_COUNT_ARGS ( __VA_ARGS__ ) , VIR_MOCK_ARGTYPENAME_UNUSED , __VA_ARGS__ )
/*
* The VIR_MOCK_LINK_NNN_MMM ( ) macros are intended for use in
* LD_PRELOAD based wrappers . They provide a replacement for
* for an existing shared library symbol export . They will
* then lookup the same symbol name but with ' wrap_ ' prefixed
* on it , and call that .
*
* The actual test suite should provide the implemention of
* the wrap_XXXX symbol , using the VIR_MOCK_WRAP_NNN_MMM
* macros .
*/
/**
* VIR_MOCK_LINK_RET_ARGS :
* @ name : the symbol name to replace
* @ rettype : the return type
* @ . . . : pairs of parameter type and parameter name
*
* Define a replacement for @ name which invokes wrap_ @ name
* forwarding on all args , and passing back the return value .
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_LINK_RET_ARGS(name, rettype, ...) \
rettype name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) \
{ \
static rettype ( * wrap_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
if ( wrap_ # # name = = NULL & & \
! ( wrap_ # # name = dlsym ( RTLD_DEFAULT , \
" wrap_ " # name ) ) ) { \
fprintf ( stderr , " Missing symbol 'wrap_ " # name " ' \n " ) ; \
abort ( ) ; \
} \
\
return wrap_ # # name ( VIR_MOCK_ARGNAMES ( __VA_ARGS__ ) ) ; \
2014-03-11 21:48:10 +04:00
}
/**
* VIR_MOCK_LINK_RET_VOID :
* @ name : the symbol name to replace
* @ rettype : the return type
*
* Define a replacement for @ name which invokes wrap_ @ name
* with no arguments , and passing back the return value .
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_LINK_RET_VOID(name, rettype) \
rettype name ( void ) \
{ \
static rettype ( * wrap_ # # name ) ( void ) ; \
if ( wrap_ # # name = = NULL & & \
! ( wrap_ # # name = dlsym ( RTLD_DEFAULT , \
" wrap_ " # name ) ) ) { \
fprintf ( stderr , " Missing symbol 'wrap_ " # name " ' \n " ) ; \
abort ( ) ; \
} \
\
return wrap_ # # name ( ) ; \
2014-03-11 21:48:10 +04:00
}
/**
* VIR_MOCK_LINK_VOID_ARGS :
* @ name : the symbol name to replace
* @ . . . : pairs of parameter type and parameter name
*
* Define a replacement for @ name which invokes wrap_ @ name
* forwarding on all args , but with no return value .
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_LINK_VOID_ARGS(name, ...) \
void name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) \
{ \
2014-03-11 21:48:10 +04:00
static void ( * wrap_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
2017-11-03 15:09:47 +03:00
if ( wrap_ # # name = = NULL & & \
! ( wrap_ # # name = dlsym ( RTLD_DEFAULT , \
" wrap_ " # name ) ) ) { \
fprintf ( stderr , " Missing symbol 'wrap_ " # name " ' \n " ) ; \
abort ( ) ; \
} \
\
wrap_ # # name ( VIR_MOCK_ARGNAMES ( __VA_ARGS__ ) ) ; \
2014-03-11 21:48:10 +04:00
}
/*
* The VIR_MOCK_STUB_NNN_MMM ( ) macros are intended for use in
* LD_PRELOAD based wrappers . They provide a replacement for
* for an existing shared library symbol export . They will
* be a pure no - op , optionally returning a dummy value .
*/
/**
* VIR_MOCK_STUB_RET_ARGS :
* @ name : the symbol name to replace
* @ rettype : the return type
* @ retval : the return value
* @ . . . : pairs of parameter type and parameter name
*
2014-11-26 13:55:59 +03:00
* Define a replacement for @ name which doesn ' t invoke anything , just
* returns @ retval .
2014-03-11 21:48:10 +04:00
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_STUB_RET_ARGS(name, rettype, retval, ...) \
rettype name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) ) \
{ \
return retval ; \
2014-03-11 21:48:10 +04:00
}
/**
* VIR_MOCK_STUB_RET_VOID :
* @ name : the symbol name to replace
* @ rettype : the return type
2014-11-26 13:55:59 +03:00
* @ retval : value to return
2014-03-11 21:48:10 +04:00
*
2014-11-26 13:55:59 +03:00
* Define a replacement for @ name which doesn ' t invoke anything , just
* returns @ retval .
2014-03-11 21:48:10 +04:00
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_STUB_RET_VOID(name, rettype, retval) \
rettype name ( void ) \
{ \
return retval ; \
2014-03-11 21:48:10 +04:00
}
/**
* VIR_MOCK_STUB_VOID_ARGS :
* @ name : the symbol name to replace
* @ . . . : pairs of parameter type and parameter name
*
2014-11-26 13:55:59 +03:00
* Define a replacement for @ name which doesn ' t invoke or return
* anything .
2014-03-11 21:48:10 +04:00
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_STUB_VOID_ARGS(name, ...) \
void name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) ) \
{ \
2014-03-11 21:48:10 +04:00
}
/**
* VIR_MOCK_STUB_VOID_VOID :
* @ name : the symbol name to replace
*
2014-11-26 13:55:59 +03:00
* Define a replacement for @ name which doesn ' t invoke or return
* anything .
2014-03-11 21:48:10 +04:00
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_STUB_VOID_VOID(name) \
void name ( void ) \
{ \
2014-03-11 21:48:10 +04:00
}
/*
* The VIR_MOCK_IMPL_NNN_MMM ( ) macros are intended for use in the
* individual test suites . The define a stub implementation of
* the wrapped method and insert the caller provided code snippet
* as the body of the method .
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_IMPL_RET_ARGS(name, rettype, ...) \
rettype name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) ; \
static rettype ( * real_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
2014-06-03 15:02:52 +04:00
rettype name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_IMPL_RET_VOID(name, rettype) \
rettype name ( void ) ; \
static rettype ( * real_ # # name ) ( void ) ; \
2014-06-03 15:02:52 +04:00
rettype name ( void )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \
void name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) ; \
static void ( * real_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
2014-06-03 15:02:52 +04:00
void name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_IMPL_VOID_VOID(name) \
void name ( void ) ; \
static void ( * real_ # # name ) ( void ) ; \
2014-06-03 15:02:52 +04:00
void name ( void )
/*
* The VIR_MOCK_WRAP_NNN_MMM ( ) macros are intended for use in the
* individual test suites . The define a stub implementation of
* the wrapped method and insert the caller provided code snippet
* as the body of the method .
*/
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_WRAP_RET_ARGS(name, rettype, ...) \
rettype wrap_ # # name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) ; \
static rettype ( * real_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
2014-03-11 21:48:10 +04:00
rettype wrap_ # # name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_WRAP_RET_VOID(name, rettype) \
rettype wrap_ # # name ( void ) ; \
static rettype ( * real_ # # name ) ( void ) ; \
2014-03-11 21:48:10 +04:00
rettype wrap_ # # name ( void )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_WRAP_VOID_ARGS(name, ...) \
void wrap_ # # name ( VIR_MOCK_ARGTYPENAMES ( __VA_ARGS__ ) ) ; \
static void ( * real_ # # name ) ( VIR_MOCK_ARGTYPES ( __VA_ARGS__ ) ) ; \
2014-03-11 21:48:10 +04:00
void wrap_ # # name ( VIR_MOCK_ARGTYPENAMES_UNUSED ( __VA_ARGS__ ) )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_WRAP_VOID_VOID(name) \
void wrap_ # # name ( void ) ; \
static void ( * real_ # # name ) ( void ) ; \
2014-03-11 21:48:10 +04:00
void wrap_ # # name ( void )
2014-06-03 15:02:52 +04:00
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_REAL_INIT(name) \
do { \
if ( real_ # # name = = NULL & & \
! ( real_ # # name = dlsym ( RTLD_NEXT , \
# name))) { \
fprintf ( stderr , " Missing symbol ' " # name " ' \n " ) ; \
abort ( ) ; \
} \
2014-06-03 15:02:52 +04:00
} while ( 0 )
2017-11-03 15:09:47 +03:00
# define VIR_MOCK_REAL_INIT_ALT(name1, name2) \
do { \
if ( ! ( real_ # # name1 = dlsym ( RTLD_NEXT , # name1 ) ) & & \
! ( real_ # # name2 = dlsym ( RTLD_NEXT , # name2 ) ) ) { \
fprintf ( stderr , " Cannot find real '%s' or '%s' symbol \n " , \
# name1, #name2); \
abort ( ) ; \
} \
2016-05-13 13:32:00 +03:00
} while ( 0 )
2014-03-11 21:48:10 +04:00
# endif /* __VIR_MOCK_H__ */