summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2022-08-10 12:21:35 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2022-08-11 14:34:17 +0200
commit5bbf28be59b7c04f89399c22d3b5502a75e8e4f1 (patch)
tree5f4219bef41c28ec1b30345999da04c9493b8a1a
parent58f134b650133e0e8dff13a27957f2fcc2718f61 (diff)
downloadstrace-5bbf28be59b7c04f89399c22d3b5502a75e8e4f1.tar.gz
tests: expand so_error test checks
Check decoding with various optlen values. * tests/so_error.c: Add checks.
-rw-r--r--tests/so_error.c116
1 files changed, 73 insertions, 43 deletions
diff --git a/tests/so_error.c b/tests/so_error.c
index 03211ab91..f6bc2875e 100644
--- a/tests/so_error.c
+++ b/tests/so_error.c
@@ -47,58 +47,88 @@ reserve_ephemeral_port(void)
int
main(void)
{
- in_port_t port = reserve_ephemeral_port ();
-
- /*
- * Connect to the reserved port in NONBLOCK mode.
- * The port is reserved but not listened. So
- * the client doing "connect" gets error asynchronously.
- */
- int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (fd < 0)
- perror_msg_and_skip("socket AF_UNIX SOCK_STREAM");
-
- int flag = fcntl(fd, F_GETFL);
- if (flag < 0)
- perror_msg_and_skip("fcntl F_GETFL");
- flag |= O_NONBLOCK;
- if (fcntl(fd, F_SETFL, flag) < 0)
- perror_msg_and_skip("fcntl F_SETFL");
+ static const int sizes[] = {
+ -1, 0, 1,
+ sizeof(int) - 1,
+ sizeof(int),
+ sizeof(int) + 1,
+ };
- struct sockaddr_in addr = {
+ TAIL_ALLOC_OBJECT_CONST_PTR(int, sock_errno);
+ in_port_t port = reserve_ephemeral_port();
+ const struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
.sin_port = htons(port),
};
- if (connect(fd, (void *) &addr, sizeof(addr)) == 0)
- error_msg_and_skip("connect unexpectedly succeeded");
- if (errno != EINPROGRESS)
- perror_msg_and_skip("connect failed for unexpected reason");
- struct timeval to = {
- .tv_sec = 1,
- .tv_usec = 0,
- };
- fd_set wfds;
- FD_ZERO(&wfds);
- FD_SET(fd, &wfds);
- if (select(fd + 1, NULL, &wfds, NULL, &to) < 0)
- perror_msg_and_skip("select");
+ for (size_t i = 0; i < ARRAY_SIZE(sizes); i++) {
+ /*
+ * Connect to the reserved port in NONBLOCK mode.
+ * The port is reserved but not listened. So
+ * the client doing "connect" gets error asynchronously.
+ */
+ int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0)
+ perror_msg_and_skip("socket AF_UNIX SOCK_STREAM");
+
+ int flag = fcntl(fd, F_GETFL);
+ if (flag < 0)
+ perror_msg_and_skip("fcntl F_GETFL");
+ flag |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flag) < 0)
+ perror_msg_and_skip("fcntl F_SETFL");
+
+ if (connect(fd, (void *) &addr, sizeof(addr)) == 0)
+ error_msg_and_skip("connect unexpectedly succeeded");
+ if (errno != EINPROGRESS)
+ perror_msg_and_skip("connect failed for unexpected reason");
+
+ struct timeval to = {
+ .tv_sec = 1,
+ .tv_usec = 0,
+ };
+ fd_set wfds;
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+ if (select(fd + 1, NULL, &wfds, NULL, &to) < 0)
+ perror_msg_and_skip("select");
+
+ *sock_errno = 0xbadc0ded;
+ socklen_t optlen = sizes[i];
+ long rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, sock_errno,
+ &optlen);
+ const char *errstr = sprintrc(rc);
+ if (sizes[i] > 0 && rc < 0)
+ perror_msg_and_skip("getsockopt");
+ if (sizes[i] >= (int) sizeof(*sock_errno)
+ && *sock_errno != ECONNREFUSED) {
+ errno = *sock_errno;
+ perror_msg_and_skip("unexpected socket error");
+ }
+ if (sizes[i] >= (int) sizeof(*sock_errno)
+ && optlen != sizeof(*sock_errno)) {
+ error_msg_and_skip("unexpected data size for error"
+ " option: %d", optlen);
+ }
+
+ printf("getsockopt(%d, SOL_SOCKET, SO_ERROR, ", fd);
+ if (sizes[i] <= 0) {
+ printf("%p, [%d]", sock_errno, sizes[i]);
+ } else if (sizes[i] < (int) sizeof(*sock_errno)) {
+ print_quoted_hex(sock_errno, sizes[i]);
+ printf(", [%u]", sizes[i]);
+ } else if (sizes[i] == sizeof(*sock_errno)) {
+ printf("[ECONNREFUSED], [%zu]", sizeof(*sock_errno));
+ } else {
+ printf("[ECONNREFUSED], [%u => %zu]",
+ sizes[i], sizeof(*sock_errno));
+ }
+ printf(") = %s\n", errstr);
- int sock_errno;
- socklen_t optlen = sizeof(sock_errno);
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen) < 0)
- perror_msg_and_skip("getsockopt");
- if (sock_errno != ECONNREFUSED) {
- errno = sock_errno;
- perror_msg_and_skip("unexpected socket error");
+ close(fd);
}
- if (optlen != sizeof(sock_errno))
- error_msg_and_skip("unexpected data size for error option: %d",
- optlen);
- printf("getsockopt(%d, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [%u]) = 0\n",
- fd, optlen);
puts("+++ exited with 0 +++");
return 0;
}