/*********************************************************************
* Cmockery macro demo hacking
* 说明:
* 本文记录对Cmockery的宏使用的示例进行测试、跟踪。
*
* 2016-5-7 深圳 南山平山村 曾剑锋
********************************************************************/ 一、cat src/example/assert_macro.c
/*
* 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.
*/
#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 = ; i < sizeof(status_code_strings) /
sizeof(status_code_strings[]); i++) {
if (strcmp(status_code_strings[i], status_code_string) == ) {
return i;
}
}
return ~0U;
} 二、cat src/example/assert_macro_test.c
/*
* 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.
*/
#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(), "Address not found"); --+
assert_string_equal(get_status_code_string(), "Connection timed out"); |
} |
|
// This test will fail since the status code of "Connection timed out" isn't 1 |
void string_to_status_code_test(void **state) { |
assert_int_equal(string_to_status_code("Address not found"), ); --*-+
assert_int_equal(string_to_status_code("Connection timed out"), ); | |
} | |
| |
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); | |
} | |
| |
三、macro hacking | |
| |
// 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__) | |
| |
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); | |
} | |
} | |
| |
/* 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) == ) { | |
return ; | |
} | |
print_error("\"%s\" != \"%s\"\n", left, right); | |
return ; | |
} | |
| |
// 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__) | |
| |
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); ----------*-+
} | |
} | |
| |
/* 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 LargestIntegralType left, | |
const LargestIntegralType right) { | |
const int equal = left == right; | |
if (!equal) { | |
print_error(LargestIntegralTypePrintfFormat " != " | |
LargestIntegralTypePrintfFormat "\n", left, right); | |
} | |
return equal; | |
} | |
| |
void print_error(const char* const format, ...) { <-------+ |
va_list args; |
va_start(args, format); |
vprint_error(format, args); --------+ |
va_end(args); | |
} | |
| |
void vprint_error(const char* const format, va_list args) { <-------+ |
char buffer[]; |
vsnprintf(buffer, sizeof(buffer), format, args); |
fprintf(stderr, buffer); |
#ifdef _WIN32 |
OutputDebugString(buffer); |
#endif // _WIN32 |
} |
|
void _fail(const char * const file, const int line) { <--------+
print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line);
exit_test(); --------+
} |
|
// Exit the currently executing test. |
static void exit_test(const int quit_application) { <------+
if (global_running_test) {
longjmp(global_run_test_env, );
} else if (quit_application) {
exit(-);
}
} 四、运行结果:
myzr@myzr:~/c_program/cmockery-master/src/example$ gcc assert_macro* -lcmockery
myzr@myzr:~/c_program/cmockery-master/src/example$ ./a.out
get_status_code_string_test: Starting test
"Connection dropped" != "Connection timed out"
ERROR: assert_macro_test.c: Failure!
get_status_code_string_test: Test failed.
string_to_status_code_test: Starting test
!=
ERROR: assert_macro_test.c: Failure!
string_to_status_code_test: Test failed.
out of tests failed!
get_status_code_string_test
string_to_status_code_test
myzr@myzr:~/c_program/cmockery-master/src/example$