mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-07-28 23:07:49 +00:00
Verify that our handling of const and pointers now preserve order properly (Verifies #485)
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# =========================================================================
|
||||
# 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: |
|
||||
|
||||
:mockable: |
|
||||
int *const foo(float const *const self);
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
int *const exercise(float const *const self);
|
||||
|
||||
:code: |
|
||||
int *const exercise(float const *const self)
|
||||
{
|
||||
return foo(self);
|
||||
}
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
static float f1 = 1.0f;
|
||||
static float f2 = 2.0f;
|
||||
static int i1 = 10;
|
||||
static int i2 = 20;
|
||||
static float const *const self_a = &f1;
|
||||
static float const *const self_b = &f2;
|
||||
static int *const ret_a = &i1;
|
||||
static int *const ret_b = &i2;
|
||||
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'compile and pass when the correct argument is passed and return value matches'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
foo_ExpectAndReturn(self_a, ret_a);
|
||||
TEST_ASSERT_EQUAL_PTR(ret_a, exercise(self_a));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'fail when the wrong argument pointer is passed'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
foo_ExpectAndReturn(self_a, ret_a);
|
||||
exercise(self_b);
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'return the exact pointer provided to ExpectAndReturn'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
foo_ExpectAndReturn(self_a, ret_b);
|
||||
TEST_ASSERT_EQUAL_PTR(ret_b, exercise(self_a));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'fail when the returned pointer does not match what the test expects'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
foo_ExpectAndReturn(self_a, ret_b);
|
||||
TEST_ASSERT_EQUAL_PTR(ret_a, exercise(self_a));
|
||||
}
|
||||
|
||||
...
|
||||
@@ -187,4 +187,98 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module W
|
||||
returned = @cmock_generator_plugin_expect.mock_verify(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "preserve const-pointer ordering in typedef struct fields for arguments" do
|
||||
function = {
|
||||
:name => "Willow",
|
||||
:args => [
|
||||
{ :name => "ptr_to_const", :type => "const int*", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :name => "const_ptr", :type => "int*", :ptr? => true, :const? => false, :const_ptr? => true },
|
||||
{ :name => "both_const", :type => "const int*", :ptr? => true, :const? => true, :const_ptr? => true },
|
||||
{ :name => "plain_ptr", :type => "int*", :ptr? => true, :const? => false, :const_ptr? => false },
|
||||
],
|
||||
:return => test_return[:void]
|
||||
}
|
||||
# Struct fields use arg[:type] directly (no reconstruction via arg_type_with_const):
|
||||
# - "const int*" preserved as "const int*" (pointer to const data)
|
||||
# - "int*" (from int* const) stored as "int*" — the const_ptr? is intentionally omitted
|
||||
# because a const struct field can never be written to, making the mock unworkable
|
||||
# - "const int*" (from const int* const) similarly stored without the trailing const
|
||||
expected = " const int* Expected_ptr_to_const;\n" +
|
||||
" int* Expected_const_ptr;\n" +
|
||||
" const int* Expected_both_const;\n" +
|
||||
" int* Expected_plain_ptr;\n"
|
||||
returned = @cmock_generator_plugin_expect.instance_typedefs(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "preserve const-before-pointer in return typedef struct field" do
|
||||
const_int_ptr_return = { :type => "const int*", :name => "cmock_to_return", :ptr? => true,
|
||||
:const? => true, :const_ptr? => false, :void? => false,
|
||||
:str => "const int* cmock_to_return" }
|
||||
function = { :name => "Elm", :args => [], :return => const_int_ptr_return }
|
||||
# ReturnVal uses return[:type] = "const int*"
|
||||
expected = " const int* ReturnVal;\n"
|
||||
returned = @cmock_generator_plugin_expect.instance_typedefs(function)
|
||||
assert_equal(expected, returned)
|
||||
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,
|
||||
:str => "int* const cmock_to_return" }
|
||||
function = { :name => "Elm", :args => [], :return => int_ptr_const_return }
|
||||
# ReturnVal uses return[:type] = "int*"; the trailing const is intentionally dropped
|
||||
# so that the struct field remains assignable
|
||||
expected = " int* ReturnVal;\n"
|
||||
returned = @cmock_generator_plugin_expect.instance_typedefs(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "preserve const and pointer order in mock function declaration" do
|
||||
int_ptr_const_return = { :type => "int*", :name => "cmock_to_return", :ptr? => true,
|
||||
:const? => false, :const_ptr? => true, :void? => false,
|
||||
:str => "int* const cmock_to_return" }
|
||||
function = {
|
||||
:name => "Cedar",
|
||||
:args => [
|
||||
{ :name => "p", :type => "const int*", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :name => "q", :type => "int*", :ptr? => true, :const? => false, :const_ptr? => true }
|
||||
],
|
||||
:args_string => "const int* p, int* const q",
|
||||
:args_call => "p, q",
|
||||
:return => int_ptr_const_return
|
||||
}
|
||||
expected = "#define Cedar_Expect(p, q) TEST_FAIL_MESSAGE(\"Cedar requires _ExpectAndReturn\");\n" +
|
||||
"#define Cedar_ExpectAndReturn(p, q, cmock_retval) Cedar_CMockExpectAndReturn(__LINE__, p, q, cmock_retval)\n" +
|
||||
"void Cedar_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, const int* p, int* const q, int* const cmock_to_return);\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "preserve const-before-pointer return type in mock function declaration for void-arg functions" do
|
||||
const_int_ptr_return = { :type => "const int*", :name => "cmock_to_return", :ptr? => true,
|
||||
:const? => true, :const_ptr? => false, :void? => false,
|
||||
:str => "const int* cmock_to_return" }
|
||||
function = { :name => "Oak", :args => [], :args_string => "void", :args_call => "",
|
||||
:return => const_int_ptr_return }
|
||||
expected = "#define Oak_Expect() TEST_FAIL_MESSAGE(\"Oak requires _ExpectAndReturn\");\n" +
|
||||
"#define Oak_ExpectAndReturn(cmock_retval) Oak_CMockExpectAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void Oak_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, const int* cmock_to_return);\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "preserve const-after-pointer return type in mock function declaration for void-arg functions" do
|
||||
int_ptr_const_return = { :type => "int*", :name => "cmock_to_return", :ptr? => true,
|
||||
:const? => false, :const_ptr? => true, :void? => false,
|
||||
:str => "int* const cmock_to_return" }
|
||||
function = { :name => "Oak", :args => [], :args_string => "void", :args_call => "",
|
||||
:return => int_ptr_const_return }
|
||||
expected = "#define Oak_Expect() TEST_FAIL_MESSAGE(\"Oak requires _ExpectAndReturn\");\n" +
|
||||
"#define Oak_ExpectAndReturn(cmock_retval) Oak_CMockExpectAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void Oak_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, int* const cmock_to_return);\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -207,4 +207,74 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "converts single pointer type to pointer-to-const via ptr_to_const" do
|
||||
plugin = @cmock_generator_plugin_return_thru_ptr
|
||||
assert_equal("int const*", plugin.ptr_to_const("int*"))
|
||||
assert_equal("char const*", plugin.ptr_to_const("char*"))
|
||||
assert_equal("uint8_t const*", plugin.ptr_to_const("uint8_t*"))
|
||||
assert_equal("void const*", plugin.ptr_to_const("void*"))
|
||||
assert_equal("MY_TYPE const*", plugin.ptr_to_const("MY_TYPE*"))
|
||||
end
|
||||
|
||||
it "converts double pointer type by making inner pointer const via ptr_to_const" do
|
||||
plugin = @cmock_generator_plugin_return_thru_ptr
|
||||
assert_equal("char* const*", plugin.ptr_to_const("char**"))
|
||||
assert_equal("int* const*", plugin.ptr_to_const("int**"))
|
||||
end
|
||||
|
||||
it "includes int* const args (const pointer, mutable data) in typedef but excludes const int* args" do
|
||||
# int* const: const_ptr?=true, const?=false → data is mutable, pointer is const
|
||||
# The condition `!(arg[:const?])` checks whether the POINTED-TO data is const.
|
||||
# const? is about the data, not the pointer itself, so int* const IS included.
|
||||
const_ptr_func = {
|
||||
:name => "Birch",
|
||||
:args => [
|
||||
{ :type => "int*", :name => "mutable_ptr", :ptr? => true, :const? => false, :const_ptr? => false },
|
||||
{ :type => "int*", :name => "const_ptr", :ptr? => true, :const? => false, :const_ptr? => true },
|
||||
{ :type => "const int*", :name => "ptr_to_const", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
],
|
||||
:return => test_return[:void]
|
||||
}
|
||||
|
||||
@utils.expect :ptr_or_str?, true, ["int*"]
|
||||
@utils.expect :ptr_or_str?, true, ["int*"]
|
||||
@utils.expect :ptr_or_str?, true, ["const int*"]
|
||||
|
||||
# mutable_ptr and const_ptr are included; ptr_to_const is excluded (const?=true)
|
||||
expected = " char ReturnThruPtr_mutable_ptr_Used;\n" +
|
||||
" int const* ReturnThruPtr_mutable_ptr_Val;\n" +
|
||||
" size_t ReturnThruPtr_mutable_ptr_Size;\n" +
|
||||
" char ReturnThruPtr_const_ptr_Used;\n" +
|
||||
" int const* ReturnThruPtr_const_ptr_Val;\n" +
|
||||
" size_t ReturnThruPtr_const_ptr_Size;\n"
|
||||
|
||||
returned = @cmock_generator_plugin_return_thru_ptr.instance_typedefs(const_ptr_func)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "generates correct function signature for int* const args in mock interface" do
|
||||
const_ptr_func = {
|
||||
:name => "Birch",
|
||||
:args => [
|
||||
{ :type => "int*", :name => "const_ptr", :ptr? => true, :const? => false, :const_ptr? => true },
|
||||
],
|
||||
:return => test_return[:void]
|
||||
}
|
||||
|
||||
@utils.expect :ptr_or_str?, true, ["int*"]
|
||||
|
||||
# ptr_to_const("int*") = "int const*", so the helper function takes int const* const_ptr
|
||||
expected =
|
||||
"#define Birch_ReturnThruPtr_const_ptr(const_ptr)" +
|
||||
" Birch_CMockReturnMemThruPtr_const_ptr(__LINE__, const_ptr, sizeof(int))\n" +
|
||||
"#define Birch_ReturnArrayThruPtr_const_ptr(const_ptr, cmock_len)" +
|
||||
" Birch_CMockReturnMemThruPtr_const_ptr(__LINE__, const_ptr, (cmock_len * sizeof(*const_ptr)))\n" +
|
||||
"#define Birch_ReturnMemThruPtr_const_ptr(const_ptr, cmock_size)" +
|
||||
" Birch_CMockReturnMemThruPtr_const_ptr(__LINE__, const_ptr, (cmock_size))\n" +
|
||||
"void Birch_CMockReturnMemThruPtr_const_ptr(UNITY_LINE_TYPE cmock_line, int const* const_ptr, size_t cmock_size);\n"
|
||||
|
||||
returned = @cmock_generator_plugin_return_thru_ptr.mock_function_declarations(const_ptr_func)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -508,4 +508,65 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" }\n"
|
||||
assert_equal(expected, utils.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
|
||||
it 'correctly reconstruct type strings preserving const and pointer order' do
|
||||
# non-pointer: no const
|
||||
assert_equal("int", CMockGeneratorUtils.arg_type_with_const({:type => "int", :ptr? => false, :const? => false, :const_ptr? => false}))
|
||||
# non-pointer: const (prepended)
|
||||
assert_equal("const int", CMockGeneratorUtils.arg_type_with_const({:type => "int", :ptr? => false, :const? => true, :const_ptr? => false}))
|
||||
|
||||
# pointer to mutable: no const
|
||||
assert_equal("int*", CMockGeneratorUtils.arg_type_with_const({:type => "int*", :ptr? => true, :const? => false, :const_ptr? => false}))
|
||||
|
||||
# pointer to const (const int*): const already in :type, no trailing const
|
||||
assert_equal("const int*", CMockGeneratorUtils.arg_type_with_const({:type => "const int*", :ptr? => true, :const? => true, :const_ptr? => false}))
|
||||
|
||||
# const pointer (int* const): :type has no const, const_ptr? appends " const"
|
||||
assert_equal("int* const", CMockGeneratorUtils.arg_type_with_const({:type => "int*", :ptr? => true, :const? => false, :const_ptr? => true}))
|
||||
|
||||
# const pointer to const (const int* const)
|
||||
assert_equal("const int* const", CMockGeneratorUtils.arg_type_with_const({:type => "const int*", :ptr? => true, :const? => true, :const_ptr? => true}))
|
||||
|
||||
# trailing-const form: int const* (same semantics as const int* but different spelling)
|
||||
assert_equal("int const*", CMockGeneratorUtils.arg_type_with_const({:type => "int const*", :ptr? => true, :const? => true, :const_ptr? => false}))
|
||||
|
||||
# trailing-const pointer to const: int const* const
|
||||
assert_equal("int const* const", CMockGeneratorUtils.arg_type_with_const({:type => "int const*", :ptr? => true, :const? => true, :const_ptr? => true}))
|
||||
|
||||
# custom type pointer
|
||||
assert_equal("MY_TYPE*", CMockGeneratorUtils.arg_type_with_const({:type => "MY_TYPE*", :ptr? => true, :const? => false, :const_ptr? => false}))
|
||||
assert_equal("const MY_TYPE", CMockGeneratorUtils.arg_type_with_const({:type => "MY_TYPE", :ptr? => false, :const? => true, :const_ptr? => false}))
|
||||
|
||||
# double pointer: no const_ptr, so :type used as-is
|
||||
assert_equal("int**", CMockGeneratorUtils.arg_type_with_const({:type => "int**", :ptr? => true, :const? => false, :const_ptr? => false}))
|
||||
assert_equal("const int**", CMockGeneratorUtils.arg_type_with_const({:type => "const int**", :ptr? => true, :const? => true, :const_ptr? => false}))
|
||||
# double pointer with const_ptr: appends " const" after last *
|
||||
assert_equal("int** const", CMockGeneratorUtils.arg_type_with_const({:type => "int**", :ptr? => true, :const? => false, :const_ptr? => true}))
|
||||
end
|
||||
|
||||
it 'produce correct C declarations preserving const and pointer order' do
|
||||
# const pointer to mutable int: int* const p
|
||||
arg = {:type => "int*", :name => "p", :ptr? => true, :const? => false, :const_ptr? => true}
|
||||
assert_equal("int* const p", CMockGeneratorUtils.arg_declaration(arg))
|
||||
|
||||
# pointer to const int: const int* p
|
||||
arg = {:type => "const int*", :name => "p", :ptr? => true, :const? => true, :const_ptr? => false}
|
||||
assert_equal("const int* p", CMockGeneratorUtils.arg_declaration(arg))
|
||||
|
||||
# const pointer to const int: const int* const p
|
||||
arg = {:type => "const int*", :name => "p", :ptr? => true, :const? => true, :const_ptr? => true}
|
||||
assert_equal("const int* const p", CMockGeneratorUtils.arg_declaration(arg))
|
||||
|
||||
# trailing-const form: int const* const p
|
||||
arg = {:type => "int const*", :name => "p", :ptr? => true, :const? => true, :const_ptr? => true}
|
||||
assert_equal("int const* const p", CMockGeneratorUtils.arg_declaration(arg))
|
||||
|
||||
# plain pointer: int* p
|
||||
arg = {:type => "int*", :name => "p", :ptr? => true, :const? => false, :const_ptr? => false}
|
||||
assert_equal("int* p", CMockGeneratorUtils.arg_declaration(arg))
|
||||
|
||||
# non-pointer const: const MY_TYPE v
|
||||
arg = {:type => "MY_TYPE", :name => "v", :ptr? => false, :const? => true, :const_ptr? => false}
|
||||
assert_equal("const MY_TYPE v", CMockGeneratorUtils.arg_declaration(arg))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3003,4 +3003,140 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(true, src_len_arg[:array_size?], "src_len should be marked as array_size?")
|
||||
end
|
||||
|
||||
it "correctly parse const int* const return type (both const qualifiers)" do
|
||||
sources = [
|
||||
"const int* const DoubleConst(void);\n",
|
||||
"const int *const DoubleConst(void);\n",
|
||||
]
|
||||
|
||||
# The trailing 'const' (const_ptr?) also lands in :modifier, matching the existing
|
||||
# behavior seen for 'int* const' return types (see the test above for PorkRoast).
|
||||
# The generated mock correctly uses return[:str] and function_return_type() which
|
||||
# reconstruct the full "const int* const" from :type + const_ptr? without needing :modifier.
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "DoubleConst",
|
||||
:unscoped_name => "DoubleConst",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:return => { :type => "const int*",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:const_ptr? => true,
|
||||
:str => "const int* const cmock_to_return",
|
||||
:void? => false
|
||||
},
|
||||
:modifier => "const",
|
||||
:contains_ptr? => false,
|
||||
:args => [],
|
||||
:args_string => "void",
|
||||
:args_call => ""
|
||||
}]
|
||||
|
||||
sources.each do |source|
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
end
|
||||
|
||||
it "correctly parse int const* const return type (trailing-const form, both qualifiers)" do
|
||||
sources = [
|
||||
"int const* const DoubleConst(void);\n",
|
||||
"int const *const DoubleConst(void);\n",
|
||||
]
|
||||
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "DoubleConst",
|
||||
:unscoped_name => "DoubleConst",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:return => { :type => "int const*",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:const_ptr? => true,
|
||||
:str => "int const* const cmock_to_return",
|
||||
:void? => false
|
||||
},
|
||||
:modifier => "const",
|
||||
:contains_ptr? => false,
|
||||
:args => [],
|
||||
:args_string => "void",
|
||||
:args_call => ""
|
||||
}]
|
||||
|
||||
sources.each do |source|
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
end
|
||||
|
||||
it "correctly parse double-pointer argument types preserving const and pointer ordering" do
|
||||
# Tests the full parse pipeline for double-pointer args (not just divine_ptr_and_const).
|
||||
# const int** p → const? false (const is not before the final *), type preserves "const int**"
|
||||
# int** const q → const_ptr? true, type is "int**"
|
||||
# int* const* p → const? true (const* before the last *), type is "int* const*"
|
||||
source = "void TriplePlay(const int** a, int** const b, int* const* c);\n"
|
||||
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "TriplePlay",
|
||||
:unscoped_name => "TriplePlay",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:return => { :type => "void",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:const_ptr? => false,
|
||||
:str => "void cmock_to_return",
|
||||
:void? => true
|
||||
},
|
||||
:modifier => "",
|
||||
:contains_ptr? => true,
|
||||
:args => [
|
||||
{ :type => "const int**", :name => "a", :ptr? => true, :string? => false,
|
||||
:const? => false, :const_ptr? => false },
|
||||
{ :type => "int**", :name => "b", :ptr? => true, :string? => false,
|
||||
:const? => false, :const_ptr? => true },
|
||||
{ :type => "int* const*", :name => "c", :ptr? => true, :string? => false,
|
||||
:const? => true, :const_ptr? => false },
|
||||
],
|
||||
:args_string => "const int** a, int** const b, int* const* c",
|
||||
:args_call => "a, b, c"
|
||||
}]
|
||||
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "correctly parse double-pointer argument types with all consts" do
|
||||
# const int** const p → both const forms: type "const int**", const?=false, const_ptr?=true
|
||||
# int* const* const q → both const forms: type "int* const*", const?=true, const_ptr?=true
|
||||
source = "void AllConst(const int** const a, int* const* const b);\n"
|
||||
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "AllConst",
|
||||
:unscoped_name => "AllConst",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:return => { :type => "void",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:const_ptr? => false,
|
||||
:str => "void cmock_to_return",
|
||||
:void? => true
|
||||
},
|
||||
:modifier => "",
|
||||
:contains_ptr? => true,
|
||||
:args => [
|
||||
{ :type => "const int**", :name => "a", :ptr? => true, :string? => false,
|
||||
:const? => false, :const_ptr? => true },
|
||||
{ :type => "int* const*", :name => "b", :ptr? => true, :string? => false,
|
||||
:const? => true, :const_ptr? => true },
|
||||
],
|
||||
:args_string => "const int** const a, int* const* const b",
|
||||
:args_call => "a, b"
|
||||
}]
|
||||
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user