cmocka を使用し、malloc の失敗をテストし (シミュレート)、gcov を使用して、ニッチなケースの答えを見つけるのに苦労しています。
cmocka+gcov に関する更新: cmocka テストで関数をモックするとすぐに空の gcda ファイルが取得されることに気付きました。なんで?cmocka と gcov をグーグルで検索すると、人々が 2 つを一緒に使用することについて話している結果が得られます。ほとんどの人が CMake を使用しているようですが、これについては後で説明しますが、cmake を使用する必要がある (私が考えることができる) 理由はないはずです。--coverage/-lgcov フラグを指定して cmocka を使用できないのはなぜですか?
元の質問:
私は主に 2 つの主なアイデアに基づいて、無数の組み合わせを試しました。
-Wl,--wrap=malloc を使ってみたので、malloc の呼び出しがラップされます。私の cmocka テストから、malloc の失敗をシミュレートするために will_return(__wrap_malloc, (void*)NULL) を使用しようとしました。私のラップ関数では、mock() を使用して、__real_malloc() または NULL を返す必要があるかどうかを判断しています。これには理想的な効果がありますが、gcov が gcda ファイルの作成に失敗することがわかりました。これは malloc をラップする理由の一部であるため、malloc の失敗をテストし、コード カバレッジの結果を取得できます。シンボルを使って汚いゲームをしたり、他のコンパイル ユニット (gcov? cmocka?) から呼び出される malloc() 呼び出しを台無しにしたりした気がします。
私が試した別の方法は、gcc -include で malloc の #define を使用して「my malloc」を呼び出し、ターゲット コードをコンパイルして mymalloc.c (「my malloc」を定義) でテストすることでした。そのため、#define malloc _mymalloc を使用すると、ターゲット テスト コードから "特別な malloc" のみを呼び出すことができ、それ以外の場所では malloc をそのままにしておきます (つまり、他のコンパイル ユニットをそのままにして、常に実際の malloc を呼び出すだけです)。ただし、will_return() と mock() を正しく使用して失敗ケースと成功ケースを検出する方法がわかりません。malloc() のテストに失敗した場合、必要なものが得られます。mock() が NULL を返すことに基づいて、「malloc」から NULL を返します。これはすべて、ターゲット コードでのみ呼び出される malloc のラッピング関数で行われます。ただし、実際の malloc の結果を返したい場合は、mock() から結果を返さなかったため、cmocka は失敗します。テスト中のコードが正しく機能できるように、malloc() からの実際の結果が必要なため、cmocka に mock() マクロからの結果をキューから取り出してもらい、結果を返さなくてもかまわないようにできたらいいのにと思います。
malloc テストと cmocka を組み合わせて gcov の結果を取得できるはずだと思います。
答えが何であれ、次のようなものを引き出したいと思います。
int business_code()
{
void* d = malloc(somethingCalculated);
void* e = malloc(somethingElse);
if(!d) return someRecovery();
if(!e) return someOtherRecovery();
return 0;
}
次に、次のようなcmockaテストを行います
cmocka_d_fail()
{
will_return(malloc, NULL);
int ret = business_code();
assert_int_equal(ret, ERROR_CODE_D);
}
cmocka_e_fail()
{
will_return(malloc, __LINE__); // someway to tell wrapped malloc to give me real memory because the code under test needs it
will_return(malloc, NULL); // I want "d" malloc to succeed but "e" malloc to fail
int ret = business_code();
assert_int_equal(ret, ERROR_CODE_E);
}
私が試した #define/wrap のアイデアのいくつかに近づきましたが、最終的には、malloc を台無しにして gcov がカバレッジ データを吐き出さないようにするか、cmocka に malloc ケースを実行させて実数を返す方法がありません。つまり、mock() 呼び出しから戻りません。一方では、テスト ドライバーから実際の malloc を呼び出し、それを will_return に渡すことができますが、test_code は必要なメモリのサイズを認識していません。テスト対象のコードだけがそれを認識しています。
時間の制約があるので、cmocka と現在のテスト インフラストラクチャから離れたくありません。私が望むものが不可能な場合は、将来的に他のアイデアを検討します. 私が探しているのは新しいものではありませんが、cmocka/gcov ソリューションを使用しようとしています。
ありがとう