[LTP] [PATCH v7 5/5] Extend ioctl02 to test termio and termios
Marius Kittler
mkittler@suse.de
Mon Oct 23 18:02:42 CEST 2023
Signed-off-by: Marius Kittler <mkittler@suse.de>
---
testcases/kernel/syscalls/ioctl/ioctl02.c | 170 +++++++++++++++++++---
1 file changed, 147 insertions(+), 23 deletions(-)
diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c
index 5111d7178..00d51b367 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl02.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl02.c
@@ -8,22 +8,24 @@
/*\
* [Description]
*
- * Testcase to test the TCGETS, and TCSETS ioctl implementations for
- * the tty driver
+ * Testcase to test the TCGETA/TCGETS, and TCSETA/TCSETS ioctl
+ * implementations for the tty driver
*
* In this test, the parent and child open the parentty and the childtty
* respectively. After opening the childtty the child flushes the stream
* and wakes the parent (thereby asking it to continue its testing). The
- * parent, then starts the testing. It issues a TCGETS ioctl to get all
- * the tty parameters. It then changes them to known values by issuing a
- * TCSETS ioctl. Then the parent issues a TCGETS ioctl again and compares
- * the received values with what it had set earlier. The test fails if
- * TCGETS or TCSETS fails, or if the received values don't match those
- * that were set. The parent does all the testing, the requirement of the
- * child process is to moniter the testing done by the parent, and hence
- * the child just waits for the parent.
+ * parent, then starts the testing. It issues a TCGETA/TCGETS ioctl to
+ * get all the tty parameters. It then changes them to known values by
+ * issuing a TCSETA/TCSETS ioctl. Then the parent issues a TCSETA/TCGETS
+ * ioctl again and compares the received values with what it had set
+ * earlier. The test fails if TCGETA/TCGETS or TCSETA/TCSETS fails, or if
+ * the received values don't match those that were set. The parent does
+ * all the testing, the requirement of the child process is to moniter
+ * the testing done by the parent, and hence the child just waits for the
+ * parent.
*/
+#include <asm-generic/ioctls.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
@@ -38,23 +40,54 @@
#include "tst_test.h"
#include "tst_safe_macros.h"
-static struct termios termio, save_io;
+static struct termio termio;
+static struct termios termios, termios_bak;
static char *parenttty, *childtty;
static int parentfd = -1, childfd = -1;
static int parentpid, childpid;
static int do_child_setup(void);
+static void prepare_termio(void);
+static void preapre_termios(void);
static void run_ptest(void);
static void run_ctest(void);
-static void chk_tty_parms(void);
+static void chk_tty_parms_termio(void);
+static void chk_tty_parms_termios(void);
static void setup(void);
static void cleanup(void);
static char *device;
+static struct variant {
+ const char *name;
+ void *termio, *termio_bak;
+ void (*prepare)(void);
+ void (*check)(void);
+ int tcget, tcset;
+} variants[] = {
+ {
+ .name = "termio",
+ .termio = &termio,
+ .prepare = &prepare_termio,
+ .check = &chk_tty_parms_termio,
+ .tcget = TCGETA,
+ .tcset = TCSETA,
+ },
+ {
+ .name = "termios",
+ .termio = &termios,
+ .prepare = preapre_termios,
+ .check = &chk_tty_parms_termios,
+ .tcget = TCGETS,
+ .tcset = TCSETS,
+ },
+};
+
static void verify_ioctl(void)
{
+ tst_res(TINFO, "Testing %s variant", variants[tst_variant].name);
+
parenttty = device;
childtty = device;
@@ -80,11 +113,7 @@ static void verify_ioctl(void)
TST_CHECKPOINT_WAKE(0);
}
-/*
- * run_ptest() - setup the various termio structure values and issue
- * the TCSETS ioctl call with the TEST macro.
- */
-static void run_ptest(void)
+static void prepare_termio(void)
{
/* Use "old" line discipline */
termio.c_line = 0;
@@ -110,12 +139,50 @@ static void run_ptest(void)
/* Set output modes. */
termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR;
+}
- SAFE_IOCTL(parentfd, TCSETS, &termio);
+static void preapre_termios(void)
+{
+ /* Use "old" line discipline */
+ termios.c_line = 0;
+
+ /* Set control modes */
+ termios.c_cflag = B50 | CS7 | CREAD | PARENB | PARODD | CLOCAL;
+
+ /* Set control chars. */
+ for (int i = 0; i < NCC; i++) {
+ if (i == VEOL2)
+ continue;
+ termios.c_cc[i] = CSTART;
+ }
+
+ /* Set local modes. */
+ termios.c_lflag =
+ ((unsigned short)(ISIG | ICANON | XCASE | ECHO | ECHOE | NOFLSH));
+
+ /* Set input modes. */
+ termios.c_iflag =
+ BRKINT | IGNPAR | INPCK | ISTRIP | ICRNL | IUCLC | IXON | IXANY |
+ IXOFF;
+
+ /* Set output modes. */
+ termios.c_oflag = OPOST | OLCUC | ONLCR | ONOCR;
+}
+
+/*
+ * run_ptest() - setup the various termio/termios structure values and issue
+ * the TCSETA/TCSETS ioctl call with the TEST macro.
+ */
+static void run_ptest(void)
+{
+ struct variant *v = &variants[tst_variant];
+
+ v->prepare();
+ SAFE_IOCTL(parentfd, v->tcset, v->termio);
/* Get termio and see if all parameters actually got set */
- SAFE_IOCTL(parentfd, TCGETS, &termio);
- chk_tty_parms();
+ SAFE_IOCTL(parentfd, v->tcget, v->termio);
+ v->check();
}
static void run_ctest(void)
@@ -125,7 +192,7 @@ static void run_ctest(void)
SAFE_CLOSE(childfd);
}
-static void chk_tty_parms(void)
+static void chk_tty_parms_termio(void)
{
int i, flag = 0;
@@ -174,6 +241,62 @@ static void chk_tty_parms(void)
flag++;
}
+ if (flag != 0)
+ tst_res(TFAIL, "TCGETA/TCSETA tests FAILED with "
+ "%d %s", flag, flag > 1 ? "errors" : "error");
+ else
+ tst_res(TPASS, "TCGETA/TCSETA tests SUCCEEDED");
+}
+
+static void chk_tty_parms_termios(void)
+{
+ int i, flag = 0;
+
+ if (termios.c_line != 0) {
+ tst_res(TINFO, "line discipline has incorrect value %o",
+ termios.c_line);
+ flag++;
+ }
+
+ for (i = 0; i < NCC; i++) {
+ if (i == VEOL2) {
+ if (!termios.c_cc[i]) {
+ continue;
+ } else {
+ tst_res(TINFO, "control char %d has "
+ "incorrect value %d", i, termios.c_cc[i]);
+ flag++;
+ continue;
+ }
+ }
+
+ if (termios.c_cc[i] != CSTART) {
+ tst_res(TINFO, "control char %d has incorrect "
+ "value %d.", i, termios.c_cc[i]);
+ flag++;
+ }
+ }
+
+ if (termios.c_lflag != (ISIG | ICANON | XCASE | ECHO | ECHOE
+ | NOFLSH)) {
+ tst_res(TINFO, "lflag has incorrect value. %o",
+ termios.c_lflag);
+ flag++;
+ }
+
+ if (termios.c_iflag != (BRKINT | IGNPAR | INPCK | ISTRIP
+ | ICRNL | IUCLC | IXON | IXANY | IXOFF)) {
+ tst_res(TINFO, "iflag has incorrect value. %o",
+ termios.c_iflag);
+ flag++;
+ }
+
+ if (termios.c_oflag != (OPOST | OLCUC | ONLCR | ONOCR)) {
+ tst_res(TINFO, "oflag has incorrect value. %o",
+ termios.c_oflag);
+ flag++;
+ }
+
if (flag != 0)
tst_res(TFAIL, "TCGETS/TCSETS tests FAILED with "
"%d %s", flag, flag > 1 ? "errors" : "error");
@@ -202,7 +325,7 @@ static void setup(void)
int fd = SAFE_OPEN(device, O_RDWR, 0777);
/* Save the current device information - to be restored in cleanup() */
- SAFE_IOCTL(fd, TCGETS, &save_io);
+ SAFE_IOCTL(fd, TCGETS, &termios_bak);
/* Close the device */
SAFE_CLOSE(fd);
@@ -211,7 +334,7 @@ static void setup(void)
static void cleanup(void)
{
if (parentfd >= 0) {
- SAFE_IOCTL(parentfd, TCSETS, &save_io);
+ SAFE_IOCTL(parentfd, TCSETS, &termios_bak);
SAFE_CLOSE(parentfd);
}
}
@@ -223,6 +346,7 @@ static struct tst_test test = {
.setup = setup,
.cleanup = cleanup,
.test_all = verify_ioctl,
+ .test_variants = 2,
.options = (struct tst_option[]) {
{"D:", &device, "Tty device. For example, /dev/tty[0-9]"},
{}
--
2.42.0
More information about the ltp
mailing list