diff --git a/test/system/test_interactions/const_custom_type.yml b/test/system/test_interactions/const_custom_type.yml new file mode 100644 index 0000000..c7c1890 --- /dev/null +++ b/test/system/test_interactions/const_custom_type.yml @@ -0,0 +1,68 @@ +# ========================================================================= +# CMock - Automatic Mock Generation for C +# ThrowTheSwitch.org +# Copyright (c) 2007-26 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +:cmock: + :plugins: + - # none + +:systest: + :types: | + typedef enum { + MyTypeA, + MyTypeB, + MyTypeC, + } MyType_t; + + :mockable: | + int myFunc(const MyType_t t_MyType); + + :source: + :header: | + int exercise(const MyType_t t_MyType); + + :code: | + int exercise(const MyType_t t_MyType) + { + return myFunc(t_MyType); + } + + :tests: + :common: | + void setUp(void) {} + void tearDown(void) {} + + :units: + - :pass: TRUE + :should: 'compile and pass when the correct enum value is passed and return value matches' + :code: | + test() + { + myFunc_ExpectAndReturn(MyTypeB, 42); + TEST_ASSERT_EQUAL(42, exercise(MyTypeB)); + } + + - :pass: FALSE + :should: 'fail when the wrong enum value is passed' + :code: | + test() + { + myFunc_ExpectAndReturn(MyTypeB, 42); + exercise(MyTypeC); + } + + - :pass: TRUE + :should: 'pass when called with a const MyType_t variable' + :code: | + test() + { + const MyType_t val = MyTypeA; + myFunc_ExpectAndReturn(MyTypeA, 0); + TEST_ASSERT_EQUAL(0, exercise(val)); + } + +... diff --git a/test/unit/cmock_generator_plugin_expect_a_test.rb b/test/unit/cmock_generator_plugin_expect_a_test.rb index 8d12c2e..f649ba1 100644 --- a/test/unit/cmock_generator_plugin_expect_a_test.rb +++ b/test/unit/cmock_generator_plugin_expect_a_test.rb @@ -223,6 +223,26 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module W assert_equal(expected, returned) end + it "preserve const on non-pointer custom type in mock function declaration but drop it from struct field" do + function = { + :name => "myFunc", + :args => [{ :name => "t_MyType", :type => "MyType_t", :ptr? => false, :const? => true, :const_ptr? => false }], + :args_string => "const MyType_t t_MyType", + :args_call => "t_MyType", + :return => test_return[:int] + } + # struct field uses arg[:type] directly — no const, so the field stays writable + expected_typedef = " int ReturnVal;\n" \ + " MyType_t Expected_t_MyType;\n" + assert_equal(expected_typedef, @cmock_generator_plugin_expect.instance_typedefs(function)) + + # function declaration uses args_string — const MyType_t must appear in the C signature + expected_decl = "#define myFunc_Expect(t_MyType) TEST_FAIL_MESSAGE(\"myFunc requires _ExpectAndReturn\");\n" \ + "#define myFunc_ExpectAndReturn(t_MyType, cmock_retval) myFunc_CMockExpectAndReturn(__LINE__, t_MyType, cmock_retval)\n" \ + "void myFunc_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, const MyType_t t_MyType, int cmock_to_return);\n" + assert_equal(expected_decl, @cmock_generator_plugin_expect.mock_function_declarations(function)) + end + it "store const-pointer return value without trailing const in typedef struct field (for writability)" do int_ptr_const_return = { :type => "int*", :name => "cmock_to_return", :ptr? => true, :const? => false, :const_ptr? => true, :void? => false, diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index 1d632f7..50615c1 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -3139,4 +3139,33 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do assert_equal(expected, @parser.parse("module", source)[:functions]) end + it "preserve const on non-pointer custom type arguments (e.g. const MyType_t)" do + source = "int myFunc(const MyType_t t_MyType);\n" + + expected = [{ :var_arg => nil, + :name => "myFunc", + :unscoped_name => "myFunc", + :namespace => [], + :class => nil, + :return => { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :const_ptr? => false, + :str => "int cmock_to_return", + :void? => false + }, + :modifier => "", + :contains_ptr? => false, + :args => [ + { :type => "MyType_t", :name => "t_MyType", :ptr? => false, :string? => false, + :const? => true, :const_ptr? => false } + ], + :args_string => "const MyType_t t_MyType", + :args_call => "t_MyType" + }] + + assert_equal(expected, @parser.parse("module", source)[:functions]) + end + end