diff --git a/.gitignore b/.gitignore index 0187b3d..ed09e27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ build/ *~ +*.sublime-project +*.sublime-workspace diff --git a/README.md b/README.md index fbac485..bf593d0 100644 --- a/README.md +++ b/README.md @@ -448,6 +448,32 @@ TEST_F(FFFTestSuite, test_fake_with_function_pointer) /* and ofcourse our custom fake correctly calls the registered callback */ ASSERT_EQ(cb_timeout_called, 1); } +``` +## How do I reuse a fake across multiple test-suites? +FFF functions like FAKE_VALUE_FUNC will perform both the declaration AND the definition of the fake function and the corresponding data structs. This cannot be placed in a header, since it will lead to multiple definitions of the fake functions. + +The solution is to separate declaration and definition of the fakes, and place the declaration into a public header file, and the definition into a private source file. + +Here is an example of how it could be done: + +``` +/* Public header file */ +#include "fff.h" + +DECLARE_FAKE_VALUE_FUNC(int, value_function, int, int); +DECLARE_FAKE_VOID_FUNC(void_function, int, int); +DECLARE_FAKE_VALUE_FUNC_VARARG(int, value_function_vargs, const char *, int, ...); +DECLARE_FAKE_VOID_FUNC_VARARG(void_function_vargs, const char *, int, ...); + + +/* Private source file file */ +#include "public_header.h" + +DEFINE_FAKE_VALUE_FUNC(int, value_function, int, int); +DEFINE_FAKE_VOID_FUNC(void_function, int, int); +DEFINE_FAKE_VALUE_FUNC_VARARG(int, value_function_vargs, const char *, int, ...); +DEFINE_FAKE_VOID_FUNC_VARARG(void_function_vargs, const char *, int, ...); + ``` ## Find out more... diff --git a/fakegen.rb b/fakegen.rb index b030974..a393eed 100644 --- a/fakegen.rb +++ b/fakegen.rb @@ -403,6 +403,11 @@ def include_guard putd "#endif /* FAKE_FUNCTIONS */" end +def generate_arg_sequence(args, prefix, do_reverse, joinstr) + fmap = (0..args).flat_map {|i| [prefix + i.to_s]} + if do_reverse then fmap.reverse.join(joinstr) else fmap.join(", ") end +end + def output_macro_counting_shortcuts putd <<-MACRO_COUNTING @@ -412,12 +417,27 @@ def output_macro_counting_shortcuts #define PP_NARG_MINUS2_(...) \ PP_ARG_MINUS2_N(__VA_ARGS__) -#define PP_ARG_MINUS2_N(returnVal, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, N, ...) N +#define PP_ARG_MINUS2_N(returnVal, #{generate_arg_sequence($MAX_ARGS - 1, '_', false, ", ")}, N, ...) N #define PP_RSEQ_N_MINUS2() \ - 19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + #{generate_arg_sequence($MAX_ARGS - 1, '', true, ',')} +#define PP_NARG_MINUS1(...) \ + PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()) + +#define PP_NARG_MINUS1_(...) \ + PP_ARG_MINUS1_N(__VA_ARGS__) + +#define PP_ARG_MINUS1_N(#{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N + +#define PP_RSEQ_N_MINUS1() \ + #{generate_arg_sequence($MAX_ARGS, '', true, ',')} + + + +/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */ + #define FAKE_VALUE_FUNC(...) \ FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) @@ -428,19 +448,6 @@ def output_macro_counting_shortcuts FAKE_VALUE_FUNC ## N(__VA_ARGS__) - -#define PP_NARG_MINUS1(...) \ - PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()) - -#define PP_NARG_MINUS1_(...) \ - PP_ARG_MINUS1_N(__VA_ARGS__) - -#define PP_ARG_MINUS1_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N - -#define PP_RSEQ_N_MINUS1() \ - 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 - - #define FAKE_VOID_FUNC(...) \ FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) @@ -470,6 +477,92 @@ def output_macro_counting_shortcuts #define FUNC_VOID_VARARG_N(N,...) \ FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + + +/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */ + +#define DECLARE_FAKE_VALUE_FUNC(...) \ + DEC_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VALUE_(N,...) \ + DEC_FUNC_VALUE_N(N,__VA_ARGS__) + +#define DEC_FUNC_VALUE_N(N,...) \ + DECLARE_FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + +#define DECLARE_FAKE_VOID_FUNC(...) \ + DEC_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VOID_(N,...) \ + DEC_FUNC_VOID_N(N, __VA_ARGS__) + +#define DEC_FUNC_VOID_N(N,...) \ + DECLARE_FAKE_VOID_FUNC ## N(__VA_ARGS__) + + +#define DECLARE_FAKE_VALUE_FUNC_VARARG(...) \ + DEC_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VALUE_VARARG_(N,...) \ + DEC_FUNC_VALUE_VARARG_N(N, __VA_ARGS__) + +#define DEC_FUNC_VALUE_VARARG_N(N,...) \ + DECLARE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__) + + +#define DECLARE_FAKE_VOID_FUNC_VARARG(...) \ + DEC_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VOID_VARARG_(N,...) \ + DEC_FUNC_VOID_VARARG_N(N, __VA_ARGS__) + +#define DEC_FUNC_VOID_VARARG_N(N,...) \ + DECLARE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + + + +/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */ + +#define DEFINE_FAKE_VALUE_FUNC(...) \ + DEF_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VALUE_(N,...) \ + DEF_FUNC_VALUE_N(N,__VA_ARGS__) + +#define DEF_FUNC_VALUE_N(N,...) \ + DEFINE_FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + +#define DEFINE_FAKE_VOID_FUNC(...) \ + DEF_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VOID_(N,...) \ + DEF_FUNC_VOID_N(N,__VA_ARGS__) + +#define DEF_FUNC_VOID_N(N,...) \ + DEFINE_FAKE_VOID_FUNC ## N(__VA_ARGS__) + + +#define DEFINE_FAKE_VALUE_FUNC_VARARG(...) \ + DEF_FUNC_VALUE_VARARG(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VALUE_VARARG(N,...) \ + DEF_FUNC_VALUE_VARARG_N(N,__VA_ARGS__) + +#define DEF_FUNC_VALUE_VARARG_N(N,...) \ + DEFINE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__) + + +#define DEFINE_FAKE_VOID_FUNC_VARARG(...) \ + DEF_FUNC_VOID_VARARG(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VOID_VARARG(N,...) \ + DEF_FUNC_VOID_VARARG_N(N,__VA_ARGS__) + +#define DEF_FUNC_VOID_VARARG_N(N,...) \ + DEFINE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + MACRO_COUNTING end diff --git a/fff.h b/fff.h index d807ab4..4094b91 100644 --- a/fff.h +++ b/fff.h @@ -5821,14 +5821,6 @@ FFF_END_EXTERN_C \ #define PP_RSEQ_N_MINUS2() 19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 -#define FAKE_VALUE_FUNC(...) FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) - -#define FUNC_VALUE_(N,...) FUNC_VALUE_N(N,__VA_ARGS__) - -#define FUNC_VALUE_N(N,...) FAKE_VALUE_FUNC ## N(__VA_ARGS__) - - - #define PP_NARG_MINUS1(...) PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()) #define PP_NARG_MINUS1_(...) PP_ARG_MINUS1_N(__VA_ARGS__) @@ -5838,6 +5830,16 @@ FFF_END_EXTERN_C \ #define PP_RSEQ_N_MINUS1() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + +/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */ + +#define FAKE_VALUE_FUNC(...) FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define FUNC_VALUE_(N,...) FUNC_VALUE_N(N,__VA_ARGS__) + +#define FUNC_VALUE_N(N,...) FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + #define FAKE_VOID_FUNC(...) FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) #define FUNC_VOID_(N,...) FUNC_VOID_N(N,__VA_ARGS__) @@ -5859,4 +5861,66 @@ FFF_END_EXTERN_C \ #define FUNC_VOID_VARARG_N(N,...) FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + +/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */ + +#define DECLARE_FAKE_VALUE_FUNC(...) DEC_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VALUE_(N,...) DEC_FUNC_VALUE_N(N,__VA_ARGS__) + +#define DEC_FUNC_VALUE_N(N,...) DECLARE_FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + +#define DECLARE_FAKE_VOID_FUNC(...) DEC_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VOID_(N,...) DEC_FUNC_VOID_N(N, __VA_ARGS__) + +#define DEC_FUNC_VOID_N(N,...) DECLARE_FAKE_VOID_FUNC ## N(__VA_ARGS__) + + +#define DECLARE_FAKE_VALUE_FUNC_VARARG(...) DEC_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VALUE_VARARG_(N,...) DEC_FUNC_VALUE_VARARG_N(N, __VA_ARGS__) + +#define DEC_FUNC_VALUE_VARARG_N(N,...) DECLARE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__) + + +#define DECLARE_FAKE_VOID_FUNC_VARARG(...) DEC_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEC_FUNC_VOID_VARARG_(N,...) DEC_FUNC_VOID_VARARG_N(N, __VA_ARGS__) + +#define DEC_FUNC_VOID_VARARG_N(N,...) DECLARE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + + + +/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */ + +#define DEFINE_FAKE_VALUE_FUNC(...) DEF_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VALUE_(N,...) DEF_FUNC_VALUE_N(N,__VA_ARGS__) + +#define DEF_FUNC_VALUE_N(N,...) DEFINE_FAKE_VALUE_FUNC ## N(__VA_ARGS__) + + +#define DEFINE_FAKE_VOID_FUNC(...) DEF_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VOID_(N,...) DEF_FUNC_VOID_N(N,__VA_ARGS__) + +#define DEF_FUNC_VOID_N(N,...) DEFINE_FAKE_VOID_FUNC ## N(__VA_ARGS__) + + +#define DEFINE_FAKE_VALUE_FUNC_VARARG(...) DEF_FUNC_VALUE_VARARG(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VALUE_VARARG(N,...) DEF_FUNC_VALUE_VARARG_N(N,__VA_ARGS__) + +#define DEF_FUNC_VALUE_VARARG_N(N,...) DEFINE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__) + + +#define DEFINE_FAKE_VOID_FUNC_VARARG(...) DEF_FUNC_VOID_VARARG(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__) + +#define DEF_FUNC_VOID_VARARG(N,...) DEF_FUNC_VOID_VARARG_N(N,__VA_ARGS__) + +#define DEF_FUNC_VOID_VARARG_N(N,...) DEFINE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__) + + #endif /* FAKE_FUNCTIONS */ diff --git a/test/global_fakes.c b/test/global_fakes.c index 1b93394..0acfe05 100644 --- a/test/global_fakes.c +++ b/test/global_fakes.c @@ -1,15 +1,16 @@ #include "global_fakes.h" #include // for memcpy -DEFINE_FAKE_VOID_FUNC1(voidfunc1, int); -DEFINE_FAKE_VOID_FUNC2(voidfunc2, char, char); -DEFINE_FAKE_VOID_FUNC1(voidfunc1outparam, char *); -DEFINE_FAKE_VALUE_FUNC0(long, longfunc0); -DEFINE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0); -DEFINE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0); -DEFINE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...); -DEFINE_FAKE_VALUE_FUNC3_VARARG(int, valuefunc3var, const char *, int, ...); +DEFINE_FAKE_VOID_FUNC(voidfunc1, int); +DEFINE_FAKE_VOID_FUNC(voidfunc2, char, char); +DEFINE_FAKE_VOID_FUNC(voidfunc1outparam, char *); + +DEFINE_FAKE_VALUE_FUNC(long, longfunc0); +DEFINE_FAKE_VALUE_FUNC(enum MYBOOL, enumfunc0); +DEFINE_FAKE_VALUE_FUNC(struct MyStruct, structfunc0); +DEFINE_FAKE_VOID_FUNC_VARARG(voidfunc3var, const char *, int, ...); +DEFINE_FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, const char *, int, ...); #ifndef __cplusplus -DEFINE_FAKE_VALUE_FUNC3(int, strlcpy3, char* const, const char* const, const size_t); +DEFINE_FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t); #endif /* __cplusplus */ -DEFINE_FAKE_VOID_FUNC20(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); +DEFINE_FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); diff --git a/test/global_fakes.h b/test/global_fakes.h index 8ee7c3f..57afb4d 100644 --- a/test/global_fakes.h +++ b/test/global_fakes.h @@ -24,18 +24,18 @@ enum MYBOOL enumfunc(); struct MyStruct structfunc(); //// End Imaginary production code header file /// -DECLARE_FAKE_VOID_FUNC1(voidfunc1, int); -DECLARE_FAKE_VOID_FUNC2(voidfunc2, char, char); -DECLARE_FAKE_VOID_FUNC1(voidfunc1outparam, char *); -DECLARE_FAKE_VALUE_FUNC0(long, longfunc0); -DECLARE_FAKE_VALUE_FUNC0(enum MYBOOL, enumfunc0); -DECLARE_FAKE_VALUE_FUNC0(struct MyStruct, structfunc0); -DECLARE_FAKE_VOID_FUNC3_VARARG(voidfunc3var, const char *, int, ...); -DECLARE_FAKE_VALUE_FUNC3_VARARG(int, valuefunc3var, const char *, int, ...); -DECLARE_FAKE_VOID_FUNC20(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); +DECLARE_FAKE_VOID_FUNC(voidfunc1, int); +DECLARE_FAKE_VOID_FUNC(voidfunc2, char, char); +DECLARE_FAKE_VOID_FUNC(voidfunc1outparam, char *); +DECLARE_FAKE_VALUE_FUNC(long, longfunc0); +DECLARE_FAKE_VALUE_FUNC(enum MYBOOL, enumfunc0); +DECLARE_FAKE_VALUE_FUNC(struct MyStruct, structfunc0); +DECLARE_FAKE_VOID_FUNC_VARARG(voidfunc3var, const char *, int, ...); +DECLARE_FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, const char *, int, ...); +DECLARE_FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); #ifndef __cplusplus int strlcpy3(char* const, const char* const, const size_t); -DECLARE_FAKE_VALUE_FUNC3(int, strlcpy3, char* const, const char* const, const size_t); +DECLARE_FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t); #endif /* __cplusplus */ #endif /* GLOBAL_FAKES_H_ */