C/C++のスタブを自動生成するツールを公開しました

2021年7月2日

どもです。

突然ですが、C/C++の単体テストで使用する「スタブ」を自動で生成するツールを公開しました。

作成したのは5年くらい前で、その後細々使用していましたが、自宅のSVNサーバーが少し前に壊れた、メインのPCを入れ替えたなど、環境の変化がありましたので、保管場所(?)をGitHubに変更することにしました。
それに伴い、公開します。

1.ビルド環境

以下の環境でのビルドを確認しています。

OS Windows10 Pro (バージョン:1903)
CPU: Intel Core i7-8700
メモリ 16GB
IDE Eclipse
Version 2019-06(4.12.0)
Cygwin gcc
x86_64-pc-cygwin

2.使い方

2.1.ツールの使い方

下記のような使い方をします。

./cstubmk.exe -f ev3_brick.txt

ここで、"ev3_brick.txt"はスタブを作成したい関数の定義が入力されたファイル名です。
具体的な内容は、下記の通りです。

SLONG ev3_brick_initialize(VOID);
SLONG ev3_brick_finalize(VOID);

このファイルを入力とした場合、次のようなスタブのコードが生成されます。

#define EV3_BRICK_BUF_SIZE			(10)

/*-----------------------------------------*/
/*----                                 ----*/
/*---- Start ev3_brick_initialize stub ----*/
/*----                                 ----*/
/*-----------------------------------------*/
int ev3_brick_initialize_stub_called_count;
int ev3_brick_initialize_stub_ret_val[EV3_BRICK_BUF_SIZE];
SLONG ev3_brick_initialize_stub()
{
	int ret_val =
		ev3_brick_initialize_stub_ret_val
		[ev3_brick_initialize_stub_called_count];


	ev3_brick_initialize_stub_called_count++;

	return (ret_val);
}
void ev3_brick_initialize_init()
{
	int idx = 0;

	ev3_brick_initialize_stub_called_count = 0;
	for (idx = 0; idx < EV3_BRICK_BUF_SIZE; idx++) {
		ev3_brick_initialize_stub_ret_val[idx] = 0;
	}
}

/*---------------------------------------*/
/*----                               ----*/
/*---- Start ev3_brick_finalize stub ----*/
/*----                               ----*/
/*---------------------------------------*/
int ev3_brick_finalize_stub_called_count;
int ev3_brick_finalize_stub_ret_val[EV3_BRICK_BUF_SIZE];
SLONG ev3_brick_finalize_stub()
{
	int ret_val =
		ev3_brick_finalize_stub_ret_val
		[ev3_brick_finalize_stub_called_count];


	ev3_brick_finalize_stub_called_count++;

	return (ret_val);
}
void ev3_brick_finalize_init()
{
	int idx = 0;

	ev3_brick_finalize_stub_called_count = 0;
	for (idx = 0; idx < EV3_BRICK_BUF_SIZE; idx++) {
		ev3_brick_finalize_stub_ret_val[idx] = 0;
	}
}
#ifndef EV3_BRICK_STUB_H_
#define EV3_BRICK_STUB_H_

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*-----------------------------------------*/
/*----                                 ----*/
/*---- Start ev3_brick_initialize stub ----*/
/*----                                 ----*/
/*-----------------------------------------*/
extern void ev3_brick_initialize_init();
extern SLONG ev3_brick_initialize_stub();
extern int ev3_brick_initialize_stub_called_count;
extern int ev3_brick_initialize_stub_ret_val[];
#define	GET_EV3_BRICK_INITIALIZE_STUB_CALLED_COUNT()	\
	(ev3_brick_initialize_stub_called_count)
#define	SET_EV3_BRICK_INITIALIZE_STUB_CALLED_COUNT(value)	\
	(ev3_brick_initialize_stub_called_count = value)
#define	GET_EV3_BRICK_INITIALIZE_STUB_RET_VAL(idx)	\
	(ev3_brick_initialize_stub_ret_val[idx])
#define	SET_EV3_BRICK_INITIALIZE_STUB_RET_VAL(idx, value)	\
	(ev3_brick_initialize_stub_ret_val[idx] = value)

/*---------------------------------------*/
/*----                               ----*/
/*---- Start ev3_brick_finalize stub ----*/
/*----                               ----*/
/*---------------------------------------*/
extern void ev3_brick_finalize_init();
extern SLONG ev3_brick_finalize_stub();
extern int ev3_brick_finalize_stub_called_count;
extern int ev3_brick_finalize_stub_ret_val[];
#define	GET_EV3_BRICK_FINALIZE_STUB_CALLED_COUNT()	\
	(ev3_brick_finalize_stub_called_count)
#define	SET_EV3_BRICK_FINALIZE_STUB_CALLED_COUNT(value)	\
	(ev3_brick_finalize_stub_called_count = value)
#define	GET_EV3_BRICK_FINALIZE_STUB_RET_VAL(idx)	\
	(ev3_brick_finalize_stub_ret_val[idx])
#define	SET_EV3_BRICK_FINALIZE_STUB_RET_VAL(idx, value)	\
	(ev3_brick_finalize_stub_ret_val[idx] = value)

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* EV3_BRICK_STUB_H_ */

2.2.生成されたスタブ

  • 生成された関数には、末尾に"_stub"が付加されています。
    必要に応じて、これは削除して下さい。
  • スタブの戻り値を予め設定しておくためのバッファーも、生成されます。
  • バッファーも、呼び出された順番ごとに戻り値を設定できます。
  • バッファーを初期化するための関数も、同時に生成されます。
  • バッファーに関しては、呼び出し回数と引数のバッファーについては、GETマクロ、戻り値のバッファーについてはSETマクロが用意されます。

3.言い訳コーナー

3.1.CMakeじゃないの?

はい。
CMakeではございません。
make/Makefileでのビルドになります。
また、上記Windows環境でのみビルドが確認できています。

3.2.Windows10だけ?

はい。
動作確認ができているのが、Windows10/cygwinのみです。
LinuxとかMacでの確認はできていません。

4.公開しています

GitHubに公開しています。
自宅サーバーが壊れた関係で、開発の途中経過は一切残っていません。
申し訳ありません。
また、設計資料もastahで作成しており、データを救出できなかったので公開を避けました。

5.まとめ

だいぶ昔に作ったモノで、今コードを読み返すと
「ひどい設計、ひどいコードになっているなぁ」
と思ってしまいます。
それでも、自分で使っていた時には
「お。役に立つな」
と感じていました。

「ソフトの造」はよくないのに、「ソフトの効果」は高い…。
それが自分の作ったソフトとなると、だいぶ複雑な気分になりますね。

ではっ!