completed first pass at testing slimmed down cmock_header_parser using new function prototype parser; added functionality to raise exception upon failed parsing or no prototypes in file to be parsed

git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@95 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
mkarlesky
2009-05-14 19:10:42 +00:00
parent 17631c66f8
commit e6c84d9e07
3 changed files with 225 additions and 151 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ class CMock
path = File.dirname(src)
@cfg.set_path(path)
cm_parser = CMockHeaderParser.new(CMockFunctionPrototypeParser.new, File.read(src), @cfg)
cm_parser = CMockHeaderParser.new(CMockFunctionPrototypeParser.new, File.read(src), @cfg, name)
cm_unityhelper = CMockUnityHelperParser.new(@cfg)
cm_writer = CMockFileWriter.new(@cfg)
cm_gen_utils = CMockGeneratorUtils.new(@cfg, {:unity_helper => cm_unityhelper})
+8 -2
View File
@@ -3,12 +3,15 @@ class CMockHeaderParser
attr_reader :src_lines, :prototypes, :c_attributes
def initialize(parser, source, cfg)
def initialize(parser, source, cfg, name)
@src_lines = []
@prototypes = []
@c_attributes = cfg.attributes
@prototype_parse_matcher = /([\d\w\s\*\(\),]+??)\(([\d\w\s\*\(\),\.]*)\)$/m
@c_attributes = cfg.attributes
@parser = parser
@name = name
import_source(source)
end
@@ -41,6 +44,8 @@ class CMockHeaderParser
source.gsub!(/^\s+/, '') # remove extra white space
source.gsub!(/\s+$/, '') # remove extra white space
source.gsub!(/\s*\(\s*/, '(') # remove extra white space
source.gsub!(/\s*\)\s*/, ')') # remove extra white space
source.gsub!(/\s+/, ' ') # remove extra white space
@src_lines = source.split(/\s*;\s*/) # split source at end of statements (removing extra white space)
@@ -52,6 +57,7 @@ class CMockHeaderParser
@src_lines.each do |line|
@prototypes << line if (line =~ @prototype_parse_matcher)
end
raise "No function prototypes found in '#{@name}'" if @prototypes.empty?
end
def parse_prototype(prototype)
+216 -148
View File
@@ -5,25 +5,28 @@ class CMockHeaderParserTest < Test::Unit::TestCase
def setup
create_mocks :config, :prototype_parser, :parsed
@test_name = 'test_file.h'
@config.expect.attributes.returns(['static', 'inline', '__ramfunc'])
end
def teardown
end
should "create and initialize variables to defaults appropriately" do
@parser = CMockHeaderParser.new(@prototype_parser, "", @config)
@parser = CMockHeaderParser.new(@prototype_parser, "", @config, @test_name)
assert_equal([], @parser.prototypes)
assert_equal([], @parser.src_lines)
assert_equal(['static', 'inline', '__ramfunc'], @parser.c_attributes)
end
should "strip out line comments" do
source =
" abcd;\n" +
"// hello;\n" +
"who // is you\n"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -34,13 +37,14 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "remove block comments" do
source =
" abcd;\n" +
"/* hello;*/\n" +
"who /* is you\n" +
"// embedded line comment */\n"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -51,23 +55,25 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "treat preprocessor directives as single line" do
should "remove preprocessor directives" do
source =
"#when stuff_happens\n" +
"#ifdef _TEST\n" +
"#pragma stack_switch"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected = []
assert_equal(expected, @parser.src_lines)
end
should "smush lines together that contain continuation characters" do
source =
"hoo hah \\\n" +
"when \\ \n"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -77,6 +83,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "remove typedef statements" do
source =
"typedef uint32 (unsigned int)\n" +
@@ -84,7 +91,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
"typedef who cares what really comes here \\\n" + # exercise multiline typedef
" continuation\n" +
"this should remain!"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -94,6 +101,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "remove defines" do
source =
"#define whatever you feel like defining\n" +
@@ -102,7 +110,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
"#deFINE\n" +
"#define get_foo() \\\n ((Thing)foo.bar)" # exercise multiline define
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -112,8 +120,8 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "handle odd case of typedef'd void" do
should "handle odd case of typedef'd void" do
source =
"typedef void SILLY_VOID_TYPE1;\n" +
"typedef (void) SILLY_VOID_TYPE2 ;\n" +
@@ -122,7 +130,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
"void\n shiz(SILLY_VOID_TYPE1 *);\n" +
"void tat(FUNCPTR);\n"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -134,12 +142,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "strip default values from function parameter lists" do
should "strip default values from function parameter lists" do
source =
"void Foo(int a = 57, float b=37.52, char c= 'd', char* e=\"junk\");\n"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
expected =
[
@@ -149,149 +157,209 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.src_lines)
end
should "raise upon prototype parsing failure" do
should "raise upon empty file" do
source = ''
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, 'thinger.h')
# ensure it's expected type of exception
assert_raise RuntimeError do
@parser.parse
end
assert_equal([], @parser.prototypes)
# verify exception message
begin
@parser.parse
rescue RuntimeError => e
assert_equal("No function prototypes found in 'thinger.h'", e.message)
end
end
should "raise upon no function prototypes found in file" do
source =
"typedef void SILLY_VOID_TYPE1;\n" +
"typedef (void) SILLY_VOID_TYPE2 ;\n" +
"typedef ( void ) (*FUNCPTR)(void);\n\n" +
"#define get_foo() \\\n ((Thing)foo.bar)"
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, 'hello_world.h')
# ensure it's expected type of exception
assert_raise(RuntimeError) do
@parser.parse
end
assert_equal([], @parser.prototypes)
# verify exception message
begin
@parser.parse
rescue RuntimeError => e
assert_equal("No function prototypes found in 'hello_world.h'", e.message)
end
end
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"
@prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(nil)
@prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(nil)
@parser = CMockHeaderParser.new(@prototype_parser, source, @config)
begin
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
# ensure it's expected type of exception
assert_raise(RuntimeError) do
@parser.parse
assert_fail('should have raised')
rescue
end
# verify exception message
begin
@parser.parse
rescue RuntimeError => e
assert_equal("Failed parsing function prototype: 'int Foo(int a, unsigned int b)'", e.message)
end
end
# 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
should "extract and return function declarations" do
source =
"int Foo(int a, unsigned int b);\n" +
"void FunkyChicken (\n uint la,\n int de,\n bool da) ; \n" +
" void \n tat();\n" +
# following lines should yield no function prototypes:
"#define get_foo() \\\n (Thing)foo())\n" +
"ARRAY_TYPE array[((U8)10)];\n" +
"THINGER_MASK = (0x0001 << 5),\n"
@prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(@parsed)
@parsed.expect.get_function_name.returns('buzz lightyear')
@parsed.expect.get_argument_list.returns('woody')
@parsed.expect.get_arguments.returns([{:type => 'what up', :name => 'dawg'}])
@parsed.expect.get_return_type.returns('bo peep')
@parsed.expect.get_var_arg.returns('...')
@prototype_parser.expect.parse('void FunkyChicken(uint la, int de, bool da)').returns(@parsed)
@parsed.expect.get_function_name.returns('marty')
@parsed.expect.get_argument_list.returns('mcfly')
@parsed.expect.get_arguments.returns([{:type => 'back', :name => 'to'}])
@parsed.expect.get_return_type.returns('the future')
@parsed.expect.get_var_arg.returns(nil)
@prototype_parser.expect.parse('void tat()').returns(@parsed)
@parsed.expect.get_function_name.returns('neo')
@parsed.expect.get_argument_list.returns('the matrix')
@parsed.expect.get_arguments.returns([{:type => 'trinity', :name => 'the one'}])
@parsed.expect.get_return_type.returns('agent smith')
@parsed.expect.get_var_arg.returns('...')
expected_prototypes =
[
'int Foo(int a, unsigned int b)',
'void FunkyChicken(uint la, int de, bool da)',
'void tat()'
]
expected_hashes =
[
{
:modifier => '',
:args_string => 'woody',
:rettype => 'bo peep',
:var_arg => '...',
:args => [{:type => 'what up', :name => 'dawg'}],
:name => 'buzz lightyear'
},
{
:modifier => '',
:args_string => 'mcfly',
:rettype => 'the future',
:var_arg => nil,
:args => [{:type => 'back', :name => 'to'}],
:name => 'marty'
},
{
:modifier => '',
:args_string => 'the matrix',
:rettype => 'agent smith',
:var_arg => '...',
:args => [{:type => 'trinity', :name => 'the one'}],
:name => 'neo'
},
]
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
parsed_stuff = @parser.parse
assert_equal(expected_prototypes, @parser.prototypes)
assert_equal(expected_hashes, parsed_stuff[:functions])
end
should "extract and return function declarations with attributes" do
source =
"static inline int Foo(int a, unsigned int b);\n" +
" __ramfunc void \n tat();\n"
@prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(@parsed)
@parsed.expect.get_function_name.returns('buzz lightyear')
@parsed.expect.get_argument_list.returns('woody')
@parsed.expect.get_arguments.returns([{:type => 'what up', :name => 'dawg'}])
@parsed.expect.get_return_type.returns('bo peep')
@parsed.expect.get_var_arg.returns('...')
@prototype_parser.expect.parse('void tat()').returns(@parsed)
@parsed.expect.get_function_name.returns('neo')
@parsed.expect.get_argument_list.returns('the matrix')
@parsed.expect.get_arguments.returns([{:type => 'trinity', :name => 'the one'}])
@parsed.expect.get_return_type.returns('agent smith')
@parsed.expect.get_var_arg.returns('...')
expected_prototypes =
[
'int Foo(int a, unsigned int b)',
'void tat()'
]
expected_hashes =
[
{
:modifier => 'static inline',
:args_string => 'woody',
:rettype => 'bo peep',
:var_arg => '...',
:args => [{:type => 'what up', :name => 'dawg'}],
:name => 'buzz lightyear'
},
{
:modifier => '__ramfunc',
:args_string => 'the matrix',
:rettype => 'agent smith',
:var_arg => '...',
:args => [{:type => 'trinity', :name => 'the one'}],
:name => 'neo'
},
]
@parser = CMockHeaderParser.new(@prototype_parser, source, @config, @test_name)
parsed_stuff = @parser.parse
assert_equal(expected_prototypes, @parser.prototypes)
assert_equal(expected_hashes, parsed_stuff[:functions])
end
end