diff --git a/gcc.yml b/gcc.yml index 0308614..7c0d816 100644 --- a/gcc.yml +++ b/gcc.yml @@ -17,7 +17,9 @@ compiler: - *unit_tests_path - *systest_mocks_path - 'vendor/unity/src/' + - 'vendor/c_exception/lib/' - 'test/system/test_compilation/' + - 'test/' defines: prefix: '-D' items: diff --git a/iar_v4.yml b/iar_v4.yml index 2f7e26f..c9233ef 100644 --- a/iar_v4.yml +++ b/iar_v4.yml @@ -36,7 +36,9 @@ compiler: - *unit_tests_path - *systest_mocks_path - 'vendor/unity/src/' + - 'vendor/c_exception/lib/' - 'test/system/test_compilation/' + - 'test\' defines: prefix: '-D' items: diff --git a/iar_v5.yml b/iar_v5.yml index e695d10..29477ea 100644 --- a/iar_v5.yml +++ b/iar_v5.yml @@ -34,8 +34,10 @@ compiler: - *unit_tests_path - *systest_mocks_path - 'vendor/unity/src/' + - 'vendor/c_exception/lib/' - 'iar\iar_v5\incIAR\' - 'test\system\test_compilation\' + - 'test\' defines: prefix: '-D' items: diff --git a/lib/cmock_generator.rb b/lib/cmock_generator.rb index 467c7bc..bb10be3 100644 --- a/lib/cmock_generator.rb +++ b/lib/cmock_generator.rb @@ -86,7 +86,7 @@ class CMockGenerator file << "#include \"unity.h\"\n" file << @plugins.run(:include_files) includes = @config.includes - includes.each {|include| file << "#include \"#{include}\"\n"} if (!includes.nil?) + includes.each {|inc| file << "#include \"#{inc}\"\n"} if (!includes.nil?) file << "#include \"#{header_file}\"\n\n" end diff --git a/lib/cmock_generator_plugin_cexception.rb b/lib/cmock_generator_plugin_cexception.rb index 7b2109d..c97e130 100644 --- a/lib/cmock_generator_plugin_cexception.rb +++ b/lib/cmock_generator_plugin_cexception.rb @@ -20,7 +20,7 @@ class CMockGeneratorPluginCException end def instance_structure(function) - call_count_type = @config.cexception_call_count_type + call_count_type = @config.expect_call_count_type throw_type = @config.cexception_throw_type [ "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount;\n", "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount_Head;\n", @@ -56,7 +56,7 @@ class CMockGeneratorPluginCException def mock_interfaces(function) arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, " - call_count_type = @config.cexception_call_count_type + call_count_type = @config.expect_call_count_type throw_type = @config.cexception_throw_type [ "void #{function[:name]}_ExpectAndThrow(#{arg_insert}#{throw_type} toThrow)\n", "{\n", diff --git a/lib/cmock_unityhelper_parser.rb b/lib/cmock_unityhelper_parser.rb index 4828c04..3dc3458 100644 --- a/lib/cmock_unityhelper_parser.rb +++ b/lib/cmock_unityhelper_parser.rb @@ -29,7 +29,6 @@ class CMockUnityHelperParser def import_source source = @config.load_unity_helper return {} if source.nil? - c_types = {} source = source.gsub(/\/\/.*$/, '') #remove line comments source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments diff --git a/rakefile_helper.rb b/rakefile_helper.rb index 283e62a..a546d37 100644 --- a/rakefile_helper.rb +++ b/rakefile_helper.rb @@ -117,7 +117,7 @@ module RakefileHelpers def link(exe_name, obj_list) linker = build_linker_fields cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + - (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join + + (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).uniq.join + $cfg['linker']['bin_files']['prefix'] + ' ' + $cfg['linker']['bin_files']['destination'] + exe_name + $cfg['linker']['bin_files']['extension'] @@ -205,7 +205,8 @@ module RakefileHelpers runner_name = test_base + '_runner.c' runner_path = $cfg['compiler']['source_path'] + runner_name test_gen = UnityTestRunnerGenerator.new - test_gen.run(test, runner_path, []) + gen_inc, gen_opt = test_gen.grab_config(SYSTEST_GENERATED_FILES_PATH + cmock_config) + test_gen.run(test, runner_path, gen_inc, ' ', gen_opt) compile(runner_path) obj_list << runner_name.ext($cfg['compiler']['object_files']['extension']) diff --git a/test/Exception.h b/test/Exception.h new file mode 100644 index 0000000..2ac40b3 --- /dev/null +++ b/test/Exception.h @@ -0,0 +1,8 @@ +#ifndef _EXCEPTION_H +#define _EXCEPTION_H + +// Just use defaults +// INCLUDE THE ACTUAL CEXCEPTION LIBRARY +#include "CException.h" + +#endif // _EXCEPTION_H diff --git a/test/system/systest_generator.rb b/test/system/systest_generator.rb index 7bdd8bd..b355e1d 100644 --- a/test/system/systest_generator.rb +++ b/test/system/systest_generator.rb @@ -45,7 +45,7 @@ class SystemTestGenerator cmock[:mock_prefix] = MOCK_PREFIX if not yaml_hash[:systest][:unity_helper].nil? cmock[:includes] << namix + UNITY_HELPER_H - cmock[:unity_helper] = GENERATED_PATH + namix + UNITY_HELPER_C + cmock[:unity_helper] = GENERATED_PATH + namix + UNITY_HELPER_H end File.open(GENERATED_PATH + namix + 'cmock' + YAML_EXTENSION, 'w') do |out| diff --git a/test/system/test_interactions/basic_expect_and_return.yml b/test/system/test_interactions/basic_expect_and_return.yml index 294f205..790ec8a 100644 --- a/test/system/test_interactions/basic_expect_and_return.yml +++ b/test/system/test_interactions/basic_expect_and_return.yml @@ -57,7 +57,7 @@ } - :pass: FALSE - :should: 'fail because bar() is called but not expected' + :should: 'fail because bar() is not called but is expected' :code: | test() { @@ -66,7 +66,7 @@ } - :pass: FALSE - :should: 'fail because bar() is not called but is expected' + :should: 'fail because bar() is called but is not expected' :code: | test() { @@ -89,7 +89,7 @@ test() { foo_char_strings_ExpectAndReturn("larry", "curly", "moe"); - TEST_ASSERT_EQUAL("moe", function_d("larry", "curly")); + TEST_ASSERT_EQUAL_STRING("moe", function_d("larry", "curly")); } ... diff --git a/test/system/test_interactions/expect_and_return_custom_types.yml b/test/system/test_interactions/expect_and_return_custom_types.yml new file mode 100644 index 0000000..d52a9d9 --- /dev/null +++ b/test/system/test_interactions/expect_and_return_custom_types.yml @@ -0,0 +1,108 @@ +--- +:cmock: + :plugins: + - # none + :memcmp_if_unknown: false + :tab: ' ' + +:systest: + :types: | + typedef struct _EXAMPLE_STRUCT_T { int x; int y; } EXAMPLE_STRUCT_T; + + :mockable: | + EXAMPLE_STRUCT_T foo(EXAMPLE_STRUCT_T a); + + :source: + :header: | + EXAMPLE_STRUCT_T function_a(EXAMPLE_STRUCT_T a, EXAMPLE_STRUCT_T b); + EXAMPLE_STRUCT_T function_b(EXAMPLE_STRUCT_T a, EXAMPLE_STRUCT_T b); + + :code: | + EXAMPLE_STRUCT_T function_a(EXAMPLE_STRUCT_T a, EXAMPLE_STRUCT_T b) + { + EXAMPLE_STRUCT_T retval = foo(a); + retval.x += b.x; + retval.y += b.y; + return retval; + } + + EXAMPLE_STRUCT_T function_b(EXAMPLE_STRUCT_T a, EXAMPLE_STRUCT_T b) + { + EXAMPLE_STRUCT_T retval = foo(b); + retval.x *= a.x; + retval.y *= a.y; + return retval; + } + + :tests: + :common: | + #include "expect_and_return_custom_types_unity_helper.h" + void setUp(void) {} + void tearDown(void) {} + + :units: + - :pass: TRUE + :should: 'successfully exercise simple ExpectAndReturn mock calls' + :code: | + test() + { + EXAMPLE_STRUCT_T c = {1,2}; + EXAMPLE_STRUCT_T d = {3,4}; + EXAMPLE_STRUCT_T e = {2,4}; + EXAMPLE_STRUCT_T f = {5,8}; + foo_ExpectAndReturn(c, e); + TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(f, function_a(c,d)); + } + + - :pass: FALSE + :should: 'fail because it is expecting to call foo with c not d' + :code: | + test() + { + EXAMPLE_STRUCT_T c = {1,2}; + EXAMPLE_STRUCT_T d = {3,4}; + EXAMPLE_STRUCT_T e = {2,4}; + EXAMPLE_STRUCT_T f = {5,8}; + foo_ExpectAndReturn(d, e); + TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(f, function_a(c,d)); + } + + - :pass: TRUE + :should: 'successfully exercise simple ExpectAndReturn mock calls on other function' + :code: | + test() + { + EXAMPLE_STRUCT_T c = {1,2}; + EXAMPLE_STRUCT_T d = {3,4}; + EXAMPLE_STRUCT_T e = {2,4}; + EXAMPLE_STRUCT_T f = {2,8}; + foo_ExpectAndReturn(d, e); + TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(f, function_b(c,d)); + } + + - :pass: FALSE + :should: 'fail because it is expecting to call foo with d not c' + :code: | + test() + { + EXAMPLE_STRUCT_T c = {1,2}; + EXAMPLE_STRUCT_T d = {3,4}; + EXAMPLE_STRUCT_T e = {2,4}; + EXAMPLE_STRUCT_T f = {2,8}; + foo_ExpectAndReturn(c, e); + TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(f, function_b(c,d)); + } + + :unity_helper: + :header: | + void AssertEqualExampleStruct(EXAMPLE_STRUCT_T expected, EXAMPLE_STRUCT_T actual); + #define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) {AssertEqualExampleStruct(expected, actual);} + + :code: | + void AssertEqualExampleStruct(EXAMPLE_STRUCT_T expected, EXAMPLE_STRUCT_T actual) + { + TEST_ASSERT_EQUAL_INT_MESSAGE(expected.x, actual.x, "Example Struct Failed For Field x"); + TEST_ASSERT_EQUAL_INT_MESSAGE(expected.y, actual.y, "Example Struct Failed For Field y"); + } + +... diff --git a/test/system/test_interactions/expect_and_return_treat_as.yml b/test/system/test_interactions/expect_and_return_treat_as.yml new file mode 100644 index 0000000..7108b2e --- /dev/null +++ b/test/system/test_interactions/expect_and_return_treat_as.yml @@ -0,0 +1,80 @@ +--- +:cmock: + :plugins: + - # none + :treat_as: + MY_STRING: STRING + MY_INT: INT + MY_HEX: HEX32 + +:systest: + :types: | + typedef char* MY_STRING; + typedef int MY_INT; + typedef unsigned int MY_HEX; + + :mockable: | + MY_INT foo(MY_HEX a); + MY_INT bar(MY_HEX b); + MY_STRING foo_char_strings(MY_STRING a, MY_STRING b); + + :source: + :header: | + MY_INT function_a(MY_INT a, MY_INT b); + MY_STRING function_b(MY_STRING a, MY_STRING b); + + :code: | + MY_INT function_a(MY_INT a, MY_INT b) + { + return foo((MY_HEX)a) + bar((MY_HEX)b); + } + + MY_STRING function_b(MY_STRING a, MY_STRING b) + { + return foo_char_strings(a, b); + } + + :tests: + :common: | + void setUp(void) {} + void tearDown(void) {} + + :units: + - :pass: TRUE + :should: 'successfully exercise two simple ExpectAndReturn mock calls' + :code: | + test() + { + foo_ExpectAndReturn((MY_HEX)1, 10); + bar_ExpectAndReturn((MY_HEX)2, 20); + TEST_ASSERT_EQUAL(30, function_a(1, 2)); + } + + - :pass: FALSE + :should: 'fail because bar() is expected but not called' + :code: | + test() + { + foo_ExpectAndReturn((MY_HEX)1, 10); + TEST_ASSERT_EQUAL(30, function_a(1, 2)); + } + + - :pass: FALSE + :should: 'fail because foo_char_strings() is called but is not expected' + :code: | + test() + { + foo_char_strings_ExpectAndReturn((MY_STRING)"jello", (MY_STRING)"jiggle", (MY_STRING)"boing!"); + function_a(1,2); + } + + - :pass: TRUE + :should: 'handle char strings' + :code: | + test() + { + foo_char_strings_ExpectAndReturn((MY_STRING)"jello", (MY_STRING)"jiggle", (MY_STRING)"boing!"); + TEST_ASSERT_EQUAL_STRING("boing!", function_b((MY_STRING)"jello", (MY_STRING)"jiggle")); + } + +... diff --git a/test/system/test_interactions/expect_and_throw.yml b/test/system/test_interactions/expect_and_throw.yml new file mode 100644 index 0000000..6b55350 --- /dev/null +++ b/test/system/test_interactions/expect_and_throw.yml @@ -0,0 +1,119 @@ +--- +:cmock: + :plugins: + - cexception + +:systest: + :types: | + #define UINT32 unsigned int + typedef signed int custom_type; + + :mockable: | + #include "Exception.h" + UINT32 foo(custom_type a); + UINT32 bar(custom_type b); + UINT32 foo_varargs(custom_type a, ...); + + :source: + :header: | + #include "Exception.h" + UINT32 function_a(int a); + void function_b(char a); + + :code: | + UINT32 function_a(int a) + { + UINT32 r = 0; + EXCEPTION_T e; + + Try + { + r = (UINT32)foo((custom_type)a); + } + Catch(e) + { + r = (UINT32)e*2; + } + return r; + } + + void function_b(char a) + { + if (a) + { + Throw((EXCEPTION_T)a); + } + } + + :tests: + :common: | + #include "CException.h" + void setUp(void) {} + void tearDown(void) {} + + :units: + - :pass: TRUE + :should: 'successfully exercise a simple ExpectAndReturn mock calls' + :code: | + test() + { + foo_ExpectAndReturn((custom_type)1, 10); + TEST_ASSERT_EQUAL(10, function_a(1)); + } + + - :pass: TRUE + :should: 'successfully throw an error on first call' + :code: | + test() + { + foo_ExpectAndThrow((custom_type)1, 55); + TEST_ASSERT_EQUAL(110, function_a(1)); + } + + - :pass: TRUE + :should: 'successfully throw an error on later calls' + :code: | + test() + { + foo_ExpectAndReturn((custom_type)1, 10); + foo_ExpectAndReturn((custom_type)1, 20); + foo_ExpectAndThrow((custom_type)1, 15); + TEST_ASSERT_EQUAL(10, function_a(1)); + TEST_ASSERT_EQUAL(20, function_a(1)); + TEST_ASSERT_EQUAL(30, function_a(1)); + } + + - :pass: TRUE + :should: 'pass because we nothing happens' + :code: | + test() + { + function_b(0); + } + + - :pass: FALSE + :should: 'fail because we did not expect function B to throw' + :code: | + test() + { + function_b(1); + } + + - :pass: TRUE + :should: 'fail because we expect function B to throw' + :code: | + test() + { + EXCEPTION_T e; + Try + { + function_b(3); + TEST_FAIL("Should Have Thrown"); + } + Catch(e) + { + TEST_ASSERT_EQUAL(3, e); + } + } + +... diff --git a/test/unit/cmock_generator_plugin_cexception_test.rb b/test/unit/cmock_generator_plugin_cexception_test.rb index c3036c8..2961455 100644 --- a/test/unit/cmock_generator_plugin_cexception_test.rb +++ b/test/unit/cmock_generator_plugin_cexception_test.rb @@ -34,7 +34,7 @@ class CMockGeneratorPluginCExceptionTest < Test::Unit::TestCase should "add to control structure mock needs" do function = { :name => "Oak", :args => [], :return_type => "void" } - @config.expect.cexception_call_count_type.returns("uint32") + @config.expect.expect_call_count_type.returns("uint32") @config.expect.cexception_throw_type.returns("EXCEPTION_TYPE") expected = [" uint32 *Oak_ThrowOnCallCount;\n", @@ -94,7 +94,7 @@ class CMockGeneratorPluginCExceptionTest < Test::Unit::TestCase should "add mock interfaces for functions without arguments" do function = {:name => "Pear", :args_string => "void", :args => [], :return_type => "void"} - @config.expect.cexception_call_count_type.returns("uint32") + @config.expect.expect_call_count_type.returns("uint32") @config.expect.cexception_throw_type.returns("EXCEPTION_TYPE") @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") @utils.expect.code_insert_item_into_expect_array("uint32", "Mock.Pear_ThrowOnCallCount_Head", "Mock.Pear_CallsExpected").returns("mock_return_1") @@ -117,7 +117,7 @@ class CMockGeneratorPluginCExceptionTest < Test::Unit::TestCase should "add a mock interfaces for functions with arguments" do function = {:name => "Pear", :args_string => "int blah", :args => [{ :type => "int", :name => "blah" }], :return_type => "void"} - @config.expect.cexception_call_count_type.returns("uint32") + @config.expect.expect_call_count_type.returns("uint32") @config.expect.cexception_throw_type.returns("EXCEPTION_TYPE") @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") @utils.expect.code_insert_item_into_expect_array("uint32", "Mock.Pear_ThrowOnCallCount_Head", "Mock.Pear_CallsExpected").returns("mock_return_1")