ページの先頭行へ戻る
Symfoware Server V10.0.0/V10.0.1 アプリケーション開発ガイド(埋込みSQL編)

5.2.5 テストドライバの作成および単体テストの実施

作成したファンクションルーチンは、Symfoware/RDBを介して実行する前に、テストドライバを利用して単体テストを行い、十分な品質を確保しておく必要があります。

テストドライバが直接ファンクションルーチンのライブラリを呼び出すことで、Symfoware/RDBを介さずに単体テストを行うことができます。

また、SQLSignalMSG関数を使用してファンクションルーチンから異常通知するプログラムを作成した場合の単体テストは、ダミーのSQLSignalMSG関数を用意し、Symfoware/RDBを介さずにテストを行う必要があります。

SolarisLinuxUNIX系の場合

(1) ファンクションルーチンのライブラリ作成

(2) テストドライバの実行形式作成

(3) ダミーSQLSignalMSG関数のライブラリ作成

(4) リンクするライブラリの設定

(5) リンクするライブラリの再設定

ファンクションルーチンのライブラリ作成

ファンクションルーチンのライブラリを作成します。

ライブラリ作成についての詳細は“5.2.4 ファンクションルーチンからの異常通知”を参照してください。

以下にファンクションルーチンのライブラリ作成例を示します。

Solaris

ファンクションルーチンのライブラリ作成例

cc -G -o /usr/local/lib/libuserfunc001.so userfunc001.c -mt
Linux

ファンクションルーチンのライブラリ作成例

gcc -shared -o /usr/local/lib/libuserfunc001.so userfunc001.c -D_REENTRANT
テストドライバの実行形式作成

ファンクションルーチンをテストするためのテストドライバの実行形式を作成します。

テストドライバのプログラム例およびテストドライバ実行形式の作成例を以下に示します。

ファンクションルーチン“USERFUNC002”用テストドライバ(ftestdrv001.c)のプログラム例

/*-------------------------------------------------------------*/
/* ファンクションルーチン"USERFUNC002"用テストドライバ         */
/*-------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#ifdef NT
#include <windows.h>
#else
#include <dlfcn.h>
#endif

/* 引数データのポインタリスト */
typedef struct in_ptr_list_tag {
    void  *ptr[2];    /* ファンクションのパラメタの個数×2 */
} in_ptr_list_t;

/* 結果データのポインタリスト */
typedef struct out_ptr_list_tag {
    void  *ptr[2];    /* 返却データと標識データの格納先 */
} out_ptr_list_t;

/* 呼び出し関数名 */
#define FUNC_NAME  "UserFunc002"
/* ライブラリのパス */
#ifdef NT
#define FUNC_PATH  "D:\\FORSYMFO\\FUNCLIB\\USERFUNC002.DLL"
#else
#define FUNC_PATH  "/export/home/kanda/Function/libuserfunc002.so"
#endif

int main()
{
    void        *handle_p;       /* dlopenのハンドラ       */
    void        (*sym_p)();      /* アドレスベクタ         */
    int         data1;           /* 引数1データ格納用     */
    short       ind1;            /* 引数1標識データ格納   */
    char        ret[43];         /* 結果データ格納用       */
    short       r_ind;           /* 結果の標識データ格納用 */
    short       ret_size;        /* 結果データの実データ長 */
    char        buf[41];         /* 結果データ表示用       */

    /* 入出力のポインタリスト */
    in_ptr_list_t   in_ptr_list;
    out_ptr_list_t  out_ptr_list;

#ifdef NT
    printf("drv002:LoadLibrary start\n");
    /* ファンクションルーチンのライブラリをオープン */
    handle_p = LoadLibrary(FUNC_PATH);
#else
    printf("drv002:dlopen start\n");
    /* ファンクションルーチンのライブラリをオープン */
    handle_p = dlopen(FUNC_PATH, RTLD_NOW);
#endif
    if (handle_p == NULL) {
        return(1);
    }

#ifdef NT
    printf("drv002:GetProcAddress start\n");
    /* ライブラリの入口アドレスの取得 */
    sym_p = (void (*)())GetProcAddress(handle_p, FUNC_NAME);
    if (sym_p == NULL) {
        FreeLibrary(handle_p);
        return(2);
    }
#else
    printf("drv002:dlsym start\n");
    /* ライブラリの入口アドレスの取得 */
    sym_p = (void (*)())dlsym(handle_p, FUNC_NAME);
    /* ライブラリの入口アドレスの取得 */
    sym_p = (void (*)())dlsym(handle_p, FUNC_NAME);
    if (sym_p == NULL) {
        dlclose(handle_p);
        return(2);
    }
#endif

    printf("drv002:make indata\n");
    /* 入力データの作成 */
    data1 = -100;                   /* 負の値 */
    ind1  = 0;
    in_ptr_list.ptr[0] = &data1;    /* 引数1のデータ     */
    in_ptr_list.ptr[1] = &ind1;     /* 引数1の標識データ */

    printf("drv002:make outdata area\n");
    /* 結果データ格納先の準備 */
    memset(ret, 0x00, sizeof(ret));
    r_ind = -1;
    out_ptr_list.ptr[0] = ret;      /* 結果データ格納先     */
    out_ptr_list.ptr[1] = &r_ind;   /* 結果標識データ格納先 */

    /* ファンクションルーチンの呼び出し */
    printf("drv002:call func\n");
    (*sym_p)(&in_ptr_list, &out_ptr_list);
    printf("drv002:call func end\n");

    if (r_ind < 0) {
        /* NULL値 */
        printf("drv002:ret = NULL\n");
    }
    else {
        /* VARCHARデータ長の取り出し */
        memcpy(&ret_size, ret, sizeof(short));
        printf("drv002:ret_size=%d\n", ret_size);
        /* VARCHARデータの取り出し */
        memset(buf, 0x00, sizeof(buf));
        memcpy(buf, ret + sizeof(short), ret_size);
        printf("drv002:return value = %s\n", buf);
    }

    /* ライブラリのクローズ */
#ifdef NT
    FreeLibrary(handle_p);
#else
    dlclose(handle_p);
#endif
    printf("drv002:end\n");
    return(0);
}
Solaris

