diff --git a/README b/README index 434771e..4ad5786 100644 --- a/README +++ b/README @@ -1,10 +1,25 @@ +Fake Function Framework (fff) +----------------------------- -cmock is a micro-framework for creating fake C functions for tests. +fff is a micro-framework for creating fake C functions for tests. -Here are some cmock truths: - * It maintains a call count and will capture the arguments sent - * It can be used in C or C++ tests +So whats the point? + * To make it easy to create fake functions for testing C code. + * To be simple + * To work in both C and C++ tests + +What can it do? + * It maintains a call count for each fake function + * It captures the arguments sent in each function call + * It captures a call history * It is simple - just include a header file and you are good to go. -What I'd like to add: +Under the hood: + * The fff.h header file is generated by a ruby script + * There are tests under src/test + * There are examples for testing an embedded UI under src/examples + +Still Todo: + * Function argument history * Proper mock - setting expectations, etc + diff --git a/src/fakegen.rb b/src/fakegen.rb index b5d2f9e..761e314 100644 --- a/src/fakegen.rb +++ b/src/fakegen.rb @@ -4,6 +4,9 @@ $cpp_output = true +$MAX_ARGS = 10 +$MAX_ARG_HISTORY = 10 +$MAX_CALL_HISTORY = 10 def output_macro(args, is_value_function) @@ -20,13 +23,13 @@ def output_macro(args, is_value_function) puts "{ \\" output_function_body(args, is_value_function) puts " } \\" - output_reset_function(args) + output_reset_function(args, is_value_function) } puts "STATIC_INIT(FUNCNAME) \\" if $cpp_output puts "" end -def output_reset_code +def output_cpp_reset_code puts <<-REGISTRATION #include typedef void (*void_fptr)(); @@ -44,7 +47,7 @@ void RESET_FAKES() REGISTRATION end -def output_static_initializer +def output_cpp_static_initializer puts <<-MY_STATIC_INITIALIZER #define STATIC_INIT(FUNCNAME) \\ class StaticInitializer_##FUNCNAME \\ @@ -83,13 +86,21 @@ def output_macro_name(macro_name, args, return_type) puts ") \\" end -def output_variables(args, is_value_function) - args.times { |i| puts " static ARG#{i}_TYPE FUNCNAME##_arg#{i}_val; \\" } +def output_argument_capture_variables(i) + # last argument + puts " static ARG#{i}_TYPE FUNCNAME##_arg#{i}_val; \\" + # argument history array +# puts " static ARG#{i}_TYPE FUNCNAME##_arg#{i}_history[];" +# puts " static int FUNCNAME##_arg#{i}_history_idx;" +end + +def output_variables(arg_count, is_value_function) + arg_count.times { |i| output_argument_capture_variables(i) } puts " static RETURN_TYPE FUNCNAME##_return_val; \\" unless not is_value_function puts " static int FUNCNAME##_call_count = 0; \\" end -def output_function_signature(args, is_value_function) +def output_function_signature(args_count, is_value_function) if is_value_function print " RETURN_TYPE FUNCNAME(" else @@ -97,27 +108,28 @@ def output_function_signature(args, is_value_function) end arguments = [] - args.times { |i| arguments << "ARG#{i}_TYPE arg#{i}" } + args_count.times { |i| arguments << "ARG#{i}_TYPE arg#{i}" } print arguments.join(", ") print ")" end -def output_function_body(args, is_value_function) +def output_function_body(arg_count, is_value_function) # capture arguments - args.times { |i| puts " FUNCNAME##_arg#{i}_val = arg#{i}; \\" } + arg_count.times { |i| puts " FUNCNAME##_arg#{i}_val = arg#{i}; \\" } # update call count puts " FUNCNAME##_call_count++; \\" # return something if value function puts " return FUNCNAME##_return_val; \\" unless not is_value_function end -def output_reset_function(args) +def output_reset_function(arg_count, is_value_function) puts " void FUNCNAME##_reset(){ \\" - args.times { |i| + arg_count.times { |i| puts " FUNCNAME##_arg#{i}_val = (ARG#{i}_TYPE) 0; \\" } puts " FUNCNAME##_call_count = 0; \\" + puts " FUNCNAME##_return_val = 0; \\" unless not is_value_function puts " } \\" end @@ -130,6 +142,19 @@ def define_reset_fake puts "" end +def define_call_history + puts "#define MAX_CALL_HISTORY #{$MAX_CALL_HISTORY}u" + puts "static void * call_history[MAX_CALL_HISTORY];" + puts "static unsigned int call_history_idx;" + puts "void RESET_HISTORY() { " + puts " call_history_idx = 0; " + puts "}" + + puts "#define REGISTER_CALL(function) \\" + puts " if(call_history_idx < MAX_CALL_HISTORY) call_history[call_history_idx++] = (void *)function;" +end + + def extern_c puts "extern \"C\"{ \\" unless !$cpp_output yield @@ -166,9 +191,10 @@ end # lets generate!! output_c_and_cpp{ - output_reset_code if $cpp_output - output_static_initializer if $cpp_output + output_cpp_reset_code if $cpp_output + output_cpp_static_initializer if $cpp_output 10.times {|arg_count| output_macro(arg_count, false)} 10.times {|arg_count| output_macro(arg_count, true)} define_reset_fake + define_call_history } \ No newline at end of file diff --git a/src/cmock.h b/src/fff.h similarity index 96% rename from src/cmock.h rename to src/fff.h index 61e7270..d4f7219 100644 --- a/src/cmock.h +++ b/src/fff.h @@ -313,6 +313,7 @@ extern "C"{ \ } \ void FUNCNAME##_reset(){ \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -332,6 +333,7 @@ extern "C"{ \ void FUNCNAME##_reset(){ \ FUNCNAME##_arg0_val = (ARG0_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -354,6 +356,7 @@ extern "C"{ \ FUNCNAME##_arg0_val = (ARG0_TYPE) 0; \ FUNCNAME##_arg1_val = (ARG1_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -379,6 +382,7 @@ extern "C"{ \ FUNCNAME##_arg1_val = (ARG1_TYPE) 0; \ FUNCNAME##_arg2_val = (ARG2_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -407,6 +411,7 @@ extern "C"{ \ FUNCNAME##_arg2_val = (ARG2_TYPE) 0; \ FUNCNAME##_arg3_val = (ARG3_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -438,6 +443,7 @@ extern "C"{ \ FUNCNAME##_arg3_val = (ARG3_TYPE) 0; \ FUNCNAME##_arg4_val = (ARG4_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -472,6 +478,7 @@ extern "C"{ \ FUNCNAME##_arg4_val = (ARG4_TYPE) 0; \ FUNCNAME##_arg5_val = (ARG5_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -509,6 +516,7 @@ extern "C"{ \ FUNCNAME##_arg5_val = (ARG5_TYPE) 0; \ FUNCNAME##_arg6_val = (ARG6_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -549,6 +557,7 @@ extern "C"{ \ FUNCNAME##_arg6_val = (ARG6_TYPE) 0; \ FUNCNAME##_arg7_val = (ARG7_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -592,6 +601,7 @@ extern "C"{ \ FUNCNAME##_arg7_val = (ARG7_TYPE) 0; \ FUNCNAME##_arg8_val = (ARG8_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ } \ STATIC_INIT(FUNCNAME) \ @@ -602,6 +612,14 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_reset(); \ } \ +#define MAX_CALL_HISTORY 10u +static void * call_history[MAX_CALL_HISTORY]; +static unsigned int call_history_idx; +void RESET_HISTORY() { + call_history_idx = 0; +} +#define REGISTER_CALL(function) \ + if(call_history_idx < MAX_CALL_HISTORY) call_history[call_history_idx++] = (void *)function; #else /* ansi c */ /* Defining a void function with 0 parameters*/ @@ -859,6 +877,7 @@ STATIC_INIT(FUNCNAME) \ } \ void FUNCNAME##_reset(){ \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -875,6 +894,7 @@ STATIC_INIT(FUNCNAME) \ void FUNCNAME##_reset(){ \ FUNCNAME##_arg0_val = (ARG0_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -894,6 +914,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg0_val = (ARG0_TYPE) 0; \ FUNCNAME##_arg1_val = (ARG1_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -916,6 +937,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg1_val = (ARG1_TYPE) 0; \ FUNCNAME##_arg2_val = (ARG2_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -941,6 +963,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg2_val = (ARG2_TYPE) 0; \ FUNCNAME##_arg3_val = (ARG3_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -969,6 +992,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg3_val = (ARG3_TYPE) 0; \ FUNCNAME##_arg4_val = (ARG4_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -1000,6 +1024,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg4_val = (ARG4_TYPE) 0; \ FUNCNAME##_arg5_val = (ARG5_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -1034,6 +1059,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg5_val = (ARG5_TYPE) 0; \ FUNCNAME##_arg6_val = (ARG6_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -1071,6 +1097,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg6_val = (ARG6_TYPE) 0; \ FUNCNAME##_arg7_val = (ARG7_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -1111,6 +1138,7 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_arg7_val = (ARG7_TYPE) 0; \ FUNCNAME##_arg8_val = (ARG8_TYPE) 0; \ FUNCNAME##_call_count = 0; \ + FUNCNAME##_return_val = 0; \ } \ @@ -1119,6 +1147,14 @@ STATIC_INIT(FUNCNAME) \ FUNCNAME##_reset(); \ } \ +#define MAX_CALL_HISTORY 10u +static void * call_history[MAX_CALL_HISTORY]; +static unsigned int call_history_idx; +void RESET_HISTORY() { + call_history_idx = 0; +} +#define REGISTER_CALL(function) \ + if(call_history_idx < MAX_CALL_HISTORY) call_history[call_history_idx++] = (void *)function; #endif /* cpp/ansi c */ #endif // FAKE_FUNCTIONS diff --git a/src/test/cmocktest.c b/src/test/cmocktest.c index 10e8729..ec54ada 100644 --- a/src/test/cmocktest.c +++ b/src/test/cmocktest.c @@ -6,7 +6,7 @@ */ #include "embedded.h" -#include "../cmock.h" +#include "../fff.h" #include #include diff --git a/src/test/cppmocktest.cpp b/src/test/cppmocktest.cpp index 3d3771d..c99f60e 100644 --- a/src/test/cppmocktest.cpp +++ b/src/test/cppmocktest.cpp @@ -6,7 +6,7 @@ // Description : Hello World in C++, Ansi-style //============================================================================ -#include "../cmock.h" +#include "../fff.h" extern "C"{ #include "embedded.h"