mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-09-01 07:50:00 +00:00
Handle void pointers as pointer comparisons unless the array plugin gives more information. (Fixes #400)
This commit is contained in:
@@ -20,6 +20,7 @@ class CMockGeneratorUtils
|
||||
@ignore = @config.plugins.include? :ignore
|
||||
@ignore_stateless = @config.plugins.include? :ignore_stateless
|
||||
@treat_as = @config.treat_as
|
||||
@treat_as_void = (['void'] + (@config.respond_to?(:treat_as_void) ? @config.treat_as_void : [])).uniq
|
||||
@helpers = helpers
|
||||
end
|
||||
|
||||
@@ -155,12 +156,23 @@ class CMockGeneratorUtils
|
||||
|
||||
unity_func = if (arg[:ptr?]) && ((c_type =~ /\*\*/) || (@ptr_handling == :compare_ptr))
|
||||
['UNITY_TEST_ASSERT_EQUAL_PTR', '']
|
||||
elsif arg[:ptr?] && !@arrays && void_pointer_type?(c_type)
|
||||
# void* cannot be safely dereferenced; without the array plugin there's no way
|
||||
# to specify depth, so fall back to comparing the pointer value itself
|
||||
['UNITY_TEST_ASSERT_EQUAL_PTR', '']
|
||||
else
|
||||
@helpers.nil? || @helpers[:unity_helper].nil? ? ['UNITY_TEST_ASSERT_EQUAL', ''] : @helpers[:unity_helper].get_helper(c_type)
|
||||
end
|
||||
[c_type, arg_name, expected, ignore, unity_func[0], unity_func[1]]
|
||||
end
|
||||
|
||||
def void_pointer_type?(c_type)
|
||||
base = c_type.gsub(/\bconst\b/, '').gsub(/\s+/, '')
|
||||
return false unless base.end_with?('*')
|
||||
|
||||
@treat_as_void.include?(base.chomp('*'))
|
||||
end
|
||||
|
||||
def ptr_to_array_elem_size(arg, c_type)
|
||||
# For pointer-to-array args (e.g., char (*buf)[10]), the element size is sizeof(base_type[dims])
|
||||
if arg[:ptr_to_array?] && arg[:array_dims]
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
# =========================================================================
|
||||
# CMock - Automatic Mock Generation for C
|
||||
# ThrowTheSwitch.org
|
||||
# Copyright (c) 2007-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
|
||||
# SPDX-License-Identifier: MIT
|
||||
# =========================================================================
|
||||
|
||||
---
|
||||
#The purpose of this test is to verify that void* arguments use pointer
|
||||
#comparison (not byte dereferencing) when the array plugin is not active.
|
||||
#Dereferencing void* is illegal in C, so the mock must fall back to
|
||||
#comparing pointer values via UNITY_TEST_ASSERT_EQUAL_PTR.
|
||||
:cmock:
|
||||
:plugins: []
|
||||
:treat_as_void:
|
||||
- MY_VOID
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
typedef void MY_VOID;
|
||||
|
||||
:mockable: |
|
||||
void get_v_ptr(void* ptr);
|
||||
void get_const_v_ptr(const void* ptr);
|
||||
void get_my_void_ptr(MY_VOID* ptr);
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
void function_a(void* arg);
|
||||
void function_b(const void* arg);
|
||||
void function_c(MY_VOID* arg);
|
||||
|
||||
:code: |
|
||||
void function_a(void* arg) {
|
||||
get_v_ptr(arg);
|
||||
}
|
||||
|
||||
void function_b(const void* arg) {
|
||||
get_const_v_ptr(arg);
|
||||
}
|
||||
|
||||
void function_c(MY_VOID* arg) {
|
||||
get_my_void_ptr(arg);
|
||||
}
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'handle void pointer expect passing when same pointer used'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
char* a = "Hello";
|
||||
get_v_ptr_Expect(a);
|
||||
function_a(a);
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'detect void pointer mismatch when different pointers used even with same content'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
static char a[] = "Hello";
|
||||
static char b[] = "Hello";
|
||||
get_v_ptr_Expect(a);
|
||||
function_a(b);
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'handle null void pointer expect passing'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
get_v_ptr_Expect(NULL);
|
||||
function_a(NULL);
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'detect null vs non-null void pointer mismatch'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
char* a = "Hello";
|
||||
get_v_ptr_Expect(NULL);
|
||||
function_a(a);
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'handle const void pointer expect passing when same pointer used'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
char* a = "Hello";
|
||||
get_const_v_ptr_Expect(a);
|
||||
function_b(a);
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'detect const void pointer mismatch when different pointers used'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
static char a[] = "Hello";
|
||||
static char b[] = "Hello";
|
||||
get_const_v_ptr_Expect(a);
|
||||
function_b(b);
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'handle treat_as_void alias pointer expect passing when same pointer used'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
char* a = "Hello";
|
||||
get_my_void_ptr_Expect(a);
|
||||
function_c(a);
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'detect treat_as_void alias pointer mismatch when different pointers used'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
static char a[] = "Hello";
|
||||
static char b[] = "Hello";
|
||||
get_my_void_ptr_Expect(a);
|
||||
function_c(b);
|
||||
}
|
||||
...
|
||||
@@ -401,4 +401,49 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_MY_TYPE_ARRAY', '&'], ['MY_TYPE']
|
||||
assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
|
||||
# void* tests without array plugin (when_ptr: :compare_data) - these must use pointer
|
||||
# comparison because dereferencing void* is illegal in C
|
||||
it 'handle void pointer comparison without array plugin by using pointer comparison' do
|
||||
config_stub = create_stub({
|
||||
when_ptr: :compare_data,
|
||||
enforce_strict_ordering: false,
|
||||
plugins: [],
|
||||
treat_as: {'void*' => 'HEX8_ARRAY', 'void const*' => 'HEX8_ARRAY', 'const void*' => 'HEX8_ARRAY'},
|
||||
treat_as_void: []
|
||||
})
|
||||
utils = CMockGeneratorUtils.new(config_stub, {:unity_helper => @unity_helper})
|
||||
function = { :name => 'Pear' }
|
||||
|
||||
[
|
||||
{:type => "void*", :name => 'MyVoidPtr', :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
{:type => "const void*", :name => 'MyConstVoidPtr', :ptr? => true, :const? => true, :const_ptr? => false},
|
||||
{:type => "void const*", :name => 'MyVoidConstPtr', :ptr? => true, :const? => false, :const_ptr? => true},
|
||||
].each do |arg|
|
||||
expected = " {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_#{arg[:name]});\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_PTR(cmock_call_instance->Expected_#{arg[:name]}, #{arg[:name]}, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n"
|
||||
assert_equal(expected, utils.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
end
|
||||
|
||||
it 'handle treat_as_void alias pointer comparison without array plugin by using pointer comparison' do
|
||||
config_stub = create_stub({
|
||||
when_ptr: :compare_data,
|
||||
enforce_strict_ordering: false,
|
||||
plugins: [],
|
||||
treat_as: {'MY_VOID*' => 'HEX8_ARRAY'},
|
||||
treat_as_void: ['MY_VOID']
|
||||
})
|
||||
utils = CMockGeneratorUtils.new(config_stub, {:unity_helper => @unity_helper})
|
||||
function = { :name => 'Pear' }
|
||||
|
||||
arg = {:type => "MY_VOID*", :name => 'MyVoidAliasPtr', :ptr? => true, :const? => false, :const_ptr? => false}
|
||||
expected = " {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyVoidAliasPtr);\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_PTR(cmock_call_instance->Expected_MyVoidAliasPtr, MyVoidAliasPtr, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n"
|
||||
assert_equal(expected, utils.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user