テストドライバ実行形式(ftestdrv001)の作成例

cc -o ftestdrv001 ftestdrv001.c -ldl
Linux

テストドライバ実行形式(ftestdrv001)の作成例

gcc -o ftestdrv001 ftestdrv001.c -ldl
ダミーSQLSignalMSG関数のライブラリ作成

ファンクションルーチンから異常通知する場合のテストで使用するダミーSQLSignalMSG関数のライブラリを作成します。

ダミーSQLSignalMSG関数のプログラム例およびダミーSQLSignalMSG関数のライブラリ作成例を以下に示します。

ダミーSQLSignalMSG関数“SQLSignalMSG”(fdummymsg.c)のプログラム例

/*-----------------------------------------------------------*/
/* SQLSignalMSG関数のダミープログラム                        */
/*-----------------------------------------------------------*/
#include <stdio.h>
#include <string.h>

#define MSG1 "JYP4557E ファンクションルーチン“%s”から例外が送信されました.例外メッセージ=“%s”"
void  SQLSignalMSG(char *msg_p)
{
    char    msg_data[1024];
    memset(msg_data,0x00,sizeof(msg_data));
    sprintf(msg_data,MSG1,"TestFunction",msg_p);
    /* SQLSTATE 出力  */
    printf("SQLSTATE = 60000\n");
    /* SQLMSG 出力 */
    printf("SQLMSG   = %s\n",msg_data);
    return;
}
Solaris

ダミーSQLSignalMSG関数のライブラリ作成例

cc -G -o /usr/local2/lib/libsqlsigm.so  fdummymsg.c
Linux

ダミーSQLSignalMSG関数のライブラリ作成例

gcc -shared -o /usr/local/lib/libsqlsigm.so  fdummymsg.c
リンクするライブラリの設定

単体テストを実行するために、ダミーSQLSignalMSG関数のライブラリおよびファンクションルーチンのライブラリをLD_LIBRARY_PATHに設定します。

以下に、2つのライブラリの設定例を示します。

ダミーSQLSignalMSG関数のライブラリおよびファンクションルーチンのライブラリの設定例

setenv LD_LIBRARY_PATH /usr/local2/lib:/usr/local/lib
(1) (2)

(1) ダミーSQLSignalMSG関数のライブラリ

(2) ファンクションルーチンのライブラリ

リンクするライブラリの再設定

単体テストの終了後は、ダミーSQLSignalMSG関数のライブラリをLD_LIBRARY_PATHから外し、Symfoware/RDBのSQLSignalMSG関数のライブラリをLD_LIBRARY_PATHに設定する必要があります。

以下に、ライブラリの再設定例を示します。

ライブラリの再設定例

setenv LD_LIBRARY_PATH /usr/local/lib:/opt/FSUNrdb2b/lib: …
                            (1)              (2)

(1) ファンクションルーチンのライブラリ

(2) Symfoware/RDB のSQLSignalMSG関数ライブラリ

参考

テストドライバの実行例

drv002: dlopen start
drv002: dlsym start
drv002:make indata
drv002:make outdata area
drv002:call func
SQLSTATE = 60000
SQLMSG   = JYP4557E ファンクションルーチン“TestFunction”から例外
が送信されました.例外メッセージ=“引数1が負の値です”
drv002:call func end
drv002:ret = NULL
drv002:end

WindowsWindows(R) 2000Windows Server(R) 2003Windows Server(R) 2008またはWindows Server(R) 2008 R2の場合

(1) ファンクションルーチンのライブラリ作成

(2) テストドライバの実行形式作成

(3) ダミーSQLSignalMSG関数のライブラリ作成

(4) リンクするライブラリの再設定

