1 /*
2  * Rudimentary test suite used while implementing pselect(2).
3  */
4 
5 #include <assert.h>
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 
13 static int alarm_flag = 0;
14 
15 
16 static void
17 nop(int signo)
18 {
19 }
20 
21 
22 static void
23 set_alarm_flag(int signo)
24 {
25 	alarm_flag = 1;
26 }
27 
28 
29 
30 /*
31  * Very roughly exercise pselect(2).
32  */
33 
34 static void
35 test_pselect()
36 {
37 	fd_set rset;
38 	fd_set wset;
39 	sigset_t blockset;
40 	struct timespec timeout;
41 	int des[2];
42 	int r;
43 	char buf[1];
44 
45 	printf("test_pselect\n");
46 
47 	/*
48 	 * It is always possible to write to stdout (if not redirected).
49 	 */
50 
51 	FD_ZERO(&wset);
52 	FD_SET(1, &wset);
53 
54 	r = pselect(2, NULL, &wset, NULL, NULL, NULL);
55 	assert(r == 1);
56 	assert(FD_ISSET(1, &wset));
57 
58 	/*
59 	 * Write to a pipe and check a select on the read end does not block.
60 	 */
61 
62 	r = pipe(des);
63 	assert(r == 0);
64 
65 	FD_ZERO(&rset);
66 	FD_SET(des[0], &rset);
67 
68 	buf[0] = 'f';
69 	r = write(des[1], buf, 1);
70 	assert(r == 1);
71 
72 	r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
73 	assert(r == 1);
74 	assert(FD_ISSET(des[0], &rset));
75 
76 	r = read(des[0], buf, 1);
77 	assert(r == 1);
78 	assert(buf[0] == 'f');
79 
80 	/*
81 	 * Block until signal reception.
82 	 */
83 
84 	signal(SIGALRM, nop);
85 	alarm(1);
86 
87 	FD_ZERO(&rset);
88 	FD_SET(des[0], &rset);
89 
90 	r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
91 	assert(r == -1);
92 	assert(errno == EINTR);
93 
94 	/*
95 	 * Block until timeout.
96 	 */
97 
98 	FD_ZERO(&rset);
99 	FD_SET(des[0], &rset);
100 
101 	timeout.tv_sec = 1;
102 	timeout.tv_nsec = 0;
103 	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
104 	assert(r == 0);
105 
106 	/*
107 	 * When the timeout is zero, the call should not block.
108 	 */
109 
110 	timeout.tv_sec = 0;
111 	timeout.tv_nsec = 0;
112 	FD_ZERO(&rset);
113 	FD_SET(des[0], &rset);
114 
115 	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
116 	assert(r == 0);
117 
118 	/*
119 	 * When a signal is masked, the syscall is not interrupted and the
120 	 * signal is received on completion.
121 	 */
122 
123 	sigemptyset(&blockset);
124 	sigaddset(&blockset, SIGALRM);
125 
126 	signal(SIGALRM, set_alarm_flag);
127 	alarm(1);
128 
129 	timeout.tv_sec = 2;
130 	timeout.tv_nsec = 0;
131 	r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset);
132 	assert(r == 0);
133 	assert(alarm_flag);
134 
135 	close(des[0]);
136 	close(des[1]);
137 }
138 
139 
140 int
141 main(void)
142 {
143 	test_pselect();
144 	return (0);
145 }
146