[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