xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/select/select04.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2020 Linaro Limited. All rights reserved.
4*49cdfc7eSAndroid Build Coastguard Worker  * Author: Viresh Kumar <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  */
6*49cdfc7eSAndroid Build Coastguard Worker 
7*49cdfc7eSAndroid Build Coastguard Worker /*\
8*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  * Test to check if fd set bits are cleared by select().
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * [Algorithm]
13*49cdfc7eSAndroid Build Coastguard Worker  *  - Check that writefds flag is cleared on full pipe
14*49cdfc7eSAndroid Build Coastguard Worker  *  - Check that readfds flag is cleared on empty pipe
15*49cdfc7eSAndroid Build Coastguard Worker  */
16*49cdfc7eSAndroid Build Coastguard Worker 
17*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include "select_var.h"
23*49cdfc7eSAndroid Build Coastguard Worker 
24*49cdfc7eSAndroid Build Coastguard Worker static fd_set readfds_pipe, writefds_pipe;
25*49cdfc7eSAndroid Build Coastguard Worker static int fd_empty[2], fd_full[2];
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker static struct tcases {
28*49cdfc7eSAndroid Build Coastguard Worker 	int *fd;
29*49cdfc7eSAndroid Build Coastguard Worker 	fd_set *readfds;
30*49cdfc7eSAndroid Build Coastguard Worker 	fd_set *writefds;
31*49cdfc7eSAndroid Build Coastguard Worker 	char *desc;
32*49cdfc7eSAndroid Build Coastguard Worker } tests[] = {
33*49cdfc7eSAndroid Build Coastguard Worker 	{&fd_empty[0], &readfds_pipe, NULL, "No data to read"},
34*49cdfc7eSAndroid Build Coastguard Worker 	{&fd_full[1], NULL, &writefds_pipe, "No space to write"},
35*49cdfc7eSAndroid Build Coastguard Worker };
36*49cdfc7eSAndroid Build Coastguard Worker 
run(unsigned int n)37*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int n)
38*49cdfc7eSAndroid Build Coastguard Worker {
39*49cdfc7eSAndroid Build Coastguard Worker 	struct tcases *tc = &tests[n];
40*49cdfc7eSAndroid Build Coastguard Worker 	struct timeval timeout = {.tv_sec = 0, .tv_usec = 1000};
41*49cdfc7eSAndroid Build Coastguard Worker 
42*49cdfc7eSAndroid Build Coastguard Worker 	FD_SET(fd_empty[0], &readfds_pipe);
43*49cdfc7eSAndroid Build Coastguard Worker 	FD_SET(fd_full[1], &writefds_pipe);
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker 	TEST(do_select(*tc->fd + 1, tc->readfds, tc->writefds, NULL, &timeout));
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET) {
48*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "%s: select() should have timed out", tc->desc);
49*49cdfc7eSAndroid Build Coastguard Worker 		return;
50*49cdfc7eSAndroid Build Coastguard Worker 	}
51*49cdfc7eSAndroid Build Coastguard Worker 
52*49cdfc7eSAndroid Build Coastguard Worker 	if ((tc->readfds && FD_ISSET(*tc->fd, tc->readfds)) ||
53*49cdfc7eSAndroid Build Coastguard Worker 	    (tc->writefds && FD_ISSET(*tc->fd, tc->writefds))) {
54*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "%s: select() didn't clear the fd set", tc->desc);
55*49cdfc7eSAndroid Build Coastguard Worker 		return;
56*49cdfc7eSAndroid Build Coastguard Worker 	}
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "%s: select() cleared the fd set", tc->desc);
59*49cdfc7eSAndroid Build Coastguard Worker }
60*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)61*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
62*49cdfc7eSAndroid Build Coastguard Worker {
63*49cdfc7eSAndroid Build Coastguard Worker 	int buf = 0;
64*49cdfc7eSAndroid Build Coastguard Worker 
65*49cdfc7eSAndroid Build Coastguard Worker 	select_info();
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PIPE(fd_empty);
68*49cdfc7eSAndroid Build Coastguard Worker 	FD_ZERO(&readfds_pipe);
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_PIPE2(fd_full, O_NONBLOCK);
71*49cdfc7eSAndroid Build Coastguard Worker 	FD_ZERO(&writefds_pipe);
72*49cdfc7eSAndroid Build Coastguard Worker 
73*49cdfc7eSAndroid Build Coastguard Worker 	/* Make the write buffer full for fd_full */
74*49cdfc7eSAndroid Build Coastguard Worker 	do {
75*49cdfc7eSAndroid Build Coastguard Worker 		TEST(write(fd_full[1], &buf, sizeof(buf)));
76*49cdfc7eSAndroid Build Coastguard Worker 	} while (TST_RET != -1);
77*49cdfc7eSAndroid Build Coastguard Worker 
78*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_ERR != EAGAIN)
79*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL | TTERRNO, "write() failed with unexpected error");
80*49cdfc7eSAndroid Build Coastguard Worker }
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
83*49cdfc7eSAndroid Build Coastguard Worker 	.test = run,
84*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = ARRAY_SIZE(tests),
85*49cdfc7eSAndroid Build Coastguard Worker 	.test_variants = TEST_VARIANTS,
86*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
87*49cdfc7eSAndroid Build Coastguard Worker 	.needs_tmpdir = 1,
88*49cdfc7eSAndroid Build Coastguard Worker };
89