プログラミングなどなど

プログラミングに関係しそうな内容を

GCC:重複定義(Multiple Definition)を許可するオプションを関数単体試験に利用する

このブログでは、現在「GCC:関数重複定義(Multiple Definition)を-z muldefsで許可する - プログラミングなどなど」が見られている回数が圧倒的に多く、全体の約半分を締めています。個人的には使用することが無かったため、なぜ、こんなに見られるのだろうかと気になっていました。そんな中、関数単体試験の際に役立つケースがあったので紹介したいと思います。(やっていることは前の記事と違いはありません。)

以下のような状況を想定しています。

targetModule.cに含まれるtargetFunc関数に大規模な修正を入れることになりました。その際に、同一モジュール内に含まれる長く、複雑な関数longFuncの呼び出しが追加されました。targetFuncの関数単体試験を実施したいのですが、longFuncが同一モジュールに含まれており、邪魔になっています。しかし、別モジュールへの分離も事情により行うことができません。

どの様に役立ったかというと、関数単体試験向けのlongFuncを別モジュールに用意し、リンク時に-z muldefsを使用することで、既存のlongFuncが動作しないようにしました。

targetModule.h

#ifndef TARTGET_MOD
#define TARTGET_MOD

int longFunc(int x);
int targetFunc(int x);

#endif

targetModule.c

#include <stdio.h>
#include "targetModule.h"

/* 長く複雑な関数 */
int longFunc(int x)
{
  printf("長く、複雑な関数!\n");

  return x;
}

/* 修正しテスト対象となる関数 */
int targetFunc(int x)
{
  /* 修正色々 */

  /* 同一モジュール内の長く、複雑な関数の呼び出し。*/
  int ret = longFunc(10);

  /* 修正色々 */

  return ret + 10; 
}

test.c

#include <stdio.h>
#include "targetModule.h"

int main(void)
{
  int ret = targetFunc(5);
  printf("結果 : %d\n", ret);

  return 0;
}

実行(通常)

$ gcc -Wall targetModule.c test.c 
$ ./a.out 
長く、複雑な関数!
結果 : 20

関数単体試験用のモジュール(test.cに含める方法もあり)

#include <stdio.h>

int longFunc(int x)
{
  printf("単体試験用の関数!!\n");

  return x;
}

実行(スタブ版)

リンク順序には注意します。stub.cに定義した単体試験用のlongFuncが有効になるようにtargetModule.cより前に指定しています。

$ gcc -Wall -z muldefs stub.c targetModule.c test.c 
$ ./a.out 
単体試験用の関数!!
結果 : 10

これまでは、デバッガなどを使って行っていた試験が自動化できました。