Project

General

Profile

Bug #895 » tselect.c

nthery, 12/26/2007 06:18 PM

 
/*
* Rudimentary test suite used while implementing pselect(2).
*/

#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


static int alarm_flag = 0;


static void
nop(int signo)
{
}


static void
set_alarm_flag(int signo)
{
alarm_flag = 1;
}


/*
* Try to detect regressions in select(2).
*/

static void
test_select()
{
fd_set rset;
fd_set wset;
struct timeval timeout;
int des[2];
int r;
char buf[1];

printf("test_select\n");

/*
* It is always possible to write to stdout (if not redirected).
*/

FD_ZERO(&wset);
FD_SET(1, &wset);

r = select(2, NULL, &wset, NULL, NULL);
assert(r == 1);
assert(FD_ISSET(1, &wset));

/*
* Write to a pipe and check a select on the read end does not block.
*/

r = pipe(des);
assert(r == 0);

FD_ZERO(&rset);
FD_SET(des[0], &rset);

buf[0] = 'f';
r = write(des[1], buf, 1);
assert(r == 1);

r = select(des[0]+1, &rset, NULL, NULL, NULL);
assert(r == 1);
assert(FD_ISSET(des[0], &rset));

r = read(des[0], buf, 1);
assert(r == 1);
assert(buf[0] == 'f');

/*
* Block until signal reception.
*/

signal(SIGALRM, nop);
alarm(1);

FD_ZERO(&rset);
FD_SET(des[0], &rset);

r = select(des[0]+1, &rset, NULL, NULL, NULL);
assert(r == -1);
assert(errno == EINTR);

/*
* Block until timeout.
*/

FD_ZERO(&rset);
FD_SET(des[0], &rset);

timeout.tv_sec = 1;
timeout.tv_usec = 0;
r = select(des[0]+1, &rset, NULL, NULL, &timeout);
assert(r == 0);

/*
* When the timeout is zero, the call should not block.
*/

timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(des[0], &rset);

r = select(des[0]+1, &rset, NULL, NULL, &timeout);
assert(r == 0);

close(des[0]);
close(des[1]);
}


/*
* Very roughly exercise pselect(2).
*/

static void
test_pselect()
{
fd_set rset;
fd_set wset;
sigset_t blockset;
struct timespec timeout;
int des[2];
int r;
char buf[1];

printf("test_pselect\n");

/*
* It is always possible to write to stdout (if not redirected).
*/

FD_ZERO(&wset);
FD_SET(1, &wset);

r = pselect(2, NULL, &wset, NULL, NULL, NULL);
assert(r == 1);
assert(FD_ISSET(1, &wset));

/*
* Write to a pipe and check a select on the read end does not block.
*/

r = pipe(des);
assert(r == 0);

FD_ZERO(&rset);
FD_SET(des[0], &rset);

buf[0] = 'f';
r = write(des[1], buf, 1);
assert(r == 1);

r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
assert(r == 1);
assert(FD_ISSET(des[0], &rset));

r = read(des[0], buf, 1);
assert(r == 1);
assert(buf[0] == 'f');

/*
* Block until signal reception.
*/

signal(SIGALRM, nop);
alarm(1);

FD_ZERO(&rset);
FD_SET(des[0], &rset);

r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
assert(r == -1);
assert(errno == EINTR);

/*
* Block until timeout.
*/

FD_ZERO(&rset);
FD_SET(des[0], &rset);

timeout.tv_sec = 1;
timeout.tv_nsec = 0;
r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
assert(r == 0);

/*
* When the timeout is zero, the call should not block.
*/

timeout.tv_sec = 0;
timeout.tv_nsec = 0;
FD_ZERO(&rset);
FD_SET(des[0], &rset);

r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
assert(r == 0);

/*
* When a signal is masked, the syscall is not interrupted and the
* signal is received on completion.
*/

sigemptyset(&blockset);
sigaddset(&blockset, SIGALRM);
signal(SIGALRM, set_alarm_flag);
alarm(1);

timeout.tv_sec = 2;
timeout.tv_nsec = 0;
r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset);
assert(r == 0);
assert(alarm_flag);

close(des[0]);
close(des[1]);
}


int
main(void)
{
test_select();
test_pselect();
return (0);
}
(2-2/3)