- 'extern' function stripping is now optional

- ignores can be configured to ignore args only or args and callcount

git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@162 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
mvandervoord
2010-05-05 01:58:58 +00:00
parent 36de9c6fc4
commit af9d83d181
11 changed files with 461 additions and 28 deletions
+15 -13
View File
@@ -8,20 +8,22 @@ class CMockConfig
CMockDefaultOptions =
{
:mock_path => 'mocks',
:mock_prefix => 'Mock',
:plugins => [],
:includes => [],
:attributes => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'],
:mock_path => 'mocks',
:mock_prefix => 'Mock',
:plugins => [],
:includes => [],
:attributes => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'],
:enforce_strict_ordering => false,
:cexception_include => nil,
:unity_helper => false,
:treat_as => {},
: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, #0 errors only, #1 warnings and errors, #2 normal info, #3 verbose
:cexception_include => nil,
:unity_helper => false,
:treat_as => {},
: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
:ignore => :args_and_calls, #the options being :args_and_calls or :args_only
}
def initialize(options=nil)
+3
View File
@@ -173,6 +173,9 @@ class CMockGenerator
file << @plugins.run(:mock_implementation_precheck, function)
file << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, \"Function '#{function[:name]}' called more times than expected\");\n"
file << " cmock_line = cmock_call_instance->LineNumber;\n"
if (@ordered)
file << " UNITY_TEST_ASSERT((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), cmock_line, \"Out of order function calls. Function '#{function[:name]}'\");\n"
end
file << @plugins.run(:mock_implementation, function)
file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
file << "}\n\n"
-3
View File
@@ -50,9 +50,6 @@ class CMockGeneratorPluginExpect
def mock_implementation(function)
lines = ""
if (@ordered)
lines << " UNITY_TEST_ASSERT((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), cmock_line, \"Out of order function calls. Function '#{function[:name]}'\");\n"
end
function[:args].each do |arg|
lines << @utils.code_verify_an_arg_expectation(function, arg)
end
+6 -1
View File
@@ -11,6 +11,11 @@ class CMockGeneratorPluginIgnore
def initialize(config, utils)
@config = config
if (@config.ignore == :args_and_calls)
alias :mock_implementation_precheck :mock_implementation_for_ignores
else
alias :mock_implementation :mock_implementation_for_ignores
end
@utils = utils
@priority = 2
end
@@ -33,7 +38,7 @@ class CMockGeneratorPluginIgnore
end
end
def mock_implementation_precheck(function)
def mock_implementation_for_ignores(function)
lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
if (function[:return][:void?])
lines << " return;\n }\n"
+9 -4
View File
@@ -6,7 +6,7 @@
class CMockHeaderParser
attr_accessor :funcs, :c_attributes, :treat_as_void
attr_accessor :funcs, :c_attributes, :treat_as_void, :treat_externs
def initialize(cfg)
@funcs = []
@@ -17,6 +17,7 @@ class CMockHeaderParser
@when_no_prototypes = cfg.when_no_prototypes
@local_as_void = @treat_as_void
@verbosity = cfg.verbosity
@treat_externs = cfg.treat_externs
end
def parse(name, source)
@@ -90,9 +91,13 @@ class CMockHeaderParser
#split lines on semicolons and remove things that are obviously not what we are looking for
src_lines = source.split(/\s*;\s*/)
src_lines.delete_if {|line| !(line =~ /\(\s*\*(?:.*\[\d*\])??\s*\)/).nil?} #remove function pointer arrays
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} #remove inline and extern functions
src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
src_lines.delete_if {|line| !(line =~ /\(\s*\*(?:.*\[\d*\])??\s*\)/).nil?} #remove function pointer arrays
if (@treat_externs == :include)
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil?} #remove inline functions
else
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} #remove inline and extern functions
end
end
def parse_functions(source)
@@ -0,0 +1,340 @@
---
#this test is different than all_plugins_coexist primarily because of these options
:cmock:
:enforce_strict_ordering: 1
:treat_externs: :include
:ignore: :args_only
:plugins:
- :array
- :cexception
- :ignore
- :callback
:systest:
:types: |
typedef struct _POINT_T {
int x;
int y;
} POINT_T;
:mockable: |
#include "CException.h"
void foo(POINT_T* a);
POINT_T* bar(void);
void fooa(POINT_T a[]);
void foos(const char * a);
extern const char * bars(void);
void no_pointers(int a, char* b);
int mixed(int a, int* b, int c);
:source:
:header: |
#include "CException.h"
void function_a(void);
void function_b(void);
void function_c(void);
int function_d(void);
void function_e(void);
:code: |
void function_a(void)
{
foo(bar());
}
void function_b(void) {
fooa(bar());
}
void function_c(void) {
CEXCEPTION_T e;
Try {
foos(bars());
} Catch(e) { foos("err"); }
}
int function_d(void) {
int test_list[] = { 1, 2, 3, 4, 5 };
no_pointers(1, "silly");
return mixed(6, test_list, 7);
}
void function_e(void) {
foos("Hello");
foos("Tuna");
foos("Oranges");
}
:tests:
:common: |
#include "CException.h"
void setUp(void) {}
void tearDown(void) {}
:units:
- :pass: TRUE
:should: 'handle the situation where we pass nulls to pointers'
:code: |
test()
{
bar_ExpectAndReturn(NULL);
foo_Expect(NULL);
function_a();
}
- :pass: FALSE
:should: 'handle the situation where we expected nulls to pointers but did not get that'
:code: |
test()
{
POINT_T pt = {1, 2};
bar_ExpectAndReturn(&pt);
foo_Expect(NULL);
function_a();
}
- :pass: FALSE
:should: 'handle the situation where we did not expect nulls to pointers but got null'
:code: |
test()
{
POINT_T ex = {1, 2};
bar_ExpectAndReturn(NULL);
foo_Expect(&ex);
function_a();
}
- :pass: FALSE
:should: 'handle the situation where we pass single object with expect and it is wrong'
:code: |
test()
{
POINT_T pt = {1, 2};
POINT_T ex = {1, 3};
bar_ExpectAndReturn(&pt);
foo_Expect(&ex);
function_a();
}
- :pass: TRUE
:should: 'handle the situation where we pass single object with expect and use array handler'
:code: |
test()
{
POINT_T pt = {1, 2};
POINT_T ex = {1, 2};
bar_ExpectAndReturn(&pt);
foo_ExpectWithArray(&ex, 1);
function_a();
}
- :pass: FALSE
:should: 'handle the situation where we pass single object with expect and use array handler and it is wrong'
:code: |
test()
{
POINT_T pt = {1, 2};
POINT_T ex = {1, 3};
bar_ExpectAndReturn(&pt);
foo_ExpectWithArray(&ex, 1);
function_a();
}
- :pass: TRUE
:should: 'handle the situation where we pass multiple objects with expect and use array handler'
:code: |
test()
{
POINT_T pt[] = {{1, 2}, {3, 4}, {5, 6}};
POINT_T ex[] = {{1, 2}, {3, 4}, {5, 6}};
bar_ExpectAndReturn(pt);
foo_ExpectWithArray(ex, 3);
function_a();
}
- :pass: FALSE
:should: 'handle the situation where we pass multiple objects with expect and use array handler and it is wrong at end'
:code: |
test()
{
POINT_T pt[] = {{1, 2}, {3, 4}, {5, 6}};
POINT_T ex[] = {{1, 2}, {3, 4}, {5, 9}};
bar_ExpectAndReturn(pt);
foo_ExpectWithArray(ex, 3);
function_a();
}
- :pass: TRUE
:should: 'handle the situation where we pass single array element with expect'
:code: |
test()
{
POINT_T pt = {1, 2};
POINT_T ex = {1, 2};
bar_ExpectAndReturn(&pt);
fooa_Expect(&ex);
function_b();
}
- :pass: TRUE
:should: 'handle standard c string as null terminated on not do crappy memory compares of a byte, passing'
:code: |
test()
{
bars_ExpectAndReturn("This is a\0 silly string");
foos_Expect("This is a\0 wacky string");
function_c();
}
- :pass: FALSE
:should: 'handle standard c string as null terminated on not do crappy memory compares of a byte, finding failures'
:code: |
test()
{
bars_ExpectAndReturn("This is a silly string");
foos_Expect("This is a wacky string");
function_c();
}
- :pass: TRUE
:should: 'handle creating array expects when we have mixed arguments for single object'
:code: |
test()
{
int expect_list[] = { 1, 9 };
no_pointers_Expect(1, "silly");
mixed_ExpectAndReturn(6, expect_list, 7, 13);
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: FALSE
:should: 'handle creating array expects when we have mixed arguments and handle failures for single object'
:code: |
test()
{
int expect_list[] = { 9, 1 };
no_pointers_Expect(1, "silly");
mixed_ExpectAndReturn(6, expect_list, 7, 13);
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'handle creating array expects when we have mixed arguments for multiple objects'
:code: |
test()
{
int expect_list[] = { 1, 2, 3, 4, 6 };
no_pointers_Expect(1, "silly");
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: FALSE
:should: 'handle creating array expects when we have mixed arguments and handle failures for multiple objects'
:code: |
test()
{
int expect_list[] = { 1, 2, 3, 4, 6 };
no_pointers_Expect(1, "silly");
mixed_ExpectWithArrayAndReturn(6, expect_list, 5, 7, 13);
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'handle an exception being caught'
:code: |
test()
{
bars_ExpectAndReturn("This is a\0 silly string");
foos_ExpectAndThrow("This is a\0 wacky string", 55);
foos_Expect("err");
function_c();
}
- :pass: FALSE
:should: 'handle an exception being caught but still catch following errors'
:code: |
test()
{
bars_ExpectAndReturn("This is a\0 silly string");
foos_ExpectAndThrow("This is a\0 wacky string", 55);
foos_Expect("wrong error");
function_c();
}
- :pass: FALSE
:should: 'fail strict ordering problems even though we would otherwise have passed'
:code: |
test()
{
int expect_list[] = { 1, 2, 3, 4, 6 };
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
no_pointers_Expect(1, "silly");
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'that we can properly ignore last function but the other will work properly'
:code: |
test()
{
int expect_list[] = { 1, 2, 3, 4, 6 };
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
no_pointers_Ignore();
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'that we can properly ignore first function but the other will work properly'
:code: |
test()
{
mixed_IgnoreAndReturn(13);
no_pointers_Expect(1, "silly");
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'that we are ok if we ignore a call each because we are counting calls'
:code: |
test()
{
foos_Ignore();
foos_Ignore();
foos_Ignore();
function_e();
}
- :pass: TRUE
:should: 'that we fail if we do not ignore a call once because we are counting calls'
:code: |
test()
{
foos_Ignore();
foos_Ignore();
function_e();
}
...
@@ -31,6 +31,7 @@
void function_b(void);
void function_c(void);
int function_d(void);
void function_e(void);
:code: |
void function_a(void)
@@ -55,6 +56,12 @@
return mixed(6, test_list, 7);
}
void function_e(void) {
foos("Hello");
foos("Tuna");
foos("Oranges");
}
:tests:
:common: |
#include "CException.h"
@@ -304,4 +311,14 @@
TEST_ASSERT_EQUAL(13, function_d());
}
- :pass: TRUE
:should: 'that we just have to ignore a call once because we are not counting calls'
:code: |
test()
{
foos_Ignore();
function_e();
}
...
@@ -11,17 +11,19 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase
def setup
create_mocks :config, :utils
#no strict ordering
#no strict ordering and args_and_calls
@config.expect.when_ptr.returns(:compare_data)
@config.expect.enforce_strict_ordering.returns(false)
@config.stubs!(:respond_to?).returns(true)
# @config.expect.ignore.returns(:args_and_calls)
@utils.expect.helpers.returns({})
@cmock_generator_plugin_expect = CMockGeneratorPluginExpect.new(@config, @utils)
#strict ordering
#strict ordering and args_only
@config.expect.when_ptr.returns(:compare_data)
@config.expect.enforce_strict_ordering.returns(true)
@config.stubs!(:respond_to?).returns(true)
# @config.expect.ignore.returns(:args_only)
@utils.expect.helpers.returns({})
@cmock_generator_plugin_expect_strict = CMockGeneratorPluginExpect.new(@config, @utils)
end
@@ -118,7 +120,7 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase
should "add mock function implementation using ordering if needed" do
function = {:name => "Apple", :args => [], :return => test_return[:void]}
expected = " UNITY_TEST_ASSERT((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), cmock_line, \"Out of order function calls. Function 'Apple'\");\n"
expected = ""
@cmock_generator_plugin_expect.ordered = true
returned = @cmock_generator_plugin_expect.mock_implementation(function)
assert_equal(expected, returned)
@@ -127,7 +129,7 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase
should "add mock function implementation for functions of style 'void func(int worm)' and strict ordering" do
function = {:name => "Apple", :args => [{ :type => "int", :name => "worm" }], :return => test_return[:void]}
@utils.expect.code_verify_an_arg_expectation(function, function[:args][0]).returns("mocked_retval_0")
expected = " UNITY_TEST_ASSERT((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), cmock_line, \"Out of order function calls. Function 'Apple'\");\nmocked_retval_0"
expected = "mocked_retval_0"
@cmock_generator_plugin_expect.ordered = true
returned = @cmock_generator_plugin_expect_strict.mock_implementation(function)
assert_equal(expected, returned)
@@ -10,8 +10,12 @@ require 'cmock_generator_plugin_ignore'
class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase
def setup
create_mocks :config, :utils
@config.expect.ignore.returns(:args_and_calls)
@config.stubs!(:respond_to?).returns(true)
@cmock_generator_plugin_ignore = CMockGeneratorPluginIgnore.new(@config, @utils)
@config.expect.ignore.returns(:args_only)
@cmock_generator_plugin_ignore_just_args = CMockGeneratorPluginIgnore.new(@config, @utils)
end
def teardown
@@ -49,7 +53,11 @@ class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase
assert_equal(expected, returned)
end
should "add required code to implementation with void function" do
should "not add code to implementation (when :args_and_calls)" do
assert(! @cmock_generator_plugin_ignore.methods.include?(:mock_implementation))
end
should "add required code to implementation precheck with void function (when :args_and_calls)" do
function = {:name => "Mold", :args_string => "void", :return => test_return[:void]}
expected = [" if (Mock.Mold_IgnoreBool)\n",
" {\n",
@@ -60,7 +68,7 @@ class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase
assert_equal(expected, returned)
end
should "add required code to implementation with return functions" do
should "add required code to implementation precheck with return functions (when :args_and_calls)" do
function = {:name => "Fungus", :args_string => "void", :return => test_return[:int]}
retval = test_return[:int].merge({ :name => "cmock_call_instance->ReturnVal"})
@utils.expect.code_assign_argument_quickly("Mock.Fungus_FinalReturn", retval).returns(' mock_retval_0')
@@ -76,6 +84,37 @@ class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase
assert_equal(expected, returned)
end
should "not add code to implementation prefix (when :args_only)" do
assert(! @cmock_generator_plugin_ignore_just_args.methods.include?(:mock_implementation_precheck))
end
should "add required code to implementation with void function (when :args_only)" do
function = {:name => "Mold", :args_string => "void", :return => test_return[:void]}
expected = [" if (Mock.Mold_IgnoreBool)\n",
" {\n",
" return;\n",
" }\n"
].join
returned = @cmock_generator_plugin_ignore_just_args.mock_implementation(function)
assert_equal(expected, returned)
end
should "add required code to implementation with return functions (when :args_only)" do
function = {:name => "Fungus", :args_string => "void", :return => test_return[:int]}
retval = test_return[:int].merge({ :name => "cmock_call_instance->ReturnVal"})
@utils.expect.code_assign_argument_quickly("Mock.Fungus_FinalReturn", retval).returns(' mock_retval_0')
expected = [" if (Mock.Fungus_IgnoreBool)\n",
" {\n",
" if (cmock_call_instance == NULL)\n",
" return Mock.Fungus_FinalReturn;\n",
" mock_retval_0",
" return cmock_call_instance->ReturnVal;\n",
" }\n"
].join
returned = @cmock_generator_plugin_ignore_just_args.mock_implementation(function)
assert_equal(expected, returned)
end
should "add a new mock interface for ignoring when function had no return value" do
function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:void]}
expected = ["void Slime_CMockIgnore(UNITY_LINE_TYPE cmock_line)\n",
+23 -1
View File
@@ -19,6 +19,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
@config.expect.treat_as.returns({ "BANJOS" => "INT", "TUBAS" => "HEX16"} )
@config.expect.when_no_prototypes.returns(:error)
@config.expect.verbosity.returns(1)
@config.expect.treat_externs.returns(:exclude)
@parser = CMockHeaderParser.new(@config)
end
@@ -215,7 +216,6 @@ class CMockHeaderParserTest < Test::Unit::TestCase
@parser.import_source(source).map!{|s|s.strip})
end
should "remove externed and inline functions" do
source =
" extern uint32 foobar(unsigned int);\n" +
@@ -234,6 +234,28 @@ class CMockHeaderParserTest < Test::Unit::TestCase
assert_equal(expected, @parser.import_source(source).map!{|s|s.strip})
end
should "remove just inline functions if externs to be included" do
source =
" extern uint32 foobar(unsigned int);\n" +
"uint32 extern_name_func(unsigned int);\n" +
"uint32 funcinline(unsigned int);\n" +
"extern void bar(unsigned int);\n" +
"inline void bar(unsigned int);\n" +
"extern\n" +
"void kinda_ugly_on_the_next_line(unsigned int);\n"
expected =
[ "extern uint32 foobar(unsigned int)",
"uint32 extern_name_func(unsigned int)",
"uint32 funcinline(unsigned int)",
"extern void bar(unsigned int)",
"extern void kinda_ugly_on_the_next_line(unsigned int)"
]
@parser.treat_externs = :include
assert_equal(expected, @parser.import_source(source).map!{|s|s.strip})
end
should "remove defines" do
+1
View File
@@ -13,6 +13,7 @@ class CMockPluginManagerTest < Test::Unit::TestCase
@config.stubs!(:respond_to?).returns(true)
@config.stubs!(:when_ptr).returns(:compare_data)
@config.stubs!(:enforce_strict_ordering).returns(false)
@config.stubs!(:ignore).returns(:args_and_calls)
end
def teardown