Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
be03cdc2
提交
be03cdc2
authored
11月 25, 2011
作者:
Viktor Krikun
提交者:
Travis Cross
3月 31, 2012
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add Cmockery unit-testing library as a backend for our automated tests
(closes #26)
上级
c74f85f7
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
2371 行增加
和
0 行删除
+2371
-0
cmockery.c
test/cmockery/cmockery.c
+1803
-0
cmockery.h
test/cmockery/cmockery.h
+568
-0
没有找到文件。
test/cmockery/cmockery.c
0 → 100644
浏览文件 @
be03cdc2
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <setjmp.h>
#ifndef _WIN32
#include <signal.h>
#endif // !_WIN32
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
/* HAVE_INTTYPES_H */
#ifdef _WIN32
#include <windows.h>
#endif // _WIN32
#include <cmockery.h>
#ifdef _WIN32
#define vsnprintf _vsnprintf
#endif // _WIN32
/* Backwards compatibility with headers shipped with Visual Studio 2005 and
* earlier. */
#ifdef _WIN32
WINBASEAPI
BOOL
WINAPI
IsDebuggerPresent
(
VOID
);
#endif // _WIN32
// Size of guard bytes around dynamically allocated blocks.
#define MALLOC_GUARD_SIZE 16
// Pattern used to initialize guard blocks.
#define MALLOC_GUARD_PATTERN 0xEF
// Pattern used to initialize memory allocated with test_malloc().
#define MALLOC_ALLOC_PATTERN 0xBA
#define MALLOC_FREE_PATTERN 0xCD
// Alignment of allocated blocks. NOTE: This must be base2.
#define MALLOC_ALIGNMENT sizeof(size_t)
// Printf formatting for source code locations.
#define SOURCE_LOCATION_FORMAT "%s:%d"
// Calculates the number of elements in an array.
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
// Declare and initialize the pointer member of ValuePointer variable name
// with ptr.
#define declare_initialize_value_pointer_pointer(name, ptr) \
ValuePointer name ; \
name.value = 0; \
name.pointer = (void*)(ptr)
// Declare and initialize the value member of ValuePointer variable name
// with val.
#define declare_initialize_value_pointer_value(name, val) \
ValuePointer name ; \
name.value = val
// Cast a uintmax_t to pointer_type via a ValuePointer.
#define cast_largest_integral_type_to_pointer( \
pointer_type, largest_integral_type) \
((pointer_type)((ValuePointer*)&(largest_integral_type))->pointer)
// Used to cast uintmax_t to void* and vice versa.
typedef
union
ValuePointer
{
uintmax_t
value
;
void
*
pointer
;
}
ValuePointer
;
// Doubly linked list node.
typedef
struct
ListNode
{
const
void
*
value
;
int
refcount
;
struct
ListNode
*
next
;
struct
ListNode
*
prev
;
}
ListNode
;
// Debug information for malloc().
typedef
struct
MallocBlockInfo
{
void
*
block
;
// Address of the block returned by malloc().
size_t
allocated_size
;
// Total size of the allocated block.
size_t
size
;
// Request block size.
SourceLocation
location
;
// Where the block was allocated.
ListNode
node
;
// Node within list of all allocated blocks.
}
MallocBlockInfo
;
// State of each test.
typedef
struct
TestState
{
const
ListNode
*
check_point
;
// Check point of the test if there's a
// setup function.
void
*
state
;
// State associated with the test.
}
TestState
;
// Determines whether two values are the same.
typedef
int
(
*
EqualityFunction
)(
const
void
*
left
,
const
void
*
right
);
// Value of a symbol and the place it was declared.
typedef
struct
SymbolValue
{
SourceLocation
location
;
uintmax_t
value
;
}
SymbolValue
;
/* Contains a list of values for a symbol.
* NOTE: Each structure referenced by symbol_values_list_head must have a
* SourceLocation as its' first member.
*/
typedef
struct
SymbolMapValue
{
const
char
*
symbol_name
;
ListNode
symbol_values_list_head
;
}
SymbolMapValue
;
// Used by list_free() to deallocate values referenced by list nodes.
typedef
void
(
*
CleanupListValue
)(
const
void
*
value
,
void
*
cleanup_value_data
);
// Structure used to check the range of integer types.
typedef
struct
CheckIntegerRange
{
CheckParameterEvent
event
;
uintmax_t
minimum
;
uintmax_t
maximum
;
}
CheckIntegerRange
;
// Structure used to check whether an integer value is in a set.
typedef
struct
CheckIntegerSet
{
CheckParameterEvent
event
;
const
uintmax_t
*
set
;
size_t
size_of_set
;
}
CheckIntegerSet
;
/* Used to check whether a parameter matches the area of memory referenced by
* this structure. */
typedef
struct
CheckMemoryData
{
CheckParameterEvent
event
;
const
void
*
memory
;
size_t
size
;
}
CheckMemoryData
;
static
ListNode
*
list_initialize
(
ListNode
*
const
node
);
static
ListNode
*
list_add
(
ListNode
*
const
head
,
ListNode
*
new_node
);
static
ListNode
*
list_add_value
(
ListNode
*
const
head
,
const
void
*
value
,
const
int
count
);
static
ListNode
*
list_remove
(
ListNode
*
const
node
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
);
static
void
list_remove_free
(
ListNode
*
const
node
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
);
static
int
list_empty
(
const
ListNode
*
const
head
);
static
int
list_find
(
ListNode
*
const
head
,
const
void
*
value
,
const
EqualityFunction
equal_func
,
ListNode
**
output
);
static
int
list_first
(
ListNode
*
const
head
,
ListNode
**
output
);
static
ListNode
*
list_free
(
ListNode
*
const
head
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
);
static
void
add_symbol_value
(
ListNode
*
const
symbol_map_head
,
const
char
*
const
symbol_names
[],
const
size_t
number_of_symbol_names
,
const
void
*
value
,
const
int
count
);
static
int
get_symbol_value
(
ListNode
*
const
symbol_map_head
,
const
char
*
const
symbol_names
[],
const
size_t
number_of_symbol_names
,
void
**
output
);
static
void
free_value
(
const
void
*
value
,
void
*
cleanup_value_data
);
static
void
free_symbol_map_value
(
const
void
*
value
,
void
*
cleanup_value_data
);
static
void
remove_always_return_values
(
ListNode
*
const
map_head
,
const
size_t
number_of_symbol_names
);
static
int
check_for_leftover_values
(
const
ListNode
*
const
map_head
,
const
char
*
const
error_message
,
const
size_t
number_of_symbol_names
);
// This must be called at the beginning of a test to initialize some data
// structures.
static
void
initialize_testing
(
const
char
*
test_name
);
// This must be called at the end of a test to free() allocated structures.
static
void
teardown_testing
(
const
char
*
test_name
);
// Keeps track of the calling context returned by setenv() so that the fail()
// method can jump out of a test.
static
jmp_buf
global_run_test_env
;
static
int
global_running_test
=
0
;
// Keeps track of the calling context returned by setenv() so that
// mock_assert() can optionally jump back to expect_assert_failure().
jmp_buf
global_expect_assert_env
;
int
global_expecting_assert
=
0
;
// Keeps a map of the values that functions will have to return to provide
// mocked interfaces.
static
ListNode
global_function_result_map_head
;
// Location of the last mock value returned was declared.
static
SourceLocation
global_last_mock_value_location
;
/* Keeps a map of the values that functions expect as parameters to their
* mocked interfaces. */
static
ListNode
global_function_parameter_map_head
;
// Location of last parameter value checked was declared.
static
SourceLocation
global_last_parameter_location
;
// List of all currently allocated blocks.
static
ListNode
global_allocated_blocks
;
#ifndef _WIN32
// Signals caught by exception_handler().
static
const
int
exception_signals
[]
=
{
SIGFPE
,
SIGILL
,
SIGSEGV
,
SIGBUS
,
SIGSYS
,
};
// Default signal functions that should be restored after a test is complete.
typedef
void
(
*
SignalFunction
)(
int
signal
);
static
SignalFunction
default_signal_functions
[
ARRAY_LENGTH
(
exception_signals
)];
#else // _WIN32
// The default exception filter.
static
LPTOP_LEVEL_EXCEPTION_FILTER
previous_exception_filter
;
// Fatal exceptions.
typedef
struct
ExceptionCodeInfo
{
DWORD
code
;
const
char
*
description
;
}
ExceptionCodeInfo
;
#define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code}
static
const
ExceptionCodeInfo
exception_codes
[]
=
{
EXCEPTION_CODE_INFO
(
EXCEPTION_ACCESS_VIOLATION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_ARRAY_BOUNDS_EXCEEDED
),
EXCEPTION_CODE_INFO
(
EXCEPTION_DATATYPE_MISALIGNMENT
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_DENORMAL_OPERAND
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_DIVIDE_BY_ZERO
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_INEXACT_RESULT
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_INVALID_OPERATION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_OVERFLOW
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_STACK_CHECK
),
EXCEPTION_CODE_INFO
(
EXCEPTION_FLT_UNDERFLOW
),
EXCEPTION_CODE_INFO
(
EXCEPTION_GUARD_PAGE
),
EXCEPTION_CODE_INFO
(
EXCEPTION_ILLEGAL_INSTRUCTION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_INT_DIVIDE_BY_ZERO
),
EXCEPTION_CODE_INFO
(
EXCEPTION_INT_OVERFLOW
),
EXCEPTION_CODE_INFO
(
EXCEPTION_INVALID_DISPOSITION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_INVALID_HANDLE
),
EXCEPTION_CODE_INFO
(
EXCEPTION_IN_PAGE_ERROR
),
EXCEPTION_CODE_INFO
(
EXCEPTION_NONCONTINUABLE_EXCEPTION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_PRIV_INSTRUCTION
),
EXCEPTION_CODE_INFO
(
EXCEPTION_STACK_OVERFLOW
),
};
#endif // !_WIN32
// Exit the currently executing test.
static
void
exit_test
(
const
int
quit_application
)
{
if
(
global_running_test
)
{
longjmp
(
global_run_test_env
,
1
);
}
else
if
(
quit_application
)
{
exit
(
-
1
);
}
}
// Initialize a SourceLocation structure.
static
void
initialize_source_location
(
SourceLocation
*
const
location
)
{
assert_non_null
(
location
);
location
->
file
=
NULL
;
location
->
line
=
0
;
}
// Determine whether a source location is currently set.
static
int
source_location_is_set
(
const
SourceLocation
*
const
location
)
{
assert_non_null
(
location
);
return
location
->
file
&&
location
->
line
;
}
// Set a source location.
static
void
set_source_location
(
SourceLocation
*
const
location
,
const
char
*
const
file
,
const
int
line
)
{
assert_non_null
(
location
);
location
->
file
=
file
;
location
->
line
=
line
;
}
// Create function results and expected parameter lists.
void
initialize_testing
(
const
char
*
test_name
)
{
(
void
)
test_name
;
list_initialize
(
&
global_function_result_map_head
);
initialize_source_location
(
&
global_last_mock_value_location
);
list_initialize
(
&
global_function_parameter_map_head
);
initialize_source_location
(
&
global_last_parameter_location
);
}
void
fail_if_leftover_values
(
const
char
*
test_name
)
{
int
error_occurred
=
0
;
(
void
)
test_name
;
remove_always_return_values
(
&
global_function_result_map_head
,
1
);
if
(
check_for_leftover_values
(
&
global_function_result_map_head
,
"%s() has remaining non-returned values.
\n
"
,
1
))
{
error_occurred
=
1
;
}
remove_always_return_values
(
&
global_function_parameter_map_head
,
2
);
if
(
check_for_leftover_values
(
&
global_function_parameter_map_head
,
"%s parameter still has values that haven't been checked.
\n
"
,
2
))
{
error_occurred
=
1
;
}
if
(
error_occurred
)
{
exit_test
(
1
);
}
}
void
teardown_testing
(
const
char
*
test_name
)
{
(
void
)
test_name
;
list_free
(
&
global_function_result_map_head
,
free_symbol_map_value
,
(
void
*
)
0
);
initialize_source_location
(
&
global_last_mock_value_location
);
list_free
(
&
global_function_parameter_map_head
,
free_symbol_map_value
,
(
void
*
)
1
);
initialize_source_location
(
&
global_last_parameter_location
);
}
// Initialize a list node.
static
ListNode
*
list_initialize
(
ListNode
*
const
node
)
{
node
->
value
=
NULL
;
node
->
next
=
node
;
node
->
prev
=
node
;
node
->
refcount
=
1
;
return
node
;
}
/* Adds a value at the tail of a given list.
* The node referencing the value is allocated from the heap. */
static
ListNode
*
list_add_value
(
ListNode
*
const
head
,
const
void
*
value
,
const
int
refcount
)
{
ListNode
*
const
new_node
=
(
ListNode
*
)
malloc
(
sizeof
(
ListNode
));
assert_non_null
(
head
);
assert_non_null
(
value
);
new_node
->
value
=
value
;
new_node
->
refcount
=
refcount
;
return
list_add
(
head
,
new_node
);
}
// Add new_node to the end of the list.
static
ListNode
*
list_add
(
ListNode
*
const
head
,
ListNode
*
new_node
)
{
assert_non_null
(
head
);
assert_non_null
(
new_node
);
new_node
->
next
=
head
;
new_node
->
prev
=
head
->
prev
;
head
->
prev
->
next
=
new_node
;
head
->
prev
=
new_node
;
return
new_node
;
}
// Remove a node from a list.
static
ListNode
*
list_remove
(
ListNode
*
const
node
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
)
{
assert_non_null
(
node
);
node
->
prev
->
next
=
node
->
next
;
node
->
next
->
prev
=
node
->
prev
;
if
(
cleanup_value
)
{
cleanup_value
(
node
->
value
,
cleanup_value_data
);
}
return
node
;
}
/* Remove a list node from a list and free the node. */
static
void
list_remove_free
(
ListNode
*
const
node
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
)
{
assert_non_null
(
node
);
free
(
list_remove
(
node
,
cleanup_value
,
cleanup_value_data
));
}
/* Frees memory kept by a linked list
* The cleanup_value function is called for every "value" field of nodes in the
* list, except for the head. In addition to each list value,
* cleanup_value_data is passed to each call to cleanup_value. The head
* of the list is not deallocated.
*/
static
ListNode
*
list_free
(
ListNode
*
const
head
,
const
CleanupListValue
cleanup_value
,
void
*
const
cleanup_value_data
)
{
assert_non_null
(
head
);
while
(
!
list_empty
(
head
))
{
list_remove_free
(
head
->
next
,
cleanup_value
,
cleanup_value_data
);
}
return
head
;
}
// Determine whether a list is empty.
static
int
list_empty
(
const
ListNode
*
const
head
)
{
assert_non_null
(
head
);
return
head
->
next
==
head
;
}
/* Find a value in the list using the equal_func to compare each node with the
* value.
*/
static
int
list_find
(
ListNode
*
const
head
,
const
void
*
value
,
const
EqualityFunction
equal_func
,
ListNode
**
output
)
{
ListNode
*
current
;
assert_non_null
(
head
);
for
(
current
=
head
->
next
;
current
!=
head
;
current
=
current
->
next
)
{
if
(
equal_func
(
current
->
value
,
value
))
{
*
output
=
current
;
return
1
;
}
}
return
0
;
}
// Returns the first node of a list
static
int
list_first
(
ListNode
*
const
head
,
ListNode
**
output
)
{
ListNode
*
target_node
;
assert_non_null
(
head
);
if
(
list_empty
(
head
))
{
return
0
;
}
target_node
=
head
->
next
;
*
output
=
target_node
;
return
1
;
}
// Deallocate a value referenced by a list.
static
void
free_value
(
const
void
*
value
,
void
*
cleanup_value_data
)
{
(
void
)
cleanup_value_data
;
assert_non_null
(
value
);
free
((
void
*
)
value
);
}
// Releases memory associated to a symbol_map_value.
static
void
free_symbol_map_value
(
const
void
*
value
,
void
*
cleanup_value_data
)
{
SymbolMapValue
*
const
map_value
=
(
SymbolMapValue
*
)
value
;
const
uintmax_t
children
=
cast_ptr_to_largest_integral_type
(
cleanup_value_data
);
assert_non_null
(
value
);
list_free
(
&
map_value
->
symbol_values_list_head
,
children
?
free_symbol_map_value
:
free_value
,
(
void
*
)
((
uintptr_t
)
children
-
1
));
free
(
map_value
);
}
/* Determine whether a symbol name referenced by a symbol_map_value
* matches the specified function name. */
static
int
symbol_names_match
(
const
void
*
map_value
,
const
void
*
symbol
)
{
return
!
strcmp
(((
SymbolMapValue
*
)
map_value
)
->
symbol_name
,
(
const
char
*
)
symbol
);
}
/* Adds a value to the queue of values associated with the given
* hierarchy of symbols. It's assumed value is allocated from the heap.
*/
static
void
add_symbol_value
(
ListNode
*
const
symbol_map_head
,
const
char
*
const
symbol_names
[],
const
size_t
number_of_symbol_names
,
const
void
*
value
,
const
int
refcount
)
{
const
char
*
symbol_name
;
ListNode
*
target_node
;
SymbolMapValue
*
target_map_value
;
assert_non_null
(
symbol_map_head
);
assert_non_null
(
symbol_names
);
assert_true
(
number_of_symbol_names
);
symbol_name
=
symbol_names
[
0
];
if
(
!
list_find
(
symbol_map_head
,
symbol_name
,
symbol_names_match
,
&
target_node
))
{
SymbolMapValue
*
const
new_symbol_map_value
=
(
SymbolMapValue
*
)
malloc
(
sizeof
(
*
new_symbol_map_value
));
new_symbol_map_value
->
symbol_name
=
symbol_name
;
list_initialize
(
&
new_symbol_map_value
->
symbol_values_list_head
);
target_node
=
list_add_value
(
symbol_map_head
,
new_symbol_map_value
,
1
);
}
target_map_value
=
(
SymbolMapValue
*
)
target_node
->
value
;
if
(
number_of_symbol_names
==
1
)
{
list_add_value
(
&
target_map_value
->
symbol_values_list_head
,
value
,
refcount
);
}
else
{
add_symbol_value
(
&
target_map_value
->
symbol_values_list_head
,
&
symbol_names
[
1
],
number_of_symbol_names
-
1
,
value
,
refcount
);
}
}
/* Gets the next value associated with the given hierarchy of symbols.
* The value is returned as an output parameter with the function returning the
* node's old refcount value if a value is found, 0 otherwise.
* This means that a return value of 1 indicates the node was just removed from
* the list.
*/
static
int
get_symbol_value
(
ListNode
*
const
head
,
const
char
*
const
symbol_names
[],
const
size_t
number_of_symbol_names
,
void
**
output
)
{
const
char
*
symbol_name
;
ListNode
*
target_node
;
assert_non_null
(
head
);
assert_non_null
(
symbol_names
);
assert_true
(
number_of_symbol_names
);
assert_non_null
(
output
);
symbol_name
=
symbol_names
[
0
];
if
(
list_find
(
head
,
symbol_name
,
symbol_names_match
,
&
target_node
))
{
SymbolMapValue
*
map_value
;
ListNode
*
child_list
;
int
return_value
=
0
;
assert_non_null
(
target_node
);
assert_non_null
(
target_node
->
value
);
map_value
=
(
SymbolMapValue
*
)
target_node
->
value
;
child_list
=
&
map_value
->
symbol_values_list_head
;
if
(
number_of_symbol_names
==
1
)
{
ListNode
*
value_node
=
NULL
;
return_value
=
list_first
(
child_list
,
&
value_node
);
assert_true
(
return_value
);
*
output
=
(
void
*
)
value_node
->
value
;
return_value
=
value_node
->
refcount
;
if
(
--
value_node
->
refcount
==
0
)
{
list_remove_free
(
value_node
,
NULL
,
NULL
);
}
}
else
{
return_value
=
get_symbol_value
(
child_list
,
&
symbol_names
[
1
],
number_of_symbol_names
-
1
,
output
);
}
if
(
list_empty
(
child_list
))
{
list_remove_free
(
target_node
,
free_symbol_map_value
,
(
void
*
)
0
);
}
return
return_value
;
}
else
{
print_error
(
"No entries for symbol %s.
\n
"
,
symbol_name
);
}
return
0
;
}
/* Traverse down a tree of symbol values and remove the first symbol value
* in each branch that has a refcount < -1 (i.e should always be returned
* and has been returned at least once).
*/
static
void
remove_always_return_values
(
ListNode
*
const
map_head
,
const
size_t
number_of_symbol_names
)
{
ListNode
*
current
;
assert_non_null
(
map_head
);
assert_true
(
number_of_symbol_names
);
current
=
map_head
->
next
;
while
(
current
!=
map_head
)
{
SymbolMapValue
*
const
value
=
(
SymbolMapValue
*
)
current
->
value
;
ListNode
*
const
next
=
current
->
next
;
ListNode
*
child_list
;
assert_non_null
(
value
);
child_list
=
&
value
->
symbol_values_list_head
;
if
(
!
list_empty
(
child_list
))
{
if
(
number_of_symbol_names
==
1
)
{
ListNode
*
const
child_node
=
child_list
->
next
;
// If this item has been returned more than once, free it.
if
(
child_node
->
refcount
<
-
1
)
{
list_remove_free
(
child_node
,
free_value
,
NULL
);
}
}
else
{
remove_always_return_values
(
child_list
,
number_of_symbol_names
-
1
);
}
}
if
(
list_empty
(
child_list
))
{
list_remove_free
(
current
,
free_value
,
NULL
);
}
current
=
next
;
}
}
/* Checks if there are any leftover values set up by the test that were never
* retrieved through execution, and fail the test if that is the case.
*/
static
int
check_for_leftover_values
(
const
ListNode
*
const
map_head
,
const
char
*
const
error_message
,
const
size_t
number_of_symbol_names
)
{
const
ListNode
*
current
;
int
symbols_with_leftover_values
=
0
;
assert_non_null
(
map_head
);
assert_true
(
number_of_symbol_names
);
for
(
current
=
map_head
->
next
;
current
!=
map_head
;
current
=
current
->
next
)
{
const
SymbolMapValue
*
const
value
=
(
SymbolMapValue
*
)
current
->
value
;
const
ListNode
*
child_list
;
assert_non_null
(
value
);
child_list
=
&
value
->
symbol_values_list_head
;
if
(
!
list_empty
(
child_list
))
{
if
(
number_of_symbol_names
==
1
)
{
const
ListNode
*
child_node
;
print_error
(
error_message
,
value
->
symbol_name
);
print_error
(
" Remaining item(s) declared at...
\n
"
);
for
(
child_node
=
child_list
->
next
;
child_node
!=
child_list
;
child_node
=
child_node
->
next
)
{
const
SourceLocation
*
const
location
=
(
const
SourceLocation
*
)
child_node
->
value
;
print_error
(
" "
SOURCE_LOCATION_FORMAT
"
\n
"
,
location
->
file
,
location
->
line
);
}
}
else
{
print_error
(
"%s."
,
value
->
symbol_name
);
check_for_leftover_values
(
child_list
,
error_message
,
number_of_symbol_names
-
1
);
}
symbols_with_leftover_values
++
;
}
}
return
symbols_with_leftover_values
;
}
// Get the next return value for the specified mock function.
uintmax_t
_mock
(
const
char
*
const
function
,
const
char
*
const
file
,
const
int
line
)
{
void
*
result
;
const
int
rc
=
get_symbol_value
(
&
global_function_result_map_head
,
&
function
,
1
,
&
result
);
if
(
rc
)
{
SymbolValue
*
const
symbol
=
(
SymbolValue
*
)
result
;
const
uintmax_t
value
=
symbol
->
value
;
global_last_mock_value_location
=
symbol
->
location
;
if
(
rc
==
1
)
{
free
(
symbol
);
}
return
value
;
}
else
{
print_error
(
"ERROR: "
SOURCE_LOCATION_FORMAT
" - Could not get value "
"to mock function %s
\n
"
,
file
,
line
,
function
);
if
(
source_location_is_set
(
&
global_last_mock_value_location
))
{
print_error
(
"Previously returned mock value was declared at "
SOURCE_LOCATION_FORMAT
"
\n
"
,
global_last_mock_value_location
.
file
,
global_last_mock_value_location
.
line
);
}
else
{
print_error
(
"There were no previously returned mock values for "
"this test.
\n
"
);
}
exit_test
(
1
);
}
return
0
;
}
// Add a return value for the specified mock function name.
void
_will_return
(
const
char
*
const
function_name
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
)
{
SymbolValue
*
const
return_value
=
(
SymbolValue
*
)
malloc
(
sizeof
(
*
return_value
));
assert_true
(
count
>
0
||
count
==
-
1
);
return_value
->
value
=
value
;
set_source_location
(
&
return_value
->
location
,
file
,
line
);
add_symbol_value
(
&
global_function_result_map_head
,
&
function_name
,
1
,
return_value
,
count
);
}
/* Add a custom parameter checking function. If the event parameter is NULL
* the event structure is allocated internally by this function. If event
* parameter is provided it must be allocated on the heap and doesn't need to
* be deallocated by the caller.
*/
void
_expect_check
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
CheckParameterValue
check_function
,
const
uintmax_t
check_data
,
CheckParameterEvent
*
const
event
,
const
int
count
)
{
CheckParameterEvent
*
const
check
=
event
?
event
:
(
CheckParameterEvent
*
)
malloc
(
sizeof
(
*
check
));
const
char
*
symbols
[]
=
{
function
,
parameter
};
check
->
parameter_name
=
parameter
;
check
->
check_value
=
check_function
;
check
->
check_value_data
=
check_data
;
set_source_location
(
&
check
->
location
,
file
,
line
);
add_symbol_value
(
&
global_function_parameter_map_head
,
symbols
,
2
,
check
,
count
);
}
/* Returns 1 if the specified values are equal. If the values are not equal
* an error is displayed and 0 is returned. */
static
int
values_equal_display_error
(
const
uintmax_t
left
,
const
uintmax_t
right
)
{
const
int
equal
=
left
==
right
;
if
(
!
equal
)
{
print_error
(
"%"
PRIxMAX
" != "
"%"
PRIxMAX
"
\n
"
,
left
,
right
);
}
return
equal
;
}
/* Returns 1 if the specified values are not equal. If the values are equal
* an error is displayed and 0 is returned. */
static
int
values_not_equal_display_error
(
const
uintmax_t
left
,
const
uintmax_t
right
)
{
const
int
not_equal
=
left
!=
right
;
if
(
!
not_equal
)
{
print_error
(
"%"
PRIxMAX
" == "
"%"
PRIxMAX
"
\n
"
,
left
,
right
);
}
return
not_equal
;
}
/* Determine whether value is contained within check_integer_set.
* If invert is 0 and the value is in the set 1 is returned, otherwise 0 is
* returned and an error is displayed. If invert is 1 and the value is not
* in the set 1 is returned, otherwise 0 is returned and an error is
* displayed. */
static
int
value_in_set_display_error
(
const
uintmax_t
value
,
const
CheckIntegerSet
*
const
check_integer_set
,
const
int
invert
)
{
int
succeeded
=
invert
;
assert_non_null
(
check_integer_set
);
{
const
uintmax_t
*
const
set
=
check_integer_set
->
set
;
const
size_t
size_of_set
=
check_integer_set
->
size_of_set
;
size_t
i
;
for
(
i
=
0
;
i
<
size_of_set
;
i
++
)
{
if
(
set
[
i
]
==
value
)
{
// If invert = 0 and item is found, succeeded = 1.
// If invert = 1 and item is found, succeeded = 0.
succeeded
=
!
succeeded
;
break
;
}
}
if
(
succeeded
)
{
return
1
;
}
print_error
(
"%"
PRIuMAX
" is %sin the set ("
,
value
,
invert
?
""
:
"not "
);
for
(
i
=
0
;
i
<
size_of_set
;
i
++
)
{
print_error
(
"%"
PRIuMAX
", "
,
set
[
i
]);
}
print_error
(
")
\n
"
);
}
return
0
;
}
/* Determine whether a value is within the specified range. If the value is
* within the specified range 1 is returned. If the value isn't within the
* specified range an error is displayed and 0 is returned. */
static
int
integer_in_range_display_error
(
const
uintmax_t
value
,
const
uintmax_t
range_min
,
const
uintmax_t
range_max
)
{
if
(
value
>=
range_min
&&
value
<=
range_max
)
{
return
1
;
}
print_error
(
"%"
PRIuMAX
" is not within the range %"
PRIuMAX
"-%"
PRIuMAX
"
\n
"
,
value
,
range_min
,
range_max
);
return
0
;
}
/* Determine whether a value is within the specified range. If the value
* is not within the range 1 is returned. If the value is within the
* specified range an error is displayed and zero is returned. */
static
int
integer_not_in_range_display_error
(
const
uintmax_t
value
,
const
uintmax_t
range_min
,
const
uintmax_t
range_max
)
{
if
(
value
<
range_min
||
value
>
range_max
)
{
return
1
;
}
print_error
(
"%"
PRIuMAX
" is within the range %"
PRIuMAX
"-%"
PRIuMAX
"
\n
"
,
value
,
range_min
,
range_max
);
return
0
;
}
/* Determine whether the specified strings are equal. If the strings are equal
* 1 is returned. If they're not equal an error is displayed and 0 is
* returned. */
static
int
string_equal_display_error
(
const
char
*
const
left
,
const
char
*
const
right
)
{
if
(
strcmp
(
left
,
right
)
==
0
)
{
return
1
;
}
print_error
(
"
\"
%s
\"
!=
\"
%s
\"\n
"
,
left
,
right
);
return
0
;
}
/* Determine whether the specified strings are equal. If the strings are not
* equal 1 is returned. If they're not equal an error is displayed and 0 is
* returned */
static
int
string_not_equal_display_error
(
const
char
*
const
left
,
const
char
*
const
right
)
{
if
(
strcmp
(
left
,
right
)
!=
0
)
{
return
1
;
}
print_error
(
"
\"
%s
\"
==
\"
%s
\"\n
"
,
left
,
right
);
return
0
;
}
/* Determine whether the specified areas of memory are equal. If they're equal
* 1 is returned otherwise an error is displayed and 0 is returned. */
static
int
memory_equal_display_error
(
const
char
*
const
a
,
const
char
*
const
b
,
const
size_t
size
)
{
int
differences
=
0
;
size_t
i
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
const
char
l
=
a
[
i
];
const
char
r
=
b
[
i
];
if
(
l
!=
r
)
{
print_error
(
"difference at offset %"
PRIuMAX
" 0x%02x 0x%02x
\n
"
,
cast_to_largest_integral_type
(
i
),
l
,
r
);
differences
++
;
}
}
if
(
differences
)
{
print_error
(
"%d bytes of 0x%08"
PRIxMAX
" and 0x%08"
PRIxMAX
" differ
\n
"
,
differences
,
cast_ptr_to_largest_integral_type
(
a
),
cast_ptr_to_largest_integral_type
(
b
));
return
0
;
}
return
1
;
}
/* Determine whether the specified areas of memory are not equal. If they're
* not equal 1 is returned otherwise an error is displayed and 0 is
* returned. */
static
int
memory_not_equal_display_error
(
const
char
*
const
a
,
const
char
*
const
b
,
const
size_t
size
)
{
size_t
same
=
0
;
size_t
i
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
const
char
l
=
a
[
i
];
const
char
r
=
b
[
i
];
if
(
l
==
r
)
{
same
++
;
}
}
if
(
same
==
size
)
{
print_error
(
"%"
PRIuMAX
" bytes of 0x%08"
PRIxMAX
" and 0x%08"
PRIxMAX
" the same
\n
"
,
cast_to_largest_integral_type
(
same
),
cast_ptr_to_largest_integral_type
(
a
),
cast_ptr_to_largest_integral_type
(
b
));
return
0
;
}
return
1
;
}
// CheckParameterValue callback to check whether a value is within a set.
static
int
check_in_set
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
value_in_set_display_error
(
value
,
cast_largest_integral_type_to_pointer
(
CheckIntegerSet
*
,
check_value_data
),
0
);
}
// CheckParameterValue callback to check whether a value isn't within a set.
static
int
check_not_in_set
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
value_in_set_display_error
(
value
,
cast_largest_integral_type_to_pointer
(
CheckIntegerSet
*
,
check_value_data
),
1
);
}
/* Create the callback data for check_in_set() or check_not_in_set() and
* register a check event. */
static
void
expect_set
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
CheckParameterValue
check_function
,
const
int
count
)
{
CheckIntegerSet
*
const
check_integer_set
=
(
CheckIntegerSet
*
)
malloc
(
sizeof
(
*
check_integer_set
)
+
(
sizeof
(
values
[
0
])
*
number_of_values
));
uintmax_t
*
const
set
=
(
uintmax_t
*
)(
check_integer_set
+
1
);
declare_initialize_value_pointer_pointer
(
check_data
,
check_integer_set
);
assert_non_null
(
values
);
assert_true
(
number_of_values
);
memcpy
(
set
,
values
,
number_of_values
*
sizeof
(
values
[
0
]));
check_integer_set
->
set
=
set
;
_expect_check
(
function
,
parameter
,
file
,
line
,
check_function
,
check_data
.
value
,
&
check_integer_set
->
event
,
count
);
}
// Add an event to check whether a value is in a set.
void
_expect_in_set
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
int
count
)
{
expect_set
(
function
,
parameter
,
file
,
line
,
values
,
number_of_values
,
check_in_set
,
count
);
}
// Add an event to check whether a value isn't in a set.
void
_expect_not_in_set
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
int
count
)
{
expect_set
(
function
,
parameter
,
file
,
line
,
values
,
number_of_values
,
check_not_in_set
,
count
);
}
// CheckParameterValue callback to check whether a value is within a range.
static
int
check_in_range
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
CheckIntegerRange
*
const
check_integer_range
=
cast_largest_integral_type_to_pointer
(
CheckIntegerRange
*
,
check_value_data
);
assert_non_null
(
check_integer_range
);
return
integer_in_range_display_error
(
value
,
check_integer_range
->
minimum
,
check_integer_range
->
maximum
);
}
// CheckParameterValue callback to check whether a value is not within a range.
static
int
check_not_in_range
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
CheckIntegerRange
*
const
check_integer_range
=
cast_largest_integral_type_to_pointer
(
CheckIntegerRange
*
,
check_value_data
);
assert_non_null
(
check_integer_range
);
return
integer_not_in_range_display_error
(
value
,
check_integer_range
->
minimum
,
check_integer_range
->
maximum
);
}
/* Create the callback data for check_in_range() or check_not_in_range() and
* register a check event. */
static
void
expect_range
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
CheckParameterValue
check_function
,
const
int
count
)
{
CheckIntegerRange
*
const
check_integer_range
=
(
CheckIntegerRange
*
)
malloc
(
sizeof
(
*
check_integer_range
));
declare_initialize_value_pointer_pointer
(
check_data
,
check_integer_range
);
check_integer_range
->
minimum
=
minimum
;
check_integer_range
->
maximum
=
maximum
;
_expect_check
(
function
,
parameter
,
file
,
line
,
check_function
,
check_data
.
value
,
&
check_integer_range
->
event
,
count
);
}
// Add an event to determine whether a parameter is within a range.
void
_expect_in_range
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
int
count
)
{
expect_range
(
function
,
parameter
,
file
,
line
,
minimum
,
maximum
,
check_in_range
,
count
);
}
// Add an event to determine whether a parameter is not within a range.
void
_expect_not_in_range
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
int
count
)
{
expect_range
(
function
,
parameter
,
file
,
line
,
minimum
,
maximum
,
check_not_in_range
,
count
);
}
/* CheckParameterValue callback to check whether a value is equal to an
* expected value. */
static
int
check_value
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
values_equal_display_error
(
value
,
check_value_data
);
}
// Add an event to check a parameter equals an expected value.
void
_expect_value
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
)
{
_expect_check
(
function
,
parameter
,
file
,
line
,
check_value
,
value
,
NULL
,
count
);
}
/* CheckParameterValue callback to check whether a value is not equal to an
* expected value. */
static
int
check_not_value
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
values_not_equal_display_error
(
value
,
check_value_data
);
}
// Add an event to check a parameter is not equal to an expected value.
void
_expect_not_value
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
)
{
_expect_check
(
function
,
parameter
,
file
,
line
,
check_not_value
,
value
,
NULL
,
count
);
}
// CheckParameterValue callback to check whether a parameter equals a string.
static
int
check_string
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
string_equal_display_error
(
cast_largest_integral_type_to_pointer
(
char
*
,
value
),
cast_largest_integral_type_to_pointer
(
char
*
,
check_value_data
));
}
// Add an event to check whether a parameter is equal to a string.
void
_expect_string
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
char
*
string
,
const
int
count
)
{
declare_initialize_value_pointer_pointer
(
string_pointer
,
(
char
*
)
string
);
_expect_check
(
function
,
parameter
,
file
,
line
,
check_string
,
string_pointer
.
value
,
NULL
,
count
);
}
/* CheckParameterValue callback to check whether a parameter is not equals to
* a string. */
static
int
check_not_string
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
return
string_not_equal_display_error
(
cast_largest_integral_type_to_pointer
(
char
*
,
value
),
cast_largest_integral_type_to_pointer
(
char
*
,
check_value_data
));
}
// Add an event to check whether a parameter is not equal to a string.
void
_expect_not_string
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
char
*
string
,
const
int
count
)
{
declare_initialize_value_pointer_pointer
(
string_pointer
,
(
char
*
)
string
);
_expect_check
(
function
,
parameter
,
file
,
line
,
check_not_string
,
string_pointer
.
value
,
NULL
,
count
);
}
/* CheckParameterValue callback to check whether a parameter equals an area of
* memory. */
static
int
check_memory
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
CheckMemoryData
*
const
check
=
cast_largest_integral_type_to_pointer
(
CheckMemoryData
*
,
check_value_data
);
assert_non_null
(
check
);
return
memory_equal_display_error
(
cast_largest_integral_type_to_pointer
(
const
char
*
,
value
),
(
const
char
*
)
check
->
memory
,
check
->
size
);
}
/* Create the callback data for check_memory() or check_not_memory() and
* register a check event. */
static
void
expect_memory_setup
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
void
*
const
memory
,
const
size_t
size
,
const
CheckParameterValue
check_function
,
const
int
count
)
{
CheckMemoryData
*
const
check_data
=
(
CheckMemoryData
*
)
malloc
(
sizeof
(
*
check_data
)
+
size
);
void
*
const
mem
=
(
void
*
)(
check_data
+
1
);
declare_initialize_value_pointer_pointer
(
check_data_pointer
,
check_data
);
assert_non_null
(
memory
);
assert_true
(
size
);
memcpy
(
mem
,
memory
,
size
);
check_data
->
memory
=
mem
;
check_data
->
size
=
size
;
_expect_check
(
function
,
parameter
,
file
,
line
,
check_function
,
check_data_pointer
.
value
,
&
check_data
->
event
,
count
);
}
// Add an event to check whether a parameter matches an area of memory.
void
_expect_memory
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
void
*
const
memory
,
const
size_t
size
,
const
int
count
)
{
expect_memory_setup
(
function
,
parameter
,
file
,
line
,
memory
,
size
,
check_memory
,
count
);
}
/* CheckParameterValue callback to check whether a parameter is not equal to
* an area of memory. */
static
int
check_not_memory
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
CheckMemoryData
*
const
check
=
cast_largest_integral_type_to_pointer
(
CheckMemoryData
*
,
check_value_data
);
assert_non_null
(
check
);
return
memory_not_equal_display_error
(
cast_largest_integral_type_to_pointer
(
const
char
*
,
value
),
(
const
char
*
)
check
->
memory
,
check
->
size
);
}
// Add an event to check whether a parameter doesn't match an area of memory.
void
_expect_not_memory
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
void
*
const
memory
,
const
size_t
size
,
const
int
count
)
{
expect_memory_setup
(
function
,
parameter
,
file
,
line
,
memory
,
size
,
check_not_memory
,
count
);
}
// CheckParameterValue callback that always returns 1.
static
int
check_any
(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
)
{
(
void
)
value
;
(
void
)
check_value_data
;
return
1
;
}
// Add an event to allow any value for a parameter.
void
_expect_any
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
int
count
)
{
_expect_check
(
function
,
parameter
,
file
,
line
,
check_any
,
0
,
NULL
,
count
);
}
void
_check_expected
(
const
char
*
const
function_name
,
const
char
*
const
parameter_name
,
const
char
*
file
,
const
int
line
,
const
uintmax_t
value
)
{
void
*
result
;
const
char
*
symbols
[]
=
{
function_name
,
parameter_name
};
const
int
rc
=
get_symbol_value
(
&
global_function_parameter_map_head
,
symbols
,
2
,
&
result
);
if
(
rc
)
{
CheckParameterEvent
*
const
check
=
(
CheckParameterEvent
*
)
result
;
int
check_succeeded
;
global_last_parameter_location
=
check
->
location
;
check_succeeded
=
check
->
check_value
(
value
,
check
->
check_value_data
);
if
(
rc
==
1
)
{
free
(
check
);
}
if
(
!
check_succeeded
)
{
print_error
(
"ERROR: Check of parameter %s, function %s failed
\n
"
"Expected parameter declared at "
SOURCE_LOCATION_FORMAT
"
\n
"
,
parameter_name
,
function_name
,
global_last_parameter_location
.
file
,
global_last_parameter_location
.
line
);
_fail
(
file
,
line
);
}
}
else
{
print_error
(
"ERROR: "
SOURCE_LOCATION_FORMAT
" - Could not get value "
"to check parameter %s of function %s
\n
"
,
file
,
line
,
parameter_name
,
function_name
);
if
(
source_location_is_set
(
&
global_last_parameter_location
))
{
print_error
(
"Previously declared parameter value was declared at "
SOURCE_LOCATION_FORMAT
"
\n
"
,
global_last_parameter_location
.
file
,
global_last_parameter_location
.
line
);
}
else
{
print_error
(
"There were no previously declared parameter values "
"for this test.
\n
"
);
}
exit_test
(
1
);
}
}
// Replacement for assert.
void
mock_assert
(
const
int
result
,
const
char
*
const
expression
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
result
)
{
if
(
global_expecting_assert
)
{
longjmp
(
global_expect_assert_env
,
(
int
)
expression
);
}
else
{
print_error
(
"ASSERT: %s
\n
"
,
expression
);
_fail
(
file
,
line
);
}
}
}
void
_assert_true
(
const
uintmax_t
result
,
const
char
*
const
expression
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
result
)
{
print_error
(
"%s
\n
"
,
expression
);
_fail
(
file
,
line
);
}
}
void
_assert_int_equal
(
const
uintmax_t
a
,
const
uintmax_t
b
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
values_equal_display_error
(
a
,
b
))
{
_fail
(
file
,
line
);
}
}
void
_assert_int_not_equal
(
const
uintmax_t
a
,
const
uintmax_t
b
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
values_not_equal_display_error
(
a
,
b
))
{
_fail
(
file
,
line
);
}
}
void
_assert_string_equal
(
const
char
*
const
a
,
const
char
*
const
b
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
string_equal_display_error
(
a
,
b
))
{
_fail
(
file
,
line
);
}
}
void
_assert_string_not_equal
(
const
char
*
const
a
,
const
char
*
const
b
,
const
char
*
file
,
const
int
line
)
{
if
(
!
string_not_equal_display_error
(
a
,
b
))
{
_fail
(
file
,
line
);
}
}
void
_assert_memory_equal
(
const
void
*
const
a
,
const
void
*
const
b
,
const
size_t
size
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
memory_equal_display_error
((
const
char
*
)
a
,
(
const
char
*
)
b
,
size
))
{
_fail
(
file
,
line
);
}
}
void
_assert_memory_not_equal
(
const
void
*
const
a
,
const
void
*
const
b
,
const
size_t
size
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
memory_not_equal_display_error
((
const
char
*
)
a
,
(
const
char
*
)
b
,
size
))
{
_fail
(
file
,
line
);
}
}
void
_assert_in_range
(
const
uintmax_t
value
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
integer_in_range_display_error
(
value
,
minimum
,
maximum
))
{
_fail
(
file
,
line
);
}
}
void
_assert_not_in_range
(
const
uintmax_t
value
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
char
*
const
file
,
const
int
line
)
{
if
(
!
integer_not_in_range_display_error
(
value
,
minimum
,
maximum
))
{
_fail
(
file
,
line
);
}
}
void
_assert_in_set
(
const
uintmax_t
value
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
char
*
const
file
,
const
int
line
)
{
CheckIntegerSet
check_integer_set
;
check_integer_set
.
set
=
values
;
check_integer_set
.
size_of_set
=
number_of_values
;
if
(
!
value_in_set_display_error
(
value
,
&
check_integer_set
,
0
))
{
_fail
(
file
,
line
);
}
}
void
_assert_not_in_set
(
const
uintmax_t
value
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
char
*
const
file
,
const
int
line
)
{
CheckIntegerSet
check_integer_set
;
check_integer_set
.
set
=
values
;
check_integer_set
.
size_of_set
=
number_of_values
;
if
(
!
value_in_set_display_error
(
value
,
&
check_integer_set
,
1
))
{
_fail
(
file
,
line
);
}
}
// Get the list of allocated blocks.
static
ListNode
*
get_allocated_blocks_list
()
{
// If it initialized, initialize the list of allocated blocks.
if
(
!
global_allocated_blocks
.
value
)
{
list_initialize
(
&
global_allocated_blocks
);
global_allocated_blocks
.
value
=
(
void
*
)
1
;
}
return
&
global_allocated_blocks
;
}
// Use the real malloc in this function.
#undef malloc
void
*
_test_malloc
(
const
size_t
size
,
const
char
*
file
,
const
int
line
)
{
char
*
ptr
;
MallocBlockInfo
*
block_info
;
ListNode
*
const
block_list
=
get_allocated_blocks_list
();
const
size_t
allocate_size
=
size
+
(
MALLOC_GUARD_SIZE
*
2
)
+
sizeof
(
*
block_info
)
+
MALLOC_ALIGNMENT
;
char
*
const
block
=
(
char
*
)
malloc
(
allocate_size
);
assert_non_null
(
block
);
// Calculate the returned address.
ptr
=
(
char
*
)(((
size_t
)
block
+
MALLOC_GUARD_SIZE
+
sizeof
(
*
block_info
)
+
MALLOC_ALIGNMENT
)
&
~
(
MALLOC_ALIGNMENT
-
1
));
// Initialize the guard blocks.
memset
(
ptr
-
MALLOC_GUARD_SIZE
,
MALLOC_GUARD_PATTERN
,
MALLOC_GUARD_SIZE
);
memset
(
ptr
+
size
,
MALLOC_GUARD_PATTERN
,
MALLOC_GUARD_SIZE
);
memset
(
ptr
,
MALLOC_ALLOC_PATTERN
,
size
);
block_info
=
(
MallocBlockInfo
*
)(
ptr
-
(
MALLOC_GUARD_SIZE
+
sizeof
(
*
block_info
)));
set_source_location
(
&
block_info
->
location
,
file
,
line
);
block_info
->
allocated_size
=
allocate_size
;
block_info
->
size
=
size
;
block_info
->
block
=
block
;
block_info
->
node
.
value
=
block_info
;
list_add
(
block_list
,
&
block_info
->
node
);
return
ptr
;
}
#define malloc test_malloc
void
*
_test_calloc
(
const
size_t
number_of_elements
,
const
size_t
size
,
const
char
*
file
,
const
int
line
)
{
void
*
const
ptr
=
_test_malloc
(
number_of_elements
*
size
,
file
,
line
);
if
(
ptr
)
{
memset
(
ptr
,
0
,
number_of_elements
*
size
);
}
return
ptr
;
}
// Use the real free in this function.
#undef free
void
_test_free
(
void
*
const
ptr
,
const
char
*
file
,
const
int
line
)
{
unsigned
int
i
;
char
*
block
=
(
char
*
)
ptr
;
MallocBlockInfo
*
block_info
;
_assert_true
(
cast_ptr_to_largest_integral_type
(
ptr
),
"ptr"
,
file
,
line
);
block_info
=
(
MallocBlockInfo
*
)(
block
-
(
MALLOC_GUARD_SIZE
+
sizeof
(
*
block_info
)));
// Check the guard blocks.
{
char
*
guards
[
2
]
=
{
block
-
MALLOC_GUARD_SIZE
,
block
+
block_info
->
size
};
for
(
i
=
0
;
i
<
ARRAY_LENGTH
(
guards
);
i
++
)
{
unsigned
int
j
;
char
*
const
guard
=
guards
[
i
];
for
(
j
=
0
;
j
<
MALLOC_GUARD_SIZE
;
j
++
)
{
const
char
diff
=
guard
[
j
]
-
MALLOC_GUARD_PATTERN
;
if
(
diff
)
{
print_error
(
"Guard block of 0x%08"
PRIxMAX
" size=%"
PRIuMAX
" allocated by "
SOURCE_LOCATION_FORMAT
" at 0x%08"
PRIxMAX
" is corrupt
\n
"
,
cast_ptr_to_largest_integral_type
(
ptr
),
cast_to_largest_integral_type
(
block_info
->
size
),
block_info
->
location
.
file
,
block_info
->
location
.
line
,
cast_ptr_to_largest_integral_type
(
&
guard
[
j
]));
_fail
(
file
,
line
);
}
}
}
}
list_remove
(
&
block_info
->
node
,
NULL
,
NULL
);
block
=
(
char
*
)
block_info
->
block
;
memset
(
block
,
MALLOC_FREE_PATTERN
,
block_info
->
allocated_size
);
free
(
block
);
}
#define free test_free
// Crudely checkpoint the current heap state.
static
const
ListNode
*
check_point_allocated_blocks
()
{
return
get_allocated_blocks_list
()
->
prev
;
}
/* Display the blocks allocated after the specified check point. This
* function returns the number of blocks displayed. */
static
int
display_allocated_blocks
(
const
ListNode
*
const
check_point
)
{
const
ListNode
*
const
head
=
get_allocated_blocks_list
();
const
ListNode
*
node
;
int
allocated_blocks
=
0
;
assert_non_null
(
check_point
);
assert_non_null
(
check_point
->
next
);
for
(
node
=
check_point
->
next
;
node
!=
head
;
node
=
node
->
next
)
{
const
MallocBlockInfo
*
const
block_info
=
(
const
MallocBlockInfo
*
)
node
->
value
;
assert_non_null
(
block_info
);
if
(
!
allocated_blocks
)
{
print_error
(
"Blocks allocated...
\n
"
);
}
print_error
(
" 0x%08"
PRIxMAX
" : "
SOURCE_LOCATION_FORMAT
"
\n
"
,
cast_ptr_to_largest_integral_type
(
block_info
->
block
),
block_info
->
location
.
file
,
block_info
->
location
.
line
);
allocated_blocks
++
;
}
return
allocated_blocks
;
}
// Free all blocks allocated after the specified check point.
static
void
free_allocated_blocks
(
const
ListNode
*
const
check_point
)
{
const
ListNode
*
const
head
=
get_allocated_blocks_list
();
const
ListNode
*
node
;
assert_non_null
(
check_point
);
node
=
check_point
->
next
;
assert_non_null
(
node
);
while
(
node
!=
head
)
{
MallocBlockInfo
*
const
block_info
=
(
MallocBlockInfo
*
)
node
->
value
;
node
=
node
->
next
;
free
((
char
*
)
block_info
+
sizeof
(
*
block_info
)
+
MALLOC_GUARD_SIZE
);
}
}
// Fail if any any blocks are allocated after the specified check point.
static
void
fail_if_blocks_allocated
(
const
ListNode
*
const
check_point
,
const
char
*
const
test_name
)
{
const
int
allocated_blocks
=
display_allocated_blocks
(
check_point
);
if
(
allocated_blocks
)
{
free_allocated_blocks
(
check_point
);
print_error
(
"ERROR: %s leaked %d block(s)
\n
"
,
test_name
,
allocated_blocks
);
exit_test
(
1
);
}
}
void
_fail
(
const
char
*
const
file
,
const
int
line
)
{
print_error
(
"ERROR: "
SOURCE_LOCATION_FORMAT
" Failure!
\n
"
,
file
,
line
);
exit_test
(
1
);
}
#ifndef _WIN32
static
void
exception_handler
(
int
sig
)
{
#ifdef _HPUX
print_error
(
"%d
\n
"
,
sig
);
#else
print_error
(
"%s
\n
"
,
strsignal
(
sig
));
#endif
exit_test
(
1
);
}
#else // _WIN32
static
LONG
WINAPI
exception_filter
(
EXCEPTION_POINTERS
*
exception_pointers
)
{
EXCEPTION_RECORD
*
const
exception_record
=
exception_pointers
->
ExceptionRecord
;
const
DWORD
code
=
exception_record
->
ExceptionCode
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
ARRAY_LENGTH
(
exception_codes
);
i
++
)
{
const
ExceptionCodeInfo
*
const
code_info
=
&
exception_codes
[
i
];
if
(
code
==
code_info
->
code
)
{
static
int
shown_debug_message
=
0
;
fflush
(
stdout
);
print_error
(
"%s occurred at 0x%08"
PRIxMAX
".
\n
"
,
code_info
->
description
,
cast_to_largest_integral_type
(
exception_record
->
ExceptionAddress
));
if
(
!
shown_debug_message
)
{
print_error
(
"
\n
"
"To debug in Visual Studio...
\n
"
"1. Select menu item File->Open Project
\n
"
"2. Change 'Files of type' to 'Executable Files'
\n
"
"3. Open this executable.
\n
"
"4. Select menu item Debug->Start
\n
"
"
\n
"
"Alternatively, set the environment variable
\n
"
"UNIT_TESTING_DEBUG to 1 and rebuild this executable,
\n
"
"then click 'Debug' in the popup dialog box.
\n
"
"
\n
"
);
shown_debug_message
=
1
;
}
exit_test
(
0
);
return
EXCEPTION_EXECUTE_HANDLER
;
}
}
return
EXCEPTION_CONTINUE_SEARCH
;
}
#endif // !_WIN32
// Standard output and error print methods.
void
vprint_message
(
const
char
*
const
format
,
va_list
args
)
{
char
buffer
[
1024
];
vsnprintf
(
buffer
,
sizeof
(
buffer
),
format
,
args
);
printf
(
"%s"
,
buffer
);
fflush
(
stdout
);
#ifdef _WIN32
OutputDebugString
(
buffer
);
#endif // _WIN32
}
void
vprint_error
(
const
char
*
const
format
,
va_list
args
)
{
char
buffer
[
1024
];
vsnprintf
(
buffer
,
sizeof
(
buffer
),
format
,
args
);
fprintf
(
stderr
,
"%s"
,
buffer
);
fflush
(
stderr
);
#ifdef _WIN32
OutputDebugString
(
buffer
);
#endif // _WIN32
}
void
print_message
(
const
char
*
const
format
,
...)
{
va_list
args
;
va_start
(
args
,
format
);
vprint_message
(
format
,
args
);
va_end
(
args
);
}
void
print_error
(
const
char
*
const
format
,
...)
{
va_list
args
;
va_start
(
args
,
format
);
vprint_error
(
format
,
args
);
va_end
(
args
);
}
int
_run_test
(
const
char
*
const
function_name
,
const
UnitTestFunction
Function
,
void
**
const
volatile
state
,
const
UnitTestFunctionType
function_type
,
const
void
*
const
heap_check_point
)
{
const
ListNode
*
const
volatile
check_point
=
(
const
ListNode
*
)
(
heap_check_point
?
heap_check_point
:
check_point_allocated_blocks
());
void
*
current_state
=
NULL
;
volatile
int
rc
=
1
;
int
handle_exceptions
=
1
;
#ifdef _WIN32
handle_exceptions
=
!
IsDebuggerPresent
();
#endif // _WIN32
#if UNIT_TESTING_DEBUG
handle_exceptions
=
0
;
#endif // UNIT_TESTING_DEBUG
if
(
handle_exceptions
)
{
#ifndef _WIN32
unsigned
int
i
;
for
(
i
=
0
;
i
<
ARRAY_LENGTH
(
exception_signals
);
i
++
)
{
default_signal_functions
[
i
]
=
signal
(
exception_signals
[
i
],
exception_handler
);
}
#else // _WIN32
previous_exception_filter
=
SetUnhandledExceptionFilter
(
exception_filter
);
#endif // !_WIN32
}
if
(
function_type
==
UNIT_TEST_FUNCTION_TYPE_TEST
)
{
print_message
(
"[ RUN ] %s
\n
"
,
function_name
);
}
initialize_testing
(
function_name
);
global_running_test
=
1
;
if
(
setjmp
(
global_run_test_env
)
==
0
)
{
Function
(
state
?
state
:
&
current_state
);
fail_if_leftover_values
(
function_name
);
/* If this is a setup function then ignore any allocated blocks
* only ensure they're deallocated on tear down. */
if
(
function_type
!=
UNIT_TEST_FUNCTION_TYPE_SETUP
)
{
fail_if_blocks_allocated
(
check_point
,
function_name
);
}
global_running_test
=
0
;
if
(
function_type
==
UNIT_TEST_FUNCTION_TYPE_TEST
)
{
print_message
(
"[ OK ] %s
\n
"
,
function_name
);
}
rc
=
0
;
}
else
{
global_running_test
=
0
;
print_message
(
"[ FAILED ] %s
\n
"
,
function_name
);
}
teardown_testing
(
function_name
);
if
(
handle_exceptions
)
{
#ifndef _WIN32
unsigned
int
i
;
for
(
i
=
0
;
i
<
ARRAY_LENGTH
(
exception_signals
);
i
++
)
{
signal
(
exception_signals
[
i
],
default_signal_functions
[
i
]);
}
#else // _WIN32
if
(
previous_exception_filter
)
{
SetUnhandledExceptionFilter
(
previous_exception_filter
);
previous_exception_filter
=
NULL
;
}
#endif // !_WIN32
}
return
rc
;
}
int
_run_tests
(
const
UnitTest
*
const
tests
,
const
size_t
number_of_tests
)
{
// Whether to execute the next test.
int
run_next_test
=
1
;
// Whether the previous test failed.
int
previous_test_failed
=
0
;
// Check point of the heap state.
const
ListNode
*
const
check_point
=
check_point_allocated_blocks
();
// Current test being executed.
size_t
current_test
=
0
;
// Number of tests executed.
size_t
tests_executed
=
0
;
// Number of failed tests.
size_t
total_failed
=
0
;
// Number of setup functions.
size_t
setups
=
0
;
// Number of teardown functions.
size_t
teardowns
=
0
;
/* A stack of test states. A state is pushed on the stack
* when a test setup occurs and popped on tear down. */
TestState
*
test_states
=
(
TestState
*
)
malloc
(
number_of_tests
*
sizeof
(
*
test_states
));
size_t
number_of_test_states
=
0
;
// Names of the tests that failed.
const
char
**
failed_names
=
(
const
char
**
)
malloc
(
number_of_tests
*
sizeof
(
*
failed_names
));
void
**
current_state
=
NULL
;
print_message
(
"[==========] Running %d test(s).
\n
"
,
number_of_tests
);
// Make sure uintmax_t is at least the size of a pointer.
assert_true
(
sizeof
(
uintmax_t
)
>=
sizeof
(
void
*
));
while
(
current_test
<
number_of_tests
)
{
const
ListNode
*
test_check_point
=
NULL
;
TestState
*
current_TestState
;
const
UnitTest
*
const
test
=
&
tests
[
current_test
++
];
if
(
!
test
->
function
)
{
continue
;
}
switch
(
test
->
function_type
)
{
case
UNIT_TEST_FUNCTION_TYPE_TEST
:
run_next_test
=
1
;
break
;
case
UNIT_TEST_FUNCTION_TYPE_SETUP
:
{
// Checkpoint the heap before the setup.
current_TestState
=
&
test_states
[
number_of_test_states
++
];
current_TestState
->
check_point
=
check_point_allocated_blocks
();
test_check_point
=
current_TestState
->
check_point
;
current_state
=
&
current_TestState
->
state
;
*
current_state
=
NULL
;
run_next_test
=
1
;
setups
++
;
break
;
}
case
UNIT_TEST_FUNCTION_TYPE_TEARDOWN
:
// Check the heap based on the last setup checkpoint.
assert_true
(
number_of_test_states
);
current_TestState
=
&
test_states
[
--
number_of_test_states
];
test_check_point
=
current_TestState
->
check_point
;
current_state
=
&
current_TestState
->
state
;
teardowns
++
;
break
;
default:
print_error
(
"Invalid unit test function type %d
\n
"
,
test
->
function_type
);
exit_test
(
1
);
break
;
}
if
(
run_next_test
)
{
int
failed
=
_run_test
(
test
->
name
,
test
->
function
,
current_state
,
test
->
function_type
,
test_check_point
);
if
(
failed
)
{
failed_names
[
total_failed
]
=
test
->
name
;
}
switch
(
test
->
function_type
)
{
case
UNIT_TEST_FUNCTION_TYPE_TEST
:
previous_test_failed
=
failed
;
total_failed
+=
failed
;
tests_executed
++
;
break
;
case
UNIT_TEST_FUNCTION_TYPE_SETUP
:
if
(
failed
)
{
total_failed
++
;
tests_executed
++
;
// Skip forward until the next test or setup function.
run_next_test
=
0
;
}
previous_test_failed
=
0
;
break
;
case
UNIT_TEST_FUNCTION_TYPE_TEARDOWN
:
// If this test failed.
if
(
failed
&&
!
previous_test_failed
)
{
total_failed
++
;
}
break
;
default:
#ifndef _HPUX
assert_null
(
"BUG: shouldn't be here!"
);
#endif
break
;
}
}
}
print_message
(
"[==========] %d test(s) run.
\n
"
,
tests_executed
);
print_error
(
"[ PASSED ] %d test(s).
\n
"
,
tests_executed
-
total_failed
);
if
(
total_failed
)
{
size_t
i
;
print_error
(
"[ FAILED ] %d test(s), listed below:
\n
"
,
total_failed
);
for
(
i
=
0
;
i
<
total_failed
;
i
++
)
{
print_error
(
"[ FAILED ] %s
\n
"
,
failed_names
[
i
]);
}
}
else
{
print_error
(
"
\n
%d FAILED TEST(S)
\n
"
,
total_failed
);
}
if
(
number_of_test_states
)
{
print_error
(
"[ ERROR ] Mismatched number of setup %d and "
"teardown %d functions
\n
"
,
setups
,
teardowns
);
total_failed
=
(
size_t
)
-
1
;
}
free
(
test_states
);
free
((
void
*
)
failed_names
);
fail_if_blocks_allocated
(
check_point
,
"run_tests"
);
return
(
int
)
total_failed
;
}
test/cmockery/cmockery.h
0 → 100644
浏览文件 @
be03cdc2
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CMOCKERY_H_
#define CMOCKERY_H_
#ifdef _WIN32
#if _MSC_VER < 1500
#ifdef __cplusplus
extern
"C"
{
#endif // __cplusplus
int
__stdcall
IsDebuggerPresent
();
#ifdef __cplusplus
}
/* extern "C" */
#endif // __cplusplus
#endif // _MSC_VER < 1500
#endif // _WIN32
/*
* These headers or their equivalents should be included prior to including
* this header file.
*
* #include <stdarg.h>
* #include <stddef.h>
* #include <setjmp.h>
* #include <inttypes.h>
*
* This allows test applications to use custom definitions of C standard
* library functions and types.
*/
// For those who are used to __func__ from gcc.
#ifndef __func__
#define __func__ __FUNCTION__
#endif
/* Largest integral type. This type should be large enough to hold any
* pointer or integer supported by the compiler. */
#ifndef _UINTMAX_T
#define _UINTMAX_T
typedef
unsigned
long
long
uintmax_t
;
#endif
/* _UINTMAX_T */
/* Printf formats used to display uintmax_t. */
#ifdef _WIN32
#ifndef PRIdMAX
#define PRIdMAX "I64d"
#endif
/* PRIdMAX */
#ifndef PRIiMAX
#define PRIiMAX "I64i"
#endif
/* PRIiMAX */
#ifndef PRIoMAX
#define PRIoMAX "I64o"
#endif
/* PRIoMAX */
#ifndef PRIuMAX
#define PRIuMAX "I64u"
#endif
/* PRIuMAX */
#ifndef PRIxMAX
#define PRIxMAX "I64x"
#endif
/* PRIxMAX */
#ifndef PRIXMAX
#define PRIXMAX "I64X"
#endif
/* PRIXMAX */
#else
/* _WIN32 */
#ifndef PRIdMAX
#define PRIdMAX "lld"
#endif
/* PRIdMAX */
#ifndef PRIiMAX
#define PRIiMAX "lli"
#endif
/* PRIiMAX */
#ifndef PRIoMAX
#define PRIoMAX "llo"
#endif
/* PRIoMAX */
#ifndef PRIuMAX
#define PRIuMAX "llu"
#endif
/* PRIuMAX */
#ifndef PRIxMAX
#define PRIxMAX "llx"
#endif
/* PRIxMAX */
#ifndef PRIXMAX
#define PRIXMAX "llX"
#endif
/* PRIXMAX */
#endif
/* _WIN32 */
// Perform an unsigned cast to uintmax_t.
#define cast_to_largest_integral_type(value) \
((uintmax_t)(value))
/* Smallest integral type capable of holding a pointer. */
#ifndef _UINTPTR_T
#define _UINTPTR_T
#ifdef _WIN32
/* WIN32 is an ILP32 platform */
typedef
unsigned
long
uintptr_t
;
#else
/* _WIN32 */
/* what about 64-bit windows?
* what's the right preprocessor symbol?
typedef unsigned long long uintptr_t */
/* ILP32 and LP64 platforms */
typedef
unsigned
long
uintptr_t
;
#endif
/* _WIN32 */
#endif
/* _UINTPTR_T */
/* Perform an unsigned cast to uintptr_t. */
#define cast_to_pointer_integral_type(value) \
((uintptr_t)(value))
/* Perform a cast of a pointer to uintmax_t */
#define cast_ptr_to_largest_integral_type(value) \
cast_to_largest_integral_type(cast_to_pointer_integral_type(value))
// Retrieves a return value for the current function.
#define mock() _mock(__func__, __FILE__, __LINE__)
/* Stores a value to be returned by the specified function later.
* The count parameter returns the number of times the value should be returned
* by mock(). If count is set to -1 the value will always be returned.
*/
#define will_return(function, value) \
_will_return(#function, __FILE__, __LINE__, \
cast_to_largest_integral_type(value), 1)
#define will_return_count(function, value, count) \
_will_return(#function, __FILE__, __LINE__, \
cast_to_largest_integral_type(value), count)
/* Add a custom parameter checking function. If the event parameter is NULL
* the event structure is allocated internally by this function. If event
* parameter is provided it must be allocated on the heap and doesn't need to
* be deallocated by the caller.
*/
#define expect_check(function, parameter, check_function, check_data) \
_expect_check(#function, #parameter, __FILE__, __LINE__, check_function, \
cast_to_largest_integral_type(check_data), NULL, 0)
/* Add an event to check a parameter, using check_expected(), against a set of
* values. See will_return() for a description of the count parameter.
*/
#define expect_in_set(function, parameter, value_array) \
expect_in_set_count(function, parameter, value_array, 1)
#define expect_in_set_count(function, parameter, value_array, count) \
_expect_in_set(#function, #parameter, __FILE__, __LINE__, value_array, \
sizeof(value_array) / sizeof((value_array)[0]), count)
#define expect_not_in_set(function, parameter, value_array) \
expect_not_in_set_count(function, parameter, value_array, 1)
#define expect_not_in_set_count(function, parameter, value_array, count) \
_expect_not_in_set( \
#function, #parameter, __FILE__, __LINE__, value_array, \
sizeof(value_array) / sizeof((value_array)[0]), count)
/* Add an event to check a parameter, using check_expected(), against a
* signed range. Where range is minimum <= value <= maximum.
* See will_return() for a description of the count parameter.
*/
#define expect_in_range(function, parameter, minimum, maximum) \
expect_in_range_count(function, parameter, minimum, maximum, 1)
#define expect_in_range_count(function, parameter, minimum, maximum, count) \
_expect_in_range(#function, #parameter, __FILE__, __LINE__, minimum, \
maximum, count)
/* Add an event to check a parameter, using check_expected(), against a
* signed range. Where range is value < minimum or value > maximum.
* See will_return() for a description of the count parameter.
*/
#define expect_not_in_range(function, parameter, minimum, maximum) \
expect_not_in_range_count(function, parameter, minimum, maximum, 1)
#define expect_not_in_range_count(function, parameter, minimum, maximum, \
count) \
_expect_not_in_range(#function, #parameter, __FILE__, __LINE__, \
minimum, maximum, count)
/* Add an event to check whether a parameter, using check_expected(), is or
* isn't a value. See will_return() for a description of the count parameter.
*/
#define expect_value(function, parameter, value) \
expect_value_count(function, parameter, value, 1)
#define expect_value_count(function, parameter, value, count) \
_expect_value(#function, #parameter, __FILE__, __LINE__, \
cast_to_largest_integral_type(value), count)
#define expect_not_value(function, parameter, value) \
expect_not_value_count(function, parameter, value, 1)
#define expect_not_value_count(function, parameter, value, count) \
_expect_not_value(#function, #parameter, __FILE__, __LINE__, \
cast_to_largest_integral_type(value), count)
/* Add an event to check whether a parameter, using check_expected(),
* is or isn't a string. See will_return() for a description of the count
* parameter.
*/
#define expect_string(function, parameter, string) \
expect_string_count(function, parameter, string, 1)
#define expect_string_count(function, parameter, string, count) \
_expect_string(#function, #parameter, __FILE__, __LINE__, \
(const char*)(string), count)
#define expect_not_string(function, parameter, string) \
expect_not_string_count(function, parameter, string, 1)
#define expect_not_string_count(function, parameter, string, count) \
_expect_not_string(#function, #parameter, __FILE__, __LINE__, \
(const char*)(string), count)
/* Add an event to check whether a parameter, using check_expected() does or
* doesn't match an area of memory. See will_return() for a description of
* the count parameter.
*/
#define expect_memory(function, parameter, memory, size) \
expect_memory_count(function, parameter, memory, size, 1)
#define expect_memory_count(function, parameter, memory, size, count) \
_expect_memory(#function, #parameter, __FILE__, __LINE__, \
(const void*)(memory), size, count)
#define expect_not_memory(function, parameter, memory, size) \
expect_not_memory_count(function, parameter, memory, size, 1)
#define expect_not_memory_count(function, parameter, memory, size, count) \
_expect_not_memory(#function, #parameter, __FILE__, __LINE__, \
(const void*)(memory), size, count)
/* Add an event to allow any value for a parameter checked using
* check_expected(). See will_return() for a description of the count
* parameter.
*/
#define expect_any(function, parameter) \
expect_any_count(function, parameter, 1)
#define expect_any_count(function, parameter, count) \
_expect_any(#function, #parameter, __FILE__, __LINE__, count)
/* Determine whether a function parameter is correct. This ensures the next
* value queued by one of the expect_*() macros matches the specified variable.
*/
#define check_expected(parameter) \
_check_expected(__func__, #parameter, __FILE__, __LINE__, \
cast_to_largest_integral_type(parameter))
// Assert that the given expression is true.
#define assert_true(c) _assert_true(cast_to_largest_integral_type(c), #c, \
__FILE__, __LINE__)
// Assert that the given expression is false.
#define assert_false(c) _assert_true(!(cast_to_largest_integral_type(c)), #c, \
__FILE__, __LINE__)
// Assert that the given pointer is non-NULL.
#define assert_non_null(c) _assert_true(cast_ptr_to_largest_integral_type(c), #c, \
__FILE__, __LINE__)
// Assert that the given pointer is NULL.
#define assert_null(c) _assert_true(!(cast_ptr_to_largest_integral_type(c)), #c, \
__FILE__, __LINE__)
// Assert that the two given integers are equal, otherwise fail.
#define assert_int_equal(a, b) \
_assert_int_equal(cast_to_largest_integral_type(a), \
cast_to_largest_integral_type(b), \
__FILE__, __LINE__)
// Assert that the two given integers are not equal, otherwise fail.
#define assert_int_not_equal(a, b) \
_assert_int_not_equal(cast_to_largest_integral_type(a), \
cast_to_largest_integral_type(b), \
__FILE__, __LINE__)
// Assert that the two given strings are equal, otherwise fail.
#define assert_string_equal(a, b) \
_assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \
__LINE__)
// Assert that the two given strings are not equal, otherwise fail.
#define assert_string_not_equal(a, b) \
_assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, \
__LINE__)
// Assert that the two given areas of memory are equal, otherwise fail.
#define assert_memory_equal(a, b, size) \
_assert_memory_equal((const char*)(a), (const char*)(b), size, __FILE__, \
__LINE__)
// Assert that the two given areas of memory are not equal, otherwise fail.
#define assert_memory_not_equal(a, b, size) \
_assert_memory_not_equal((const char*)(a), (const char*)(b), size, \
__FILE__, __LINE__)
// Assert that the specified value is >= minimum and <= maximum.
#define assert_in_range(value, minimum, maximum) \
_assert_in_range( \
cast_to_largest_integral_type(value), \
cast_to_largest_integral_type(minimum), \
cast_to_largest_integral_type(maximum), __FILE__, __LINE__)
// Assert that the specified value is < minumum or > maximum
#define assert_not_in_range(value, minimum, maximum) \
_assert_not_in_range( \
cast_to_largest_integral_type(value), \
cast_to_largest_integral_type(minimum), \
cast_to_largest_integral_type(maximum), __FILE__, __LINE__)
// Assert that the specified value is within a set.
#define assert_in_set(value, values, number_of_values) \
_assert_in_set(value, values, number_of_values, __FILE__, __LINE__)
// Assert that the specified value is not within a set.
#define assert_not_in_set(value, values, number_of_values) \
_assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__)
// Forces the test to fail immediately and quit.
#define fail() _fail(__FILE__, __LINE__)
// Generic method to kick off testing
#define run_test(f) _run_test(#f, f, NULL, UNIT_TEST_FUNCTION_TYPE_TEST, NULL)
// Initializes a UnitTest structure.
#define unit_test(f) { #f, f, UNIT_TEST_FUNCTION_TYPE_TEST }
#define unit_test_setup(test, setup) \
{ #test "_" #setup, setup, UNIT_TEST_FUNCTION_TYPE_SETUP }
#define unit_test_teardown(test, teardown) \
{ #test "_" #teardown, teardown, UNIT_TEST_FUNCTION_TYPE_TEARDOWN }
/* Initialize an array of UnitTest structures with a setup function for a test
* and a teardown function. Either setup or teardown can be NULL.
*/
#define unit_test_setup_teardown(test, setup, teardown) \
unit_test_setup(test, setup), \
unit_test(test), \
unit_test_teardown(test, teardown)
/*
* Run tests specified by an array of UnitTest structures. The following
* example illustrates this macro's use with the unit_test macro.
*
* void Test0();
* void Test1();
*
* int main(int argc, char* argv[]) {
* const UnitTest tests[] = {
* unit_test(Test0);
* unit_test(Test1);
* };
* return run_tests(tests);
* }
*/
#define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof(tests)[0])
// Dynamic allocators
#define test_malloc(size) _test_malloc(size, __FILE__, __LINE__)
#define test_calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
#define test_free(ptr) _test_free(ptr, __FILE__, __LINE__)
// Redirect malloc, calloc and free to the unit test allocators.
#if UNIT_TESTING
#define malloc test_malloc
#define calloc test_calloc
#define free test_free
#endif // UNIT_TESTING
/*
* Ensure mock_assert() is called. If mock_assert() is called the assert
* expression string is returned.
* For example:
*
* #define assert mock_assert
*
* void showmessage(const char *message) {
* assert(message);
* }
*
* int main(int argc, const char* argv[]) {
* expect_assert_failure(show_message(NULL));
* printf("succeeded\n");
* return 0;
* }
*/
#define expect_assert_failure(function_call) \
{ \
const int expression = setjmp(global_expect_assert_env); \
global_expecting_assert = 1; \
if (expression) { \
print_message("Expected assertion %s occurred\n", \
*((const char**)&expression)); \
global_expecting_assert = 0; \
} else { \
function_call ; \
global_expecting_assert = 0; \
print_error("Expected assert in %s\n", #function_call); \
_fail(__FILE__, __LINE__); \
} \
}
// Function prototype for setup, test and teardown functions.
typedef
void
(
*
UnitTestFunction
)(
void
**
state
);
// Function that determines whether a function parameter value is correct.
typedef
int
(
*
CheckParameterValue
)(
const
uintmax_t
value
,
const
uintmax_t
check_value_data
);
// Type of the unit test function.
typedef
enum
UnitTestFunctionType
{
UNIT_TEST_FUNCTION_TYPE_TEST
=
0
,
UNIT_TEST_FUNCTION_TYPE_SETUP
,
UNIT_TEST_FUNCTION_TYPE_TEARDOWN
,
}
UnitTestFunctionType
;
/* Stores a unit test function with its name and type.
* NOTE: Every setup function must be paired with a teardown function. It's
* possible to specify NULL function pointers.
*/
typedef
struct
UnitTest
{
const
char
*
name
;
UnitTestFunction
function
;
UnitTestFunctionType
function_type
;
}
UnitTest
;
// Location within some source code.
typedef
struct
SourceLocation
{
const
char
*
file
;
int
line
;
}
SourceLocation
;
// Event that's called to check a parameter value.
typedef
struct
CheckParameterEvent
{
SourceLocation
location
;
const
char
*
parameter_name
;
CheckParameterValue
check_value
;
uintmax_t
check_value_data
;
}
CheckParameterEvent
;
// Used by expect_assert_failure() and mock_assert().
extern
int
global_expecting_assert
;
extern
jmp_buf
global_expect_assert_env
;
// Retrieves a value for the given function, as set by "will_return".
uintmax_t
_mock
(
const
char
*
const
function
,
const
char
*
const
file
,
const
int
line
);
void
_expect_check
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
CheckParameterValue
check_function
,
const
uintmax_t
check_data
,
CheckParameterEvent
*
const
event
,
const
int
count
);
void
_expect_in_set
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
int
count
);
void
_expect_not_in_set
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
int
count
);
void
_expect_in_range
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
int
count
);
void
_expect_not_in_range
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
int
count
);
void
_expect_value
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
);
void
_expect_not_value
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
);
void
_expect_string
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
char
*
string
,
const
int
count
);
void
_expect_not_string
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
char
*
string
,
const
int
count
);
void
_expect_memory
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
void
*
const
memory
,
const
size_t
size
,
const
int
count
);
void
_expect_not_memory
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
void
*
const
memory
,
const
size_t
size
,
const
int
count
);
void
_expect_any
(
const
char
*
const
function
,
const
char
*
const
parameter
,
const
char
*
const
file
,
const
int
line
,
const
int
count
);
void
_check_expected
(
const
char
*
const
function_name
,
const
char
*
const
parameter_name
,
const
char
*
file
,
const
int
line
,
const
uintmax_t
value
);
// Can be used to replace assert in tested code so that in conjuction with
// check_assert() it's possible to determine whether an assert condition has
// failed without stopping a test.
void
mock_assert
(
const
int
result
,
const
char
*
const
expression
,
const
char
*
const
file
,
const
int
line
);
void
_will_return
(
const
char
*
const
function_name
,
const
char
*
const
file
,
const
int
line
,
const
uintmax_t
value
,
const
int
count
);
void
_assert_true
(
const
uintmax_t
result
,
const
char
*
const
expression
,
const
char
*
const
file
,
const
int
line
);
void
_assert_int_equal
(
const
uintmax_t
a
,
const
uintmax_t
b
,
const
char
*
const
file
,
const
int
line
);
void
_assert_int_not_equal
(
const
uintmax_t
a
,
const
uintmax_t
b
,
const
char
*
const
file
,
const
int
line
);
void
_assert_string_equal
(
const
char
*
const
a
,
const
char
*
const
b
,
const
char
*
const
file
,
const
int
line
);
void
_assert_string_not_equal
(
const
char
*
const
a
,
const
char
*
const
b
,
const
char
*
file
,
const
int
line
);
void
_assert_memory_equal
(
const
void
*
const
a
,
const
void
*
const
b
,
const
size_t
size
,
const
char
*
const
file
,
const
int
line
);
void
_assert_memory_not_equal
(
const
void
*
const
a
,
const
void
*
const
b
,
const
size_t
size
,
const
char
*
const
file
,
const
int
line
);
void
_assert_in_range
(
const
uintmax_t
value
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
char
*
const
file
,
const
int
line
);
void
_assert_not_in_range
(
const
uintmax_t
value
,
const
uintmax_t
minimum
,
const
uintmax_t
maximum
,
const
char
*
const
file
,
const
int
line
);
void
_assert_in_set
(
const
uintmax_t
value
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
char
*
const
file
,
const
int
line
);
void
_assert_not_in_set
(
const
uintmax_t
value
,
const
uintmax_t
values
[],
const
size_t
number_of_values
,
const
char
*
const
file
,
const
int
line
);
void
*
_test_malloc
(
const
size_t
size
,
const
char
*
file
,
const
int
line
);
void
*
_test_calloc
(
const
size_t
number_of_elements
,
const
size_t
size
,
const
char
*
file
,
const
int
line
);
void
_test_free
(
void
*
const
ptr
,
const
char
*
file
,
const
int
line
);
void
_fail
(
const
char
*
const
file
,
const
int
line
);
int
_run_test
(
const
char
*
const
function_name
,
const
UnitTestFunction
Function
,
void
**
const
volatile
state
,
const
UnitTestFunctionType
function_type
,
const
void
*
const
heap_check_point
);
int
_run_tests
(
const
UnitTest
*
const
tests
,
const
size_t
number_of_tests
);
// Standard output and error print methods.
void
print_message
(
const
char
*
const
format
,
...);
void
print_error
(
const
char
*
const
format
,
...);
void
vprint_message
(
const
char
*
const
format
,
va_list
args
);
void
vprint_error
(
const
char
*
const
format
,
va_list
args
);
#endif // CMOCKERY_H_
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论