ASSERT_STREQ(str, buf); \
} while (0)
+#define peekoffeq(fd, expected) \
+ do { \
+ socklen_t optlen = sizeof(int); \
+ int off = -1; \
+ int ret; \
+ \
+ ret = getsockopt(fd, SOL_SOCKET, SO_PEEK_OFF, \
+ &off, &optlen); \
+ ASSERT_EQ(0, ret); \
+ ASSERT_EQ((socklen_t)sizeof(off), optlen); \
+ ASSERT_EQ(expected, off); \
+ } while (0)
+
#define async \
for (pid_t pid = (pid = fork(), \
pid < 0 ? \
sendeq(self->fd[0], "aaaabbbb", 0);
recveq(self->fd[1], "aaaa", 4, MSG_PEEK);
+ peekoffeq(self->fd[1], 4);
recveq(self->fd[1], "bbbb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
+
+ recveq(self->fd[1], "aaaabbbb", 8, 0);
+ peekoffeq(self->fd[1], 0);
}
TEST_F(so_peek_off, two_chunks)
sendeq(self->fd[0], "bbbb", 0);
recveq(self->fd[1], "aaaa", 4, MSG_PEEK);
+ peekoffeq(self->fd[1], 4);
recveq(self->fd[1], "bbbb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
+
+ recveq(self->fd[1], "aaaa", 4, 0);
+ recveq(self->fd[1], "bbbb", 4, 0);
+ peekoffeq(self->fd[1], 0);
}
TEST_F(so_peek_off, two_chunks_blocking)
}
recveq(self->fd[1], "aaaa", 4, MSG_PEEK);
+ peekoffeq(self->fd[1], 4);
async {
usleep(1000);
/* goto again; -> goto redo; in unix_stream_read_generic(). */
recveq(self->fd[1], "bbbb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
+
+ recveq(self->fd[1], "aaaa", 4, 0);
+ recveq(self->fd[1], "bbbb", 4, 0);
+ peekoffeq(self->fd[1], 0);
}
TEST_F(so_peek_off, two_chunks_overlap)
{
sendeq(self->fd[0], "aaaa", 0);
recveq(self->fd[1], "aa", 2, MSG_PEEK);
+ peekoffeq(self->fd[1], 2);
sendeq(self->fd[0], "bbbb", 0);
if (variant->type == SOCK_STREAM) {
/* SOCK_STREAM tries to fill the buffer. */
recveq(self->fd[1], "aabb", 4, MSG_PEEK);
+ peekoffeq(self->fd[1], 6);
recveq(self->fd[1], "bb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
} else {
/* SOCK_DGRAM and SOCK_SEQPACKET returns at the skb boundary. */
recveq(self->fd[1], "aa", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 4);
recveq(self->fd[1], "bbbb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
}
+
+ recveq(self->fd[1], "aaaa", 4, 0);
+ recveq(self->fd[1], "bbbb", 4, 0);
+ peekoffeq(self->fd[1], 0);
}
TEST_F(so_peek_off, two_chunks_overlap_blocking)
}
recveq(self->fd[1], "aa", 2, MSG_PEEK);
+ peekoffeq(self->fd[1], 2);
async {
usleep(1000);
/* Even SOCK_STREAM does not wait if at least one byte is read. */
recveq(self->fd[1], "aa", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 4);
recveq(self->fd[1], "bbbb", 100, MSG_PEEK);
+ peekoffeq(self->fd[1], 8);
+
+ recveq(self->fd[1], "aaaa", 4, 0);
+ recveq(self->fd[1], "bbbb", 4, 0);
+ peekoffeq(self->fd[1], 0);
}
TEST_HARNESS_MAIN