/********************************************************************* * 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 = 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; } 二、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(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 1 | void 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); | | } | | | | 三、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) == 0) { | | return 1; | | } | | print_error(""%s" != "%s" ", left, right); | | return 0; | | } | | | | // 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 " ", 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[1024]; | 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! ", file, line); exit_test(1); --------+ } | | // 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); } } 四、运行结果: 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:29 Failure! get_status_code_string_test: Test failed. string_to_status_code_test: Starting test 2 != 1 ERROR: assert_macro_test.c:35 Failure! string_to_status_code_test: Test failed. 2 out of 2 tests failed! get_status_code_string_test string_to_status_code_test myzr@myzr:~/c_program/cmockery-master/src/example$