From 3c89b58fdec8dde5c2135116169a2eb7f4e8d474 Mon Sep 17 00:00:00 2001 From: jiangjianfeng Date: Thu, 13 Nov 2025 11:43:07 +0000 Subject: [PATCH] Add regression test for open ptmx --- test/src/apps/pty/open_ptmx.c | 97 ++++++++++++++++++++++++++++++++ test/src/apps/scripts/process.sh | 1 + 2 files changed, 98 insertions(+) create mode 100644 test/src/apps/pty/open_ptmx.c diff --git a/test/src/apps/pty/open_ptmx.c b/test/src/apps/pty/open_ptmx.c new file mode 100644 index 000000000..5bf620ae6 --- /dev/null +++ b/test/src/apps/pty/open_ptmx.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "../test.h" + +#define DEV_PTMX "/dev/ptmx" + +int master; +int slave; +char slave_name[128]; + +FN_SETUP(open_ptmx) +{ + master = CHECK(open(DEV_PTMX, O_RDWR)); + int slave_index; + CHECK(ioctl(master, TIOCGPTN, &slave_index)); + memset(slave_name, 0, sizeof(slave_name)); + sprintf(slave_name, "/dev/pts/%d", slave_index); +} +END_SETUP() + +FN_TEST(read_write_before_open_slave) +{ + // Set master nonblocking mode + int flags = TEST_SUCC(fcntl(master, F_GETFL, 0)); + TEST_SUCC(fcntl(master, F_SETFL, flags | O_NONBLOCK)); + + char buf[1] = { 'a' }; + TEST_ERRNO(read(master, buf, sizeof(buf)), EAGAIN); + TEST_SUCC(write(master, buf, 1)); +} +END_TEST() + +FN_TEST(clear_lock_and_open_slave) +{ + TEST_ERRNO(open(slave_name, O_RDWR), EIO); + TEST_ERRNO(ioctl(master, TIOCGPTPEER, NULL), EIO); + + // Unlock pty lock + int lock; + TEST_RES(ioctl(master, TIOCGPTLCK, &lock), lock == 1); + lock = 0; + TEST_SUCC(ioctl(master, TIOCSPTLCK, &lock)); + TEST_RES(ioctl(master, TIOCGPTLCK, &lock), lock == 0); + + slave = TEST_SUCC(open(slave_name, O_RDWR)); + int tmp_sfd = TEST_SUCC(ioctl(master, TIOCGPTPEER, NULL)); + TEST_SUCC(close(tmp_sfd)); +} +END_TEST() + +FN_TEST(read_write) +{ + // Set master blocking mode + int flags = TEST_SUCC(fcntl(master, F_GETFL, 0)); + TEST_SUCC(fcntl(master, F_SETFL, flags & (~O_NONBLOCK))); + + pid_t pid = TEST_SUCC(fork()); + if (pid == 0) { + char buf[1] = { 0 }; + CHECK_WITH(read(master, buf, sizeof(buf)), + _ret == 1 && buf[0] == 'a'); + exit(EXIT_SUCCESS); + } + + // Set slave raw mode + struct termios term; + TEST_SUCC(tcgetattr(slave, &term)); + term.c_lflag &= ~(ICANON | ECHO); + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; + TEST_SUCC(tcsetattr(slave, TCSANOW, &term)); + + // Read the byte master has written. + char buf[1] = { 0 }; + TEST_RES(read(slave, buf, sizeof(buf)), _ret == 1 && buf[0] == 'a'); + + TEST_SUCC(write(slave, buf, sizeof(buf))); + + TEST_SUCC(wait(NULL)); +} +END_TEST() + +FN_SETUP(cleanup) +{ + CHECK(close(master)); + CHECK(close(slave)); +} +END_SETUP() diff --git a/test/src/apps/scripts/process.sh b/test/src/apps/scripts/process.sh index 6f387824f..62aaf10cd 100755 --- a/test/src/apps/scripts/process.sh +++ b/test/src/apps/scripts/process.sh @@ -48,6 +48,7 @@ pseudofs/pseudo_inode pseudofs/memfd_access_err pthread/pthread_test pty/close_pty +pty/open_ptmx pty/open_pty pty/pty_blocking sched/sched_attr_getset