(六)cmockery中的assert_macro分析
所分析的assert_macro.c和assert_macro_test.c文件位于 工程中的 cmockery/src/example/ 目录下,是关于assert方法的一个应用,可以进行判断指定类型数据的逻辑关系的断言,提供了一组函数如下:
![]()
断言整数相等或者不相等assert_int_equal(a, b)assert_int_not_equal(a, b)断言字符串相等或者不相等assert_string_equal(a, b)assert_string_not_equal(a, b)断言内存相等或者不相等assert_memory_equal(a, b, size)assert_memory_not_equal(a, b, size)断言数据是不是在最大最小值之间assert_in_range(value, minimum, maximum)assert_not_in_range(value, minimum, maximum)断言数据是不是在集合中assert_in_set(value, values, number_of_values)assert_not_in_set(value, values, number_of_values)
assert_macro.c
#include <string.h>static const char* status_code_strings[] = {"Address not found","Connection dropped","Connection timed out",};const char* get_status_code_string(const unsigned int status_code) {return status_code_strings[status_code];};unsigned int string_to_status_code(const char* const status_code_string) {unsigned int i;for (i = 0; i < sizeof(status_code_strings) /sizeof(status_code_strings[0]); i++) {if (strcmp(status_code_strings[i], status_code_string) == 0) {return i;}}return ~0U;}
这个文件中有两个函数,get_status_code_string和string_to_status_code;
其中
get_status_code_string函数就是简单的根据传入整数值作为索引,然后找到数组中的字符串并返回。
string_to_status_code函数是根据传入的字符串和字符串数组中的状态值进行比较,如果找到则返回索引值,如果没有找到则返回0xffffffff
assert_macro_test.c
#include <stdarg.h>#include <stddef.h>#include <setjmp.h>#include "cmockery.h"extern const char* get_status_code_string(const unsigned int status_code);extern unsigned int string_to_status_code(const char* const status_code_string);/* This test will fail since the string returned by get_status_code_string(0)* doesn't match "Connection timed out". */void get_status_code_string_test(void **state) {assert_string_equal(get_status_code_string(0), "Address not found");assert_string_equal(get_status_code_string(1), "Connection timed out");}// This test will fail since the status code of "Connection timed out" isn't 1void string_to_status_code_test(void **state) {assert_int_equal(string_to_status_code("Address not found"), 0);assert_int_equal(string_to_status_code("Connection timed out"), 1);}int main(int argc, char *argv[]) {const UnitTest tests[] = {unit_test(get_status_code_string_test),unit_test(string_to_status_code_test),};return run_tests(tests);}
有两个单元测试函数get_status_code_string_test和string_to_status_code_test;
对于assert_string_equal,是一个宏定义如下:
#define assert_string_equal(a, b) \_assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \__LINE__)
将函数assert_string_equal(get_status_code_string(0), "Address not found");带入之后为
_assert_string_equal((const char*)(get_status_code_string(0)), (const char*)("Address not found"), __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);}}
最终这个函数的调用形式为:_assert_string_equal((const char*)("Address not found"), (const char*)("Address not found"), __FILE__, __LINE__)
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;}
将参数带入只有 left=right所以会返回1;不会有任何的报错信息。
而以同样的方式带入assert_string_equal("Connection dropped", "Connection timed out");则会在string_equal_display_error函数中打印error信息并且返回0,然后再
_assert_string_equal函数中调用_fail函数,打印日志信息,并且longjmp跳转到setjmp位置,进行下一个测试的执行。
对于assert_int_equal这个宏来说,定义如下:
#define LargestIntegralType unsigned long long#define cast_to_largest_integral_type(value) \((LargestIntegralType)((unsigned)(value)))#define assert_int_equal(a, b) \_assert_int_equal(cast_to_largest_integral_type(a), \cast_to_largest_integral_type(b), \__FILE__, __LINE__)
将程序中的函数还原到宏体中如下:
_assert_int_equal((unsigned long long)(unsigned)(0),(unsigned long long)(unsigned)(0), __FILE__, __LINE__);
void _assert_int_equal(const LargestIntegralType a, const LargestIntegralType b,const char * const file, const int line) {if (!values_equal_display_error(a, b)) {_fail(file, line);}}
static int values_equal_display_error(const LargestIntegralType left,const LargestIntegralType right) {const int equal = left == right;if (!equal) {print_error(LargestIntegralTypePrintfFormat " != "LargestIntegralTypePrintfFormat "\n", left, right);}return equal;}
很显然这个函数执行到这里的时候left==right==0;会赋值给equal为1,即返回值为1.正常结束。
而在执行_assert_int_equal((unsigned long long)(unsigned)(2),(unsigned long long)(unsigned)(1), __FILE__, __LINE__);的时候会返回0,导致在_assert_int_equal函数中调用_fail函数,跳转到setjmp位置进行下一个测试。
最后这样例程序的运行结果如下:

浙公网安备 33010602011771号