1258070Spjd/*-
2258070Spjd * Copyright (c) 2013 The FreeBSD Foundation
3258070Spjd * All rights reserved.
4258070Spjd *
5258070Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from
6258070Spjd * the FreeBSD Foundation.
7258070Spjd *
8258070Spjd * Redistribution and use in source and binary forms, with or without
9258070Spjd * modification, are permitted provided that the following conditions
10258070Spjd * are met:
11258070Spjd * 1. Redistributions of source code must retain the above copyright
12258070Spjd *    notice, this list of conditions and the following disclaimer.
13258070Spjd * 2. Redistributions in binary form must reproduce the above copyright
14258070Spjd *    notice, this list of conditions and the following disclaimer in the
15258070Spjd *    documentation and/or other materials provided with the distribution.
16258070Spjd *
17258070Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18258070Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19258070Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20258070Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21258070Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22258070Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23258070Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24258070Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25258070Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26258070Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27258070Spjd * SUCH DAMAGE.
28258070Spjd *
29258070Spjd * $FreeBSD: releng/10.3/lib/libnv/tests/nvlist_send_recv_test.c 292634 2015-12-22 23:08:50Z ngie $
30258070Spjd */
31258070Spjd
32258070Spjd#include <sys/types.h>
33258070Spjd#include <sys/socket.h>
34258070Spjd#include <sys/wait.h>
35258070Spjd
36258070Spjd#include <err.h>
37258070Spjd#include <errno.h>
38258070Spjd#include <fcntl.h>
39258070Spjd#include <stdio.h>
40258070Spjd#include <string.h>
41258070Spjd#include <unistd.h>
42258070Spjd
43258070Spjd#include <nv.h>
44258070Spjd
45258070Spjdstatic int ntest = 1;
46258070Spjd
47258070Spjd#define	CHECK(expr)	do {						\
48258070Spjd	if ((expr))							\
49258070Spjd		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
50258070Spjd	else								\
51258070Spjd		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
52258070Spjd	ntest++;							\
53258070Spjd} while (0)
54258070Spjd
55258070Spjd#define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
56258070Spjd
57258070Spjdstatic void
58258070Spjdchild(int sock)
59258070Spjd{
60258070Spjd	nvlist_t *nvl;
61292634Sngie	nvlist_t *empty;
62258070Spjd
63258070Spjd	nvl = nvlist_create(0);
64292634Sngie	empty = nvlist_create(0);
65258070Spjd
66258070Spjd	nvlist_add_bool(nvl, "nvlist/bool/true", true);
67258070Spjd	nvlist_add_bool(nvl, "nvlist/bool/false", false);
68258070Spjd	nvlist_add_number(nvl, "nvlist/number/0", 0);
69258070Spjd	nvlist_add_number(nvl, "nvlist/number/1", 1);
70258070Spjd	nvlist_add_number(nvl, "nvlist/number/-1", -1);
71258070Spjd	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
72258070Spjd	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
73258070Spjd	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
74258070Spjd	nvlist_add_string(nvl, "nvlist/string/", "");
75258070Spjd	nvlist_add_string(nvl, "nvlist/string/x", "x");
76258070Spjd	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
77258070Spjd	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
78258070Spjd	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
79258070Spjd	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
80292634Sngie	nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
81258070Spjd	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
82258070Spjd
83258070Spjd	nvlist_send(sock, nvl);
84258070Spjd
85258070Spjd	nvlist_destroy(nvl);
86258070Spjd}
87258070Spjd
88258070Spjdstatic void
89258070Spjdparent(int sock)
90258070Spjd{
91258070Spjd	nvlist_t *nvl;
92292634Sngie	const nvlist_t *cnvl, *empty;
93258070Spjd	const char *name, *cname;
94258070Spjd	void *cookie, *ccookie;
95258070Spjd	int type, ctype;
96258070Spjd	size_t size;
97258070Spjd
98258070Spjd	nvl = nvlist_recv(sock);
99258070Spjd	CHECK(nvlist_error(nvl) == 0);
100258070Spjd	if (nvlist_error(nvl) != 0)
101258070Spjd		err(1, "nvlist_recv() failed");
102258070Spjd
103258070Spjd	cookie = NULL;
104258070Spjd
105258070Spjd	name = nvlist_next(nvl, &type, &cookie);
106258070Spjd	CHECK(name != NULL);
107258070Spjd	CHECK(type == NV_TYPE_BOOL);
108258070Spjd	CHECK(strcmp(name, "nvlist/bool/true") == 0);
109258070Spjd	CHECK(nvlist_get_bool(nvl, name) == true);
110258070Spjd
111258070Spjd	name = nvlist_next(nvl, &type, &cookie);
112258070Spjd	CHECK(name != NULL);
113258070Spjd	CHECK(type == NV_TYPE_BOOL);
114258070Spjd	CHECK(strcmp(name, "nvlist/bool/false") == 0);
115258070Spjd	CHECK(nvlist_get_bool(nvl, name) == false);
116258070Spjd
117258070Spjd	name = nvlist_next(nvl, &type, &cookie);
118258070Spjd	CHECK(name != NULL);
119258070Spjd	CHECK(type == NV_TYPE_NUMBER);
120258070Spjd	CHECK(strcmp(name, "nvlist/number/0") == 0);
121258070Spjd	CHECK(nvlist_get_number(nvl, name) == 0);
122258070Spjd
123258070Spjd	name = nvlist_next(nvl, &type, &cookie);
124258070Spjd	CHECK(name != NULL);
125258070Spjd	CHECK(type == NV_TYPE_NUMBER);
126258070Spjd	CHECK(strcmp(name, "nvlist/number/1") == 0);
127258070Spjd	CHECK(nvlist_get_number(nvl, name) == 1);
128258070Spjd
129258070Spjd	name = nvlist_next(nvl, &type, &cookie);
130258070Spjd	CHECK(name != NULL);
131258070Spjd	CHECK(type == NV_TYPE_NUMBER);
132258070Spjd	CHECK(strcmp(name, "nvlist/number/-1") == 0);
133258070Spjd	CHECK((int)nvlist_get_number(nvl, name) == -1);
134258070Spjd
135258070Spjd	name = nvlist_next(nvl, &type, &cookie);
136258070Spjd	CHECK(name != NULL);
137258070Spjd	CHECK(type == NV_TYPE_NUMBER);
138258070Spjd	CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
139258070Spjd	CHECK(nvlist_get_number(nvl, name) == UINT64_MAX);
140258070Spjd
141258070Spjd	name = nvlist_next(nvl, &type, &cookie);
142258070Spjd	CHECK(name != NULL);
143258070Spjd	CHECK(type == NV_TYPE_NUMBER);
144258070Spjd	CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0);
145258070Spjd	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
146258070Spjd
147258070Spjd	name = nvlist_next(nvl, &type, &cookie);
148258070Spjd	CHECK(name != NULL);
149258070Spjd	CHECK(type == NV_TYPE_NUMBER);
150258070Spjd	CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0);
151258070Spjd	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
152258070Spjd
153258070Spjd	name = nvlist_next(nvl, &type, &cookie);
154258070Spjd	CHECK(name != NULL);
155258070Spjd	CHECK(type == NV_TYPE_STRING);
156258070Spjd	CHECK(strcmp(name, "nvlist/string/") == 0);
157258070Spjd	CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0);
158258070Spjd
159258070Spjd	name = nvlist_next(nvl, &type, &cookie);
160258070Spjd	CHECK(name != NULL);
161258070Spjd	CHECK(type == NV_TYPE_STRING);
162258070Spjd	CHECK(strcmp(name, "nvlist/string/x") == 0);
163258070Spjd	CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0);
164258070Spjd
165258070Spjd	name = nvlist_next(nvl, &type, &cookie);
166258070Spjd	CHECK(name != NULL);
167258070Spjd	CHECK(type == NV_TYPE_STRING);
168258070Spjd	CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
169258070Spjd	CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0);
170258070Spjd
171258070Spjd	name = nvlist_next(nvl, &type, &cookie);
172258070Spjd	CHECK(name != NULL);
173258070Spjd	CHECK(type == NV_TYPE_DESCRIPTOR);
174258070Spjd	CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
175258070Spjd	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name)));
176258070Spjd
177258070Spjd	name = nvlist_next(nvl, &type, &cookie);
178258070Spjd	CHECK(name != NULL);
179258070Spjd	CHECK(type == NV_TYPE_BINARY);
180258070Spjd	CHECK(strcmp(name, "nvlist/binary/x") == 0);
181258070Spjd	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
182258070Spjd	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
183258070Spjd	CHECK(size == 1);
184258070Spjd
185258070Spjd	name = nvlist_next(nvl, &type, &cookie);
186258070Spjd	CHECK(name != NULL);
187258070Spjd	CHECK(type == NV_TYPE_BINARY);
188258070Spjd	CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
189258070Spjd	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
190258070Spjd	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
191258070Spjd	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
192258070Spjd
193258070Spjd	name = nvlist_next(nvl, &type, &cookie);
194258070Spjd	CHECK(name != NULL);
195258070Spjd	CHECK(type == NV_TYPE_NVLIST);
196292634Sngie	CHECK(strcmp(name, "nvlist/nvlist/empty") == 0);
197292634Sngie	cnvl = nvlist_get_nvlist(nvl, name);
198292634Sngie	CHECK(nvlist_empty(cnvl));
199292634Sngie
200292634Sngie	name = nvlist_next(nvl, &type, &cookie);
201292634Sngie	CHECK(name != NULL);
202292634Sngie	CHECK(type == NV_TYPE_NVLIST);
203258070Spjd	CHECK(strcmp(name, "nvlist/nvlist") == 0);
204258070Spjd	cnvl = nvlist_get_nvlist(nvl, name);
205258070Spjd
206258070Spjd	ccookie = NULL;
207258070Spjd
208258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
209258070Spjd	CHECK(cname != NULL);
210258070Spjd	CHECK(ctype == NV_TYPE_BOOL);
211258070Spjd	CHECK(strcmp(cname, "nvlist/bool/true") == 0);
212258070Spjd	CHECK(nvlist_get_bool(cnvl, cname) == true);
213258070Spjd
214258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
215258070Spjd	CHECK(cname != NULL);
216258070Spjd	CHECK(ctype == NV_TYPE_BOOL);
217258070Spjd	CHECK(strcmp(cname, "nvlist/bool/false") == 0);
218258070Spjd	CHECK(nvlist_get_bool(cnvl, cname) == false);
219258070Spjd
220258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
221258070Spjd	CHECK(cname != NULL);
222258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
223258070Spjd	CHECK(strcmp(cname, "nvlist/number/0") == 0);
224258070Spjd	CHECK(nvlist_get_number(cnvl, cname) == 0);
225258070Spjd
226258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
227258070Spjd	CHECK(cname != NULL);
228258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
229258070Spjd	CHECK(strcmp(cname, "nvlist/number/1") == 0);
230258070Spjd	CHECK(nvlist_get_number(cnvl, cname) == 1);
231258070Spjd
232258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
233258070Spjd	CHECK(cname != NULL);
234258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
235258070Spjd	CHECK(strcmp(cname, "nvlist/number/-1") == 0);
236258070Spjd	CHECK((int)nvlist_get_number(cnvl, cname) == -1);
237258070Spjd
238258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
239258070Spjd	CHECK(cname != NULL);
240258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
241258070Spjd	CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
242258070Spjd	CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX);
243258070Spjd
244258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
245258070Spjd	CHECK(cname != NULL);
246258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
247258070Spjd	CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
248258070Spjd	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
249258070Spjd
250258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
251258070Spjd	CHECK(cname != NULL);
252258070Spjd	CHECK(ctype == NV_TYPE_NUMBER);
253258070Spjd	CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
254258070Spjd	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
255258070Spjd
256258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
257258070Spjd	CHECK(cname != NULL);
258258070Spjd	CHECK(ctype == NV_TYPE_STRING);
259258070Spjd	CHECK(strcmp(cname, "nvlist/string/") == 0);
260258070Spjd	CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
261258070Spjd
262258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
263258070Spjd	CHECK(cname != NULL);
264258070Spjd	CHECK(ctype == NV_TYPE_STRING);
265258070Spjd	CHECK(strcmp(cname, "nvlist/string/x") == 0);
266258070Spjd	CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
267258070Spjd
268258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
269258070Spjd	CHECK(cname != NULL);
270258070Spjd	CHECK(ctype == NV_TYPE_STRING);
271258070Spjd	CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
272258070Spjd	CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0);
273258070Spjd
274258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
275258070Spjd	CHECK(cname != NULL);
276258070Spjd	CHECK(ctype == NV_TYPE_DESCRIPTOR);
277258070Spjd	CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
278258070Spjd	CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
279258070Spjd
280258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
281258070Spjd	CHECK(cname != NULL);
282258070Spjd	CHECK(ctype == NV_TYPE_BINARY);
283258070Spjd	CHECK(strcmp(cname, "nvlist/binary/x") == 0);
284258070Spjd	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
285258070Spjd	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
286258070Spjd	CHECK(size == 1);
287258070Spjd
288258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
289258070Spjd	CHECK(cname != NULL);
290258070Spjd	CHECK(ctype == NV_TYPE_BINARY);
291258070Spjd	CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
292258070Spjd	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
293258070Spjd	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
294258070Spjd	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
295258070Spjd
296258070Spjd	cname = nvlist_next(cnvl, &ctype, &ccookie);
297292634Sngie	CHECK(cname != NULL);
298292634Sngie	CHECK(ctype == NV_TYPE_NVLIST);
299292634Sngie	CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0);
300292634Sngie	empty = nvlist_get_nvlist(cnvl, cname);
301292634Sngie	CHECK(nvlist_empty(empty));
302292634Sngie
303292634Sngie	cname = nvlist_next(cnvl, &ctype, &ccookie);
304258070Spjd	CHECK(cname == NULL);
305258070Spjd
306258070Spjd	name = nvlist_next(nvl, &type, &cookie);
307258070Spjd	CHECK(name == NULL);
308258070Spjd}
309258070Spjd
310258070Spjdint
311258070Spjdmain(void)
312258070Spjd{
313258070Spjd	int status, socks[2];
314258070Spjd	pid_t pid;
315258070Spjd
316292634Sngie	printf("1..134\n");
317258070Spjd	fflush(stdout);
318258070Spjd
319258070Spjd	if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
320258070Spjd		err(1, "socketpair() failed");
321258070Spjd	pid = fork();
322258070Spjd	switch (pid) {
323258070Spjd	case -1:
324258070Spjd		/* Failure. */
325258070Spjd		err(1, "unable to fork");
326258070Spjd	case 0:
327258070Spjd		/* Child. */
328258070Spjd		close(socks[0]);
329258070Spjd		child(socks[1]);
330258070Spjd		return (0);
331258070Spjd	default:
332258070Spjd		/* Parent. */
333258070Spjd		close(socks[1]);
334258070Spjd		parent(socks[0]);
335258070Spjd		break;
336258070Spjd	}
337258070Spjd
338258070Spjd	if (waitpid(pid, &status, 0) < 0)
339258070Spjd		err(1, "waitpid() failed");
340258070Spjd
341258070Spjd	return (0);
342258070Spjd}
343