164 lines
4.9 KiB
Ruby
164 lines
4.9 KiB
Ruby
# Creates mock files from parsed header files that can be linked into applications.
|
|
# The mocks created are compatible with CMock for use with Ceedling.
|
|
|
|
class FffMockGenerator
|
|
|
|
def self.create_mock_header(module_name, mock_name, parsed_header, pre_includes=nil,
|
|
post_includes=nil)
|
|
output = StringIO.new
|
|
write_opening_include_guard(mock_name, output)
|
|
output.puts
|
|
write_extra_includes(pre_includes, output)
|
|
write_header_includes(module_name, output)
|
|
write_extra_includes(post_includes, output)
|
|
output.puts
|
|
write_typedefs(parsed_header, output)
|
|
output.puts
|
|
write_function_declarations(parsed_header, output)
|
|
output.puts
|
|
write_control_function_prototypes(mock_name, output)
|
|
output.puts
|
|
write_closing_include_guard(mock_name, output)
|
|
output.string
|
|
end
|
|
|
|
def self.create_mock_source (mock_name, parsed_header, pre_includes=nil,
|
|
post_includes=nil)
|
|
output = StringIO.new
|
|
write_extra_includes(pre_includes, output)
|
|
write_source_includes(mock_name, output)
|
|
write_extra_includes(post_includes, output)
|
|
output.puts
|
|
write_function_definitions(parsed_header, output)
|
|
output.puts
|
|
write_control_function_definitions(mock_name, parsed_header, output)
|
|
output.string
|
|
end
|
|
|
|
private
|
|
|
|
# Header file generation functions.
|
|
|
|
def self.write_opening_include_guard(mock_name, output)
|
|
output.puts "#ifndef #{mock_name}_H"
|
|
output.puts "#define #{mock_name}_H"
|
|
end
|
|
|
|
def self.write_header_includes(module_name, output)
|
|
output.puts %{#include "fff.h"}
|
|
output.puts %{#include "fff_unity_helper.h"}
|
|
output.puts %{#include "#{module_name}.h"}
|
|
end
|
|
|
|
def self.write_typedefs(parsed_header, output)
|
|
return unless parsed_header.key?(:typedefs)
|
|
parsed_header[:typedefs].each do |typedef|
|
|
output.puts typedef
|
|
end
|
|
end
|
|
|
|
def self.write_function_declarations(parsed_header, output)
|
|
write_function_macros("DECLARE", parsed_header, output)
|
|
end
|
|
|
|
|
|
def self.write_control_function_prototypes(mock_name, output)
|
|
output.puts "void #{mock_name}_Init(void);"
|
|
output.puts "void #{mock_name}_Verify(void);"
|
|
output.puts "void #{mock_name}_Destroy(void);"
|
|
end
|
|
|
|
def self.write_closing_include_guard(mock_name, output)
|
|
output.puts "#endif // #{mock_name}_H"
|
|
end
|
|
|
|
# Source file generation functions.
|
|
|
|
def self.write_source_includes (mock_name, output)
|
|
output.puts "#include <string.h>"
|
|
output.puts %{#include "fff.h"}
|
|
output.puts %{#include "#{mock_name}.h"}
|
|
end
|
|
|
|
def self.write_function_definitions(parsed_header, output)
|
|
write_function_macros("DEFINE", parsed_header, output)
|
|
end
|
|
|
|
def self.write_control_function_definitions(mock_name, parsed_header, output)
|
|
output.puts "void #{mock_name}_Init(void)"
|
|
output.puts "{"
|
|
# In the init function, reset the FFF globals. These are used for things
|
|
# like the call history.
|
|
output.puts " FFF_RESET_HISTORY();"
|
|
|
|
# Also, reset all of the fakes.
|
|
if parsed_header[:functions]
|
|
parsed_header[:functions].each do |function|
|
|
output.puts " RESET_FAKE(#{function[:name]})"
|
|
end
|
|
end
|
|
output.puts "}"
|
|
output.puts "void #{mock_name}_Verify(void)"
|
|
output.puts "{"
|
|
output.puts "}"
|
|
output.puts "void #{mock_name}_Destroy(void)"
|
|
output.puts "{"
|
|
output.puts "}"
|
|
end
|
|
|
|
# Shared functions.
|
|
|
|
def self.write_extra_includes(includes, output)
|
|
if includes
|
|
includes.each {|inc| output.puts "#include #{inc}\n"}
|
|
end
|
|
end
|
|
|
|
def self.write_function_macros(macro_type, parsed_header, output)
|
|
return unless parsed_header.key?(:functions)
|
|
parsed_header[:functions].each do |function|
|
|
name = function[:name]
|
|
return_type = function[:return][:type]
|
|
if function.has_key? :modifier
|
|
# Prepend any modifier. If there isn't one, trim any leading whitespace.
|
|
return_type = "#{function[:modifier]} #{return_type}".lstrip
|
|
end
|
|
arg_count = function[:args].size
|
|
|
|
# Check for variable arguments.
|
|
var_arg_suffix = ""
|
|
if function[:var_arg]
|
|
# If there are are variable arguments, then we need to add this argument
|
|
# to the count, update the suffix that will get added to the macro.
|
|
arg_count += 1
|
|
var_arg_suffix = "_VARARG"
|
|
end
|
|
|
|
# Generate the correct macro.
|
|
if return_type == 'void'
|
|
output.print "#{macro_type}_FAKE_VOID_FUNC#{arg_count}#{var_arg_suffix}(#{name}"
|
|
else
|
|
output.print "#{macro_type}_FAKE_VALUE_FUNC#{arg_count}#{var_arg_suffix}(#{return_type}, #{name}"
|
|
end
|
|
|
|
# Append each argument type.
|
|
function[:args].each do |arg|
|
|
output.print ", "
|
|
if arg[:const?]
|
|
output.print "const "
|
|
end
|
|
output.print "#{arg[:type]}"
|
|
end
|
|
|
|
# If this argument list ends with a variable argument, add it here at the end.
|
|
if function[:var_arg]
|
|
output.print ", ..."
|
|
end
|
|
|
|
# Close the declaration.
|
|
output.puts ");"
|
|
end
|
|
end
|
|
|
|
end
|