/* * Parameterized test function bodies */ void test_eagain(size_t sndbufsize, size_t rcvbufsize) { int i; int sv[2]; const size_t totalsize = (sndbufsize + rcvbufsize) * 2; const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; char sndbuf[pktsize]; char recv_buf[pktsize]; ssize_t ssize, rsize; /* setup the socket pair */ do_socketpair_nonblocking(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); bzero(sndbuf, pktsize); /* Send data until we get EAGAIN */ for(i=0; i < totalsize / pktsize; i++) { ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); if (ssize == -1) { if (errno == EAGAIN) atf_tc_pass(); else { perror("send"); atf_tc_fail("send returned < 0 but not EAGAIN"); } } } atf_tc_fail("Never got EAGAIN"); }
ATF_TC_BODY(send_recv_nonblocking, tc) { int s; int sv[2]; const int bufsize = 64; const char *data = "data"; char recv_buf[bufsize]; size_t datalen; ssize_t ssize, rsize; /* setup the socket pair */ do_socketpair_nonblocking(sv); /* Verify that there is nothing to receive */ rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); ATF_CHECK_EQ(EAGAIN, errno); ATF_CHECK_EQ(-1, rsize); /* send and receive a small packet */ datalen = strlen(data) + 1; /* +1 for the null */ ssize = send(sv[0], data, datalen, MSG_EOR); if (ssize < 0) { perror("send"); atf_tc_fail("send returned < 0"); } ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", datalen, ssize); rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); ATF_CHECK_EQ(datalen, rsize); }
ATF_TC_BODY(rcvbuf_oversized, tc) { int i; int sv[2]; const ssize_t pktsize = 1024; const size_t sndbufsize = 8192; const size_t rcvbufsize = 131072; const size_t geometric_mean_bufsize = 32768; const int numpkts = geometric_mean_bufsize / pktsize; char sndbuf[pktsize]; char recv_buf[pktsize]; ssize_t ssize, rsize; /* setup the socket pair */ do_socketpair_nonblocking(sv); ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); /* * Send and receive packets that are collectively greater than the send * buffer, but less than the receive buffer */ for (i=0; i < numpkts; i++) { /* Fill the buffer */ memset(sndbuf, i, pktsize); /* send the packet */ ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); if (ssize < 0) { perror("send"); atf_tc_fail("send returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", pktsize, ssize); /* Receive it */ rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); if (rsize < 0) { perror("recv"); atf_tc_fail("recv returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", pktsize, rsize); /* Verify the contents */ ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize), "Received data miscompare"); } /* Trying to receive again should return EAGAIN */ rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); ATF_CHECK_EQ(EAGAIN, errno); ATF_CHECK_EQ(-1, rsize); }
void test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) { int s; int sv[2]; const size_t pktsize = bufsize / 2; char sndbuf[pktsize]; char recv_buf[pktsize]; ssize_t ssize, rsize; /* setup the socket pair */ if (blocking) do_socketpair(sv); else do_socketpair_nonblocking(sv); /* Setup the buffers */ s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); ATF_REQUIRE_EQ(0, s); s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); ATF_REQUIRE_EQ(0, s); /* Fill the send buffer */ bzero(sndbuf, pktsize); /* send and receive the packet */ ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); if (ssize < 0) { perror("send"); atf_tc_fail("send returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", pktsize, ssize); rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); if (rsize < 0) { perror("recv"); atf_tc_fail("recv returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", pktsize, rsize); }
ATF_TC_BODY(emsgsize_nonblocking, tc) { int sv[2]; const size_t sndbufsize = 8192; const size_t rcvbufsize = 8192; const size_t pktsize = (sndbufsize + rcvbufsize) * 2; char sndbuf[pktsize]; ssize_t ssize; /* setup the socket pair */ do_socketpair_nonblocking(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); ATF_CHECK_EQ(EMSGSIZE, errno); ATF_CHECK_EQ(-1, ssize); }
void test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize) { int s, num_sent, num_received; int sv[2]; const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; int numpkts; char sndbuf[pktsize]; char rcvbuf[pktsize]; char comparebuf[pktsize]; ssize_t ssize, rsize; bool currently_sending = true; /* setup the socket pair */ do_socketpair_nonblocking(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); /* Send a total amount of data comfortably greater than the buffers */ numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; for (num_sent=0, num_received=0; num_sent < numpkts || num_received < numpkts; ) { if (currently_sending && num_sent < numpkts) { /* The simulated sending process */ /* fill the buffer */ memset(sndbuf, num_sent, pktsize); ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); if (ssize < 0) { /* * XXX: This is bug-compatible with the kernel. * The kernel returns EMSGSIZE when it should * return EAGAIN */ if (errno == EAGAIN || errno == EMSGSIZE) currently_sending = false; else { perror("send"); atf_tc_fail("send failed"); } } else { ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", pktsize, ssize); num_sent++; } } else { /* The simulated receiving process */ rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL); if (rsize < 0) { if (errno == EAGAIN) { currently_sending = true; ATF_REQUIRE_MSG(num_sent < numpkts, "Packets were lost!"); } else { perror("recv"); atf_tc_fail("recv failed"); } } else { ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=recv(...) but got %zd", pktsize, rsize); memset(comparebuf, num_received, pktsize); ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf, pktsize), "Received data miscompare"); num_received++; } } } }