Verify that const qualifiers are retained with custom types (verifies #484)

This commit is contained in:
Mark VanderVoord
2026-06-26 12:17:24 -04:00
parent 92debabbf0
commit 783bbde34d
3 changed files with 117 additions and 0 deletions
@@ -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));
}
...
@@ -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,
+29
View File
@@ -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