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 ([email protected]) * * Date: 03/06/2010 * * Author: Gavin Ding ([email protected] / [email protected]) * * 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"\"\n Result: Succeeded\n") #define INTERNAL_USE_ONLY_FAILED(_a, _b, _oper) \ printf(" Expected: \""#_a"\" "#_oper" \""#_b"\"\n (X) Result: Failed\n") #define INTERNAL_USE_ONLY_CASE_SHOW() \ printf("Case %d =====>\n", g_case_total); \ printf(" Location: %s:%d\n", __FILE__, __LINE__); \ #define UNITEST_ERROR(_string) do { \ printf("Error: "#_string"\n"); \ 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } 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("\n"); \ } while (0) static void unitest_bar() { printf("********************************************************\n"); printf("* Unit Test *\n"); printf("********************************************************\n"); printf("\n"); } static int unitest_report() { printf("\n"); printf("********************************************************\n"); printf("* Test Report *\n"); printf("********************************************************\n"); if (0 == g_case_total) { printf("No test case is run\n"); goto pass; } printf(" Total: %d\n", g_case_total); printf("Succeeded: %d (%d%%)\n", g_case_succeeded, g_case_succeeded * 100 / g_case_total); printf("********************************************************\n"); printf("\n"); if (g_case_total != g_case_succeeded) { printf("\n"); printf(":-( Failed\n"); printf("\n"); return -1; } pass: printf("\n"); printf(":-) Passed\n"); printf("\n"); 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 ([email protected] / [email protected]) * * 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