22static void fail_operation(
const char* operation) {
23 printf(
"\nepoll PTY: %s failed (errno=%d)\n", operation, errno);
27static void expect_read_edges(
int writer,
int reader,
char first,
char second) {
28 int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
30 fail_operation(
"create read epoll");
32 struct epoll_event requested = {.events = EPOLLIN | EPOLLET, .data.u64 = 0x505459};
33 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD,
reader, &requested))
34 fail_operation(
"register reader");
36 struct epoll_event result = {0};
37 if (epoll_wait(epoll_fd, &result, 1, 0) != 0)
38 fail_operation(
"initial read readiness");
40 if (write(writer, &first, 1) != 1 || epoll_wait(epoll_fd, &result, 1, 1000) != 1 ||
41 !(result.events & EPOLLIN) || result.data.u64 != requested.data.u64)
42 fail_operation(
"first write/readiness");
45 if (read(
reader, &received, 1) != 1 || received != first ||
46 epoll_wait(epoll_fd, &result, 1, 0) != 0)
47 fail_operation(
"first read/drain");
49 if (write(writer, &second, 1) != 1 || epoll_wait(epoll_fd, &result, 1, 1000) != 1 ||
50 !(result.events & EPOLLIN))
51 fail_operation(
"second write/readiness");
53 if (read(
reader, &received, 1) != 1 || received != second)
54 fail_operation(
"second read");
59static void expect_writable(
int descriptor) {
60 int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
62 fail_operation(
"create write epoll");
64 struct epoll_event requested = {.events = EPOLLOUT, .data.fd = descriptor};
65 struct epoll_event result = {0};
66 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, descriptor, &requested) ||
67 epoll_wait(epoll_fd, &result, 1, 0) != 1 || !(result.events & EPOLLOUT) ||
68 result.data.fd != descriptor)
69 fail_operation(
"write readiness");
74void test_epoll_pty(
void) {
75 printf(
"Testing epoll PTY readiness...");
78 int master = posix_openpt(O_RDWR | O_NONBLOCK | O_NOCTTY);
79 unsigned int terminal = 0;
80 if (master < 0 || ioctl(master, TIOCGPTN, &terminal))
81 fail_operation(
"open master");
84 if (snprintf(path,
sizeof(path),
"/dev/pts/%u", terminal) >= (
int)
sizeof(path))
85 fail_operation(
"slave path");
86 int slave = open(path, O_RDWR | O_NONBLOCK | O_NOCTTY);
88 fail_operation(
"open slave");
90 struct termios attributes;
91 if (tcgetattr(slave, &attributes))
92 fail_operation(
"tcgetattr");
93 cfmakeraw(&attributes);
94 if (tcsetattr(slave, TCSANOW, &attributes))
95 fail_operation(
"tcsetattr");
97 expect_writable(master);
98 expect_writable(slave);
99 expect_read_edges(slave, master,
'a',
'\n');
100 expect_read_edges(master, slave,
'c',
'd');