#include #include #include #include #include #include #include "test.h" #include "tests.h" typedef struct priv PRIV; struct priv { int nbr; int nbw; int rfirst; int lfd; int cfd; } ; #define XFER 20000 static unsigned char data1[XFER]; static unsigned char data2[XFER]; static void set_nbio(int fd) { fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK); } static void run_big_writes_run_l(void *pv) { PRIV *p; pid_t mypid; int fd; int fd2; int i; char c; int o; struct pollfd pfd; p = pv; mypid = getpid(); printf("big-writes: listener is %d\n",(int)mypid); printf("big-writes: listener establishing connection\n"); mustwrite(p->lfd,&mypid,sizeof(pid_t)); sleep(1); SET_PIDCONN(fd,PIDCONN_LISTEN,0,0); mustwrite(p->lfd,"",1); SET_PIDCONN(fd2,PIDCONN_ACCEPT,fd,0); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); if (p->nbw) set_nbio(fd2); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); printf("big-writes: listener writing\n"); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); sleep(p->rfirst?2:1); if (p->nbw) { o = 0; while (o < XFER) { i = write(fd2,data1+o,XFER-o); if (i < 0) { if (errno == EWOULDBLOCK) { pfd.fd = fd2; pfd.events = POLLOUT | POLLWRNORM; i = poll(&pfd,1,INFTIM); if (i >= 0) continue; if (errno == EINTR) continue; printf("big-writes: polling for NBIO write to connection (at %d): %s\n",o,strerror(errno)); test_fail(); return; } printf("big-writes: write (at %d) failed: %s\n",o,strerror(errno)); test_fail(); return; } o += i; } } else { i = write(fd2,data1,XFER); if (i < 0) { printf("big-writes: write to connection: %s\n",strerror(errno)); test_fail(); } if (i != XFER) { printf("big-writes: write to connection returned %d, expected %d\n",i,XFER); test_fail(); } } mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); printf("big-writes: listener done\n"); sleep(1); } static void run_big_writes_run_c(void *pv) { PRIV *p; pid_t lpid; int fd; char c; int o; int i; struct pollfd pfd; p = pv; printf("big-writes: connecter is %d\n",(int)getpid()); mustread(p->cfd,&lpid,sizeof(pid_t)); printf("big-writes: connecter establishing connection to %d\n",(int)lpid); sleep(1); mustread(p->cfd,&c,1); SET_PIDCONN(fd,PIDCONN_CONNECT,0,lpid); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); if (p->nbr) set_nbio(fd); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); printf("big-writes: connecter reading\n"); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); sleep(p->rfirst?1:2); bzero(&data2[0],XFER); if (p->nbr) { o = 0; while (o < XFER) { i = read(fd,data2+o,XFER-o); if (i < 0) { if (errno == EWOULDBLOCK) { pfd.fd = fd; pfd.events = POLLIN | POLLRDNORM; i = poll(&pfd,1,INFTIM); if (i >= 0) continue; if (errno == EINTR) continue; printf("big-writes: polling for NBIO read from connection (at %d): %s\n",o,strerror(errno)); test_fail(); return; } printf("big-writes: read (at %d) failed: %s\n",o,strerror(errno)); test_fail(); return; } o += i; } } else { i = read(fd,data2,XFER); if (i < 0) { printf("big-writes: read from connection: %s\n",strerror(errno)); test_fail(); } if (i != XFER) { printf("big-writes: read from connection returned %d, expected %d\n",i,XFER); test_fail(); } } i = 0; for (o=0;o= 10) { printf("...more\n"); break; } printf("wrote [%d] = %02x, read [%d] = %02x\n", o,data1[o],o,data2[o]); i ++; } } mustwrite(p->cfd,"",1); mustread(p->cfd,&c,1); printf("big-writes: connecter done\n"); sleep(1); } static void do_big_writes(int nbr, int nbw, int rfirst) { PRIV p; KID *kl; KID *kc; printf("big-writes: >>>>>>>> nbr=%d nbw=%d rfirst=%d\n",nbr,nbw,rfirst); local_socketpair(&p.lfd,&p.cfd); p.nbr = nbr; p.nbw = nbw; p.rfirst = rfirst; kl = fork_kid(&run_big_writes_run_l,&p); kc = fork_kid(&run_big_writes_run_c,&p); close(p.lfd); close(p.cfd); reap_kid(kl); reap_kid(kc); } static void setup_data(void) { int i; srandom(1); for (i=XFER-1;i>=0;i--) data1[i] = (random() >> 22) & 0xff; } static void run_big_writes(void) { setup_data(); do_big_writes(0,0,0); do_big_writes(0,0,1); do_big_writes(0,1,0); do_big_writes(0,1,1); do_big_writes(1,0,0); do_big_writes(1,0,1); do_big_writes(1,1,0); do_big_writes(1,1,1); printf("big-writes: done\n"); } const TEST test_big_writes = { &run_big_writes };