xref: /freebsd/lib/libnv/tests/nvlist_send_recv_test.c (revision 57718be8fa0bd5edc11ab9a72e68cc71982939a6)
1 /*-
2  * Copyright (c) 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/wait.h>
35 
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 #include <nv.h>
44 
45 static int ntest = 1;
46 
47 #define	CHECK(expr)	do {						\
48 	if ((expr))							\
49 		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
50 	else								\
51 		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
52 	ntest++;							\
53 } while (0)
54 
55 #define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
56 
57 static void
58 child(int sock)
59 {
60 	nvlist_t *nvl;
61 
62 	nvl = nvlist_create(0);
63 
64 	nvlist_add_bool(nvl, "nvlist/bool/true", true);
65 	nvlist_add_bool(nvl, "nvlist/bool/false", false);
66 	nvlist_add_number(nvl, "nvlist/number/0", 0);
67 	nvlist_add_number(nvl, "nvlist/number/1", 1);
68 	nvlist_add_number(nvl, "nvlist/number/-1", -1);
69 	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
70 	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
71 	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
72 	nvlist_add_string(nvl, "nvlist/string/", "");
73 	nvlist_add_string(nvl, "nvlist/string/x", "x");
74 	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
75 	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
76 	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
77 	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
78 	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
79 
80 	nvlist_send(sock, nvl);
81 
82 	nvlist_destroy(nvl);
83 }
84 
85 static void
86 parent(int sock)
87 {
88 	nvlist_t *nvl;
89 	const nvlist_t *cnvl;
90 	const char *name, *cname;
91 	void *cookie, *ccookie;
92 	int type, ctype;
93 	size_t size;
94 
95 	nvl = nvlist_recv(sock);
96 	CHECK(nvlist_error(nvl) == 0);
97 	if (nvlist_error(nvl) != 0)
98 		err(1, "nvlist_recv() failed");
99 
100 	cookie = NULL;
101 
102 	name = nvlist_next(nvl, &type, &cookie);
103 	CHECK(name != NULL);
104 	CHECK(type == NV_TYPE_BOOL);
105 	CHECK(strcmp(name, "nvlist/bool/true") == 0);
106 	CHECK(nvlist_get_bool(nvl, name) == true);
107 
108 	name = nvlist_next(nvl, &type, &cookie);
109 	CHECK(name != NULL);
110 	CHECK(type == NV_TYPE_BOOL);
111 	CHECK(strcmp(name, "nvlist/bool/false") == 0);
112 	CHECK(nvlist_get_bool(nvl, name) == false);
113 
114 	name = nvlist_next(nvl, &type, &cookie);
115 	CHECK(name != NULL);
116 	CHECK(type == NV_TYPE_NUMBER);
117 	CHECK(strcmp(name, "nvlist/number/0") == 0);
118 	CHECK(nvlist_get_number(nvl, name) == 0);
119 
120 	name = nvlist_next(nvl, &type, &cookie);
121 	CHECK(name != NULL);
122 	CHECK(type == NV_TYPE_NUMBER);
123 	CHECK(strcmp(name, "nvlist/number/1") == 0);
124 	CHECK(nvlist_get_number(nvl, name) == 1);
125 
126 	name = nvlist_next(nvl, &type, &cookie);
127 	CHECK(name != NULL);
128 	CHECK(type == NV_TYPE_NUMBER);
129 	CHECK(strcmp(name, "nvlist/number/-1") == 0);
130 	CHECK((int)nvlist_get_number(nvl, name) == -1);
131 
132 	name = nvlist_next(nvl, &type, &cookie);
133 	CHECK(name != NULL);
134 	CHECK(type == NV_TYPE_NUMBER);
135 	CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
136 	CHECK(nvlist_get_number(nvl, name) == UINT64_MAX);
137 
138 	name = nvlist_next(nvl, &type, &cookie);
139 	CHECK(name != NULL);
140 	CHECK(type == NV_TYPE_NUMBER);
141 	CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0);
142 	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
143 
144 	name = nvlist_next(nvl, &type, &cookie);
145 	CHECK(name != NULL);
146 	CHECK(type == NV_TYPE_NUMBER);
147 	CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0);
148 	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
149 
150 	name = nvlist_next(nvl, &type, &cookie);
151 	CHECK(name != NULL);
152 	CHECK(type == NV_TYPE_STRING);
153 	CHECK(strcmp(name, "nvlist/string/") == 0);
154 	CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0);
155 
156 	name = nvlist_next(nvl, &type, &cookie);
157 	CHECK(name != NULL);
158 	CHECK(type == NV_TYPE_STRING);
159 	CHECK(strcmp(name, "nvlist/string/x") == 0);
160 	CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0);
161 
162 	name = nvlist_next(nvl, &type, &cookie);
163 	CHECK(name != NULL);
164 	CHECK(type == NV_TYPE_STRING);
165 	CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
166 	CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0);
167 
168 	name = nvlist_next(nvl, &type, &cookie);
169 	CHECK(name != NULL);
170 	CHECK(type == NV_TYPE_DESCRIPTOR);
171 	CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
172 	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name)));
173 
174 	name = nvlist_next(nvl, &type, &cookie);
175 	CHECK(name != NULL);
176 	CHECK(type == NV_TYPE_BINARY);
177 	CHECK(strcmp(name, "nvlist/binary/x") == 0);
178 	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
179 	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
180 	CHECK(size == 1);
181 
182 	name = nvlist_next(nvl, &type, &cookie);
183 	CHECK(name != NULL);
184 	CHECK(type == NV_TYPE_BINARY);
185 	CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
186 	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
187 	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
188 	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
189 
190 	name = nvlist_next(nvl, &type, &cookie);
191 	CHECK(name != NULL);
192 	CHECK(type == NV_TYPE_NVLIST);
193 	CHECK(strcmp(name, "nvlist/nvlist") == 0);
194 	cnvl = nvlist_get_nvlist(nvl, name);
195 
196 	ccookie = NULL;
197 
198 	cname = nvlist_next(cnvl, &ctype, &ccookie);
199 	CHECK(cname != NULL);
200 	CHECK(ctype == NV_TYPE_BOOL);
201 	CHECK(strcmp(cname, "nvlist/bool/true") == 0);
202 	CHECK(nvlist_get_bool(cnvl, cname) == true);
203 
204 	cname = nvlist_next(cnvl, &ctype, &ccookie);
205 	CHECK(cname != NULL);
206 	CHECK(ctype == NV_TYPE_BOOL);
207 	CHECK(strcmp(cname, "nvlist/bool/false") == 0);
208 	CHECK(nvlist_get_bool(cnvl, cname) == false);
209 
210 	cname = nvlist_next(cnvl, &ctype, &ccookie);
211 	CHECK(cname != NULL);
212 	CHECK(ctype == NV_TYPE_NUMBER);
213 	CHECK(strcmp(cname, "nvlist/number/0") == 0);
214 	CHECK(nvlist_get_number(cnvl, cname) == 0);
215 
216 	cname = nvlist_next(cnvl, &ctype, &ccookie);
217 	CHECK(cname != NULL);
218 	CHECK(ctype == NV_TYPE_NUMBER);
219 	CHECK(strcmp(cname, "nvlist/number/1") == 0);
220 	CHECK(nvlist_get_number(cnvl, cname) == 1);
221 
222 	cname = nvlist_next(cnvl, &ctype, &ccookie);
223 	CHECK(cname != NULL);
224 	CHECK(ctype == NV_TYPE_NUMBER);
225 	CHECK(strcmp(cname, "nvlist/number/-1") == 0);
226 	CHECK((int)nvlist_get_number(cnvl, cname) == -1);
227 
228 	cname = nvlist_next(cnvl, &ctype, &ccookie);
229 	CHECK(cname != NULL);
230 	CHECK(ctype == NV_TYPE_NUMBER);
231 	CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
232 	CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX);
233 
234 	cname = nvlist_next(cnvl, &ctype, &ccookie);
235 	CHECK(cname != NULL);
236 	CHECK(ctype == NV_TYPE_NUMBER);
237 	CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
238 	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
239 
240 	cname = nvlist_next(cnvl, &ctype, &ccookie);
241 	CHECK(cname != NULL);
242 	CHECK(ctype == NV_TYPE_NUMBER);
243 	CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
244 	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
245 
246 	cname = nvlist_next(cnvl, &ctype, &ccookie);
247 	CHECK(cname != NULL);
248 	CHECK(ctype == NV_TYPE_STRING);
249 	CHECK(strcmp(cname, "nvlist/string/") == 0);
250 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
251 
252 	cname = nvlist_next(cnvl, &ctype, &ccookie);
253 	CHECK(cname != NULL);
254 	CHECK(ctype == NV_TYPE_STRING);
255 	CHECK(strcmp(cname, "nvlist/string/x") == 0);
256 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
257 
258 	cname = nvlist_next(cnvl, &ctype, &ccookie);
259 	CHECK(cname != NULL);
260 	CHECK(ctype == NV_TYPE_STRING);
261 	CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
262 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0);
263 
264 	cname = nvlist_next(cnvl, &ctype, &ccookie);
265 	CHECK(cname != NULL);
266 	CHECK(ctype == NV_TYPE_DESCRIPTOR);
267 	CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
268 	CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
269 
270 	cname = nvlist_next(cnvl, &ctype, &ccookie);
271 	CHECK(cname != NULL);
272 	CHECK(ctype == NV_TYPE_BINARY);
273 	CHECK(strcmp(cname, "nvlist/binary/x") == 0);
274 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
275 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
276 	CHECK(size == 1);
277 
278 	cname = nvlist_next(cnvl, &ctype, &ccookie);
279 	CHECK(cname != NULL);
280 	CHECK(ctype == NV_TYPE_BINARY);
281 	CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
282 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
283 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
284 	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
285 
286 	cname = nvlist_next(cnvl, &ctype, &ccookie);
287 	CHECK(cname == NULL);
288 
289 	name = nvlist_next(nvl, &type, &cookie);
290 	CHECK(name == NULL);
291 }
292 
293 int
294 main(void)
295 {
296 	int status, socks[2];
297 	pid_t pid;
298 
299 	printf("1..126\n");
300 	fflush(stdout);
301 
302 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
303 		err(1, "socketpair() failed");
304 	pid = fork();
305 	switch (pid) {
306 	case -1:
307 		/* Failure. */
308 		err(1, "unable to fork");
309 	case 0:
310 		/* Child. */
311 		close(socks[0]);
312 		child(socks[1]);
313 		return (0);
314 	default:
315 		/* Parent. */
316 		close(socks[1]);
317 		parent(socks[0]);
318 		break;
319 	}
320 
321 	if (waitpid(pid, &status, 0) < 0)
322 		err(1, "waitpid() failed");
323 
324 	return (0);
325 }
326