[RFC/PATCH v3 2/2] tests: Improve tests for watchdog ioctl commands

Sahil Siddiq icegambit91 at gmail.com
Wed Aug 7 19:59:56 UTC 2024


Add new tests for WDIOC_GETSUPPORT and WDIOC_SETOPTIONS
decoders. Also enhance tests for currently available
watchdog ioctl decoders. This enables the verification
of their behaviour when:

1. the ioctl is successful (returns a non-negative
   integer).
2. strace is run with the -v option.

* tests/.gitignore (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
* tests/Makefile.am (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
* tests/gen_tests.in (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
* tests/ioctl_watchdog-success.c: New file.
* tests/ioctl_watchdog-success-v.c: New file.
* tests/ioctl_watchdog.c:
  - (do_ioctl, do_ioctl_ptr): New functions.
  - (main): Place argc, argv in argument list.
  - (WDIOC_GETSUPPORT, WDIOC_SETOPTIONS): Add decoder tests.
  - (WDIOC_GET*): Improve existing decoder tests.

Signed-off-by: Sahil Siddiq <sahilcdq at proton.me>
---
Changes v1 -> v2: None

Changes v2 -> v3:
- Moved tests from v2 into its own commit.
- tests/.gitignore (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
- tests/Makefile.am (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
- tests/gen_tests.in (ioctl_watchdog-success.c,
  ioctl_watchdog-success-v.c): New entries.
- ioctl_watchdog-success-v.c: New file.
- ioctl_watchdog-success.c: New file.
- tests/ioctl_watchdog.c:
  - Added tests that use syscall retval injection.
  - Added tests to check behaviour under -v/--no-abbrev
    option.

 tests/.gitignore                 |   2 +
 tests/Makefile.am                |   2 +
 tests/gen_tests.in               |   4 +-
 tests/ioctl_watchdog-success-v.c |   2 +
 tests/ioctl_watchdog-success.c   |   2 +
 tests/ioctl_watchdog.c           | 154 ++++++++++++++++++++++++++-----
 6 files changed, 143 insertions(+), 23 deletions(-)
 create mode 100644 tests/ioctl_watchdog-success-v.c
 create mode 100644 tests/ioctl_watchdog-success.c

diff --git a/tests/.gitignore b/tests/.gitignore
index 1944c808f..b437b21d9 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -430,6 +430,8 @@ ioctl_v4l2-v-Xabbrev
 ioctl_v4l2-v-Xraw
 ioctl_v4l2-v-Xverbose
 ioctl_watchdog
+ioctl_watchdog-success
+ioctl_watchdog-success-v
 ioctl_winsize
 ioperm
 iopl
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 378146b6f..e1254c364 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -243,6 +243,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
 	ioctl_v4l2-success-v-Xabbrev \
 	ioctl_v4l2-success-v-Xraw \
 	ioctl_v4l2-success-v-Xverbose \
+	ioctl_watchdog-success \
+	ioctl_watchdog-success-v \
 	ioprio--pidns-translation \
 	ip_local_port_range-success \
 	ip_local_port_range-success-Xabbrev \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 80e4b266f..140d43a2b 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -450,7 +450,9 @@ ioctl_v4l2-v	+ioctl.test -v
 ioctl_v4l2-v-Xabbrev	+ioctl.test -v -Xabbrev
 ioctl_v4l2-v-Xraw	+ioctl.test -v -Xraw
 ioctl_v4l2-v-Xverbose	+ioctl.test -v -Xverbose
-ioctl_watchdog	+ioctl.test
+ioctl_watchdog	+ioctl.test -a14
+ioctl_watchdog-success	+ioctl-success.sh -a14
+ioctl_watchdog-success-v	+ioctl-success.sh -a14 -v
 ioctl_winsize	+ioctl.test
 ioperm	-a27
 iopl	-a8
diff --git a/tests/ioctl_watchdog-success-v.c b/tests/ioctl_watchdog-success-v.c
new file mode 100644
index 000000000..69b3c590b
--- /dev/null
+++ b/tests/ioctl_watchdog-success-v.c
@@ -0,0 +1,2 @@
+#define VERBOSE 1
+#include "ioctl_watchdog-success.c"
diff --git a/tests/ioctl_watchdog-success.c b/tests/ioctl_watchdog-success.c
new file mode 100644
index 000000000..34e0b997d
--- /dev/null
+++ b/tests/ioctl_watchdog-success.c
@@ -0,0 +1,2 @@
+#define INJECT_RETVAL 42
+#include "ioctl_watchdog.c"
diff --git a/tests/ioctl_watchdog.c b/tests/ioctl_watchdog.c
index 744947e87..f3ad2d787 100644
--- a/tests/ioctl_watchdog.c
+++ b/tests/ioctl_watchdog.c
@@ -10,6 +10,7 @@
 #include "tests.h"
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <linux/watchdog.h>
@@ -18,41 +19,150 @@
 #include "xlat/watchdog_ioctl_cmds.h"
 #undef XLAT_MACROS_ONLY
 
+static const char *errstr;
+
+static int
+do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
+{
+	int rc = ioctl(-1, cmd, arg);
+	errstr = sprintrc(rc);
+
+#ifdef INJECT_RETVAL
+	if (rc != INJECT_RETVAL)
+		error_msg_and_fail("Return value [%d] does not match"
+				   " expectations [%d]", rc, INJECT_RETVAL);
+
+	static char inj_errstr[4096];
+
+	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
+	errstr = inj_errstr;
+#endif
+
+	return rc;
+}
+
+static int
+do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
+{
+	return do_ioctl(cmd, (uintptr_t) arg);
+}
+
 int
-main(void)
+main(int argc, const char *argv[])
 {
-	int val = 123;
+#ifdef INJECT_RETVAL
+	unsigned long num_skip;
+	bool locked = false;
+
+	if (argc < 2)
+		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
+
+	num_skip = strtoul(argv[1], NULL, 0);
+
+	for (size_t i = 0; i < num_skip; i++) {
+		long ret = ioctl(-1, WDIOC_GETSUPPORT, 0);
+
+		printf("ioctl(-1, WDIOC_GETSUPPORT, NULL) = %s%s\n",
+		       sprintrc(ret),
+		       ret == INJECT_RETVAL ? " (INJECTED)" : "");
+
+		if (ret != INJECT_RETVAL)
+			continue;
+
+		locked = true;
+		break;
+	}
+
+	if (!locked)
+		error_msg_and_fail("Issued %lu ioctl syscalls but failed"
+				   " to detect an injected return code %d",
+				   num_skip, INJECT_RETVAL);
+#endif
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct watchdog_info, ident);
+#define IDENT_OPTIONS 0x87ff
+	ident->options = IDENT_OPTIONS;
+	ident->firmware_version = 6;
+	memset(ident->identity, 'A', sizeof(ident->identity));
+	ident->identity[sizeof(ident->identity) - 1] = '\0';
+
+	int rc = do_ioctl_ptr(WDIOC_GETSUPPORT, ident);
+	if (rc < 0) {
+		printf("ioctl(-1, WDIOC_GETSUPPORT, %p) = %s\n", ident, errstr);
+	} else {
+		printf("ioctl(-1, WDIOC_GETSUPPORT, {options=%s, ",
+		       XLAT_KNOWN(IDENT_OPTIONS,
+				  "WDIOF_OVERHEAT|WDIOF_FANFAULT|"
+				  "WDIOF_EXTERN1|WDIOF_EXTERN2|"
+				  "WDIOF_POWERUNDER|WDIOF_CARDRESET|"
+				  "WDIOF_POWEROVER|WDIOF_SETTIMEOUT|"
+				  "WDIOF_MAGICCLOSE|WDIOF_PRETIMEOUT|"
+				  "WDIOF_ALARMONLY|WDIOF_KEEPALIVEPING"));
+#if VERBOSE
+		printf("firmware_version=%u, identity=\"%s\"",
+		       ident->firmware_version,
+			   ident->identity);
+#else
+		printf("...");
+#endif
+		printf("}) = %s\n", errstr);
+	}
+
+	static const struct {
+		uint32_t cmd;
+		const char *str;
+	} simple_get_cmds[] = {
+		{ ARG_STR(WDIOC_GETSTATUS) },
+		{ ARG_STR(WDIOC_GETBOOTSTATUS) },
+		{ ARG_STR(WDIOC_GETTEMP) },
+		{ ARG_STR(WDIOC_GETTIMEOUT) },
+		{ ARG_STR(WDIOC_GETPRETIMEOUT) },
+		{ ARG_STR(WDIOC_GETTIMELEFT) },
+	};
 
-	ioctl(-1, WDIOC_GETSTATUS, &val);
-	printf("ioctl(-1, WDIOC_GETSTATUS, %p)" RVAL_EBADF, &val);
+	TAIL_ALLOC_OBJECT_CONST_PTR(int, val);
+	*val = 123;
 
-	ioctl(-1, WDIOC_GETBOOTSTATUS, &val);
-	printf("ioctl(-1, WDIOC_GETBOOTSTATUS, %p)" RVAL_EBADF, &val);
+	for (size_t i = 0; i < ARRAY_SIZE(simple_get_cmds); ++i) {
+		int rc = do_ioctl_ptr(simple_get_cmds[i].cmd, val);
+		printf("ioctl(-1, " XLAT_FMT ", ",
+		       XLAT_SEL(simple_get_cmds[i].cmd, simple_get_cmds[i].str));
+		if (rc < 0) {
+			printf("%p) = %s\n", val, errstr);
+		} else {
+			printf("[%d]) = %s\n", *val, errstr);
+		}
+	}
 
-	ioctl(-1, WDIOC_GETTEMP, &val);
-	printf("ioctl(-1, WDIOC_GETTEMP, %p)" RVAL_EBADF, &val);
+	do_ioctl_ptr(WDIOC_SETTIMEOUT, val);
+	printf("ioctl(-1, WDIOC_SETTIMEOUT, [123]) = %s\n", errstr);
 
-	ioctl(-1, WDIOC_GETTIMEOUT, &val);
-	printf("ioctl(-1, WDIOC_GETTIMEOUT, %p)" RVAL_EBADF, &val);
+	do_ioctl_ptr(WDIOC_SETPRETIMEOUT, val);
+	printf("ioctl(-1, WDIOC_SETPRETIMEOUT, [123]) = %s\n", errstr);
 
-	ioctl(-1, WDIOC_GETPRETIMEOUT, &val);
-	printf("ioctl(-1, WDIOC_GETPRETIMEOUT, %p)" RVAL_EBADF, &val);
+	TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, options);
 
-	ioctl(-1, WDIOC_GETTIMELEFT, &val);
-	printf("ioctl(-1, WDIOC_GETTIMELEFT, %p)" RVAL_EBADF, &val);
+	*options = 1;
+	do_ioctl_ptr(WDIOC_SETOPTIONS, options);
+	printf("ioctl(-1, WDIOC_SETOPTIONS, [%s]) = %s\n",
+	       XLAT_KNOWN(0x1, "WDIOS_DISABLECARD"), errstr);
 
-	ioctl(-1, WDIOC_SETTIMEOUT, &val);
-	printf("ioctl(-1, WDIOC_SETTIMEOUT, [123])" RVAL_EBADF);
+	*options = 6;
+	do_ioctl_ptr(WDIOC_SETOPTIONS, options);
+	printf("ioctl(-1, WDIOC_SETOPTIONS, [%s]) = %s\n",
+	       XLAT_KNOWN(0x6, "WDIOS_ENABLECARD|WDIOS_TEMPPANIC"), errstr);
 
-	ioctl(-1, WDIOC_SETPRETIMEOUT, &val);
-	printf("ioctl(-1, WDIOC_SETPRETIMEOUT, [123])" RVAL_EBADF);
+	*options = 0xfed8;
+	do_ioctl_ptr(WDIOC_SETOPTIONS, options);
+	printf("ioctl(-1, WDIOC_SETOPTIONS, [%s]) = %s\n",
+	       XLAT_UNKNOWN(0xfed8, "WDIOS_???"), errstr);
 
-	ioctl(-1, WDIOC_KEEPALIVE);
-	printf("ioctl(-1, WDIOC_KEEPALIVE)" RVAL_EBADF);
+	do_ioctl_ptr(WDIOC_KEEPALIVE, NULL);
+	printf("ioctl(-1, WDIOC_KEEPALIVE) = %s\n", errstr);
 
 	ioctl(-1, _IOC(_IOC_NONE, 'W', 0xff, 0), &val);
-	printf("ioctl(-1, _IOC(_IOC_NONE, %#x, 0xff, 0), %p)" RVAL_EBADF,
-	       'W', &val);
+	printf("ioctl(-1, _IOC(_IOC_NONE, %#x, 0xff, 0), %p) = %s\n",
+	       'W', &val, errstr);
 
 	puts("+++ exited with 0 +++");
 	return 0;
-- 
2.45.2



More information about the Strace-devel mailing list