unitest.h
/****************************************************************************** * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed * * under the GNU Lesser General Public License Version 3, 29 June 2007. * * The complete license can be accessed from the following location: * * http://opensource.org/licenses/lgpl-3.0.html * * * * Author: Yun Li (yunli.open@gmail.com) * * Date: 03/06/2010 * * Author: Gavin Ding (gavin_ding@sina.cn / fanfan.ding.ict@gmail.com) * * Date: 07/07/2013 * ******************************************************************************/ /****************************************************************************** REVISION HISTORY ================ Date Version Name Description ---------- ------------ ---------------- -------------------------------- 03/17/2013 V001.000.000 Gavin Ding rewrite this file ---------- ------------ ---------------- -------------------------------- Date Version Name Description ---------- ------------ ---------------- -------------------------------- 07/07/2013 V001.001.000 Gavin Ding make it more useful ---------- ------------ ---------------- -------------------------------- ******************************************************************************/ #ifndef __UNITEST_H #define __UNITEST_H #include <stdio.h> #include <string.h> static int g_case_total = 0; static int g_case_succeeded = 0; static int g_case_failed = 0; #ifndef NULL #define NULL ((void*)0) #endif #define INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, _oper) printf(" Expected: ""#_a"" "#_oper" ""#_b"" Result: Succeeded ") #define INTERNAL_USE_ONLY_FAILED(_a, _b, _oper) printf(" Expected: ""#_a"" "#_oper" ""#_b"" (X) Result: Failed ") #define INTERNAL_USE_ONLY_CASE_SHOW() printf("Case %d =====> ", g_case_total); printf(" Location: %s:%d ", __FILE__, __LINE__); #define UNITEST_ERROR(_string) do { printf("Error: "#_string" "); return -1; } while (0) #define UNITEST_EQUALS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) == (_b)) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, ==); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, ==); g_case_failed++; } printf(" "); } while (0) #define UNITEST_DIFFERS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) == (_b)) { INTERNAL_USE_ONLY_FAILED(_a, _b, !=); g_case_failed++; } else { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, !=); g_case_succeeded++; } printf(" "); } while (0) #define UNITEST_LESS_THAN(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) < (_b)) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, <); g_case_succeeded ++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, <); g_case_failed++; } printf(" "); } while (0) #define UNITEST_LESS_THAN_EQUALS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) <= (_b)) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, <=); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, <=); g_case_failed++; } printf(" "); } while (0) #define UNITEST_GREATER_THAN(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) > (_b)) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, >); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, >); g_case_failed++; } printf(" "); } while (0) #define UNITEST_GREATER_THAN_EQUALS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ((_a) >= (_b)) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, >=); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, >=); g_case_failed++; } printf(" "); } while (0) #define UNITEST_STR_EQUALS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ( NULL == (_a) || NULL == (_b) ) { UNITEST_ERROR(ptr should not be NULL); } if ( !strcmp((_a), (_b)) ) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, ==); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, ==); g_case_failed++; } printf(" "); } while (0) #define UNITEST_STR_DIFFERS(_a, _b) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ( NULL == (_a) || NULL == (_b) ) { UNITEST_ERROR(ptr should not be NULL); } if ( !strcmp((_a), (_b)) ) { INTERNAL_USE_ONLY_FAILED(_a, _b, !=); g_case_failed++; } else { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, !=); g_case_succeeded++; } printf(" "); } while (0) #define UNITEST_MEM_EQUALS(_a, _b, _len) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ( NULL == (_a) || NULL == (_b) ) { UNITEST_ERROR(ptr should not be NULL); } if ( (_len) <= 0 ) { UNITEST_ERROR(mem len should be positive); } if ( !memcmp((void*)(_a),(void*)(_b), (int)(_len)) ) { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, ==); g_case_succeeded++; } else { INTERNAL_USE_ONLY_FAILED(_a, _b, ==); g_case_failed++; } printf(" "); } while (0) #define UNITEST_MEM_DIFFERS(_a, _b, _len) do { g_case_total++; INTERNAL_USE_ONLY_CASE_SHOW(); if ( NULL == (_a) || NULL == (_b) ) { UNITEST_ERROR(ptr should not be NULL); } if ( (_len) <= 0 ) { UNITEST_ERROR(mem len should be positive); } if ( !memcmp((void*)(_a), (void*)(_b), (int)(_len)) ) { INTERNAL_USE_ONLY_FAILED(_a, _b, !=); g_case_failed++; } else { INTERNAL_USE_ONLY_SUCCEEDED(_a, _b, !=); g_case_succeeded++; } printf(" "); } while (0) static void unitest_bar() { printf("******************************************************** "); printf("* Unit Test * "); printf("******************************************************** "); printf(" "); } static int unitest_report() { printf(" "); printf("******************************************************** "); printf("* Test Report * "); printf("******************************************************** "); if (0 == g_case_total) { printf("No test case is run "); goto pass; } printf(" Total: %d ", g_case_total); printf("Succeeded: %d (%d%%) ", g_case_succeeded, g_case_succeeded * 100 / g_case_total); printf("******************************************************** "); printf(" "); if (g_case_total != g_case_succeeded) { printf(" "); printf(":-( Failed "); printf(" "); return -1; } pass: printf(" "); printf(":-) Passed "); printf(" "); return 0; } #ifndef HAVE_MAIN extern int unitest_main(int _argc, char *_argv[]); int main(int _argc, char *_argv[]) { unitest_bar(); unitest_main(_argc, _argv); return unitest_report(); } #endif /* end of HAVE_MAIN */ #endif /* end of __UNITEST_H */
unitest_demo.c
/****************************************************************************** * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed * * under the GNU Lesser General Public License Version 3, 29 June 2007. * * The complete license can be accessed from the following location: * * http://opensource.org/licenses/lgpl-3.0.html * * * * Author: Gavin Ding (gavin_ding@sina.cn / fanfan.ding.ict@gmail.com) * * Date: 07/07/2013 * * * ******************************************************************************/ /****************************************************************************** REVISION HISTORY ================ Date Version Name Description -------- ------- ------------ -------------------------------------------- -------- ------- ------------ -------------------------------------------- ******************************************************************************/ #include "unitest.h" #include <stdlib.h> #define UNUSED(param) ((param) = (param)) int unitest_main (int argc, char *argv[]) { char *str1 = "YT"; char *str2 = "HW"; char *str3 = "HW"; void *p1 = NULL; void *p2 = NULL; UNUSED(argc); UNUSED(argv); UNITEST_EQUALS(87, 87); UNITEST_DIFFERS(10, 13); UNITEST_LESS_THAN(41, 70); UNITEST_LESS_THAN_EQUALS(8, 8); UNITEST_LESS_THAN_EQUALS(7, 8); UNITEST_GREATER_THAN(70, 41); UNITEST_GREATER_THAN_EQUALS(8, 8); UNITEST_GREATER_THAN_EQUALS(8, 7); UNITEST_STR_EQUALS(str2, str3); UNITEST_STR_DIFFERS(str1, str2); p1 = malloc(10); memset(p1, 2, 10); p2 = malloc(10); memset(p2, 2, 10); UNITEST_MEM_EQUALS(p1, p2, 10); memset(p2, 5, 10); UNITEST_MEM_DIFFERS(p1, p2, 10); free(p1); p1 = NULL; free(p2); p2 = NULL; return 0; }
unitest_demo.result
./unitest/unitest_demo.exe ******************************************************** * Unit Test * ******************************************************** Case 1 =====> Location: unitest_demo.c:41 Expected: "87" == "87" Result: Succeeded Case 2 =====> Location: unitest_demo.c:43 Expected: "10" != "13" Result: Succeeded Case 3 =====> Location: unitest_demo.c:45 Expected: "41" < "70" Result: Succeeded Case 4 =====> Location: unitest_demo.c:47 Expected: "8" <= "8" Result: Succeeded Case 5 =====> Location: unitest_demo.c:48 Expected: "7" <= "8" Result: Succeeded Case 6 =====> Location: unitest_demo.c:50 Expected: "70" > "41" Result: Succeeded Case 7 =====> Location: unitest_demo.c:52 Expected: "8" >= "8" Result: Succeeded Case 8 =====> Location: unitest_demo.c:53 Expected: "8" >= "7" Result: Succeeded Case 9 =====> Location: unitest_demo.c:55 Expected: "str2" == "str3" Result: Succeeded Case 10 =====> Location: unitest_demo.c:57 Expected: "str1" != "str2" Result: Succeeded Case 11 =====> Location: unitest_demo.c:65 Expected: "p1" == "p2" Result: Succeeded Case 12 =====> Location: unitest_demo.c:68 Expected: "p1" != "p2" Result: Succeeded ******************************************************** * Test Report * ******************************************************** Total: 12 Succeeded: 12 (100%) ******************************************************** :-) Passed