/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 : * ===================================================================== * sc_unittest.c * Copyright (c) 2003 - 2011 sys0tem * LICENSE : * LGPL (GNU Lesser General Public License - Version 3,29 June 2007) * http://www.gnu.org/copyleft/lesser.html * or * EPL (Eclipse Public License - v1.0) * http://www.eclipse.org/legal/epl-v10.html * ===================================================================== */ #include <stdio.h> #include <string.h> #include <sc_assert.h> #include <sc_mmgr.h> #include <sc_error.h> #include <sc_unittest.h> /* -------------------------------------------------------------------- * 定数定義 * -------------------------------------------------------------------- */ /* assert エラー時に呼び出す最大関数登録数 */ #define SC_UNITTEST_FUNC_MAX (8192) #define SC_UNITTEST_OUTPUT stderr /** * テスト用関数リスト. */ typedef struct { const char* funcName; void (*testFunc)(void); } SC_Unittest_FuncEntry; /* プロトタイプ宣言 */ static void SC_Unittest_cleanup(void); static void SC_Unittest_checkMemoryLeak(SC_MMgr* mmgr); static void SC_Unittest_checkMemoryError(SC_MMgr* mmgr); /* テスト関数のリスト */ static SC_Unittest_FuncEntry SC_Unittest_testFuncs[SC_UNITTEST_FUNC_MAX]; static int SC_Unittest_testRunIndex = 0; static int SC_Unittest_testRunSize = 0; static int SC_Unittest_otherFuncSize = 0; /** * テスト用関数を追加します. * * @param testfunc テスト用関数 */ void SC_Unittest_add(const char* funcName, void (*testFunc)(void)) { SC_Unittest_testFuncs[SC_Unittest_testRunSize + SC_Unittest_otherFuncSize].funcName = funcName; SC_Unittest_testFuncs[SC_Unittest_testRunSize + SC_Unittest_otherFuncSize].testFunc = testFunc; if (strcmp("OTHER", funcName) == 0) { SC_Unittest_otherFuncSize++; } else { SC_Unittest_testRunSize++; } } /** * 単体テストを実行します. */ void SC_Unittest_run(void) { int i; SC_setAssertOutput(SC_UNITTEST_OUTPUT); SC_assertAtExit(SC_Unittest_cleanup); SC_Unittest_testRunIndex = 0; for (i = 0; i < (SC_Unittest_testRunSize + SC_Unittest_otherFuncSize); i++) { SC_MMgr_setHandler(NULL, NULL, SC_Unittest_checkMemoryError); if (strcmp("OTHER", SC_Unittest_testFuncs[i].funcName) != 0) { fprintf(SC_UNITTEST_OUTPUT, "[No.%04d] %-50s\n", (SC_Unittest_testRunIndex + 1), SC_Unittest_testFuncs[i].funcName); SC_Unittest_testRunIndex++; } SC_Unittest_testFuncs[i].testFunc(); } SC_Unittest_cleanup(); } /** * 単体試験終了時に実行します. */ static void SC_Unittest_cleanup(void) { SC_MMgr_entries(SC_Unittest_checkMemoryLeak); fprintf(SC_UNITTEST_OUTPUT, "run test case [ %d / %d ]\n", SC_Unittest_testRunIndex, SC_Unittest_testRunSize); } /** * メモリリークが発生していないかチェックします。 * * @param mmgr メモリ管理部 */ static void SC_Unittest_checkMemoryLeak(SC_MMgr* mmgr) { fprintf(SC_UNITTEST_OUTPUT, "%s:%08d (size = %08d byte) memory Leak\n", mmgr->file, mmgr->line, mmgr->size); } /** * メモリエラーが発生している場合に実行されます。 * * @param mmgr メモリエラーが発生したメモリ管理部 */ static void SC_Unittest_checkMemoryError(SC_MMgr* mmgr) { const char* errorType; int nowError = SC_getError(); int ret; switch (nowError) { case SC_EINVAL: errorType = "memory duplicate free"; break; case SC_ENOMEM: errorType = "memory allocate error"; break; default: errorType = "other error"; break; } /* メモリ管理部分 (src/ut_scmmgr.c) のテストでは * エラーの試験しているため、エラー出力対象外とする */ ret = strcmp("src/ut_sc_mmgr.c", mmgr->file); if (ret != 0) { fprintf(SC_UNITTEST_OUTPUT, "%s:%08d (size = %08d byte) %s\n", mmgr->file, mmgr->line, mmgr->size, errorType); } }