Add regression test for pty packet mode
This commit is contained in:
parent
7d74429247
commit
b552bdbc51
|
|
@ -12,7 +12,7 @@ int master;
|
|||
int slave;
|
||||
char slave_name[256];
|
||||
|
||||
#define POLL_EVENTS (POLLIN | POLLOUT | POLLRDHUP)
|
||||
#define POLL_EVENTS (POLLIN | POLLOUT | POLLRDHUP | POLLPRI | POLLRDNORM)
|
||||
|
||||
void open_and_set_slave_raw_mode()
|
||||
{
|
||||
|
|
@ -69,7 +69,7 @@ FN_TEST(close_slave)
|
|||
TEST_SUCC(close(slave));
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLHUP));
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLHUP | POLLRDNORM));
|
||||
TEST_RES(ioctl(master, FIONREAD, &bytes), bytes == 1);
|
||||
TEST_RES(read(master, buf, sizeof(buf)), _ret == 1 && buf[0] == 'b');
|
||||
|
||||
|
|
@ -109,14 +109,15 @@ FN_TEST(close_master)
|
|||
struct pollfd in_pfd = { .fd = slave, .events = POLLIN };
|
||||
TEST_RES(poll(&in_pfd, 1, -1), in_pfd.revents == POLLIN);
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1), pfd.revents == (POLLIN | POLLOUT));
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLRDNORM));
|
||||
TEST_RES(ioctl(slave, FIONREAD, &bytes), bytes == 1);
|
||||
|
||||
TEST_SUCC(close(master));
|
||||
TEST_ERRNO(unlink(slave_name), ENOENT);
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLERR | POLLHUP));
|
||||
TEST_RES(poll(&pfd, 1, -1), pfd.revents == (POLLIN | POLLOUT | POLLERR |
|
||||
POLLHUP | POLLRDNORM));
|
||||
TEST_ERRNO(ioctl(slave, FIONREAD, &bytes), EIO);
|
||||
TEST_RES(read(slave, buf, sizeof(buf)), _ret == 0);
|
||||
TEST_ERRNO(write(slave, buf, sizeof(buf)), EIO);
|
||||
|
|
@ -151,7 +152,8 @@ FN_TEST(reopen_slave_after_close)
|
|||
TEST_SUCC(write(slave2, buf, sizeof(buf)));
|
||||
in_pfd.fd = master;
|
||||
TEST_RES(poll(&in_pfd, 1, -1), in_pfd.revents == POLLIN);
|
||||
TEST_RES(poll(&pfd, 1, -1), pfd.revents == (POLLIN | POLLOUT));
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLRDNORM));
|
||||
TEST_RES(ioctl(master, FIONREAD, &bytes), bytes == 1);
|
||||
TEST_RES(read(master, buf, sizeof(buf)), _ret == 1 && buf[0] == 'd');
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <pty.h>
|
||||
#include <poll.h>
|
||||
#include "../test.h"
|
||||
|
||||
int master;
|
||||
int slave;
|
||||
struct pollfd pfd;
|
||||
|
||||
#define POLL_EVENTS (POLLIN | POLLOUT | POLLRDHUP | POLLPRI | POLLRDNORM)
|
||||
|
||||
FN_SETUP(init)
|
||||
{
|
||||
CHECK(openpty(&master, &slave, NULL, NULL, NULL));
|
||||
|
||||
struct termios term;
|
||||
CHECK(tcgetattr(slave, &term));
|
||||
|
||||
// Disable canonical mode and echoing.
|
||||
term.c_lflag &= ~(ICANON | ECHO);
|
||||
|
||||
term.c_cc[VMIN] = 1;
|
||||
term.c_cc[VTIME] = 0;
|
||||
|
||||
// Enable software flow control (IXON) and set start/stop characters.
|
||||
term.c_iflag |= IXON;
|
||||
term.c_cc[VSTOP] = '\023';
|
||||
term.c_cc[VSTART] = '\021';
|
||||
|
||||
CHECK(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
pfd.fd = master;
|
||||
pfd.events = POLL_EVENTS;
|
||||
}
|
||||
END_SETUP()
|
||||
|
||||
FN_TEST(set_get_packet_mode)
|
||||
{
|
||||
int packet_mode;
|
||||
TEST_RES(ioctl(master, TIOCGPKT, &packet_mode), packet_mode == 0);
|
||||
TEST_ERRNO(ioctl(slave, TIOCGPKT, &packet_mode), ENOTTY);
|
||||
|
||||
packet_mode = 1;
|
||||
TEST_SUCC(ioctl(master, TIOCPKT, &packet_mode));
|
||||
TEST_ERRNO(ioctl(slave, TIOCPKT, &packet_mode), ENOTTY);
|
||||
|
||||
TEST_RES(ioctl(master, TIOCGPKT, &packet_mode), packet_mode == 1);
|
||||
TEST_ERRNO(ioctl(slave, TIOCGPKT, &packet_mode), ENOTTY);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(read_write)
|
||||
{
|
||||
char buf[1] = { 'a' };
|
||||
TEST_SUCC(write(master, buf, sizeof(buf)));
|
||||
char read_buf[128] = { 0 };
|
||||
TEST_RES(read(slave, read_buf, sizeof(read_buf)), _ret == 1);
|
||||
TEST_SUCC(write(slave, buf, sizeof(buf)));
|
||||
|
||||
TEST_RES(read(master, read_buf, 1), _ret == 1 && read_buf[0] == 0);
|
||||
TEST_RES(read(master, read_buf, 1), _ret == 1 && read_buf[0] == 0);
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 2 && read_buf[0] == 0 && read_buf[1] == 'a');
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(pkt_ioctl)
|
||||
{
|
||||
// Changing the EXTPROC flag on the slave (either setting or unsetting)
|
||||
// should generate a TIOCPKT_IOCTL control packet on the master.
|
||||
|
||||
struct termios term;
|
||||
TEST_SUCC(tcgetattr(slave, &term));
|
||||
term.c_lflag |= EXTPROC;
|
||||
TEST_SUCC(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLPRI | POLLOUT | POLLRDNORM));
|
||||
|
||||
char read_buf[128] = { 0 };
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 1 && read_buf[0] == TIOCPKT_IOCTL);
|
||||
|
||||
TEST_SUCC(tcgetattr(slave, &term));
|
||||
term.c_lflag &= ~EXTPROC;
|
||||
TEST_SUCC(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
char buf[1] = { 'a' };
|
||||
TEST_SUCC(write(slave, buf, sizeof(buf)));
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLPRI | POLLOUT | POLLRDNORM));
|
||||
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 1 && read_buf[0] == TIOCPKT_IOCTL);
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 2 && read_buf[0] == 0 && read_buf[1] == 'a');
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(pkt_nostop)
|
||||
{
|
||||
// Disabling IXON on the slave should generate a TIOCPKT_NOSTOP packet.
|
||||
|
||||
struct termios term;
|
||||
TEST_SUCC(tcgetattr(slave, &term));
|
||||
term.c_iflag &= ~IXON;
|
||||
TEST_SUCC(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLPRI | POLLOUT | POLLRDNORM));
|
||||
|
||||
char buf[1] = { 'a' };
|
||||
TEST_SUCC(write(slave, buf, sizeof(buf)));
|
||||
char read_buf[128] = { 0 };
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 1 && read_buf[0] == TIOCPKT_NOSTOP);
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLOUT | POLLRDNORM));
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 2 && read_buf[1] == 'a');
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(pkt_dostop)
|
||||
{
|
||||
// Enabling IXON on the slave should generate a TIOCPKT_DOSTOP packet.
|
||||
|
||||
struct termios term;
|
||||
TEST_SUCC(tcgetattr(slave, &term));
|
||||
term.c_iflag |= IXON;
|
||||
TEST_SUCC(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLPRI | POLLOUT | POLLRDNORM));
|
||||
|
||||
char read_buf[128] = { 0 };
|
||||
TEST_RES(read(master, read_buf, sizeof(read_buf)),
|
||||
_ret == 1 && read_buf[0] == TIOCPKT_DOSTOP);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(close_and_reopen_slave)
|
||||
{
|
||||
// Closing the pty slave will not reset the packet status.
|
||||
|
||||
struct termios term;
|
||||
TEST_SUCC(tcgetattr(slave, &term));
|
||||
term.c_lflag |= EXTPROC;
|
||||
TEST_SUCC(tcsetattr(slave, TCSANOW, &term));
|
||||
|
||||
TEST_RES(poll(&pfd, 1, -1),
|
||||
pfd.revents == (POLLIN | POLLPRI | POLLOUT | POLLRDNORM));
|
||||
|
||||
TEST_SUCC(close(slave));
|
||||
|
||||
int packet_mode;
|
||||
TEST_RES(ioctl(master, TIOCGPKT, &packet_mode), packet_mode == 1);
|
||||
|
||||
slave = TEST_SUCC(ioctl(master, TIOCGPTPEER, NULL));
|
||||
TEST_RES(ioctl(master, TIOCGPKT, &packet_mode), packet_mode == 1);
|
||||
|
||||
char buf[128];
|
||||
TEST_RES(read(master, buf, sizeof(buf)),
|
||||
_ret == 1 && buf[0] == TIOCPKT_IOCTL);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(no_data_read)
|
||||
{
|
||||
int flags = TEST_SUCC(fcntl(master, F_GETFL, 0));
|
||||
TEST_SUCC(fcntl(master, F_SETFL, flags | O_NONBLOCK));
|
||||
|
||||
char buf[1];
|
||||
TEST_ERRNO(read(master, buf, 1), EAGAIN);
|
||||
TEST_SUCC(close(slave));
|
||||
TEST_ERRNO(read(master, buf, 1), EIO);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_SETUP(cleanup)
|
||||
{
|
||||
CHECK(close(master));
|
||||
}
|
||||
END_SETUP()
|
||||
|
|
@ -55,6 +55,7 @@ pty/close_pty
|
|||
pty/open_ptmx
|
||||
pty/open_pty
|
||||
pty/pty_blocking
|
||||
pty/pty_packet_mode
|
||||
sched/sched_attr_getset
|
||||
sched/sched_param_getset
|
||||
sched/sched_param_idle
|
||||
|
|
|
|||
Loading…
Reference in New Issue