ファンクションルーチンのライブラリ作成

ファンクションルーチンのライブラリを作成します。

ライブラリ作成についての詳細は“5.2.4 ファンクションルーチンからの異常通知”を参照してください。

テストドライバの実行形式作成

ファンクションルーチンをテストするためのテストドライバの実行形式を作成します。

テストドライバのプログラム例についてはUNIX系の場合を参照してください。

以下にテストドライバ実行形式の作成例を示します。

テストドライバ実行形式(ftestdrv001)の作成例

cl ftestdrv001.c /Feftestdrv001 -DNT
ダミーSQLSignalMSG関数のライブラリ作成

ファンクションルーチンから異常通知する場合のテストで使用するダミーSQLSignalMSG関数のライブラリを作成します。

ダミーSQLSignalMSG関数のプログラム例についてはUNIX系の場合を参照してください。

ダミーSQLSignalMSG関数のライブラリ作成例として、Microsoft(R) Visual StudioにおけるStatic Libraryの作成例を以下に示します。

  1. [ファイル(F)]メニューから、[新規作成(N)]で[プロジェクト(P)]を選択します。

  2. [新しいプロジェクト]ウインドウにて、[プロジェクトの種類(P)]で[Visual C++]の[Win32]を選択し、[テンプレート(T)]で[Win32 プロジェクト]を選択します。

  3. [新しいプロジェクト]ウインドウにて、[プロジェクト名(N)]を指定し、[場所(L)]にライブラリ作成場所を指定します。[ソリューションのディレクトリを作成(D)]のチェックボックスのチェックを外します。[OK]を選択します。

    プロジェクト名 = F3CWSQLSIGM
    位置 = D:\FORSYMFO\FUNCMAKE\F3CWSQLSIGM

    指定した位置に、作成したCプログラムファイルを格納しておきます。

  4. [Win32 アプリケーション ウィザード]ウインドウの[Win32 アプリケーション ウィザードへようこそ]の画面にて[次へ>]を選択します。

  5. [Win32 アプリケーション ウィザード]ウインドウの[アプリケーションの設定]の画面にて[アプリケーションの種類]で[スタティック ライブラリ(S)]を選択します。[追加オプション]で[プリコンパイル済みヘッダー(P)]のチェックボックスのチェックを外します。[完了]を選択します。

  6. [プロジェクト(P)]の、[既存項目の追加(G)]から、作成したCプログラムファイルをプロジェクトに追加します。

    D:\FORSYMFO\FUNCMAKE\F3CWSQLSIGM\FDUMMYMSG.C
  7. [ビルド(B)]から[ソリューションのビルド(B)]を選択して、ライブラリを作成します。

リンクするライブラリの再設定

単体テストの終了後は、ダミーSQLSignalMSG関数のライブラリの設定を外し、Symfoware/RDBのSQLSignalMSG関数のライブラリを設定する必要があります。

Microsoft(R) Visual Studioにおけるライブラリの再設定例を以下に示します。

  1. [ファイル(F)]メニューから、[開く(O)]で[プロジェクト/ソリューション(P)]を選択しファンクションルーチンのライブラリを指定します。

    ファイル場所 = D:\FORSYMFO\FUNCMAKE\USERFUNC001
    ファイル名 = USERFUNC001.sln
  2. ファンクションルーチンのライブラリ内で使用したダミーSQLSignalMSG関数の設定を外しSymfoware/RDBのSQLSignalMSG関数のライブラリを設定します。

    1. [ツール(T)]から[オプション(O)]を選択し、[プロジェクトおよびソリューション]の[VC++ ディレクトリ]を開きます。

    2. [ディレクトリを表示するプロジェクト(S)]に“ライブラリファイル”を選択して、[ディレクトリ]にダミーSQLSignalMSG関数のライブラリが存在する場合は指定を外し、<サーバ機能のインストール先>\ESQL\LIBまたは<クライアント機能のインストール先>\ESQL\LIBの指定を追加します。

    なお、ライブラリの対象プラットフォームは、サーバが動作するプラットフォームと同じにします。

  3. [ビルド(B)]から[ソリューションのリビルド(R)]を選択して、ライブラリを再作成します。

  4. 作成したライブラリを、ファンクションルーチン定義文のLIBRARY句で指定するディレクトリに格納します。

    D:\FORSYMFO\FUNCMAKE\USERFUNC001\RELEASE\USERFUNC001.DLL
                 ↓ 複写
    D:\FORSYMFO\FUNCLIB\USERFUNC001.DLL

    参考

    テストドライバの実行例

    drv002: LoadLibrary start
    drv002: GetProcAddress start
    drv002:make indata
    drv002:make outdata area
    drv002:call func
    SQLSTATE = 60000
    SQLMSG   = JYP4557E ファンクションルーチン"TestFunction"から例外が送信されました.例外メッセージ="引数1が負の値です"
    drv002:call func end
    drv002:ret = NULL
    drv002:end