mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-09-21 01:27:27 +00:00
Merge pull request #187 from jlindgren90/array-typedefs
Add treat_as_array configuration option.
This commit is contained in:
@@ -479,6 +479,18 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
* 'float': 'FLOAT'
|
||||
* 'double': 'FLOAT'
|
||||
|
||||
* `:treat_as_array`:
|
||||
A specialized sort of `:treat_as` to be used when you've created a
|
||||
typedef of an array type, such as `typedef int TenIntegers[10];`. This
|
||||
is a hash of typedef name to element type. For example:
|
||||
|
||||
{ "TenIntegers" => "int",
|
||||
"ArrayOfFloat" => "float" }
|
||||
|
||||
Telling CMock about these typedefs allows it to be more intelligent
|
||||
about parameters of such types, so that you can use features like
|
||||
ExpectWithArray and ReturnArrayThruPtr with them.
|
||||
|
||||
* `:treat_as_void`:
|
||||
We've seen "fun" legacy systems typedef 'void' with a custom type,
|
||||
like MY_VOID. Add any instances of those to this list to help CMock
|
||||
|
||||
@@ -22,6 +22,7 @@ class CMockConfig
|
||||
:fail_on_unexpected_calls => true,
|
||||
:unity_helper_path => false,
|
||||
:treat_as => {},
|
||||
:treat_as_array => {},
|
||||
:treat_as_void => [],
|
||||
:memcmp_if_unknown => true,
|
||||
:when_no_prototypes => :warn, #the options being :ignore, :warn, or :error
|
||||
|
||||
@@ -73,7 +73,10 @@ class CMockGeneratorUtils
|
||||
if (arg[:ptr?] or @treat_as.include?(arg[:type]))
|
||||
" #{dest} = #{arg[:name]};\n"
|
||||
else
|
||||
" memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}), sizeof(#{arg[:type]}));\n"
|
||||
assert_expr = "sizeof(#{arg[:name]}) == sizeof(#{arg[:type]}) ? 1 : -1"
|
||||
comment = "/* add #{arg[:type]} to :treat_as_array if this causes an error */"
|
||||
" memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" +
|
||||
" sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class CMockHeaderParser
|
||||
@c_attr_noconst = cfg.attributes.uniq - ['const']
|
||||
@c_attributes = ['const'] + c_attr_noconst
|
||||
@c_calling_conventions = cfg.c_calling_conventions.uniq
|
||||
@treat_as_array = cfg.treat_as_array
|
||||
@treat_as_void = (['void'] + cfg.treat_as_void).uniq
|
||||
@declaration_parse_matcher = /([\d\w\s\*\(\),\[\]]+??)\(([\d\w\s\*\(\),\.\[\]+-]*)\)$/m
|
||||
@standards = (['int','short','char','long','unsigned','signed'] + cfg.treat_as.keys).uniq
|
||||
@@ -186,6 +187,15 @@ class CMockHeaderParser
|
||||
arg_info = parse_type_and_name(arg)
|
||||
arg_info.delete(:modifier) # don't care about this
|
||||
arg_info.delete(:c_calling_convention) # don't care about this
|
||||
|
||||
# in C, array arguments implicitly degrade to pointers
|
||||
# make the translation explicit here to simplify later logic
|
||||
if @treat_as_array[arg_info[:type]] and not arg_info[:ptr?] then
|
||||
arg_info[:type] = "#{@treat_as_array[arg_info[:type]]}*"
|
||||
arg_info[:type] = "const #{arg_info[:type]}" if arg_info[:const?]
|
||||
arg_info[:ptr?] = true
|
||||
end
|
||||
|
||||
args << arg_info
|
||||
end
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected3 = " cmock_call_instance->Expected_Kiwi = Kiwi;\n"
|
||||
|
||||
arg4 = { :name => "Lime", :const? => false, :type => 'LIME_T', :ptr? => false }
|
||||
expected4 = " memcpy((void*)(&cmock_call_instance->Expected_Lime), (void*)(&Lime), sizeof(LIME_T));\n"
|
||||
expected4 = " memcpy((void*)(&cmock_call_instance->Expected_Lime), (void*)(&Lime),\n" +
|
||||
" sizeof(LIME_T[sizeof(Lime) == sizeof(LIME_T) ? 1 : -1])); /* add LIME_T to :treat_as_array if this causes an error */\n"
|
||||
|
||||
assert_equal(expected1, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg1))
|
||||
assert_equal(expected2, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg2))
|
||||
@@ -131,7 +132,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" cmock_call_instance->ReturnThruPtr_Kiwi_Used = 0;\n"
|
||||
|
||||
arg4 = { :name => "Lime", :const? => false, :type => 'LIME_T', :ptr? => false }
|
||||
expected4 = " memcpy((void*)(&cmock_call_instance->Expected_Lime), (void*)(&Lime), sizeof(LIME_T));\n" +
|
||||
expected4 = " memcpy((void*)(&cmock_call_instance->Expected_Lime), (void*)(&Lime),\n" +
|
||||
" sizeof(LIME_T[sizeof(Lime) == sizeof(LIME_T) ? 1 : -1])); /* add LIME_T to :treat_as_array if this causes an error */\n" +
|
||||
" cmock_call_instance->IgnoreArg_Lime = 0;\n"
|
||||
|
||||
assert_equal(expected1, @cmock_generator_utils_complex.code_add_an_arg_expectation(arg1))
|
||||
@@ -153,7 +155,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
}
|
||||
expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, stuff)\n{\n" +
|
||||
" cmock_call_instance->Expected_MyIntPtr = MyIntPtr;\n" +
|
||||
" memcpy((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType), sizeof(MY_TYPE));\n" +
|
||||
" memcpy((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType),\n" +
|
||||
" sizeof(MY_TYPE[sizeof(MyMyType) == sizeof(MY_TYPE) ? 1 : -1])); /* add MY_TYPE to :treat_as_array if this causes an error */\n" +
|
||||
" cmock_call_instance->Expected_MyStr = MyStr;\n" +
|
||||
"}\n\n"
|
||||
assert_equal(expected, @cmock_generator_utils_simple.code_add_argument_loader(function))
|
||||
@@ -169,7 +172,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" cmock_call_instance->Expected_MyIntPtr_Depth = MyIntPtr_Depth;\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyIntPtr = 0;\n" +
|
||||
" cmock_call_instance->ReturnThruPtr_MyIntPtr_Used = 0;\n" +
|
||||
" memcpy((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType), sizeof(MY_TYPE));\n" +
|
||||
" memcpy((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType),\n" +
|
||||
" sizeof(MY_TYPE[sizeof(MyMyType) == sizeof(MY_TYPE) ? 1 : -1])); /* add MY_TYPE to :treat_as_array if this causes an error */\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyMyType = 0;\n" +
|
||||
" cmock_call_instance->Expected_MyStr = MyStr;\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyStr = 0;\n" +
|
||||
|
||||
@@ -19,6 +19,7 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
@config.expect :c_calling_conventions, ['__stdcall']
|
||||
@config.expect :treat_as_void, ['MY_FUNKY_VOID']
|
||||
@config.expect :treat_as, { "BANJOS" => "INT", "TUBAS" => "HEX16"}
|
||||
@config.expect :treat_as_array, {"IntArray" => "int", "Book" => "Page"}
|
||||
@config.expect :when_no_prototypes, :error
|
||||
@config.expect :verbosity, 1
|
||||
@config.expect :treat_externs, :exclude
|
||||
@@ -951,6 +952,32 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "converts typedef'd array arguments to pointers" do
|
||||
|
||||
source = "Book AddToBook(Book book, const IntArray values);\n"
|
||||
|
||||
expected = [{ :name => "AddToBook",
|
||||
:modifier=>"",
|
||||
:return => { :type => "Book",
|
||||
:name => "cmock_to_return",
|
||||
:str => "Book cmock_to_return",
|
||||
:void? => false,
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:const_ptr? => false
|
||||
},
|
||||
:var_arg => nil,
|
||||
:args => [{ :type => "Page*", :name => "book", :ptr? => true, :const? => false, :const_ptr? => false },
|
||||
{ :type => "const int*", :name => "values", :ptr? => true, :const? => true, :const_ptr? => false }],
|
||||
:args_string => "Book book, const IntArray values",
|
||||
:args_call => "book, values",
|
||||
:contains_ptr? => true
|
||||
}]
|
||||
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
|
||||
end
|
||||
|
||||
it "properly detect typedef'd variants of void and use those" do
|
||||
|
||||
source = "typedef (void) FUNKY_VOID_T;\n" +
|
||||
|
||||
Reference in New Issue
Block a user