class CMockGeneratorUtils

CMock Project - Automatic Mock Generation for C
Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
[Released under MIT License. Please refer to license.txt for details]

Attributes

arrays[RW]
cexception[RW]
config[RW]
helpers[RW]
ordered[RW]
ptr_handling[RW]

Public Class Methods

arg_type_with_const(arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 25
def self.arg_type_with_const(arg)
  # Restore any "const" that was removed in header parsing
  if arg[:type].include?('*')
    arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type]
  else
    arg[:const?] ? "const #{arg[:type]}" : arg[:type]
  end
end
new(config, helpers = {}) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 10
def initialize(config, helpers = {})
  @config = config
  @ptr_handling = @config.when_ptr
  @ordered      = @config.enforce_strict_ordering
  @arrays       = @config.plugins.include? :array
  @cexception   = @config.plugins.include? :cexception
  @expect_any   = @config.plugins.include? :expect_any_args
  @return_thru_ptr = @config.plugins.include? :return_thru_ptr
  @ignore_arg = @config.plugins.include? :ignore_arg
  @ignore = @config.plugins.include? :ignore
  @ignore_stateless = @config.plugins.include? :ignore_stateless
  @treat_as = @config.treat_as
  @helpers = helpers
end

Public Instance Methods

arg_type_with_const(arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 34
def arg_type_with_const(arg)
  self.class.arg_type_with_const(arg)
end
code_add_an_arg_expectation(arg, depth = 1) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 64
def code_add_an_arg_expectation(arg, depth = 1)
  lines =  code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg)
  lines << "  cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if @arrays && (depth.class == String)
  lines << "  cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if @ignore_arg
  lines << "  cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if @return_thru_ptr && ptr_or_str?(arg[:type]) && !(arg[:const?])
  lines
end
code_add_argument_loader(function) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 83
def code_add_argument_loader(function)
  if function[:args_string] != 'void'
    if @arrays
      args_string = function[:args].map do |m|
        type = arg_type_with_const(m)
        m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
      end.join(', ')
      "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string});\n" \
        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
        function[:args].inject('') { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1)) } +
        "}\n\n"
    else
      "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]});\n" \
        "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" +
        function[:args].inject('') { |all, arg| all + code_add_an_arg_expectation(arg) } +
        "}\n\n"
    end
  else
    ''
  end
end
code_add_base_expectation(func_name, global_ordering_supported = true) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 50
def code_add_base_expectation(func_name, global_ordering_supported = true)
  lines =  "  CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n"
  lines << "  CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n"
  lines << "  UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n"
  lines << "  memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n"
  lines << "  Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n"
  lines << "  Mock.#{func_name}_IgnoreBool = (char)0;\n" if @ignore || @ignore_stateless
  lines << "  cmock_call_instance->LineNumber = cmock_line;\n"
  lines << "  cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if @ordered && global_ordering_supported
  lines << "  cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if @cexception
  lines << "  cmock_call_instance->ExpectAnyArgsBool = (char)0;\n" if @expect_any
  lines
end
code_assign_argument_quickly(dest, arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 72
def code_assign_argument_quickly(dest, arg)
  if arg[:ptr?] || @treat_as.include?(arg[:type])
    "  #{dest} = #{arg[:name]};\n"
  else
    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
code_call_argument_loader(function) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 105
def code_call_argument_loader(function)
  if function[:args_string] != 'void'
    args = function[:args].map do |m|
      if @arrays && m[:ptr?] && !(m[:array_data?])
        "#{m[:name]}, 1"
      elsif @arrays && m[:array_size?]
        "#{m[:name]}, #{m[:name]}"
      else
        m[:name]
      end
    end
    "  CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
  else
    ''
  end
end
code_verify_an_arg_expectation(function, arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 38
def code_verify_an_arg_expectation(function, arg)
  if @arrays
    case @ptr_handling
    when :smart        then code_verify_an_arg_expectation_with_smart_arrays(function, arg)
    when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg)
    when :compare_ptr  then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only.  Disable one option."
    end
  else
    code_verify_an_arg_expectation_with_no_arrays(function, arg)
  end
end
code_verify_an_arg_expectation_with_no_arrays(function, arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 142
def code_verify_an_arg_expectation_with_no_arrays(function, arg)
  c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
  lines = ''
  lines << "  if (!#{ignore})\n" if @ignore_arg
  lines << "  {\n"
  lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
  case unity_func
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
    c_type_local = c_type.gsub(/\*$/, '')
    lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
    if pre == '&'
      lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << "    else\n"
      lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch); }\n"
    end
  when /_ARRAY/
    if pre == '&'
      lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << "    else\n"
      lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n"
    end
  else
    lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
  end
  lines << "  }\n"
  lines
end
code_verify_an_arg_expectation_with_normal_arrays(function, arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 177
def code_verify_an_arg_expectation_with_normal_arrays(function, arg)
  c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
  depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
  lines = ''
  lines << "  if (!#{ignore})\n" if @ignore_arg
  lines << "  {\n"
  lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
  case unity_func
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
    c_type_local = c_type.gsub(/\*$/, '')
    lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
    if pre == '&'
      lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << "    else\n"
      lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
    end
  when /_ARRAY/
    if pre == '&'
      lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << "    else\n"
      lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
    end
  else
    lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
  end
  lines << "  }\n"
  lines
end
code_verify_an_arg_expectation_with_smart_arrays(function, arg) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 213
def code_verify_an_arg_expectation_with_smart_arrays(function, arg)
  c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
  depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
  lines = ''
  lines << "  if (!#{ignore})\n" if @ignore_arg
  lines << "  {\n"
  lines << "    UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
  case unity_func
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
    c_type_local = c_type.gsub(/\*$/, '')
    lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
  when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
    if pre == '&'
      lines << "    UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << (depth_name != 1 ? "    else if (#{depth_name} == 0)\n      { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
      lines << "    else\n"
      lines << "      { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
    end
  when /_ARRAY/
    if pre == '&'
      lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
    else
      lines << "    if (#{pre}#{expected} == NULL)\n"
      lines << "      { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
      lines << (depth_name != 1 ? "    else if (#{depth_name} == 0)\n      { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
      lines << "    else\n"
      lines << "      { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
    end
  else
    lines << "    #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
  end
  lines << "  }\n"
  lines
end
lookup_expect_type(_function, arg) click to toggle source

private ######################

# File vendor/cmock/lib/cmock_generator_utils.rb, line 129
def lookup_expect_type(_function, arg)
  c_type     = arg[:type]
  arg_name   = arg[:name]
  expected   = "cmock_call_instance->Expected_#{arg_name}"
  ignore     = "cmock_call_instance->IgnoreArg_#{arg_name}"
  unity_func = if (arg[:ptr?]) && ((c_type =~ /\*\*/) || (@ptr_handling == :compare_ptr))
                 ['UNITY_TEST_ASSERT_EQUAL_PTR', '']
               else
                 @helpers.nil? || @helpers[:unity_helper].nil? ? ['UNITY_TEST_ASSERT_EQUAL', ''] : @helpers[:unity_helper].get_helper(c_type)
               end
  [c_type, arg_name, expected, ignore, unity_func[0], unity_func[1]]
end
ptr_or_str?(arg_type) click to toggle source
# File vendor/cmock/lib/cmock_generator_utils.rb, line 122
def ptr_or_str?(arg_type)
  (arg_type.include?('*') ||
          @treat_as.fetch(arg_type, '').include?('*'))
end