1 /*
2  * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "_main.h"
8 
happy_path(const int family,const char * family_s,const int type,const char * type_s,const int proto,const char * proto_s)9 static void happy_path(
10 	const int family, const char *family_s,
11 	const int type, const char *type_s,
12 	const int proto, const char *proto_s
13 )
14 {
15 	int res;
16 	int sv[2] = {-1, -1};
17 
18 	const char *expected_msg = "Hello, socketpair(2) world!";
19 	const unsigned int expected_msg_len = strlen(expected_msg);
20 	char actual_msg[32];
21 	size_t actual_msg_len;
22 	struct iovec iovec;
23 	struct msghdr msghdr;
24 
25 	LOG_DBG("calling socketpair(%u, %u, %u, %p)", family, type, proto, sv);
26 	res = socketpair(family, type, proto, sv);
27 	zassert_true(res == -1 || res == 0,
28 		     "socketpair returned an unspecified value");
29 	zassert_equal(res, 0, "socketpair failed");
30 	LOG_DBG("sv: {%d, %d}", sv[0], sv[1]);
31 
32 	socklen_t len;
33 
34 	/* sockets are bidirectional. test functions from both ends */
35 	for (int i = 0; i < 2; ++i) {
36 
37 		/*
38 		 * Test with send() / recv()
39 		 */
40 
41 		res = send(sv[i], expected_msg, expected_msg_len, 0);
42 
43 		zassert_not_equal(res, -1, "send() failed: %d", errno);
44 		actual_msg_len = res;
45 		zassert_equal(actual_msg_len, expected_msg_len,
46 				  "did not send entire message");
47 
48 		memset(actual_msg, 0, sizeof(actual_msg));
49 
50 		res = recv(sv[(!i) & 1], actual_msg, sizeof(actual_msg), 0);
51 
52 		zassert_not_equal(res, -1, "recv() failed: %d", errno);
53 		actual_msg_len = res;
54 		zassert_equal(actual_msg_len, expected_msg_len,
55 			      "wrong return value");
56 
57 		zassert_true(strncmp(expected_msg, actual_msg,
58 			actual_msg_len) == 0,
59 			"the wrong message was passed through the socketpair");
60 
61 		/*
62 		 * Test with sendto(2) / recvfrom(2)
63 		 */
64 
65 		res = sendto(sv[i], expected_msg, expected_msg_len, 0, NULL, 0);
66 
67 		zassert_not_equal(res, -1, "sendto() failed: %d", errno);
68 		actual_msg_len = res;
69 		zassert_equal(actual_msg_len, expected_msg_len,
70 				  "did not sendto entire message");
71 
72 		memset(actual_msg, 0, sizeof(actual_msg));
73 
74 		len = 0;
75 		res = recvfrom(sv[(!i) & 1], actual_msg, sizeof(actual_msg), 0,
76 			NULL, &len);
77 		zassert_true(res >= 0, "recvfrom() failed: %d", errno);
78 		actual_msg_len = res;
79 		zassert_equal(actual_msg_len, expected_msg_len,
80 			      "wrong return value");
81 
82 		zassert_true(strncmp(expected_msg, actual_msg,
83 			actual_msg_len) == 0,
84 			"the wrong message was passed through the socketpair");
85 
86 		/*
87 		 * Test with sendmsg(2) / recv(2) - Zephyr lacks recvmsg atm
88 		 */
89 
90 		memset(&msghdr, 0, sizeof(msghdr));
91 		msghdr.msg_iov = &iovec;
92 		msghdr.msg_iovlen = 1;
93 		iovec.iov_base = (void *)expected_msg;
94 		iovec.iov_len = expected_msg_len;
95 
96 		res = sendmsg(sv[i], &msghdr, 0);
97 
98 		zassert_not_equal(res, -1, "sendmsg() failed: %d", errno);
99 		actual_msg_len = res;
100 		zassert_equal(actual_msg_len, expected_msg_len,
101 				  "did not sendmsg entire message");
102 
103 		res = recv(sv[(!i) & 1], actual_msg, sizeof(actual_msg), 0);
104 
105 		zassert_not_equal(res, -1, "recv() failed: %d", errno);
106 		actual_msg_len = res;
107 		zassert_equal(actual_msg_len, expected_msg_len,
108 			      "wrong return value");
109 
110 		zassert_true(strncmp(expected_msg, actual_msg,
111 			actual_msg_len) == 0,
112 			"the wrong message was passed through the socketpair");
113 	}
114 
115 	res = close(sv[0]);
116 	zassert_equal(res, 0, "close failed");
117 
118 	res = close(sv[1]);
119 	zassert_equal(res, 0, "close failed");
120 }
121 
ZTEST_USER(net_socketpair,test_AF_LOCAL_SOCK_STREAM_0)122 ZTEST_USER(net_socketpair, test_AF_LOCAL_SOCK_STREAM_0)
123 {
124 	happy_path(
125 		AF_LOCAL, "AF_LOCAL",
126 		SOCK_STREAM, "SOCK_STREAM",
127 		0, "0"
128 	);
129 }
130 
ZTEST_USER(net_socketpair,test_AF_UNIX_SOCK_STREAM_0)131 ZTEST_USER(net_socketpair, test_AF_UNIX_SOCK_STREAM_0)
132 {
133 	happy_path(
134 		AF_UNIX, "AF_UNIX",
135 		SOCK_STREAM, "SOCK_STREAM",
136 		0, "0"
137 	);
138 }
139