tselect.c

nthery, 12/26/2007 06:18 pm

Download (3.6 kB)

 
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
 * Try to detect regressions in select(2).
31
 */
32
33
static void
34
test_select()
35
{
36
        fd_set rset;
37
        fd_set wset;
38
        struct timeval timeout;
39
        int des[2];
40
        int r;
41
        char buf[1];
42
43
        printf("test_select\n");
44
45
        /*
46
         * It is always possible to write to stdout (if not redirected).
47
         */
48
49
        FD_ZERO(&wset);
50
        FD_SET(1, &wset);
51
52
        r = select(2, NULL, &wset, NULL, NULL);
53
        assert(r == 1);
54
        assert(FD_ISSET(1, &wset));
55
56
        /*
57
         * Write to a pipe and check a select on the read end does not block.
58
         */
59
60
        r = pipe(des);
61
        assert(r == 0);
62
63
        FD_ZERO(&rset);
64
        FD_SET(des[0], &rset);
65
66
        buf[0] = 'f';
67
        r = write(des[1], buf, 1);
68
        assert(r == 1);
69
70
        r = select(des[0]+1, &rset, NULL, NULL, NULL);
71
        assert(r == 1);
72
        assert(FD_ISSET(des[0], &rset));
73
74
        r = read(des[0], buf, 1);
75
        assert(r == 1);
76
        assert(buf[0] == 'f');
77
78
        /*
79
         * Block until signal reception.
80
         */
81
82
        signal(SIGALRM, nop);
83
        alarm(1);
84
85
        FD_ZERO(&rset);
86
        FD_SET(des[0], &rset);
87
88
        r = select(des[0]+1, &rset, NULL, NULL, NULL);
89
        assert(r == -1);
90
        assert(errno == EINTR);
91
92
        /*
93
         * Block until timeout.
94
         */
95
96
        FD_ZERO(&rset);
97
        FD_SET(des[0], &rset);
98
99
        timeout.tv_sec = 1;
100
        timeout.tv_usec = 0;
101
        r = select(des[0]+1, &rset, NULL, NULL, &timeout);
102
        assert(r == 0);
103
104
        /*
105
         * When the timeout is zero, the call should not block.
106
         */
107
108
        timeout.tv_sec = 0;
109
        timeout.tv_usec = 0;
110
        FD_ZERO(&rset);
111
        FD_SET(des[0], &rset);
112
113
        r = select(des[0]+1, &rset, NULL, NULL, &timeout);
114
        assert(r == 0);
115
116
        close(des[0]);
117
        close(des[1]);
118
}
119
120
121
/*
122
 * Very roughly exercise pselect(2).
123
 */
124
125
static void
126
test_pselect()
127
{
128
        fd_set rset;
129
        fd_set wset;
130
        sigset_t blockset;
131
        struct timespec timeout;
132
        int des[2];
133
        int r;
134
        char buf[1];
135
136
        printf("test_pselect\n");
137
138
        /*
139
         * It is always possible to write to stdout (if not redirected).
140
         */
141
142
        FD_ZERO(&wset);
143
        FD_SET(1, &wset);
144
145
        r = pselect(2, NULL, &wset, NULL, NULL, NULL);
146
        assert(r == 1);
147
        assert(FD_ISSET(1, &wset));
148
149
        /*
150
         * Write to a pipe and check a select on the read end does not block.
151
         */
152
153
        r = pipe(des);
154
        assert(r == 0);
155
156
        FD_ZERO(&rset);
157
        FD_SET(des[0], &rset);
158
159
        buf[0] = 'f';
160
        r = write(des[1], buf, 1);
161
        assert(r == 1);
162
163
        r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
164
        assert(r == 1);
165
        assert(FD_ISSET(des[0], &rset));
166
167
        r = read(des[0], buf, 1);
168
        assert(r == 1);
169
        assert(buf[0] == 'f');
170
171
        /*
172
         * Block until signal reception.
173
         */
174
175
        signal(SIGALRM, nop);
176
        alarm(1);
177
178
        FD_ZERO(&rset);
179
        FD_SET(des[0], &rset);
180
181
        r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
182
        assert(r == -1);
183
        assert(errno == EINTR);
184
185
        /*
186
         * Block until timeout.
187
         */
188
189
        FD_ZERO(&rset);
190
        FD_SET(des[0], &rset);
191
192
        timeout.tv_sec = 1;
193
        timeout.tv_nsec = 0;
194
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
195
        assert(r == 0);
196
197
        /*
198
         * When the timeout is zero, the call should not block.
199
         */
200
201
        timeout.tv_sec = 0;
202
        timeout.tv_nsec = 0;
203
        FD_ZERO(&rset);
204
        FD_SET(des[0], &rset);
205
206
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
207
        assert(r == 0);
208
209
        /*
210
         * When a signal is masked, the syscall is not interrupted and the
211
         * signal is received on completion.
212
         */
213
214
        sigemptyset(&blockset);
215
        sigaddset(&blockset, SIGALRM);
216
        
217
        signal(SIGALRM, set_alarm_flag);
218
        alarm(1);
219
220
        timeout.tv_sec = 2;
221
        timeout.tv_nsec = 0;
222
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset);
223
        assert(r == 0);
224
        assert(alarm_flag);
225
226
        close(des[0]);
227
        close(des[1]);
228
}
229
230
231
int
232
main(void)
233
{
234
        test_select();
235
        test_pselect();
236
        return (0);
237
}