[PATCH v2] tests/fcntl-common.c: extend coverage for other fcntl flags

Zhibin Li 08826794brmt at gmail.com
Fri Jun 15 09:00:05 UTC 2018


* fcntl-common.c: Include <assert.h> and "signal2name.c".
(fcntl_cmd_check): New structure.
(print_retval_flags, test_other_set_cmd, test_other_get_cmd,
print_flags_getfd, print_flags_getsig, print_flags_getlease,
test_fcntl_others): New functions.
(main): Use test_fcntl_others.
---
I skipped F_[ADD|GET]_SEALS and F_GETFL because hardcoding those flags is indeed
not a good idea. Besides, there are actually a lot of combinations of F_xxx_SEALS
flags (e.g. F_SEAL_SHRINK|F_SEAL_GROW|...). In other words, these flags do not
mutually exclude (I had made mistakes) so I'm thinking about a better way to check
decoding of these flags/options in function print_flags_xxx.
 tests/fcntl-common.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/tests/fcntl-common.c b/tests/fcntl-common.c
index 55e048c8..b7462cc5 100644
--- a/tests/fcntl-common.c
+++ b/tests/fcntl-common.c
@@ -31,7 +31,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <assert.h>
 #include "flock.h"
+#include "signal2name.c"
 
 #define FILE_LEN 4096
 
@@ -238,6 +240,135 @@ test_f_owner_ex(void)
 }
 #endif /* TEST_F_OWNER_EX */
 
+struct fcntl_cmd_check {
+	int fd;
+	int cmd;
+	const char *cmd_str;
+	long arg;
+	const char *arg_str;
+	void (*print_flags)(long rc);
+};
+
+static void
+print_retval_flags(const struct fcntl_cmd_check *check, long rc)
+{
+	if (check->print_flags) {
+		check->print_flags(rc);
+	} else {
+		printf("%s", errstr);
+	}
+	printf("\n");
+}
+
+static void
+test_other_set_cmd(const struct fcntl_cmd_check *check)
+{
+	invoke_test_syscall(check->fd, check->cmd, (void *) check->arg);
+	printf("%s(%d, %s, %s) = %s\n",
+	       TEST_SYSCALL_STR, check->fd,
+	       check->cmd_str, check->arg_str, errstr);
+
+	/* bad file fd */
+	invoke_test_syscall(-1, check->cmd, (void *) check->arg);
+	printf("%s(-1, %s, %s) = %s\n",
+	       TEST_SYSCALL_STR, check->cmd_str,
+	       check->arg_str, errstr);
+}
+
+static void
+test_other_get_cmd(const struct fcntl_cmd_check *check)
+{
+	long rc = invoke_test_syscall(check->fd, check->cmd, NULL);
+	printf("%s(%d, %s) = ",
+	       TEST_SYSCALL_STR, check->fd, check->cmd_str);
+	print_retval_flags(check, rc);
+
+	/* bad file fd */
+	invoke_test_syscall(-1, check->cmd, NULL);
+	printf("%s(-1, %s) = %s\n",
+	       TEST_SYSCALL_STR, check->cmd_str, errstr);
+}
+
+static void
+print_flags_getfd(long rc)
+{
+	assert(rc >= 0);
+	const char *text;
+	text = rc & 1 ? " (flags FD_CLOEXEC)" : "";
+	printf("%#lx%s", rc, text);
+}
+
+static void
+print_flags_getsig(long rc)
+{
+	assert(rc >= 0);
+	const char *text;
+
+	if (!rc) {
+		text = "";
+		printf("%ld", rc);
+	} else {
+		text = signal2name((int) rc);
+		printf("%ld (%s)", rc, text);
+	}
+}
+
+static void
+print_flags_getlease(long rc)
+{
+	assert(rc >= 0);
+	const char *text;
+
+	switch (rc) {
+	case 0:
+		text = "F_RDLCK";
+		break;
+	case 1:
+		text = "F_WRLCK";
+		break;
+	case 2:
+		text = "F_UNLCK";
+		break;
+	default:
+		error_msg_and_fail("fcntl returned %#lx, does the"
+				   " test have to be updated?", rc);
+	}
+	printf("%#lx (%s)", rc, text);
+}
+
+static void
+test_fcntl_others(void)
+{
+	static const struct fcntl_cmd_check set_checks[] = {
+		{ 0, ARG_STR(F_SETFD), ARG_STR(FD_CLOEXEC) },
+		{ 0, ARG_STR(F_SETOWN), ARG_STR(20) },
+		{ 0, ARG_STR(F_SETPIPE_SZ), ARG_STR(4097) },
+		{ 0, ARG_STR(F_DUPFD), ARG_STR(0) },
+		{ 0, ARG_STR(F_DUPFD_CLOEXEC), ARG_STR(0) },
+		{ 0, ARG_STR(F_SETFL), ARG_STR(O_RDWR|O_LARGEFILE) },
+		{ 0, ARG_STR(F_NOTIFY), ARG_STR(DN_ACCESS) },
+		{ 1, ARG_STR(F_SETLEASE), ARG_STR(F_RDLCK) },
+		{ 0, ARG_STR(F_SETSIG), 0, "SIG_0" },
+		{ 1, ARG_STR(F_SETSIG), 1, "SIGHUP" }
+	};
+	for (unsigned int i = 0; i < ARRAY_SIZE(set_checks); i++) {
+		test_other_set_cmd(set_checks + i);
+	}
+
+	static const struct fcntl_cmd_check get_checks[] = {
+		{ 0, ARG_STR(F_GETFD), .print_flags = print_flags_getfd },
+		{ 1, ARG_STR(F_GETFD), .print_flags = print_flags_getfd },
+		{ 0, ARG_STR(F_GETOWN) },
+		{ 0, ARG_STR(F_GETPIPE_SZ) },
+		{ 1, ARG_STR(F_GETLEASE), .print_flags = print_flags_getlease },
+		{ 0, ARG_STR(F_GETSIG), .print_flags = print_flags_getsig },
+		{ 1, ARG_STR(F_GETSIG), .print_flags = print_flags_getsig }
+	};
+	for (unsigned int j = 0; j < ARRAY_SIZE(get_checks); j++) {
+		test_other_get_cmd(get_checks + j);
+	}
+}
+
 static void
 create_sample(void)
 {
@@ -261,6 +392,7 @@ main(void)
 #ifdef TEST_F_OWNER_EX
 	test_f_owner_ex();
 #endif
+	test_fcntl_others();
 
 	puts("+++ exited with 0 +++");
 	return 0;
-- 
2.14.4



More information about the Strace-devel mailing list