/* 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);
}
}