mirror of
https://github.com/ThrowTheSwitch/CMock
synced 2025-02-01 09:58:42 -05:00
185 lines
7.4 KiB
Ruby
185 lines
7.4 KiB
Ruby
# =========================================================================
|
|
# CMock - Automatic Mock Generation for C
|
|
# ThrowTheSwitch.org
|
|
# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams
|
|
# SPDX-License-Identifier: MIT
|
|
# =========================================================================
|
|
|
|
class CMockConfig
|
|
CMOCK_DEFAULT_OPTIONS =
|
|
{
|
|
:framework => :unity,
|
|
:mock_path => 'mocks',
|
|
:mock_prefix => 'Mock',
|
|
:mock_suffix => '',
|
|
:skeleton_path => '',
|
|
:weak => '',
|
|
:subdir => nil,
|
|
:plugins => [],
|
|
:strippables => ['(?:__attribute__\s*\([ (]*.*?[ )]*\)+)'],
|
|
:attributes => %w[__ramfunc __irq __fiq register extern],
|
|
:c_calling_conventions => %w[__stdcall __cdecl __fastcall],
|
|
:enforce_strict_ordering => false,
|
|
: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
|
|
:when_ptr => :compare_data, # the options being :compare_ptr, :compare_data, or :smart
|
|
:verbosity => 2, # the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
|
|
:treat_externs => :exclude, # the options being :include or :exclude
|
|
:treat_inlines => :exclude, # the options being :include or :exclude
|
|
:callback_include_count => true,
|
|
:callback_after_arg_check => false,
|
|
:includes => nil,
|
|
:includes_h_pre_orig_header => nil,
|
|
:includes_h_post_orig_header => nil,
|
|
:includes_c_pre_header => nil,
|
|
:includes_c_post_header => nil,
|
|
:orig_header_include_fmt => '#include "%s"',
|
|
:array_size_type => [],
|
|
:array_size_name => 'size|len',
|
|
:skeleton => false,
|
|
:exclude_setjmp_h => false,
|
|
|
|
# Format to look for inline functions.
|
|
# This is a combination of "static" and "inline" keywords ("static inline", "inline static", "inline", "static")
|
|
# There are several possibilities:
|
|
# - sometimes they appear together, sometimes individually,
|
|
# - The keywords can appear before or after the return type (this is a compiler warning but people do weird stuff),
|
|
# so we check for word boundaries when searching for them
|
|
# - We first remove "static inline" combinations and boil down to single inline or static statements
|
|
:inline_function_patterns => ['(static\s+inline|inline\s+static)\s*', '(\binline\b)\s*', '(?:static\s*)?(?:__inline__)?__attribute__\s*\([ (]*always_inline[ )]*\)', 'static __inline__'] # Last part (\s*) is just to remove whitespaces (only to prettify the output)
|
|
}.freeze
|
|
|
|
def initialize(options = nil)
|
|
case options
|
|
when NilClass then options = CMOCK_DEFAULT_OPTIONS.dup
|
|
when String then options = CMOCK_DEFAULT_OPTIONS.dup.merge(load_config_file_from_yaml(options))
|
|
when Hash then options = CMOCK_DEFAULT_OPTIONS.dup.merge(options)
|
|
else raise 'If you specify arguments, it should be a filename or a hash of options'
|
|
end
|
|
|
|
# do some quick type verification
|
|
%i[plugins attributes treat_as_void].each do |opt|
|
|
unless options[opt].instance_of?(Array)
|
|
options[opt] = []
|
|
puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
|
|
end
|
|
end
|
|
%i[includes includes_h_pre_orig_header includes_h_post_orig_header includes_c_pre_header includes_c_post_header].each do |opt|
|
|
unless options[opt].nil? || options[opt].instance_of?(Array)
|
|
options[opt] = []
|
|
puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
|
|
end
|
|
end
|
|
options[:unity_helper_path] ||= options[:unity_helper]
|
|
options[:unity_helper_path] = [options[:unity_helper_path]] if options[:unity_helper_path].is_a? String
|
|
|
|
if options[:unity_helper_path]
|
|
require 'pathname'
|
|
includes1 = options[:includes_c_post_header] || []
|
|
includes2 = options[:unity_helper_path].map do |path|
|
|
Pathname(File.expand_path(path)).relative_path_from(Pathname(File.expand_path(options[:mock_path]))).to_s
|
|
rescue StandardError
|
|
path
|
|
end
|
|
options[:includes_c_post_header] = (includes1 + includes2).uniq
|
|
end
|
|
|
|
options[:plugins].compact!
|
|
options[:plugins].map!(&:to_sym)
|
|
|
|
raise 'The :ignore plugin is required to disable :fail_on_unexpected_calls' if (!options[:plugins].include? :ignore) && (!options[:fail_on_unexpected_calls])
|
|
|
|
@options = options
|
|
|
|
treat_as_map = standard_treat_as_map # .clone
|
|
treat_as_map.merge!(@options[:treat_as])
|
|
@options[:treat_as] = treat_as_map
|
|
|
|
@options.each_key do |key|
|
|
unless methods.include?(key)
|
|
eval("def #{key}() return @options[:#{key}] end")
|
|
end
|
|
end
|
|
end
|
|
|
|
def load_config_file_from_yaml(yaml_filename)
|
|
self.class.load_config_file_from_yaml yaml_filename
|
|
end
|
|
|
|
def self.load_config_file_from_yaml(yaml_filename)
|
|
require 'yaml'
|
|
require 'fileutils'
|
|
begin
|
|
YAML.load_file(yaml_filename, aliases: true)[:cmock]
|
|
rescue ArgumentError
|
|
YAML.load_file(yaml_filename)[:cmock]
|
|
end
|
|
end
|
|
|
|
def path(new_path)
|
|
@src_path = new_path
|
|
end
|
|
|
|
def load_unity_helper
|
|
return nil unless @options[:unity_helper_path]
|
|
|
|
@options[:unity_helper_path].inject('') do |unity_helper, filename|
|
|
unity_helper + "\n#{File.new(filename).read}"
|
|
end
|
|
end
|
|
|
|
def standard_treat_as_map
|
|
{
|
|
'int' => 'INT',
|
|
'char' => 'INT8',
|
|
'short' => 'INT16',
|
|
'long' => 'INT',
|
|
'int8' => 'INT8',
|
|
'int16' => 'INT16',
|
|
'int32' => 'INT',
|
|
'int8_t' => 'INT8',
|
|
'int16_t' => 'INT16',
|
|
'int32_t' => 'INT',
|
|
'INT8_T' => 'INT8',
|
|
'INT16_T' => 'INT16',
|
|
'INT32_T' => 'INT',
|
|
'bool' => 'INT',
|
|
'bool_t' => 'INT',
|
|
'BOOL' => 'INT',
|
|
'BOOL_T' => 'INT',
|
|
'unsigned int' => 'HEX32',
|
|
'unsigned long' => 'HEX32',
|
|
'uint32' => 'HEX32',
|
|
'uint32_t' => 'HEX32',
|
|
'UINT32' => 'HEX32',
|
|
'UINT32_T' => 'HEX32',
|
|
'void*' => 'HEX8_ARRAY',
|
|
'void const*' => 'HEX8_ARRAY',
|
|
'const void*' => 'HEX8_ARRAY',
|
|
'unsigned short' => 'HEX16',
|
|
'uint16' => 'HEX16',
|
|
'uint16_t' => 'HEX16',
|
|
'UINT16' => 'HEX16',
|
|
'UINT16_T' => 'HEX16',
|
|
'unsigned char' => 'HEX8',
|
|
'uint8' => 'HEX8',
|
|
'uint8_t' => 'HEX8',
|
|
'UINT8' => 'HEX8',
|
|
'UINT8_T' => 'HEX8',
|
|
'char*' => 'STRING',
|
|
'char const*' => 'STRING',
|
|
'const char*' => 'STRING',
|
|
'pCHAR' => 'STRING',
|
|
'cstring' => 'STRING',
|
|
'CSTRING' => 'STRING',
|
|
'float' => 'FLOAT',
|
|
'double' => 'FLOAT'
|
|
}
|
|
end
|
|
end
|