xref: /freebsd/lib/libnv/tests/nvlist_send_recv_test.c (revision b740c88bfb6453416926271c089262e7164dace3)
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 	nvlist_t *empty;
62 
63 	nvl = nvlist_create(0);
64 	empty = nvlist_create(0);
65 
66 	nvlist_add_bool(nvl, "nvlist/bool/true", true);
67 	nvlist_add_bool(nvl, "nvlist/bool/false", false);
68 	nvlist_add_number(nvl, "nvlist/number/0", 0);
69 	nvlist_add_number(nvl, "nvlist/number/1", 1);
70 	nvlist_add_number(nvl, "nvlist/number/-1", -1);
71 	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
72 	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
73 	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
74 	nvlist_add_string(nvl, "nvlist/string/", "");
75 	nvlist_add_string(nvl, "nvlist/string/x", "x");
76 	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
77 	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
78 	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
79 	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
80 	nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
81 	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
82 
83 	nvlist_send(sock, nvl);
84 
85 	nvlist_destroy(nvl);
86 }
87 
88 static void
89 parent(int sock)
90 {
91 	nvlist_t *nvl;
92 	const nvlist_t *cnvl, *empty;
93 	const char *name, *cname;
94 	void *cookie, *ccookie;
95 	int type, ctype;
96 	size_t size;
97 
98 	nvl = nvlist_recv(sock);
99 	CHECK(nvlist_error(nvl) == 0);
100 	if (nvlist_error(nvl) != 0)
101 		err(1, "nvlist_recv() failed");
102 
103 	cookie = NULL;
104 
105 	name = nvlist_next(nvl, &type, &cookie);
106 	CHECK(name != NULL);
107 	CHECK(type == NV_TYPE_BOOL);
108 	CHECK(strcmp(name, "nvlist/bool/true") == 0);
109 	CHECK(nvlist_get_bool(nvl, name) == true);
110 
111 	name = nvlist_next(nvl, &type, &cookie);
112 	CHECK(name != NULL);
113 	CHECK(type == NV_TYPE_BOOL);
114 	CHECK(strcmp(name, "nvlist/bool/false") == 0);
115 	CHECK(nvlist_get_bool(nvl, name) == false);
116 
117 	name = nvlist_next(nvl, &type, &cookie);
118 	CHECK(name != NULL);
119 	CHECK(type == NV_TYPE_NUMBER);
120 	CHECK(strcmp(name, "nvlist/number/0") == 0);
121 	CHECK(nvlist_get_number(nvl, name) == 0);
122 
123 	name = nvlist_next(nvl, &type, &cookie);
124 	CHECK(name != NULL);
125 	CHECK(type == NV_TYPE_NUMBER);
126 	CHECK(strcmp(name, "nvlist/number/1") == 0);
127 	CHECK(nvlist_get_number(nvl, name) == 1);
128 
129 	name = nvlist_next(nvl, &type, &cookie);
130 	CHECK(name != NULL);
131 	CHECK(type == NV_TYPE_NUMBER);
132 	CHECK(strcmp(name, "nvlist/number/-1") == 0);
133 	CHECK((int)nvlist_get_number(nvl, name) == -1);
134 
135 	name = nvlist_next(nvl, &type, &cookie);
136 	CHECK(name != NULL);
137 	CHECK(type == NV_TYPE_NUMBER);
138 	CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
139 	CHECK(nvlist_get_number(nvl, name) == UINT64_MAX);
140 
141 	name = nvlist_next(nvl, &type, &cookie);
142 	CHECK(name != NULL);
143 	CHECK(type == NV_TYPE_NUMBER);
144 	CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0);
145 	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
146 
147 	name = nvlist_next(nvl, &type, &cookie);
148 	CHECK(name != NULL);
149 	CHECK(type == NV_TYPE_NUMBER);
150 	CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0);
151 	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
152 
153 	name = nvlist_next(nvl, &type, &cookie);
154 	CHECK(name != NULL);
155 	CHECK(type == NV_TYPE_STRING);
156 	CHECK(strcmp(name, "nvlist/string/") == 0);
157 	CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0);
158 
159 	name = nvlist_next(nvl, &type, &cookie);
160 	CHECK(name != NULL);
161 	CHECK(type == NV_TYPE_STRING);
162 	CHECK(strcmp(name, "nvlist/string/x") == 0);
163 	CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0);
164 
165 	name = nvlist_next(nvl, &type, &cookie);
166 	CHECK(name != NULL);
167 	CHECK(type == NV_TYPE_STRING);
168 	CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
169 	CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0);
170 
171 	name = nvlist_next(nvl, &type, &cookie);
172 	CHECK(name != NULL);
173 	CHECK(type == NV_TYPE_DESCRIPTOR);
174 	CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
175 	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name)));
176 
177 	name = nvlist_next(nvl, &type, &cookie);
178 	CHECK(name != NULL);
179 	CHECK(type == NV_TYPE_BINARY);
180 	CHECK(strcmp(name, "nvlist/binary/x") == 0);
181 	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
182 	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
183 	CHECK(size == 1);
184 
185 	name = nvlist_next(nvl, &type, &cookie);
186 	CHECK(name != NULL);
187 	CHECK(type == NV_TYPE_BINARY);
188 	CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
189 	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
190 	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
191 	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
192 
193 	name = nvlist_next(nvl, &type, &cookie);
194 	CHECK(name != NULL);
195 	CHECK(type == NV_TYPE_NVLIST);
196 	CHECK(strcmp(name, "nvlist/nvlist/empty") == 0);
197 	cnvl = nvlist_get_nvlist(nvl, name);
198 	CHECK(nvlist_empty(cnvl));
199 
200 	name = nvlist_next(nvl, &type, &cookie);
201 	CHECK(name != NULL);
202 	CHECK(type == NV_TYPE_NVLIST);
203 	CHECK(strcmp(name, "nvlist/nvlist") == 0);
204 	cnvl = nvlist_get_nvlist(nvl, name);
205 
206 	ccookie = NULL;
207 
208 	cname = nvlist_next(cnvl, &ctype, &ccookie);
209 	CHECK(cname != NULL);
210 	CHECK(ctype == NV_TYPE_BOOL);
211 	CHECK(strcmp(cname, "nvlist/bool/true") == 0);
212 	CHECK(nvlist_get_bool(cnvl, cname) == true);
213 
214 	cname = nvlist_next(cnvl, &ctype, &ccookie);
215 	CHECK(cname != NULL);
216 	CHECK(ctype == NV_TYPE_BOOL);
217 	CHECK(strcmp(cname, "nvlist/bool/false") == 0);
218 	CHECK(nvlist_get_bool(cnvl, cname) == false);
219 
220 	cname = nvlist_next(cnvl, &ctype, &ccookie);
221 	CHECK(cname != NULL);
222 	CHECK(ctype == NV_TYPE_NUMBER);
223 	CHECK(strcmp(cname, "nvlist/number/0") == 0);
224 	CHECK(nvlist_get_number(cnvl, cname) == 0);
225 
226 	cname = nvlist_next(cnvl, &ctype, &ccookie);
227 	CHECK(cname != NULL);
228 	CHECK(ctype == NV_TYPE_NUMBER);
229 	CHECK(strcmp(cname, "nvlist/number/1") == 0);
230 	CHECK(nvlist_get_number(cnvl, cname) == 1);
231 
232 	cname = nvlist_next(cnvl, &ctype, &ccookie);
233 	CHECK(cname != NULL);
234 	CHECK(ctype == NV_TYPE_NUMBER);
235 	CHECK(strcmp(cname, "nvlist/number/-1") == 0);
236 	CHECK((int)nvlist_get_number(cnvl, cname) == -1);
237 
238 	cname = nvlist_next(cnvl, &ctype, &ccookie);
239 	CHECK(cname != NULL);
240 	CHECK(ctype == NV_TYPE_NUMBER);
241 	CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
242 	CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX);
243 
244 	cname = nvlist_next(cnvl, &ctype, &ccookie);
245 	CHECK(cname != NULL);
246 	CHECK(ctype == NV_TYPE_NUMBER);
247 	CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
248 	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
249 
250 	cname = nvlist_next(cnvl, &ctype, &ccookie);
251 	CHECK(cname != NULL);
252 	CHECK(ctype == NV_TYPE_NUMBER);
253 	CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
254 	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
255 
256 	cname = nvlist_next(cnvl, &ctype, &ccookie);
257 	CHECK(cname != NULL);
258 	CHECK(ctype == NV_TYPE_STRING);
259 	CHECK(strcmp(cname, "nvlist/string/") == 0);
260 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
261 
262 	cname = nvlist_next(cnvl, &ctype, &ccookie);
263 	CHECK(cname != NULL);
264 	CHECK(ctype == NV_TYPE_STRING);
265 	CHECK(strcmp(cname, "nvlist/string/x") == 0);
266 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
267 
268 	cname = nvlist_next(cnvl, &ctype, &ccookie);
269 	CHECK(cname != NULL);
270 	CHECK(ctype == NV_TYPE_STRING);
271 	CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
272 	CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0);
273 
274 	cname = nvlist_next(cnvl, &ctype, &ccookie);
275 	CHECK(cname != NULL);
276 	CHECK(ctype == NV_TYPE_DESCRIPTOR);
277 	CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
278 	CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
279 
280 	cname = nvlist_next(cnvl, &ctype, &ccookie);
281 	CHECK(cname != NULL);
282 	CHECK(ctype == NV_TYPE_BINARY);
283 	CHECK(strcmp(cname, "nvlist/binary/x") == 0);
284 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
285 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
286 	CHECK(size == 1);
287 
288 	cname = nvlist_next(cnvl, &ctype, &ccookie);
289 	CHECK(cname != NULL);
290 	CHECK(ctype == NV_TYPE_BINARY);
291 	CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
292 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
293 	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
294 	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
295 
296 	cname = nvlist_next(cnvl, &ctype, &ccookie);
297 	CHECK(cname != NULL);
298 	CHECK(ctype == NV_TYPE_NVLIST);
299 	CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0);
300 	empty = nvlist_get_nvlist(cnvl, cname);
301 	CHECK(nvlist_empty(empty));
302 
303 	cname = nvlist_next(cnvl, &ctype, &ccookie);
304 	CHECK(cname == NULL);
305 
306 	name = nvlist_next(nvl, &type, &cookie);
307 	CHECK(name == NULL);
308 }
309 
310 int
311 main(void)
312 {
313 	int status, socks[2];
314 	pid_t pid;
315 
316 	printf("1..134\n");
317 	fflush(stdout);
318 
319 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
320 		err(1, "socketpair() failed");
321 	pid = fork();
322 	switch (pid) {
323 	case -1:
324 		/* Failure. */
325 		err(1, "unable to fork");
326 	case 0:
327 		/* Child. */
328 		close(socks[0]);
329 		child(socks[1]);
330 		return (0);
331 	default:
332 		/* Parent. */
333 		close(socks[1]);
334 		parent(socks[0]);
335 		break;
336 	}
337 
338 	if (waitpid(pid, &status, 0) < 0)
339 		err(1, "waitpid() failed");
340 
341 	return (0);
342 }
343