[LTP] [PATCH v4 03/12] Refactor ptem01 test
Andrea Cervesato
andrea.cervesato@suse.com
Fri Jan 17 10:44:44 CET 2025
Pushed a patch to fix this test compiling on Alpine:
426d78f62 ptem01: fix compiling on alpine
Andrea
On 1/16/25 12:36, Andrea Cervesato wrote:
> From: Andrea Cervesato <andrea.cervesato@suse.com>
>
> Fix test failure when running inside a new session via setsid() and
> start spliting its internal tests cases implementations into multiple
> files.
>
> Fixes: https://github.com/linux-test-project/kirk/issues/28
> Reviewed-by: Petr Vorel <pvorel@suse.cz>
> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
> ---
> testcases/kernel/pty/common.h | 68 +++++++
> testcases/kernel/pty/ptem01.c | 456 ++++--------------------------------------
> 2 files changed, 105 insertions(+), 419 deletions(-)
>
> diff --git a/testcases/kernel/pty/common.h b/testcases/kernel/pty/common.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..51760b1d39fa0518f3e7c4ece2281286e056cc48
> --- /dev/null
> +++ b/testcases/kernel/pty/common.h
> @@ -0,0 +1,68 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> + */
> +
> +#ifndef PTEM_H
> +#define PTEM_H
> +
> +#define _GNU_SOURCE
> +
> +#include "tst_test.h"
> +
> +#define MASTERCLONE "/dev/ptmx"
> +
> +static inline int open_master(void)
> +{
> + int masterfd;
> +
> + if (access(MASTERCLONE, F_OK))
> + tst_brk(TCONF, "%s device doesn't exist", MASTERCLONE);
> +
> + tst_res(TINFO, "opening master %s", MASTERCLONE);
> +
> + masterfd = SAFE_OPEN(MASTERCLONE, O_RDWR);
> +
> + if (grantpt(masterfd) == -1)
> + tst_brk(TBROK | TERRNO, "grantpt() error");
> +
> + if (unlockpt(masterfd) == -1)
> + tst_brk(TBROK | TERRNO, "unlockpt() error");
> +
> + return masterfd;
> +}
> +
> +static inline int open_slave(const int masterfd)
> +{
> + int slavefd;
> + char *slavename;
> +
> + slavename = SAFE_PTSNAME(masterfd);
> +
> + tst_res(TINFO, "opening slave %s", slavename);
> +
> +#ifndef __BIONIC__
> + /* grantpt() is a no-op in bionic. */
> + struct stat st;
> +
> + SAFE_STAT(slavename, &st);
> +
> + uid_t uid = getuid();
> +
> + if (st.st_uid != uid) {
> + tst_brk(TBROK, "uid mismatch st.st_uid(%d) != getuid(%d)",
> + st.st_uid, uid);
> + }
> +
> + if (st.st_mode != (S_IFCHR | 0620)) {
> + tst_brk(TBROK, "unexpected slave device permission: %o",
> + st.st_mode);
> + }
> +#endif
> +
> + slavefd = SAFE_OPEN(slavename, O_RDWR);
> +
> + return slavefd;
> +}
> +
> +#endif
> diff --git a/testcases/kernel/pty/ptem01.c b/testcases/kernel/pty/ptem01.c
> index 20ef5d0a739a55262c1c32ec03e57885dfe09787..b14e247c8ba53e098d44a3904621f8f2ec21fd1a 100644
> --- a/testcases/kernel/pty/ptem01.c
> +++ b/testcases/kernel/pty/ptem01.c
> @@ -1,441 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> /*
> - * Copyright (c) International Business Machines Corp., 2002
> - * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> - * the GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + * Copyright (c) International Business Machines Corp., 2002
> + * Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
> + * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
> */
>
> -/* 12/23/2002 Port to LTP robbiew@us.ibm.com */
> -/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
> +/*\
> + * [Description]
> + *
> + * Verify that it's possible to open a pseudo-terminal via /dev/ptmx, obtain a
> + * slave device and configure termos/termios ioctls.
> + */
>
> #define _GNU_SOURCE
> -#include <errno.h>
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <termios.h>
> -#include <fcntl.h>
> -#include <sys/stat.h>
> -#include <sys/poll.h>
> -#include <sys/types.h>
> -
> -#include "test.h"
> -#include "safe_macros.h"
> -#include "lapi/ioctl.h"
>
> -char *TCID = "ptem01"; /* Test program identifier. */
> -int TST_TOTAL = 6; /* Total number of test cases. */
> -/**************/
> -
> -/*
> - * pty master clone device
> - */
> -#define MASTERCLONE "/dev/ptmx"
> +#include <termio.h>
> +#include <termios.h>
> +#include "common.h"
>
> -#define BUFSZ 4096
> +static int masterfd = -1;
>
> -/*
> - * test termio/termios ioctls
> - */
> -int test1(void)
> +static void run(void)
> {
> - int masterfd, slavefd;
> - char *slavename;
> + int slavefd;
> struct termio termio;
> struct termios termios;
>
> - masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
> -
> - slavename = ptsname(masterfd);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
> - }
> -
> - if (grantpt(masterfd) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
> - }
> -
> - if (unlockpt(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TFAIL, NULL, "Could not open %s", slavename);
> - }
> -
> - if (ioctl(slavefd, TCGETS, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCGETS");
> - }
> -
> - if (ioctl(slavefd, TCSETS, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETS");
> - }
> -
> - if (ioctl(slavefd, TCSETSW, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETSW");
> - }
> -
> - if (ioctl(slavefd, TCSETSF, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETSF");
> - }
> -
> - if (ioctl(slavefd, TCSETS, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETS");
> - }
> -
> - if (ioctl(slavefd, TCGETA, &termio) != 0) {
> - tst_brkm(TFAIL, NULL, "TCGETA");
> - }
> -
> - if (ioctl(slavefd, TCSETA, &termio) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETA");
> - }
> -
> - if (ioctl(slavefd, TCSETAW, &termio) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETAW");
> - }
> -
> - if (ioctl(slavefd, TCSETAF, &termio) != 0) {
> - tst_brkm(TFAIL, NULL, "TCSETAF");
> - }
> -
> - if (close(slavefd) != 0) {
> - tst_brkm(TBROK, NULL, "close slave");
> - }
> -
> - if (close(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "close master");
> - }
> - tst_resm(TPASS, "test1");
> -
> - /** NOT REACHED **/
> - return 0;
> -}
> -
> -/*
> - * test window size setting and getting
> - */
> -int test2(void)
> -{
> - int masterfd, slavefd;
> - char *slavename;
> - struct winsize wsz;
> - struct winsize wsz1 = { 24, 80, 5, 10 };
> - struct winsize wsz2 = { 60, 100, 11, 777 };
> -
> - masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
> -
> - slavename = ptsname(masterfd);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
> - }
> -
> - if (grantpt(masterfd) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
> - }
> -
> - if (unlockpt(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TBROK, NULL, "Could not open %s", slavename);
> - }
> -
> - if (ioctl(masterfd, TIOCSWINSZ, &wsz1) != 0) {
> - tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
> - }
> -
> - if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
> - tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
> - }
> -
> - if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
> - wsz.ws_xpixel != wsz1.ws_xpixel ||
> - wsz.ws_ypixel != wsz1.ws_ypixel) {
> - tst_brkm(TFAIL, NULL, "unexpected window size returned");
> - }
> -
> - if (ioctl(masterfd, TIOCGWINSZ, &wsz) != 0) {
> - tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
> - }
> -
> - if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
> - wsz.ws_xpixel != wsz1.ws_xpixel ||
> - wsz.ws_ypixel != wsz1.ws_ypixel) {
> - tst_brkm(TFAIL, NULL, "unexpected window size returned");
> - }
> -
> - if (ioctl(slavefd, TIOCSWINSZ, &wsz2) != 0) {
> - tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
> - }
> -
> - if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
> - tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
> - }
> -
> - if (wsz.ws_row != wsz2.ws_row || wsz.ws_col != wsz2.ws_col ||
> - wsz.ws_xpixel != wsz2.ws_xpixel ||
> - wsz.ws_ypixel != wsz2.ws_ypixel) {
> - tst_brkm(TFAIL, NULL, "unexpected window size returned");
> - }
> -
> - if (close(slavefd) != 0) {
> - tst_brkm(TBROK, NULL, "close");
> - }
> -
> - if (close(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "close");
> - }
> - tst_resm(TPASS, "test2");
> -
> - /** NOT REACHED **/
> - return 0;
> -}
> -
> -/*
> - * test sending a break
> - */
> -int test3(void)
> -{
> - int masterfd, slavefd;
> - char *slavename;
> -
> - masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
> -
> - slavename = ptsname(masterfd);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
> - }
> -
> - if (grantpt(masterfd) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
> - }
> -
> - if (unlockpt(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TBROK, NULL, "Could not open %s", slavename);
> - }
> -
> - if (tcsendbreak(masterfd, 10) != 0) {
> - tst_brkm(TFAIL, NULL, "tcsendbreak");
> - }
> -
> - if (tcsendbreak(slavefd, 10) != 0) {
> - tst_brkm(TFAIL, NULL, "tcsendbreak");
> - }
> -
> - if (close(slavefd) != 0) {
> - tst_brkm(TBROK, NULL, "close slave");
> - }
> -
> - if (close(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "close master");
> - }
> - tst_resm(TPASS, "test3");
> -
> - /** NOT REACHED **/
> - return 0;
> -}
> -
> -/*
> - * test multiple opens of slave side
> - */
> -int test4(void)
> -{
> - int masterfd, slavefd, slavefd2, slavefd3;
> - char *slavename;
> -
> - masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
> -
> - slavename = ptsname(masterfd);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
> - }
> + slavefd = open_slave(masterfd);
>
> - if (grantpt(masterfd) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
> - }
> + TST_EXP_PASS(ioctl(slavefd, TCGETS, &termios));
> + TST_EXP_PASS(ioctl(slavefd, TCSETS, &termios));
> + TST_EXP_PASS(ioctl(slavefd, TCSETSW, &termios));
> + TST_EXP_PASS(ioctl(slavefd, TCSETSF, &termios));
> + TST_EXP_PASS(ioctl(slavefd, TCSETS, &termios));
> + TST_EXP_PASS(ioctl(slavefd, TCGETA, &termio));
> + TST_EXP_PASS(ioctl(slavefd, TCSETA, &termio));
> + TST_EXP_PASS(ioctl(slavefd, TCSETAW, &termio));
> + TST_EXP_PASS(ioctl(slavefd, TCSETAF, &termio));
>
> - if (unlockpt(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TBROK, NULL, "Could not open %s", slavename);
> - }
> -
> - if ((slavefd2 = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TFAIL, NULL, "Could not open %s (again)", slavename);
> - }
> -
> - if ((slavefd3 = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TFAIL, NULL, "Could not open %s (once more)",
> - slavename);
> - }
> -
> - if (close(slavefd) != 0) {
> - tst_brkm(TBROK, NULL, "close slave");
> - }
> - if (close(slavefd2) != 0) {
> - tst_brkm(TBROK, NULL, "close slave again");
> - }
> - if (close(slavefd3) != 0) {
> - tst_brkm(TBROK, NULL, "close slave once more");
> - }
> - if (close(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "close master");
> - }
> - tst_resm(TPASS, "test4");
> -
> - /** NOT REACHED **/
> - return 0;
> + SAFE_CLOSE(slavefd);
> }
>
> -#define NUMOPENS 6
> -
> -/*
> - * test several simultaneous opens
> - */
> -int test5(void)
> +static void setup(void)
> {
> - static int masterfd[NUMOPENS];
> - static int slavefd[NUMOPENS];
> - char *slavename;
> - int i;
> -
> - for (i = 0; i < NUMOPENS; ++i) {
> - masterfd[i] = open(MASTERCLONE, O_RDWR);
> - if (masterfd[i] < 0) {
> - tst_resm(TBROK, "%s", MASTERCLONE);
> - tst_resm(TBROK, "out of ptys");
> - for (i = 0; i < NUMOPENS; ++i) {
> - if (masterfd[i] != 0) {
> - (void)close(masterfd[i]);
> - }
> - if (slavefd[i] != 0) {
> - (void)close(slavefd[i]);
> - }
> - }
> - tst_exit();
> - }
> -
> - slavename = ptsname(masterfd[i]);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL,
> - "ptsname() call failed");
> - }
> -
> - if (grantpt(masterfd[i]) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL,
> - "grantpt() call failed");
> - }
> -
> - if (unlockpt(masterfd[i]) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd[i] = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TFAIL, NULL,
> - "Iteration %d: Could not open %s", i,
> - slavename);
> - }
> -
> - }
> -
> - for (i = 0; i < NUMOPENS; ++i) {
> - if (close(slavefd[i]) != 0) {
> - tst_brkm(TBROK, NULL, "Iteration %d: close slave", i);
> - }
> - if (close(masterfd[i]) != 0) {
> - tst_brkm(TBROK, NULL, "close master");
> - }
> - }
> - tst_resm(TPASS, "test5");
> -
> - /** NOT REACHED **/
> - return 0;
> + masterfd = open_master();
> }
>
> -/*
> - * test hangup semantics
> - */
> -int test6(void)
> +static void cleanup(void)
> {
> - static int masterfd;
> - static int slavefd;
> - char *slavename;
> - struct termios termios;
> -
> - masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
> -
> - slavename = ptsname(masterfd);
> - if (slavename == NULL) {
> - tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
> - }
> -
> - if (grantpt(masterfd) != 0) {
> - tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
> - }
> -
> - if (unlockpt(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "unlockpt() call failed");
> - }
> -
> - if ((slavefd = open(slavename, O_RDWR)) < 0) {
> - tst_brkm(TBROK, NULL, "Could not open %s", slavename);
> - }
> -
> - if (ioctl(slavefd, TCGETS, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCGETS");
> - }
> -
> - termios.c_cflag &= ~CBAUD;
> - termios.c_cflag |= B0 & CBAUD;
> - if (ioctl(slavefd, TCSETS, &termios) != 0) {
> - tst_brkm(TFAIL, NULL, "TCGETS");
> - }
> -
> - if (close(slavefd) != 0) {
> - tst_brkm(TBROK, NULL, "close");
> - }
> - if (close(masterfd) != 0) {
> - tst_brkm(TBROK, NULL, "close");
> - }
> - tst_resm(TPASS, "test6");
> -
> - /** NOT REACHED **/
> - return 0;
> + if (masterfd != -1)
> + SAFE_CLOSE(masterfd);
> }
>
> -/*
> - * main test driver
> - */
> -int main(void)
> -{
> - test1();
> - test2();
> - test3();
> - test4();
> - test5();
> - test6();
> - /*
> - * all done
> - */
> - tst_exit();
> -}
> +static struct tst_test test = {
> + .test_all = run,
> + .setup = setup,
> + .cleanup = cleanup,
> +};
>
More information about the ltp
mailing list