mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-07-29 23:37:50 +00:00
intermediate check in; integrating new parser and tests thereof yet in progress
git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@93 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
+7
-1
@@ -1,4 +1,10 @@
|
||||
$here = File.dirname __FILE__
|
||||
|
||||
require 'rubygems'
|
||||
require 'treetop'
|
||||
|
||||
require "#{$here}/cmock_function_prototype_node_classes"
|
||||
require "#{$here}/cmock_function_prototype_parser"
|
||||
require "#{$here}/cmock_header_parser"
|
||||
require "#{$here}/cmock_generator"
|
||||
require "#{$here}/cmock_file_writer"
|
||||
@@ -26,7 +32,7 @@ class CMock
|
||||
path = File.dirname(src)
|
||||
@cfg.set_path(path)
|
||||
|
||||
cm_parser = CMockHeaderParser.new(File.read(src), @cfg)
|
||||
cm_parser = CMockHeaderParser.new(CMockFunctionPrototypeParser.new, File.read(src), @cfg)
|
||||
cm_unityhelper = CMockUnityHelperParser.new(@cfg)
|
||||
cm_writer = CMockFileWriter.new(@cfg)
|
||||
cm_gen_utils = CMockGeneratorUtils.new(@cfg, {:unity_helper => cm_unityhelper})
|
||||
|
||||
+43
-95
@@ -1,23 +1,23 @@
|
||||
|
||||
class CMockHeaderParser
|
||||
|
||||
attr_accessor :src_lines, :funcs, :c_attributes
|
||||
attr_accessor :src_lines, :prototypes, :c_attributes
|
||||
|
||||
def initialize(source, cfg)
|
||||
@funcs = []
|
||||
def initialize(parser, source, cfg)
|
||||
@src_lines = []
|
||||
@prototypes = []
|
||||
@c_attributes = cfg.attributes
|
||||
@declaration_parse_matcher = /([\d\w\s\*\(\),]+??)\(([\d\w\s\*\(\),\.]*)\)$/m
|
||||
|
||||
@prototype_parse_matcher = /([\d\w\s\*\(\),]+??)\(([\d\w\s\*\(\),\.]*)\)$/m
|
||||
@parser = parser
|
||||
import_source(source)
|
||||
end
|
||||
|
||||
def parse
|
||||
mod = {:includes => nil, :functions => []}
|
||||
parse_functions
|
||||
if !@funcs.nil? and @funcs.length > 0
|
||||
@funcs.each do |decl|
|
||||
mod[:functions] << parse_declaration(decl)
|
||||
end
|
||||
end
|
||||
# build prototype list
|
||||
extract_prototypes
|
||||
# parse all prototyes into hashes of components and add to array
|
||||
@prototypes.each {|prototype| mod[:functions] << parse_prototype(prototype)} if (@prototypes.length > 0)
|
||||
return mod
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ class CMockHeaderParser
|
||||
# look for any edge cases of typedef'd void;
|
||||
# void must be void for cmock AndReturn calls to process properly.
|
||||
# to a certain extent, these replacements assume we're chewing on pre-processed header files
|
||||
void_types = source.scan(/typedef\s+void\s+([\w\d]+)\s*;/)
|
||||
void_types = source.scan(/typedef\s+(\(\s*)?void(\s*\))?\s+([\w\d]+)\s*;/)
|
||||
void_types.each {|type| source.gsub!(/#{type}/, 'void')} if void_types.size > 0
|
||||
|
||||
source.gsub!(/\s*\\\s*/m, ' ') # smush multiline into single line
|
||||
@@ -35,7 +35,10 @@ class CMockHeaderParser
|
||||
source.gsub!(/\/\/.*$/, '') # remove line comments
|
||||
source.gsub!(/#.*/, '') # remove preprocessor statements
|
||||
source.gsub!(/typedef.*/, '') # remove typedef statements
|
||||
|
||||
source.gsub!(/^\s+/, '') # remove excessive white space
|
||||
source.gsub!(/\s+$/, '') # remove excessive white space
|
||||
source.gsub!(/\s+/, ' ') # remove excessive white space
|
||||
|
||||
@src_lines = source.split(/\s*;\s*/) # split source at end of statements (removing extra white space)
|
||||
@src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
|
||||
end
|
||||
@@ -45,96 +48,41 @@ class CMockHeaderParser
|
||||
@attribute_match = Regexp.compile(%|(#{@c_attributes.join('|')}\s+)*|)
|
||||
end
|
||||
|
||||
def parse_functions
|
||||
def extract_prototypes
|
||||
@src_lines.each do |line|
|
||||
@funcs << line.strip.gsub(/\s+/, ' ') if line =~ @declaration_parse_matcher
|
||||
end
|
||||
return @funcs
|
||||
end
|
||||
|
||||
def parse_args(arg_list)
|
||||
args = []
|
||||
arg_list.split(',').each do |arg|
|
||||
arg = arg.strip
|
||||
return args if ((arg == '...') || (arg == 'void'))
|
||||
arg_elements = arg.split
|
||||
args << {:type => arg_elements[0..-2].join(' '), :name => arg_elements[-1]}
|
||||
end
|
||||
return args
|
||||
end
|
||||
|
||||
def clean_args(arg_list)
|
||||
if ((arg_list.strip == 'void') or (arg_list.empty?))
|
||||
return 'void'
|
||||
else
|
||||
c=0
|
||||
arg_list.gsub!(/\s+\*/,'*') # remove space to place asterisks with type (where they belong)
|
||||
arg_list.gsub!(/\*(\w)/,'* \1') # pull asterisks away from param to place asterisks with type (where they belong)
|
||||
arg_list.split(/\s*,\s*/).map{|arg| (arg =~ /^(\w+|.+\*|.+\)|.+const)$/) ? "#{arg} cmock_arg#{c+=1}" : arg}.join(', ')
|
||||
end
|
||||
end
|
||||
|
||||
def parse_declaration(declaration)
|
||||
decl = {}
|
||||
|
||||
regex_match = @declaration_parse_matcher.match(declaration)
|
||||
raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil?
|
||||
|
||||
# grab argument list
|
||||
args = regex_match[2].strip
|
||||
|
||||
# process function attributes, return type, and name
|
||||
descriptors = regex_match[1]
|
||||
descriptors.gsub!(/\s+\*/,'*') # remove space to place asterisks with return type (where they belong)
|
||||
descriptors.gsub!(/\*(\w)/,'* \1') # pull asterisks away from function name to place asterisks with return type (where they belong)
|
||||
descriptors = descriptors.split # array of all descriptor strings
|
||||
|
||||
# grab name
|
||||
decl[:name] = descriptors[-1] # snag name as last array item
|
||||
|
||||
# build attribute and return type strings
|
||||
decl[:modifier] = []
|
||||
decl[:rettype] = []
|
||||
descriptors[0..-2].each do |word|
|
||||
if @c_attributes.include?(word)
|
||||
decl[:modifier] << word
|
||||
else
|
||||
decl[:rettype] << word
|
||||
# build array of function prototypes
|
||||
if (line =~ @prototype_parse_matcher)
|
||||
# (remove any default parameter statements from argument lists while scanning)
|
||||
line.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, '')
|
||||
@prototypes << line
|
||||
end
|
||||
end
|
||||
decl[:modifier] = decl[:modifier].join(' ')
|
||||
decl[:rettype] = decl[:rettype].join(' ')
|
||||
|
||||
# remove default parameter statements from mock definitions
|
||||
args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*\,/, ',')
|
||||
args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ')
|
||||
return @prototypes
|
||||
end
|
||||
|
||||
def parse_prototype(prototype)
|
||||
hash = {}
|
||||
|
||||
#check for var args
|
||||
if (args =~ /\.\.\./)
|
||||
decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip
|
||||
if (args =~ /\,[\w\s]*\.\.\./)
|
||||
args = args.gsub!(/\,[\w\s]*\.\.\./,'')
|
||||
else
|
||||
args = 'void'
|
||||
modifiers = []
|
||||
@c_attributes.each do |attribute|
|
||||
if (prototype =~ /#{attribute}\s+/i)
|
||||
modifiers << attribute
|
||||
prototype.gsub!(/#{attribute}\s+/i, '')
|
||||
end
|
||||
else
|
||||
decl[:var_arg] = nil
|
||||
end
|
||||
hash[:modifier] = modifiers.join(' ')
|
||||
|
||||
args = clean_args(args)
|
||||
decl[:args_string] = args
|
||||
decl[:args] = parse_args(args)
|
||||
|
||||
if decl[:rettype].nil? or decl[:name].nil? or decl[:args].nil?
|
||||
raise "Declaration parse failed!\n" +
|
||||
" declaration: #{declaration}\n" +
|
||||
" modifier: #{decl[:modifier]}\n" +
|
||||
" return: #{decl[:rettype]}\n" +
|
||||
" function: #{decl[:name]}\n" +
|
||||
" args:#{decl[:args]}\n"
|
||||
end
|
||||
parsed = @parser.parse(prototype)
|
||||
|
||||
raise "Failed parsing function prototype: '#{prototype}'" if parsed.nil?
|
||||
|
||||
return decl
|
||||
hash[:name] = parsed.get_function_name
|
||||
hash[:args_string] = parsed.get_argument_list
|
||||
hash[:args] = parsed.get_arguments
|
||||
hash[:rettype] = parsed.get_return_type
|
||||
hash[:var_arg] = parsed.get_var_arg
|
||||
|
||||
return hash
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -34,12 +34,9 @@ task :treetop do
|
||||
treetop_files.each do |file|
|
||||
compiler.compile(file)
|
||||
end
|
||||
|
||||
#`vendor/gems/treetop-1.2.5/bin/tt lib/cmock_function_prototype_parser.treetop`
|
||||
end
|
||||
|
||||
namespace :test do
|
||||
|
||||
desc "Run all unit and system tests"
|
||||
task :all => ['test:units', 'test:system']
|
||||
|
||||
@@ -55,5 +52,4 @@ namespace :test do
|
||||
tests_failed = run_systests(FileList['test/system/cases/*.yml'])
|
||||
raise "System tests failed." if (tests_failed > 0)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -15,6 +15,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
def teardown
|
||||
end
|
||||
|
||||
|
||||
should "parse simple void function prototypes" do
|
||||
parsed = @parser.parse("void foo_bar(void)")
|
||||
|
||||
@@ -35,6 +36,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(parsed.get_var_arg)
|
||||
end
|
||||
|
||||
|
||||
should "fail to parse garbage, broken function prototypes, and strings that only appear to be prototypes" do
|
||||
assert_nil(@parser.parse("** !"))
|
||||
assert_nil(@parser.parse("ashjfhskdh"))
|
||||
@@ -51,6 +53,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(@parser.parse("(parenthetical comment)"))
|
||||
end
|
||||
|
||||
|
||||
should "parse and normalize white space" do
|
||||
parsed = @parser.parse("void foo_bar ( void )")
|
||||
assert_equal("void foo_bar(void)", parsed.get_declaration)
|
||||
@@ -74,6 +77,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_equal("float (*GetPtr( const char opCode ))( float, float )", parsed.get_declaration)
|
||||
end
|
||||
|
||||
|
||||
should "parse out simple arguments from an argument list into an array of hashes" do
|
||||
# function pointers & var args tested elsewhere
|
||||
|
||||
@@ -115,6 +119,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(parsed.get_var_arg)
|
||||
end
|
||||
|
||||
|
||||
should "fail to parse arguments that mix multiple custom types or a custom type and a primitive" do
|
||||
# parser can only recognize strings of primitves followed by optional name or
|
||||
# a single custom type followed by optional name;
|
||||
@@ -125,6 +130,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(@parser.parse("void foo_bar(CUSTOM_TYPE1 CUSTOM_TYPE2 abc, CUSTOM_TYPE1 CUSTOM_TYPE2 xyz)"))
|
||||
end
|
||||
|
||||
|
||||
should "parse out simple return types" do
|
||||
# function pointers tested elsewhere
|
||||
|
||||
@@ -144,13 +150,14 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_equal('CUSTOM_TYPE', parsed.get_return_type)
|
||||
end
|
||||
|
||||
|
||||
should "normalize pointer notation" do
|
||||
parsed = @parser.parse("void * foo(unsigned int * a, char * *b, int* c, int (* func)(void))")
|
||||
parsed = @parser.parse("void * foo(unsigned int * * * a, char * *b, int* c, int (* func)(void))")
|
||||
|
||||
assert_equal('void*', parsed.get_return_type)
|
||||
assert_equal('unsigned int* a, char** b, int* c, int (*func)(void)', parsed.get_argument_list)
|
||||
assert_equal('unsigned int*** a, char** b, int* c, int (*func)(void)', parsed.get_argument_list)
|
||||
assert_equal([
|
||||
{:type => 'unsigned int*', :name => 'a'},
|
||||
{:type => 'unsigned int***', :name => 'a'},
|
||||
{:type => 'char**', :name => 'b'},
|
||||
{:type => 'int*', :name => 'c'},
|
||||
{:type => 'int (*)(void)', :name => 'func'}],
|
||||
@@ -158,6 +165,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(parsed.get_var_arg)
|
||||
end
|
||||
|
||||
|
||||
should "specially process var args in preparation for mocking" do
|
||||
parsed = @parser.parse("void foo_bar(...)")
|
||||
assert_equal('void', parsed.get_argument_list)
|
||||
@@ -179,8 +187,12 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_nil(parsed.get_var_arg) # no var args for thing(), just for the function pointer param
|
||||
end
|
||||
|
||||
|
||||
should "parse prototypes handling function pointers" do
|
||||
# function pointer prototypes in argument lists (i.e. no typedef)
|
||||
|
||||
# handle this? --> "int slinkydog(bool thing, int (* const)(void));\n" +
|
||||
|
||||
parsed = @parser.parse("void thing(int (*func_ptr)(int, int))")
|
||||
assert_equal('int (*func_ptr)( int, int )', parsed.get_argument_list)
|
||||
assert_equal(
|
||||
@@ -211,6 +223,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
assert_equal('unsigned int* (*)( unsigned int a )', parsed.get_return_type)
|
||||
end
|
||||
|
||||
|
||||
should "create unique typedefs for function pointer prototypes in argument lists and return types" do
|
||||
# function prototype argument list handling
|
||||
parsed = @parser.parse("void foo_bar(unsigned int a, void (*func)(int *, unsigned long int, ...))")
|
||||
@@ -246,13 +259,14 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
|
||||
parsed.get_typedefs)
|
||||
end
|
||||
|
||||
should "insert unique names for top-level nameless arguments" do
|
||||
parsed = @parser.parse("void foo_bar(int (*)(int, int), char, unsigned int c, CUSTOM_THING)")
|
||||
|
||||
assert_equal('int (*cmock_arg1)( int, int ), char cmock_arg2, unsigned int c, CUSTOM_THING cmock_arg4', parsed.get_argument_list)
|
||||
should "insert unique names for top-level nameless arguments" do
|
||||
parsed = @parser.parse("void foo_bar(int (*)(int, int), char* const, unsigned int c, CUSTOM_THING)")
|
||||
|
||||
assert_equal('int (*cmock_arg1)( int, int ), char* const cmock_arg2, unsigned int c, CUSTOM_THING cmock_arg4', parsed.get_argument_list)
|
||||
assert_equal(
|
||||
[{:type => 'int (*)( int, int )', :name => 'cmock_arg1'},
|
||||
{:type => 'char', :name => 'cmock_arg2'},
|
||||
{:type => 'char* const', :name => 'cmock_arg2'},
|
||||
{:type => 'unsigned int', :name => 'c'},
|
||||
{:type => 'CUSTOM_THING', :name => 'cmock_arg4'}],
|
||||
parsed.get_arguments)
|
||||
|
||||
@@ -4,7 +4,7 @@ require 'cmock_header_parser'
|
||||
class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
create_mocks :config
|
||||
create_mocks :config, :prototype_parser, :parsed
|
||||
@config.expect.attributes.returns(['static', 'inline', '__ramfunc'])
|
||||
end
|
||||
|
||||
@@ -12,8 +12,9 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
should "create and initialize variables to defaults appropriately" do
|
||||
@parser = CMockHeaderParser.new("", @config)
|
||||
assert_equal([], @parser.funcs)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, "", @config)
|
||||
assert_equal([], @parser.prototypes)
|
||||
assert_equal([], @parser.src_lines)
|
||||
assert_equal(['static', 'inline', '__ramfunc'], @parser.c_attributes)
|
||||
end
|
||||
|
||||
@@ -22,12 +23,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
" abcd;\n" +
|
||||
"// hello;\n" +
|
||||
"who // is you\n"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
" abcd",
|
||||
"who \n"
|
||||
"abcd",
|
||||
"who"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -39,12 +40,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"/* hello;*/\n" +
|
||||
"who /* is you\n" +
|
||||
"// embedded line comment */\n"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
" abcd",
|
||||
"who \n"
|
||||
"abcd",
|
||||
"who"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -55,7 +56,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"#when stuff_happens\n" +
|
||||
"#ifdef _TEST\n" +
|
||||
"#pragma stack_switch"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected = []
|
||||
|
||||
@@ -66,11 +67,11 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
source =
|
||||
"hoo hah \\\n" +
|
||||
"when \\ \n"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"hoo hah when "
|
||||
"hoo hah when"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -83,11 +84,11 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"typedef who cares what really comes here \\\n" + # exercise multiline typedef
|
||||
" continuation\n" +
|
||||
"this should remain!"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"\nwhack me? \n\nthis should remain!"
|
||||
"whack me? this should remain!"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -100,12 +101,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"#DEFINE I JUST DON'T CARE\n" +
|
||||
"#deFINE\n" +
|
||||
"#define get_foo() \\\n ((Thing)foo.bar)" # exercise multiline define
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"\nvoid hello(void)",
|
||||
"void hello(void)",
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -115,360 +116,167 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
source =
|
||||
"typedef void SILLY_VOID_TYPE1;\n" +
|
||||
"typedef void SILLY_VOID_TYPE2 ;\n" +
|
||||
"typedef void (*FUNCPTR)(void);\n\n" + # don't get fooled by function pointer typedef with void as return type
|
||||
"typedef (void) SILLY_VOID_TYPE2 ;\n" +
|
||||
"typedef ( void ) (*FUNCPTR)(void);\n\n" + # don't get fooled by function pointer typedef with void as return type
|
||||
"SILLY_VOID_TYPE2 Foo(int a, unsigned int b);\n" +
|
||||
"void\n shiz(SILLY_VOID_TYPE1 *);\n" +
|
||||
"void tat(FUNCPTR);\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "int a, unsigned int b",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}],
|
||||
:name => "Foo"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "void* cmock_arg1",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "void*", :name => "cmock_arg1"}],
|
||||
:name => "shiz"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "FUNCPTR cmock_arg1",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "FUNCPTR", :name => "cmock_arg1"}],
|
||||
:name => "tat"
|
||||
}
|
||||
"void Foo(int a, unsigned int b)",
|
||||
"void shiz(void *)",
|
||||
"void tat(FUNCPTR)"
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
end
|
||||
|
||||
should "extract and return function declarations" do
|
||||
|
||||
should "raise upon prototype parsing failure" do
|
||||
|
||||
source =
|
||||
"int Foo(int a, unsigned int b);\n" +
|
||||
"void bar \n(uint la, int de, bool da) ; \n" +
|
||||
"void FunkyChicken (\n uint la,\n int de,\n bool da);\n" +
|
||||
"void\n shiz(void);\n" +
|
||||
"void tat();\n" +
|
||||
# following lines should yield no function declarations:
|
||||
"#define get_foo() \\\n (Thing)foo())\n" +
|
||||
"ARRAY_TYPE array[((U8)10)];\n" +
|
||||
"THINGER_MASK = (0x0001 << 5),\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
"void bar \n(uint la, int de, bool da) ; \n"
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "int a, unsigned int b",
|
||||
:rettype => "int",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}],
|
||||
:name => "Foo"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "uint la, int de, bool da",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "uint", :name => "la"},
|
||||
{:type => "int", :name => "de"},
|
||||
{:type => "bool", :name => "da"}
|
||||
],
|
||||
:name => "bar"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "uint la, int de, bool da",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "uint", :name => "la"},
|
||||
{:type => "int", :name => "de"},
|
||||
{:type => "bool", :name => "da"}
|
||||
],
|
||||
:name => "FunkyChicken"
|
||||
},
|
||||
@prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(nil)
|
||||
|
||||
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
|
||||
begin
|
||||
@parser.parse
|
||||
assert_fail('should have raised')
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "void",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args => [],
|
||||
:name => "shiz"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "void",
|
||||
:rettype => "void",
|
||||
:var_arg => nil,
|
||||
:args => [],
|
||||
:name => "tat"
|
||||
}
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
end
|
||||
|
||||
should "extract and return function declarations with attributes" do
|
||||
|
||||
source =
|
||||
"static \tint \n Foo(int a, unsigned int b);\n" +
|
||||
"inline\t bool bar \n(uint la, int de, bool da);\n" +
|
||||
"inline static __ramfunc bool bar ( uint thinger );\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "static",
|
||||
:args_string => "int a, unsigned int b",
|
||||
:rettype => "int",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}],
|
||||
:name => "Foo"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "inline",
|
||||
:args_string => "uint la, int de, bool da",
|
||||
:rettype => "bool",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "uint", :name => "la"},
|
||||
{:type => "int", :name => "de"},
|
||||
{:type => "bool", :name => "da"}
|
||||
],
|
||||
:name => "bar"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "inline static __ramfunc",
|
||||
:args_string => "uint thinger",
|
||||
:rettype => "bool",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "uint", :name => "thinger"},
|
||||
],
|
||||
:name => "bar"
|
||||
}
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
end
|
||||
|
||||
should "extract and return function declarations with variable argument lists" do
|
||||
|
||||
source =
|
||||
"\tint \n printf(char * const format, ...);\n" +
|
||||
"bool bar \n(...);\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "char* const format",
|
||||
:rettype => "int",
|
||||
:var_arg => "...",
|
||||
:args => [{:type => "char* const", :name => "format"}],
|
||||
:name => "printf"
|
||||
},
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "void",
|
||||
:rettype => "bool",
|
||||
:var_arg => "...",
|
||||
:args => [],
|
||||
:name => "bar"
|
||||
}
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
end
|
||||
|
||||
should "attach * to type" do
|
||||
|
||||
source =
|
||||
"MY_STRUCT* HooWah(char *** format);\n" +
|
||||
"bool* HotShot(HIS_STRUCT **p, unsigned int* pint);\n" +
|
||||
"bool * HotDog(BOW_WOW *p, unsigned int* pint);\n" +
|
||||
"bool ** HotDog(BOW_WOW* p, unsigned int* pint);\n" +
|
||||
"static bool *HotToTrot(unsigned int * struttin);\n" +
|
||||
"static bool ***HotToTrot(unsigned int ** struttin);\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "char*** format",
|
||||
:rettype => "MY_STRUCT*",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "char***", :name => "format"}],
|
||||
:name => "HooWah"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "HIS_STRUCT** p, unsigned int* pint",
|
||||
:rettype => "bool*",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "HIS_STRUCT**", :name => "p"},
|
||||
{:type => "unsigned int*", :name => "pint"}
|
||||
],
|
||||
:name => "HotShot"
|
||||
},
|
||||
# should "extract and return function declarations" do
|
||||
#
|
||||
# source =
|
||||
# "int Foo(int a, unsigned int b);\n" +
|
||||
# "void bar \n(uint la, int de, bool da) ; \n" +
|
||||
# "void FunkyChicken (\n uint la,\n int de,\n bool da);\n" +
|
||||
# "void\n shiz(void);\n" +
|
||||
# "void tat();\n" +
|
||||
# # following lines should yield no function declarations:
|
||||
# "#define get_foo() \\\n (Thing)foo())\n" +
|
||||
# "ARRAY_TYPE array[((U8)10)];\n" +
|
||||
# "THINGER_MASK = (0x0001 << 5),\n"
|
||||
#
|
||||
# @parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
# parsed_stuff = @parser.parse
|
||||
#
|
||||
# expected =
|
||||
# [
|
||||
# {
|
||||
# :modifier => "",
|
||||
# :args_string => "int a, unsigned int b",
|
||||
# :rettype => "int",
|
||||
# :var_arg => nil,
|
||||
# :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}],
|
||||
# :name => "Foo"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "",
|
||||
# :args_string => "uint la, int de, bool da",
|
||||
# :rettype => "void",
|
||||
# :var_arg => nil,
|
||||
# :args =>
|
||||
# [
|
||||
# {:type => "uint", :name => "la"},
|
||||
# {:type => "int", :name => "de"},
|
||||
# {:type => "bool", :name => "da"}
|
||||
# ],
|
||||
# :name => "bar"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "",
|
||||
# :args_string => "uint la, int de, bool da",
|
||||
# :rettype => "void",
|
||||
# :var_arg => nil,
|
||||
# :args =>
|
||||
# [
|
||||
# {:type => "uint", :name => "la"},
|
||||
# {:type => "int", :name => "de"},
|
||||
# {:type => "bool", :name => "da"}
|
||||
# ],
|
||||
# :name => "FunkyChicken"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "",
|
||||
# :args_string => "void",
|
||||
# :rettype => "void",
|
||||
# :var_arg => nil,
|
||||
# :args => [],
|
||||
# :name => "shiz"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "",
|
||||
# :args_string => "void",
|
||||
# :rettype => "void",
|
||||
# :var_arg => nil,
|
||||
# :args => [],
|
||||
# :name => "tat"
|
||||
# }
|
||||
# ]
|
||||
#
|
||||
# assert_equal(expected, parsed_stuff[:functions])
|
||||
# end
|
||||
#
|
||||
# should "extract and return function declarations with attributes" do
|
||||
#
|
||||
# source =
|
||||
# "static \tint \n Foo(int a, unsigned int b);\n" +
|
||||
# "inline\t bool bar \n(uint la, int de, bool da);\n" +
|
||||
# "inline static __ramfunc bool bar ( uint thinger );\n"
|
||||
#
|
||||
# @parser = CMockHeaderParser.new(@prototype_parser, source, @config)
|
||||
# parsed_stuff = @parser.parse
|
||||
#
|
||||
# expected =
|
||||
# [
|
||||
# {
|
||||
# :modifier => "static",
|
||||
# :args_string => "int a, unsigned int b",
|
||||
# :rettype => "int",
|
||||
# :var_arg => nil,
|
||||
# :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}],
|
||||
# :name => "Foo"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "inline",
|
||||
# :args_string => "uint la, int de, bool da",
|
||||
# :rettype => "bool",
|
||||
# :var_arg => nil,
|
||||
# :args =>
|
||||
# [
|
||||
# {:type => "uint", :name => "la"},
|
||||
# {:type => "int", :name => "de"},
|
||||
# {:type => "bool", :name => "da"}
|
||||
# ],
|
||||
# :name => "bar"
|
||||
# },
|
||||
#
|
||||
# {
|
||||
# :modifier => "inline static __ramfunc",
|
||||
# :args_string => "uint thinger",
|
||||
# :rettype => "bool",
|
||||
# :var_arg => nil,
|
||||
# :args =>
|
||||
# [
|
||||
# {:type => "uint", :name => "thinger"},
|
||||
# ],
|
||||
# :name => "bar"
|
||||
# }
|
||||
# ]
|
||||
#
|
||||
# assert_equal(expected, parsed_stuff[:functions])
|
||||
# end
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "BOW_WOW* p, unsigned int* pint",
|
||||
:rettype => "bool*",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "BOW_WOW*", :name => "p"},
|
||||
{:type => "unsigned int*", :name => "pint"}
|
||||
],
|
||||
:name => "HotDog"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "BOW_WOW* p, unsigned int* pint",
|
||||
:rettype => "bool**",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "BOW_WOW*", :name => "p"},
|
||||
{:type => "unsigned int*", :name => "pint"}
|
||||
],
|
||||
:name => "HotDog"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "static",
|
||||
:args_string => "unsigned int* struttin",
|
||||
:rettype => "bool*",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "unsigned int*", :name => "struttin"}
|
||||
],
|
||||
:name => "HotToTrot"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "static",
|
||||
:args_string => "unsigned int** struttin",
|
||||
:rettype => "bool***",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "unsigned int**", :name => "struttin"}
|
||||
],
|
||||
:name => "HotToTrot"
|
||||
}
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
end
|
||||
|
||||
should "extract and return function declarations with just types (no argument names)" do
|
||||
|
||||
source =
|
||||
"int buzzlightyear(char*, bool);\n" +
|
||||
"bool woody();\n" +
|
||||
"int slinkydog(bool thing, int (* const)(void));\n" +
|
||||
"int andy(int* const);\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
expected =
|
||||
[
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "char* cmock_arg1, bool cmock_arg2",
|
||||
:rettype => "int",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "char*", :name => "cmock_arg1"},
|
||||
{:type => "bool", :name => "cmock_arg2"}
|
||||
],
|
||||
:name => "buzzlightyear"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "void",
|
||||
:rettype => "bool",
|
||||
:var_arg => nil,
|
||||
:args => [],
|
||||
:name => "woody"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "bool thing, int (* const)(void) cmock_arg1",
|
||||
:rettype => "int",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "bool", :name => "thing"},
|
||||
{:type => "int (* const)(void)", :name => "cmock_arg1"}
|
||||
],
|
||||
:name => "slinkydog"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "int* const cmock_arg1",
|
||||
:rettype => "int",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "int* const", :name => "cmock_arg1"},
|
||||
],
|
||||
:name => "andy"
|
||||
}
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:functions])
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user