git » libfiu » commit 4df0f02

tests: Add test for the handling of FILE * errors

author Alberto Bertogli
2018-09-30 21:37:05 UTC
committer Alberto Bertogli
2018-10-14 20:11:19 UTC
parent 20cd73583b0d807813720b74a2d53db88821db8f

tests: Add test for the handling of FILE * errors

The handling of FILE * errors is tricky, as we keep track of the streams
with errors internally.

This patch adds a test that exercises some of the cases related to error
handling. It is not overly tricky, but it covers quite a few corner
cases and already detected a couple of problems (fixed in previous
patches).

tests/Makefile +6 -3
tests/test-ferror.c +67 -0

diff --git a/tests/Makefile b/tests/Makefile
index 5d1ae36..f0d3c85 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -13,12 +13,15 @@ endif
 
 ifneq ($(V), 1)
 	NICE_CC = @echo "  CC  $@"; $(CC)
-	NICE_RUN = @echo "  RUN $<"; LD_LIBRARY_PATH=../libfiu/
+	NICE_RUN = @echo "  RUN $<"; \
+		   LD_LIBRARY_PATH=../libfiu/ \
+		   LD_PRELOAD=./libs/fiu_run_preload.so:./libs/fiu_posix_preload.so
 	NICE_PY = @echo "  PY  $<"; ./wrap-python 2
 	NICE_LN = @echo "  LN $@"; ln -f
 else
 	NICE_CC = $(CC)
-	NICE_RUN = LD_LIBRARY_PATH=../libfiu/
+	NICE_RUN = LD_LIBRARY_PATH=../libfiu/ \
+		   LD_PRELOAD=./libs/fiu_run_preload.so:./libs/fiu_posix_preload.so
 	NICE_PY = ./wrap-python 2
 	NICE_LN = ln -f
 endif
@@ -67,7 +70,7 @@ test-enable_stac%: test-enable_stac%.c build-flags
 	$(NICE_CC) $(ALL_CFLAGS) \
 		-rdynamic -fno-optimize-sibling-calls $< -lfiu -lpthread -o $@
 
-c-run-%: %
+c-run-%: % lnlibs
 	$(NICE_RUN) ./$<
 
 
diff --git a/tests/test-ferror.c b/tests/test-ferror.c
new file mode 100644
index 0000000..ab1e079
--- /dev/null
+++ b/tests/test-ferror.c
@@ -0,0 +1,67 @@
+/* Test the handling of FILE * errors. */
+
+#include <fiu.h>
+#include <fiu-control.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+int test(const char *prefix) {
+	FILE *fp = fopen("/dev/zero", "r");
+
+	unsigned char buf[1024];
+	ssize_t r;
+
+	fiu_enable("posix/stdio/rw/fread", 1, (void *) EIO, 0);
+
+	r = fread(buf, 1, 1024, fp);
+
+	fiu_disable("posix/stdio/rw/fread");
+
+	if (r != 0) {
+		printf("%s: fread() succeeded, should have failed\n", prefix);
+		return -1;
+	}
+
+	if (errno != EIO) {
+		printf("%s: errno not set appropriately: ", prefix);
+		printf("errno = %d / %s, expected EIO\n", errno, strerror(errno));
+		return -1;
+	}
+
+	if (ferror(fp) == 0) {
+		printf("%s: ferror() said there was no failure, but there was\n",
+				prefix);
+		return -1;
+	}
+
+	clearerr(fp);
+
+	if (ferror(fp) != 0) {
+		printf("%s: clearerr(), ferror() said there were failures\n",
+				prefix);
+		return -1;
+	}
+
+	fclose(fp);
+	// Unfortunately we can't easily test after fclose() has been called,
+	// because it's impossible to distinguish between a libfiu failure
+	// from a libc error (which would appear due to an operation on a
+	// closed file). To make things worse, some versions of glibc make
+	// ferror() return an error on closed files, but others work.
+
+	return 0;
+}
+
+int main(void) {
+	// Run the test many times, to stress structure reuse a bit. This is
+	// not as thorough but does exercise some bugs we've had, such as
+	// forgetting to decrement the recursion counter.
+	char prefix[8];
+	for (int i = 0; i < 200; i++) {
+		snprintf(prefix, 8, "%2d", i);
+		test(prefix);
+	}
+}