フィザーがfclose()
2回呼び出すのは安全ではないことを思い出させたので、テストのためだけに、これをテストする方法を次に示します。
独自の動作を使用して、プログラム内で (または libc のその他の関数を)再定義 することができます。Unix ライクなシステムでは、リンカは文句を言いません。Windows では試したことがありませんが、cygwin では試していません。もちろん、これにより他のテストが real を使用できなくなるため、そのようなテストは別のテスト実行可能ファイルに入れる必要があります。fclose()
fclose()
minunitを使用したオールインワンの例を次に示します。
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
/* from minunit.h : http://www.jera.com/techinfo/jtns/jtn002.html */
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; \
if (message) return message; } while (0)
int tests_run = 0;
bool fclose_shall_fail_on_EINTR = false;
//--- our implemention of fclose()
int fclose(FILE *fp) {
if (fclose_shall_fail_on_EINTR) {
errno = EINTR;
fclose_shall_fail_on_EINTR = false; //--- reset for next call
return EOF;
} else { return 0; }
}
//--- this is the "production" function to be tested
void uninterruptible_close(FILE *fp) {
// Given an open FILE *fp
while (fclose(fp)==EOF && errno==EINTR) {
errno = 0;
}
}
char *test_non_interrupted_fclose(void) {
FILE *theHandle = NULL; //--- don't care here
uninterruptible_close(theHandle);
mu_assert("test fclose wo/ interruption", 0 == errno);
return 0;
}
char *test_interrupted_fclose(void) {
FILE *theHandle = NULL; //--- don't care here
fclose_shall_fail_on_EINTR = true;
uninterruptible_close(theHandle);
mu_assert("test fclose wo/ interruption", 0 == errno);
return 0;
}
char *test_suite(void)
{
mu_run_test(test_non_interrupted_fclose);
mu_run_test(test_interrupted_fclose);
return 0;
}
int main(int ac, char **av)
{
char *result = test_suite();
printf("number of tests run: %d\n", tests_run);
if (result) { printf("FAIL: %s\n", result); }
return 0 != result;
}