[Midnightbsd-cvs] src [10442] trunk/lib/libnv: add libnv

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Jun 6 19:27:13 EDT 2018


Revision: 10442
          http://svnweb.midnightbsd.org/src/?rev=10442
Author:   laffer1
Date:     2018-06-06 19:27:13 -0400 (Wed, 06 Jun 2018)
Log Message:
-----------
add libnv

Added Paths:
-----------
    trunk/lib/libnv/
    trunk/lib/libnv/Makefile
    trunk/lib/libnv/common_impl.h
    trunk/lib/libnv/msgio.c
    trunk/lib/libnv/msgio.h
    trunk/lib/libnv/nv.3
    trunk/lib/libnv/tests/
    trunk/lib/libnv/tests/Makefile
    trunk/lib/libnv/tests/dnv_tests.cc
    trunk/lib/libnv/tests/nv_tests.cc
    trunk/lib/libnv/tests/nvlist_add_test.c
    trunk/lib/libnv/tests/nvlist_exists_test.c
    trunk/lib/libnv/tests/nvlist_free_test.c
    trunk/lib/libnv/tests/nvlist_get_test.c
    trunk/lib/libnv/tests/nvlist_move_test.c
    trunk/lib/libnv/tests/nvlist_send_recv_test.c

Added: trunk/lib/libnv/Makefile
===================================================================
--- trunk/lib/libnv/Makefile	                        (rev 0)
+++ trunk/lib/libnv/Makefile	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,93 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/lib/libnv/Makefile 292637 2015-12-22 23:21:06Z ngie $
+
+SHLIBDIR?= /lib
+
+.include <bsd.own.mk>
+
+LIB=	nv
+SHLIB_MAJOR= 0
+
+.PATH: ${.CURDIR}/../../sys/kern ${.CURDIR}/../../sys/sys
+CFLAGS+=-I${.CURDIR}/../../sys -I${.CURDIR}
+
+SRCS=	subr_dnvlist.c
+SRCS+=	msgio.c
+SRCS+=	subr_nvlist.c
+SRCS+=	subr_nvpair.c
+
+INCS=	dnv.h
+INCS+=	nv.h
+
+MAN+=	nv.3
+
+MLINKS+=nv.3 libnv.3 \
+	nv.3 nvlist.3
+MLINKS+=nv.3 nvlist_add_binary.3 \
+	nv.3 nvlist_add_bool.3 \
+	nv.3 nvlist_add_descriptor.3 \
+	nv.3 nvlist_add_null.3 \
+	nv.3 nvlist_add_number.3 \
+	nv.3 nvlist_add_nvlist.3 \
+	nv.3 nvlist_add_string.3 \
+	nv.3 nvlist_add_stringf.3 \
+	nv.3 nvlist_add_stringv.3 \
+	nv.3 nvlist_clone.3 \
+	nv.3 nvlist_create.3 \
+	nv.3 nvlist_destroy.3 \
+	nv.3 nvlist_dump.3 \
+	nv.3 nvlist_empty.3 \
+	nv.3 nvlist_error.3 \
+	nv.3 nvlist_exists.3 \
+	nv.3 nvlist_exists_binary.3 \
+	nv.3 nvlist_exists_bool.3 \
+	nv.3 nvlist_exists_descriptor.3 \
+	nv.3 nvlist_exists_null.3 \
+	nv.3 nvlist_exists_number.3 \
+	nv.3 nvlist_exists_nvlist.3 \
+	nv.3 nvlist_exists_string.3 \
+	nv.3 nvlist_exists_type.3 \
+	nv.3 nvlist_fdump.3 \
+	nv.3 nvlist_flags.3 \
+	nv.3 nvlist_free.3 \
+	nv.3 nvlist_free_binary.3 \
+	nv.3 nvlist_free_bool.3 \
+	nv.3 nvlist_free_descriptor.3 \
+	nv.3 nvlist_free_null.3 \
+	nv.3 nvlist_free_number.3 \
+	nv.3 nvlist_free_nvlist.3 \
+	nv.3 nvlist_free_string.3 \
+	nv.3 nvlist_free_type.3 \
+	nv.3 nvlist_get_binary.3 \
+	nv.3 nvlist_get_bool.3 \
+	nv.3 nvlist_get_descriptor.3 \
+	nv.3 nvlist_get_number.3 \
+	nv.3 nvlist_get_nvlist.3 \
+	nv.3 nvlist_get_parent.3 \
+	nv.3 nvlist_get_string.3 \
+	nv.3 nvlist_move_binary.3 \
+	nv.3 nvlist_move_descriptor.3 \
+	nv.3 nvlist_move_nvlist.3 \
+	nv.3 nvlist_move_string.3 \
+	nv.3 nvlist_next.3 \
+	nv.3 nvlist_pack.3 \
+	nv.3 nvlist_recv.3 \
+	nv.3 nvlist_send.3 \
+	nv.3 nvlist_set_error.3 \
+	nv.3 nvlist_size.3 \
+	nv.3 nvlist_take_binary.3 \
+	nv.3 nvlist_take_bool.3 \
+	nv.3 nvlist_take_descriptor.3 \
+	nv.3 nvlist_take_number.3 \
+	nv.3 nvlist_take_nvlist.3 \
+	nv.3 nvlist_take_string.3 \
+	nv.3 nvlist_unpack.3 \
+	nv.3 nvlist_xfer.3
+
+WARNS?=	6
+
+.if ${MK_TESTS} != "no"
+SUBDIR+=	tests
+.endif
+
+.include <bsd.lib.mk>


Property changes on: trunk/lib/libnv/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/common_impl.h
===================================================================
--- trunk/lib/libnv/common_impl.h	                        (rev 0)
+++ trunk/lib/libnv/common_impl.h	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/common_impl.h 258065 2013-11-12 19:39:14Z pjd $
+ */
+
+#ifndef	_COMMON_IMPL_H_
+#define	_COMMON_IMPL_H_
+
+#define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+#endif	/* !_COMMON_IMPL_H_ */


Property changes on: trunk/lib/libnv/common_impl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/msgio.c
===================================================================
--- trunk/lib/libnv/msgio.c	                        (rev 0)
+++ trunk/lib/libnv/msgio.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,470 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * Copyright (c) 2013 Mariusz Zaborski <oshogbo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libnv/msgio.c 292632 2015-12-22 23:05:43Z ngie $");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_PJDLOG
+#include <pjdlog.h>
+#endif
+
+#include "common_impl.h"
+#include "msgio.h"
+
+#ifndef	HAVE_PJDLOG
+#include <assert.h>
+#define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
+#define	PJDLOG_RASSERT(expr, ...)	assert(expr)
+#define	PJDLOG_ABORT(...)		abort()
+#endif
+
+#define	PKG_MAX_SIZE	(MCLBYTES / CMSG_SPACE(sizeof(int)) - 1)
+
+static int
+msghdr_add_fd(struct cmsghdr *cmsg, int fd)
+{
+
+	PJDLOG_ASSERT(fd >= 0);
+
+	if (!fd_is_valid(fd)) {
+		errno = EBADF;
+		return (-1);
+	}
+
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+	bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd));
+
+	return (0);
+}
+
+static int
+msghdr_get_fd(struct cmsghdr *cmsg)
+{
+	int fd;
+
+	if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET ||
+	    cmsg->cmsg_type != SCM_RIGHTS ||
+	    cmsg->cmsg_len != CMSG_LEN(sizeof(fd))) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	bcopy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+#ifndef MSG_CMSG_CLOEXEC
+	/*
+	 * If the MSG_CMSG_CLOEXEC flag is not available we cannot set the
+	 * close-on-exec flag atomically, but we still want to set it for
+	 * consistency.
+	 */
+	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+	return (fd);
+}
+
+static void
+fd_wait(int fd, bool doread)
+{
+	fd_set fds;
+
+	PJDLOG_ASSERT(fd >= 0);
+
+	FD_ZERO(&fds);
+	FD_SET(fd, &fds);
+	(void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds,
+	    NULL, NULL);
+}
+
+static int
+msg_recv(int sock, struct msghdr *msg)
+{
+	int flags;
+
+	PJDLOG_ASSERT(sock >= 0);
+
+#ifdef MSG_CMSG_CLOEXEC
+	flags = MSG_CMSG_CLOEXEC;
+#else
+	flags = 0;
+#endif
+
+	for (;;) {
+		fd_wait(sock, true);
+		if (recvmsg(sock, msg, flags) == -1) {
+			if (errno == EINTR)
+				continue;
+			return (-1);
+		}
+		break;
+	}
+
+	return (0);
+}
+
+static int
+msg_send(int sock, const struct msghdr *msg)
+{
+
+	PJDLOG_ASSERT(sock >= 0);
+
+	for (;;) {
+		fd_wait(sock, false);
+		if (sendmsg(sock, msg, 0) == -1) {
+			if (errno == EINTR)
+				continue;
+			return (-1);
+		}
+		break;
+	}
+
+	return (0);
+}
+
+int
+cred_send(int sock)
+{
+	unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))];
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	struct iovec iov;
+	uint8_t dummy;
+
+	bzero(credbuf, sizeof(credbuf));
+	bzero(&msg, sizeof(msg));
+	bzero(&iov, sizeof(iov));
+
+	/*
+	 * XXX: We send one byte along with the control message, because
+	 *      setting msg_iov to NULL only works if this is the first
+	 *      packet send over the socket. Once we send some data we
+	 *      won't be able to send credentials anymore. This is most
+	 *      likely a kernel bug.
+	 */
+	dummy = 0;
+	iov.iov_base = &dummy;
+	iov.iov_len = sizeof(dummy);
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = credbuf;
+	msg.msg_controllen = sizeof(credbuf);
+
+	cmsg = CMSG_FIRSTHDR(&msg);
+	cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_CREDS;
+
+	if (msg_send(sock, &msg) == -1)
+		return (-1);
+
+	return (0);
+}
+
+int
+cred_recv(int sock, struct cmsgcred *cred)
+{
+	unsigned char credbuf[CMSG_SPACE(sizeof(struct cmsgcred))];
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	struct iovec iov;
+	uint8_t dummy;
+
+	bzero(credbuf, sizeof(credbuf));
+	bzero(&msg, sizeof(msg));
+	bzero(&iov, sizeof(iov));
+
+	iov.iov_base = &dummy;
+	iov.iov_len = sizeof(dummy);
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = credbuf;
+	msg.msg_controllen = sizeof(credbuf);
+
+	if (msg_recv(sock, &msg) == -1)
+		return (-1);
+
+	cmsg = CMSG_FIRSTHDR(&msg);
+	if (cmsg == NULL ||
+	    cmsg->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred)) ||
+	    cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDS) {
+		errno = EINVAL;
+		return (-1);
+	}
+	bcopy(CMSG_DATA(cmsg), cred, sizeof(*cred));
+
+	return (0);
+}
+
+static int
+fd_package_send(int sock, const int *fds, size_t nfds)
+{
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	struct iovec iov;
+	unsigned int i;
+	int serrno, ret;
+	uint8_t dummy;
+
+	PJDLOG_ASSERT(sock >= 0);
+	PJDLOG_ASSERT(fds != NULL);
+	PJDLOG_ASSERT(nfds > 0);
+
+	bzero(&msg, sizeof(msg));
+
+	/*
+	 * XXX: Look into cred_send function for more details.
+	 */
+	dummy = 0;
+	iov.iov_base = &dummy;
+	iov.iov_len = sizeof(dummy);
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
+	msg.msg_control = calloc(1, msg.msg_controllen);
+	if (msg.msg_control == NULL)
+		return (-1);
+
+	ret = -1;
+
+	for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL;
+	    i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (msghdr_add_fd(cmsg, fds[i]) == -1)
+			goto end;
+	}
+
+	if (msg_send(sock, &msg) == -1)
+		goto end;
+
+	ret = 0;
+end:
+	serrno = errno;
+	free(msg.msg_control);
+	errno = serrno;
+	return (ret);
+}
+
+static int
+fd_package_recv(int sock, int *fds, size_t nfds)
+{
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	unsigned int i;
+	int serrno, ret;
+	struct iovec iov;
+	uint8_t dummy;
+
+	PJDLOG_ASSERT(sock >= 0);
+	PJDLOG_ASSERT(nfds > 0);
+	PJDLOG_ASSERT(fds != NULL);
+
+	i = 0;
+	bzero(&msg, sizeof(msg));
+	bzero(&iov, sizeof(iov));
+
+	/*
+	 * XXX: Look into cred_send function for more details.
+	 */
+	iov.iov_base = &dummy;
+	iov.iov_len = sizeof(dummy);
+
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
+	msg.msg_control = calloc(1, msg.msg_controllen);
+	if (msg.msg_control == NULL)
+		return (-1);
+
+	ret = -1;
+
+	if (msg_recv(sock, &msg) == -1)
+		goto end;
+
+	for (i = 0, cmsg = CMSG_FIRSTHDR(&msg); i < nfds && cmsg != NULL;
+	    i++, cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		fds[i] = msghdr_get_fd(cmsg);
+		if (fds[i] < 0)
+			break;
+	}
+
+	if (cmsg != NULL || i < nfds) {
+		int fd;
+
+		/*
+		 * We need to close all received descriptors, even if we have
+		 * different control message (eg. SCM_CREDS) in between.
+		 */
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+		    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			fd = msghdr_get_fd(cmsg);
+			if (fd >= 0)
+				close(fd);
+		}
+		errno = EINVAL;
+		goto end;
+	}
+
+	ret = 0;
+end:
+	serrno = errno;
+	free(msg.msg_control);
+	errno = serrno;
+	return (ret);
+}
+
+int
+fd_recv(int sock, int *fds, size_t nfds)
+{
+	unsigned int i, step, j;
+	int ret, serrno;
+
+	if (nfds == 0 || fds == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	ret = i = step = 0;
+	while (i < nfds) {
+		if (PKG_MAX_SIZE < nfds - i)
+			step = PKG_MAX_SIZE;
+		else
+			step = nfds - i;
+		ret = fd_package_recv(sock, fds + i, step);
+		if (ret != 0) {
+			/* Close all received descriptors. */
+			serrno = errno;
+			for (j = 0; j < i; j++)
+				close(fds[j]);
+			errno = serrno;
+			break;
+		}
+		i += step;
+	}
+
+	return (ret);
+}
+
+int
+fd_send(int sock, const int *fds, size_t nfds)
+{
+	unsigned int i, step;
+	int ret;
+
+	if (nfds == 0 || fds == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	ret = i = step = 0;
+	while (i < nfds) {
+		if (PKG_MAX_SIZE < nfds - i)
+			step = PKG_MAX_SIZE;
+		else
+			step = nfds - i;
+		ret = fd_package_send(sock, fds + i, step);
+		if (ret != 0)
+			break;
+		i += step;
+	}
+
+	return (ret);
+}
+
+int
+buf_send(int sock, void *buf, size_t size)
+{
+	ssize_t done;
+	unsigned char *ptr;
+
+	PJDLOG_ASSERT(sock >= 0);
+	PJDLOG_ASSERT(size > 0);
+	PJDLOG_ASSERT(buf != NULL);
+
+	ptr = buf;
+	do {
+		fd_wait(sock, false);
+		done = send(sock, ptr, size, 0);
+		if (done == -1) {
+			if (errno == EINTR)
+				continue;
+			return (-1);
+		} else if (done == 0) {
+			errno = ENOTCONN;
+			return (-1);
+		}
+		size -= done;
+		ptr += done;
+	} while (size > 0);
+
+	return (0);
+}
+
+int
+buf_recv(int sock, void *buf, size_t size)
+{
+	ssize_t done;
+	unsigned char *ptr;
+
+	PJDLOG_ASSERT(sock >= 0);
+	PJDLOG_ASSERT(buf != NULL);
+
+	ptr = buf;
+	while (size > 0) {
+		fd_wait(sock, true);
+		done = recv(sock, ptr, size, 0);
+		if (done == -1) {
+			if (errno == EINTR)
+				continue;
+			return (-1);
+		} else if (done == 0) {
+			errno = ENOTCONN;
+			return (-1);
+		}
+		size -= done;
+		ptr += done;
+	}
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/msgio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/msgio.h
===================================================================
--- trunk/lib/libnv/msgio.h	                        (rev 0)
+++ trunk/lib/libnv/msgio.h	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,51 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Copyright (c) 2013 Mariusz Zaborski <oshogbo at FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/msgio.h 292631 2015-12-22 23:02:12Z ngie $
+ */
+
+#ifndef	_MSGIO_H_
+#define	_MSGIO_H_
+
+struct cmsgcred;
+struct iovec;
+struct msghdr;
+
+int cred_send(int sock);
+int cred_recv(int sock, struct cmsgcred *cred);
+
+int fd_send(int sock, const int *fds, size_t nfds);
+int fd_recv(int sock, int *fds, size_t nfds);
+
+int buf_send(int sock, void *buf, size_t size);
+int buf_recv(int sock, void *buf, size_t size);
+
+#endif	/* !_MSGIO_H_ */


Property changes on: trunk/lib/libnv/msgio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/nv.3
===================================================================
--- trunk/lib/libnv/nv.3	                        (rev 0)
+++ trunk/lib/libnv/nv.3	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,654 @@
+.\" $MidnightBSD$
+.\"
+.\" Copyright (c) 2013 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: stable/10/lib/libnv/nv.3 292637 2015-12-22 23:21:06Z ngie $
+.\"
+.Dd May 1, 2015
+.Dt NV 3
+.Os
+.Sh NAME
+.Nm nvlist_create ,
+.Nm nvlist_destroy ,
+.Nm nvlist_error ,
+.Nm nvlist_set_error ,
+.Nm nvlist_empty ,
+.Nm nvlist_flags ,
+.Nm nvlist_exists ,
+.Nm nvlist_free ,
+.Nm nvlist_clone ,
+.Nm nvlist_dump ,
+.Nm nvlist_fdump ,
+.Nm nvlist_size ,
+.Nm nvlist_pack ,
+.Nm nvlist_unpack ,
+.Nm nvlist_send ,
+.Nm nvlist_recv ,
+.Nm nvlist_xfer ,
+.Nm nvlist_next ,
+.Nm nvlist_add ,
+.Nm nvlist_move ,
+.Nm nvlist_get ,
+.Nm nvlist_take
+.Nd "library for name/value pairs"
+.Sh LIBRARY
+.Lb libnv
+.Sh SYNOPSIS
+.In nv.h
+.Ft "nvlist_t *"
+.Fn nvlist_create "int flags"
+.Ft void
+.Fn nvlist_destroy "nvlist_t *nvl"
+.Ft int
+.Fn nvlist_error "const nvlist_t *nvl"
+.Ft void
+.Fn nvlist_set_error "nvlist_t *nvl, int error"
+.Ft bool
+.Fn nvlist_empty "const nvlist_t *nvl"
+.Ft int
+.Fn nvlist_flags "const nvlist_t *nvl"
+.\"
+.Ft "nvlist_t *"
+.Fn nvlist_clone "const nvlist_t *nvl"
+.\"
+.Ft void
+.Fn nvlist_dump "const nvlist_t *nvl, int fd"
+.Ft void
+.Fn nvlist_fdump "const nvlist_t *nvl, FILE *fp"
+.\"
+.Ft size_t
+.Fn nvlist_size "const nvlist_t *nvl"
+.Ft "void *"
+.Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep"
+.Ft "nvlist_t *"
+.Fn nvlist_unpack "const void *buf" "size_t size"
+.\"
+.Ft int
+.Fn nvlist_send "int sock" "const nvlist_t *nvl"
+.Ft "nvlist_t *"
+.Fn nvlist_recv "int sock"
+.Ft "nvlist_t *"
+.Fn nvlist_xfer "int sock" "nvlist_t *nvl"
+.\"
+.Ft "const char *"
+.Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep"
+.\"
+.Ft bool
+.Fn nvlist_exists "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_type "const nvlist_t *nvl" "const char *name" "int type"
+.Ft bool
+.Fn nvlist_exists_null "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_bool "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_number "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_string "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_nvlist "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name"
+.Ft bool
+.Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name"
+.\"
+.Ft void
+.Fn nvlist_add_null "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_add_bool "nvlist_t *nvl" "const char *name" "bool value"
+.Ft void
+.Fn nvlist_add_number "nvlist_t *nvl" "const char *name" "uint64_t value"
+.Ft void
+.Fn nvlist_add_string "nvlist_t *nvl" "const char *name" "const char *value"
+.Ft void
+.Fn nvlist_add_stringf "nvlist_t *nvl" "const char *name" "const char *valuefmt" "..."
+.Ft void
+.Fn nvlist_add_stringv "nvlist_t *nvl" "const char *name" "const char *valuefmt" "va_list valueap"
+.Ft void
+.Fn nvlist_add_nvlist "nvlist_t *nvl" "const char *name" "const nvlist_t *value"
+.Ft void
+.Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value"
+.Ft void
+.Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size"
+.\"
+.Ft void
+.Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value"
+.Ft void
+.Fn nvlist_move_nvlist "nvlist_t *nvl" "const char *name" "nvlist_t *value"
+.Ft void
+.Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value"
+.Ft void
+.Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size"
+.\"
+.Ft bool
+.Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name"
+.Ft uint64_t
+.Fn nvlist_get_number "const nvlist_t *nvl" "const char *name"
+.Ft "const char *"
+.Fn nvlist_get_string "const nvlist_t *nvl" "const char *name"
+.Ft "const nvlist_t *"
+.Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name"
+.Ft int
+.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
+.Ft "const void *"
+.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
+.Ft "const nvlist_t *"
+.Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
+.\"
+.Ft bool
+.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
+.Ft uint64_t
+.Fn nvlist_take_number "nvlist_t *nvl" "const char *name"
+.Ft "char *"
+.Fn nvlist_take_string "nvlist_t *nvl" "const char *name"
+.Ft "nvlist_t *"
+.Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name"
+.Ft int
+.Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name"
+.Ft "void *"
+.Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep"
+.\"
+.Ft void
+.Fn nvlist_free "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_type "nvlist_t *nvl" "const char *name" "int type"
+.\"
+.Ft void
+.Fn nvlist_free_null "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_bool "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_number "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_string "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_nvlist "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name"
+.Ft void
+.Fn nvlist_free_binary "nvlist_t *nvl" "const char *name"
+.Sh DESCRIPTION
+The
+.Nm libnv
+library allows to easily manage name value pairs as well as send and receive
+them over sockets.
+A group (list) of name value pairs is called an
+.Nm nvlist .
+The API supports the following data types:
+.Bl -ohang -offset indent
+.It Sy null ( NV_TYPE_NULL )
+There is no data associated with the name.
+.It Sy bool ( NV_TYPE_BOOL )
+The value can be either
+.Dv true
+or
+.Dv false .
+.It Sy number ( NV_TYPE_NUMBER )
+The value is a number stored as
+.Vt uint64_t .
+.It Sy string ( NV_TYPE_STRING )
+The value is a C string.
+.It Sy nvlist ( NV_TYPE_NVLIST )
+The value is a nested nvlist.
+.It Sy descriptor ( NV_TYPE_DESCRIPTOR )
+The value is a file descriptor.
+Note that file descriptors can be sent only over
+.Xr unix 4
+domain sockets.
+.It Sy binary ( NV_TYPE_BINARY )
+The value is a binary buffer.
+.El
+.Pp
+The
+.Fn nvlist_create
+function allocates memory and initializes an nvlist.
+.Pp
+The following flag can be provided:
+.Pp
+.Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
+.It Dv NV_FLAG_IGNORE_CASE
+Perform case-insensitive lookups of provided names.
+.El
+.Pp
+The
+.Fn nvlist_destroy
+function destroys the given nvlist.
+Function does nothing if
+.Dv NULL
+nvlist is provided.
+Function never modifies the
+.Va errno
+global variable.
+.Pp
+The
+.Fn nvlist_error
+function returns any error value that the nvlist accumulated.
+If the given nvlist is
+.Dv NULL
+the
+.Er ENOMEM
+error will be returned.
+.Pp
+The
+.Fn nvlist_set_error
+function sets an nvlist to be in the error state.
+Subsequent calls to
+.Fn nvlist_error
+will return the given error value.
+This function cannot be used to clear the error state from an nvlist.
+This function does nothing if the nvlist is already in the error state.
+.Pp
+The
+.Fn nvlist_empty
+function returns
+.Dv true
+if the given nvlist is empty and
+.Dv false
+otherwise.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_flags
+function returns flags used to create the nvlist with the
+.Fn nvlist_create
+function.
+.Pp
+The
+.Fn nvlist_clone
+functions clones the given nvlist.
+The clone shares no resources with its origin.
+This also means that all file descriptors that are part of the nvlist will be
+duplicated with the
+.Xr dup 2
+system call before placing them in the clone.
+.Pp
+The
+.Fn nvlist_dump
+dumps nvlist content for debugging purposes to the given file descriptor
+.Fa fd .
+.Pp
+The
+.Fn nvlist_fdump
+dumps nvlist content for debugging purposes to the given file stream
+.Fa fp .
+.Pp
+The
+.Fn nvlist_size
+function returns the size of the given nvlist after converting it to binary
+buffer with the
+.Fn nvlist_pack
+function.
+.Pp
+The
+.Fn nvlist_pack
+function converts the given nvlist to a binary buffer.
+The function allocates memory for the buffer, which should be freed with the
+.Xr free 3
+function.
+If the
+.Fa sizep
+argument is not
+.Dv NULL ,
+the size of the buffer will be stored there.
+The function returns
+.Dv NULL
+in case of an error (allocation failure).
+If the nvlist contains any file descriptors
+.Dv NULL
+will be returned.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_unpack
+function converts the given buffer to the nvlist.
+The function returns
+.Dv NULL
+in case of an error.
+.Pp
+The
+.Fn nvlist_send
+function sends the given nvlist over the socket given by the
+.Fa sock
+argument.
+Note that nvlist that contains file descriptors can only be send over
+.Xr unix 4
+domain sockets.
+.Pp
+The
+.Fn nvlist_recv
+function receives nvlist over the socket given by the
+.Fa sock
+argument.
+.Pp
+The
+.Fn nvlist_xfer
+function sends the given nvlist over the socket given by the
+.Fa sock
+argument and receives nvlist over the same socket.
+The given nvlist is always destroyed.
+.Pp
+The
+.Fn nvlist_next
+function iterates over the given nvlist returning names and types of subsequent
+elements.
+The
+.Fa cookiep
+argument allows the function to figure out which element should be returned
+next.
+The
+.Va *cookiep
+should be set to
+.Dv NULL
+for the first call and should not be changed later.
+Returning
+.Dv NULL
+means there are no more elements on the nvlist.
+The
+.Fa typep
+argument can be NULL.
+Elements may not be removed from the nvlist while traversing it.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_exists
+function returns
+.Dv true
+if element of the given name exists (besides of its type) or
+.Dv false
+otherwise.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_exists_type
+function returns
+.Dv true
+if element of the given name and the given type exists or
+.Dv false
+otherwise.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_exists_null ,
+.Fn nvlist_exists_bool ,
+.Fn nvlist_exists_number ,
+.Fn nvlist_exists_string ,
+.Fn nvlist_exists_nvlist ,
+.Fn nvlist_exists_descriptor ,
+.Fn nvlist_exists_binary
+functions return
+.Dv true
+if element of the given name and the given type determined by the function name
+exists or
+.Dv false
+otherwise.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_add_null ,
+.Fn nvlist_add_bool ,
+.Fn nvlist_add_number ,
+.Fn nvlist_add_string ,
+.Fn nvlist_add_stringf ,
+.Fn nvlist_add_stringv ,
+.Fn nvlist_add_nvlist ,
+.Fn nvlist_add_descriptor ,
+.Fn nvlist_add_binary
+functions add element to the given nvlist.
+When adding string or binary buffor the functions will allocate memory
+and copy the data over.
+When adding nvlist, the nvlist will be cloned and clone will be added.
+When adding descriptor, the descriptor will be duplicated using the
+.Xr dup 2
+system call and the new descriptor will be added.
+If an error occurs while adding new element, internal error is set which can be
+examined using the
+.Fn nvlist_error
+function.
+.Pp
+The
+.Fn nvlist_move_string ,
+.Fn nvlist_move_nvlist ,
+.Fn nvlist_move_descriptor ,
+.Fn nvlist_move_binary
+functions add new element to the given nvlist, but unlike
+.Fn nvlist_add_<type>
+functions they will consume the given resource.
+If an error occurs while adding new element, the resource is destroyed and
+internal error is set which can be examined using the
+.Fn nvlist_error
+function.
+.Pp
+The
+.Fn nvlist_get_bool ,
+.Fn nvlist_get_number ,
+.Fn nvlist_get_string ,
+.Fn nvlist_get_nvlist ,
+.Fn nvlist_get_descriptor ,
+.Fn nvlist_get_binary
+functions allow to obtain value of the given name.
+In case of string, nvlist, descriptor or binary, returned resource should
+not be modified - it still belongs to the nvlist.
+If element of the given name does not exist, the program will be aborted.
+To avoid that the caller should check for existence before trying to obtain
+the value or use
+.Xr dnvlist 3
+extension, which allows to provide default value for a missing element.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_get_parent
+function allows to obtain the parent nvlist from the nested nvlist.
+.Pp
+The
+.Fn nvlist_take_bool ,
+.Fn nvlist_take_number ,
+.Fn nvlist_take_string ,
+.Fn nvlist_take_nvlist ,
+.Fn nvlist_take_descriptor ,
+.Fn nvlist_take_binary
+functions return value associated with the given name and remove the element
+from the nvlist.
+In case of string and binary values, the caller is responsible for free returned
+memory using the
+.Xr free 3
+function.
+In case of nvlist, the caller is responsible for destroying returned nvlist
+using the
+.Fn nvlist_destroy
+function.
+In case of descriptor, the caller is responsible for closing returned descriptor
+using the
+.Fn close 2
+system call.
+If element of the given name does not exist, the program will be aborted.
+To avoid that the caller should check for existence before trying to obtain
+the value or use
+.Xr dnvlist 3
+extension, which allows to provide default value for a missing element.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_free
+function removes element of the given name from the nvlist (besides of its type)
+and frees all resources associated with it.
+If element of the given name does not exist, the program will be aborted.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_free_type
+function removes element of the given name and the given type from the nvlist
+and frees all resources associated with it.
+If element of the given name and the given type does not exist, the program
+will be aborted.
+The nvlist must not be in error state.
+.Pp
+The
+.Fn nvlist_free_null ,
+.Fn nvlist_free_bool ,
+.Fn nvlist_free_number ,
+.Fn nvlist_free_string ,
+.Fn nvlist_free_nvlist ,
+.Fn nvlist_free_descriptor ,
+.Fn nvlist_free_binary
+functions remove element of the given name and the given type determined by the
+function name from the nvlist and free all resources associated with it.
+If element of the given name and the given type does not exist, the program
+will be aborted.
+The nvlist must not be in error state.
+.Sh EXAMPLES
+The following example demonstrates how to prepare an nvlist and send it over
+.Xr unix 4
+domain socket.
+.Bd -literal
+nvlist_t *nvl;
+int fd;
+
+fd = open("/tmp/foo", O_RDONLY);
+if (fd < 0)
+        err(1, "open(\\"/tmp/foo\\") failed");
+
+nvl = nvlist_create(0);
+/*
+ * There is no need to check if nvlist_create() succeeded,
+ * as the nvlist_add_<type>() functions can cope.
+ * If it failed, nvlist_send() will fail.
+ */
+nvlist_add_string(nvl, "filename", "/tmp/foo");
+nvlist_add_number(nvl, "flags", O_RDONLY);
+/*
+ * We just want to send the descriptor, so we can give it
+ * for the nvlist to consume (that's why we use nvlist_move
+ * not nvlist_add).
+ */
+nvlist_move_descriptor(nvl, "fd", fd);
+if (nvlist_send(sock, nvl) < 0) {
+	nvlist_destroy(nvl);
+	err(1, "nvlist_send() failed");
+}
+nvlist_destroy(nvl);
+.Ed
+.Pp
+Receiving nvlist and getting data:
+.Bd -literal
+nvlist_t *nvl;
+const char *command;
+char *filename;
+int fd;
+
+nvl = nvlist_recv(sock);
+if (nvl == NULL)
+	err(1, "nvlist_recv() failed");
+
+/* For command we take pointer to nvlist's buffer. */
+command = nvlist_get_string(nvl, "command");
+/*
+ * For filename we remove it from the nvlist and take
+ * ownership of the buffer.
+ */
+filename = nvlist_take_string(nvl, "filename");
+/* The same for the descriptor. */
+fd = nvlist_take_descriptor(nvl, "fd");
+
+printf("command=%s filename=%s fd=%d\n", command, filename, fd);
+
+nvlist_destroy(nvl);
+free(filename);
+close(fd);
+/* command was freed by nvlist_destroy() */
+.Ed
+.Pp
+Iterating over nvlist:
+.Bd -literal
+nvlist_t *nvl;
+const char *name;
+void *cookie;
+int type;
+
+nvl = nvlist_recv(sock);
+if (nvl == NULL)
+	err(1, "nvlist_recv() failed");
+
+cookie = NULL;
+while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
+	printf("%s=", name);
+	switch (type) {
+	case NV_TYPE_NUMBER:
+		printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
+		break;
+	case NV_TYPE_STRING:
+		printf("%s", nvlist_get_string(nvl, name));
+		break;
+	default:
+		printf("N/A");
+		break;
+	}
+	printf("\\n");
+}
+.Ed
+.Pp
+Iterating over every nested nvlist:
+.Bd -literal
+nvlist_t *nvl;
+const char *name;
+void *cookie;
+int type;
+
+nvl = nvlist_recv(sock);
+if (nvl == NULL)
+	err(1, "nvlist_recv() failed");
+
+cookie = NULL;
+do {
+	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
+		if (type == NV_TYPE_NVLIST) {
+			nvl = nvlist_get_nvlist(nvl, name);
+			cookie = NULL;
+		}
+	}
+} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
+.Ed
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr dup 2 ,
+.Xr open 2 ,
+.Xr err 3 ,
+.Xr free 3 ,
+.Xr printf 3 ,
+.Xr unix 4
+.Sh HISTORY
+The
+.Nm libnv
+library appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm libnv
+library was implemented by
+.An Pawel Jakub Dawidek Aq pawel at dawidek.net
+under sponsorship from the FreeBSD Foundation.


Property changes on: trunk/lib/libnv/nv.3
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/Makefile
===================================================================
--- trunk/lib/libnv/tests/Makefile	                        (rev 0)
+++ trunk/lib/libnv/tests/Makefile	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,20 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/lib/libnv/tests/Makefile 313488 2017-02-09 22:49:48Z ngie $
+
+ATF_TESTS_CXX=	\
+	dnv_tests \
+	nv_tests \
+
+TAP_TESTS_C+=	nvlist_add_test
+TAP_TESTS_C+=	nvlist_exists_test
+TAP_TESTS_C+=	nvlist_free_test
+TAP_TESTS_C+=	nvlist_get_test
+TAP_TESTS_C+=	nvlist_move_test
+TAP_TESTS_C+=	nvlist_send_recv_test
+
+DPADD+=		${LIBNV}
+LDADD+=		-lnv
+
+WARNS?=		3
+
+.include <bsd.test.mk>


Property changes on: trunk/lib/libnv/tests/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/dnv_tests.cc
===================================================================
--- trunk/lib/libnv/tests/dnv_tests.cc	                        (rev 0)
+++ trunk/lib/libnv/tests/dnv_tests.cc	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,568 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014-2015 Sandvine Inc.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libnv/tests/dnv_tests.cc 319370 2017-06-01 06:16:57Z ngie $");
+
+#include <atf-c++.hpp>
+#include <dnv.h>
+#include <nv.h>
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_bool__present);
+ATF_TEST_CASE_BODY(dnvlist_get_bool__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	bool value;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	value = true;
+	nvlist_add_bool(nvl, key, value);
+
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, key, false), value);
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, "name", false), value);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_bool__default_value);
+ATF_TEST_CASE_BODY(dnvlist_get_bool__default_value)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	key = "123";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, key, false), false);
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, "123", true), true);
+
+	nvlist_add_bool(nvl, key, true);
+
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, "otherkey", true), true);
+	ATF_REQUIRE_EQ(dnvlist_get_bool(nvl, "12c", false), false);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_number__present);
+ATF_TEST_CASE_BODY(dnvlist_get_number__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	uint64_t value;
+
+	nvl = nvlist_create(0);
+
+	key = "key";
+	value = 48952;
+	nvlist_add_number(nvl, key, value);
+
+	ATF_REQUIRE_EQ(dnvlist_get_number(nvl, key, 19), value);
+	ATF_REQUIRE_EQ(dnvlist_get_number(nvl, "key", 65), value);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_number__default_value);
+ATF_TEST_CASE_BODY(dnvlist_get_number__default_value)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	key = "123";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(dnvlist_get_number(nvl, key, 5), 5);
+	ATF_REQUIRE_EQ(dnvlist_get_number(nvl, "1234", 5), 5);
+
+	nvlist_add_number(nvl, key, 24841);
+
+	ATF_REQUIRE_EQ(dnvlist_get_number(nvl, "1234", 5641), 5641);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_string__present);
+ATF_TEST_CASE_BODY(dnvlist_get_string__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	const char *value, *actual_value;
+
+	nvl = nvlist_create(0);
+
+	key = "string";
+	value = "fjdojfdi";
+	nvlist_add_string(nvl, key, value);
+
+	ATF_REQUIRE_EQ(strcmp(dnvlist_get_string(nvl, key, "g"), value), 0);
+
+	actual_value = dnvlist_get_string(nvl, key, "rs");
+	ATF_REQUIRE_EQ(strcmp(actual_value, value), 0);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_string__default_value);
+ATF_TEST_CASE_BODY(dnvlist_get_string__default_value)
+{
+	nvlist_t *nvl;
+	const char *key;
+	const char *actual_value;
+
+	key = "123";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(strcmp(dnvlist_get_string(nvl, key, "bar"), "bar"), 0);
+
+	actual_value = dnvlist_get_string(nvl, key, "d");
+	ATF_REQUIRE_EQ(strcmp(actual_value, "d"), 0);
+
+	nvlist_add_string(nvl, key, "cxhweh");
+
+	ATF_REQUIRE_EQ(strcmp(dnvlist_get_string(nvl, "hthth", "fd"), "fd"), 0);
+	actual_value = dnvlist_get_string(nvl, "5", "5");
+	ATF_REQUIRE_EQ(strcmp(actual_value, "5"), 0);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_nvlist__present);
+ATF_TEST_CASE_BODY(dnvlist_get_nvlist__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	nvlist_t *value;
+	const nvlist_t *actual_value;
+
+	nvl = nvlist_create(0);
+
+	key = "nvlist";
+	value = nvlist_create(0);
+	nvlist_move_nvlist(nvl, key, value);
+
+	actual_value = dnvlist_get_nvlist(nvl, key, NULL);
+	ATF_REQUIRE(actual_value != NULL);
+	ATF_REQUIRE(nvlist_empty(actual_value));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_nvlist__default_value);
+ATF_TEST_CASE_BODY(dnvlist_get_nvlist__default_value)
+{
+	nvlist_t *nvl;
+	const char *key;
+	nvlist_t *dummy;
+
+	key = "123";
+	nvl = nvlist_create(0);
+	dummy = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(dnvlist_get_nvlist(nvl, key, dummy), dummy);
+
+	nvlist_move_nvlist(nvl, key, nvlist_create(0));
+	ATF_REQUIRE_EQ(dnvlist_get_nvlist(nvl, "456", dummy), dummy);
+	ATF_REQUIRE_EQ(dnvlist_get_nvlist(nvl, "gh", dummy), dummy);
+
+	nvlist_destroy(nvl);
+}
+
+static void
+set_const_binary_value(const void *&value, size_t &size, const char *str)
+{
+
+	value = str;
+	size = strlen(str) + 1; /* +1 to include '\0' */
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_binary__present);
+ATF_TEST_CASE_BODY(dnvlist_get_binary__present)
+{
+	nvlist_t *nvl;
+	const char *k;
+	const void *value, *actual_value;
+	size_t value_size, actual_size;
+
+	nvl = nvlist_create(0);
+
+	k = "binary";
+	set_const_binary_value(value, value_size, "fjdojfdi");
+	nvlist_add_binary(nvl, k, value, value_size);
+
+	actual_value = dnvlist_get_binary(nvl, k, &actual_size, "g", 1);
+	ATF_REQUIRE_EQ(value_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, value, actual_size), 0);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_get_binary__default_value);
+ATF_TEST_CASE_BODY(dnvlist_get_binary__default_value)
+{
+	nvlist_t *nvl;
+	const char *key;
+	const void *default_value, *actual_value;
+	size_t default_size, actual_size;
+
+	key = "123";
+	nvl = nvlist_create(0);
+
+	set_const_binary_value(default_value, default_size, "bar");
+	actual_value = dnvlist_get_binary(nvl, key, &actual_size, default_value,
+	    default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, default_value, actual_size), 0);
+
+	set_const_binary_value(default_value, default_size, "atf");
+	actual_value = dnvlist_get_binary(nvl, key, &actual_size, default_value,
+	    default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, default_value, actual_size), 0);
+
+	nvlist_add_binary(nvl, key, "test", 4);
+
+	set_const_binary_value(default_value, default_size, "bthrg");
+	actual_value = dnvlist_get_binary(nvl, "k", &actual_size, default_value,
+	    default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, default_value, actual_size), 0);
+
+	set_const_binary_value(default_value, default_size,
+	     "rrhgrythtyrtgbrhgrtdsvdfbtjlkul");
+	actual_value = dnvlist_get_binary(nvl, "s", &actual_size, default_value,
+	    default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, default_value, actual_size), 0);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_bool__present);
+ATF_TEST_CASE_BODY(dnvlist_take_bool__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	bool value;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	value = true;
+	nvlist_add_bool(nvl, key, value);
+
+	ATF_REQUIRE_EQ(dnvlist_take_bool(nvl, key, false), value);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_bool__empty);
+ATF_TEST_CASE_BODY(dnvlist_take_bool__empty)
+{
+	nvlist_t *nvl;
+
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(dnvlist_take_bool(nvl, "123", false), false);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_bool__default_value);
+ATF_TEST_CASE_BODY(dnvlist_take_bool__default_value)
+{
+	nvlist_t *nvl;
+
+	nvl = nvlist_create(0);
+	nvlist_add_bool(nvl, "key", true);
+
+	ATF_REQUIRE_EQ(dnvlist_take_bool(nvl, "otherkey", true), true);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_number__present);
+ATF_TEST_CASE_BODY(dnvlist_take_number__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	uint64_t value;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	value = 194154;
+	nvlist_add_number(nvl, key, value);
+
+	ATF_REQUIRE_EQ(dnvlist_take_number(nvl, key, 2), value);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_number__empty);
+ATF_TEST_CASE_BODY(dnvlist_take_number__empty)
+{
+	nvlist_t *nvl;
+
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE_EQ(dnvlist_take_number(nvl, "123", 126484), 126484);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_number__default_value);
+ATF_TEST_CASE_BODY(dnvlist_take_number__default_value)
+{
+	nvlist_t *nvl;
+
+	nvl = nvlist_create(0);
+	nvlist_add_number(nvl, "key", 12);
+
+	ATF_REQUIRE_EQ(dnvlist_take_number(nvl, "otherkey", 13), 13);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_string__present);
+ATF_TEST_CASE_BODY(dnvlist_take_string__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	const char *value;
+	char *default_val, *actual_val;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	value = "wrowm";
+	default_val = strdup("default");
+	nvlist_add_string(nvl, key, value);
+
+	actual_val = dnvlist_take_string(nvl, key, default_val);
+	ATF_REQUIRE_EQ(strcmp(actual_val, value), 0);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	free(actual_val);
+	free(default_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_string__empty);
+ATF_TEST_CASE_BODY(dnvlist_take_string__empty)
+{
+	nvlist_t *nvl;
+	char *default_val, *actual_val;
+
+	nvl = nvlist_create(0);
+	default_val = strdup("");
+
+	actual_val = dnvlist_take_string(nvl, "123", default_val);
+	ATF_REQUIRE_EQ(strcmp(actual_val, default_val), 0);
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_string__default_value);
+ATF_TEST_CASE_BODY(dnvlist_take_string__default_value)
+{
+	nvlist_t *nvl;
+	char *default_val, *actual_val;
+
+	nvl = nvlist_create(0);
+	nvlist_add_string(nvl, "key", "foobar");
+	default_val = strdup("other");
+
+	actual_val = dnvlist_take_string(nvl, "otherkey", default_val);
+	ATF_REQUIRE_EQ(strcmp(actual_val, default_val), 0);
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_nvlist__present);
+ATF_TEST_CASE_BODY(dnvlist_take_nvlist__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	nvlist_t *value, *default_val, *actual_val;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	value = nvlist_create(0);
+	default_val = nvlist_create(0);
+	nvlist_move_nvlist(nvl, key, value);
+
+	actual_val = dnvlist_take_nvlist(nvl, key, default_val);
+	ATF_REQUIRE_EQ(actual_val, value);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	free(actual_val);
+	free(default_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_nvlist__empty);
+ATF_TEST_CASE_BODY(dnvlist_take_nvlist__empty)
+{
+	nvlist_t *nvl, *actual_val;
+
+	nvl = nvlist_create(0);
+
+	actual_val = dnvlist_take_nvlist(nvl, "123", NULL);
+	ATF_REQUIRE_EQ(actual_val, static_cast<nvlist_t *>(NULL));
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_nvlist__default_value);
+ATF_TEST_CASE_BODY(dnvlist_take_nvlist__default_value)
+{
+	nvlist_t *nvl;
+	nvlist_t *default_val, *actual_val;
+
+	nvl = nvlist_create(0);
+	nvlist_move_nvlist(nvl, "key", nvlist_create(0));
+	default_val = nvlist_create(0);
+
+	actual_val = dnvlist_take_nvlist(nvl, "otherkey", default_val);
+	ATF_REQUIRE_EQ(actual_val, default_val);
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+static void
+set_binary_value(void *&value, size_t &size, const char *str)
+{
+
+	value = strdup(str);
+	size = strlen(str) + 1; /* +1 to include '\0' */
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_binary__present);
+ATF_TEST_CASE_BODY(dnvlist_take_binary__present)
+{
+	nvlist_t *nvl;
+	const char *key;
+	void *value, *default_val, *actual_val;
+	size_t value_size, default_size, actual_size;
+
+	nvl = nvlist_create(0);
+
+	key = "name";
+	set_binary_value(value, value_size, "fkdojvmo908");
+	set_binary_value(default_val, default_size, "16546");
+	nvlist_add_binary(nvl, key, value, value_size);
+
+	actual_val = dnvlist_take_binary(nvl, key, &actual_size, default_val,
+	    default_size);
+	ATF_REQUIRE_EQ(value_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_val, value, value_size), 0);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	free(actual_val);
+	free(default_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_binary__empty);
+ATF_TEST_CASE_BODY(dnvlist_take_binary__empty)
+{
+	nvlist_t *nvl;
+	void *default_val, *actual_val;
+	size_t default_size, actual_size;
+
+	nvl = nvlist_create(0);
+	set_binary_value(default_val, default_size, "\xa8\x89\x49\xff\xe2\x08");
+
+	actual_val = dnvlist_take_binary(nvl, "123", &actual_size, default_val,
+	    default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_val, default_val, actual_size), 0);
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(dnvlist_take_binary__default_value);
+ATF_TEST_CASE_BODY(dnvlist_take_binary__default_value)
+{
+	nvlist_t *nvl;
+	void *default_val, *actual_val;
+	size_t default_size, actual_size;
+
+	nvl = nvlist_create(0);
+	nvlist_add_binary(nvl, "key", "foobar", 6);
+	set_binary_value(default_val, default_size, "vbhag");
+
+	actual_val = dnvlist_take_binary(nvl, "otherkey", &actual_size,
+	    default_val, default_size);
+	ATF_REQUIRE_EQ(default_size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_val, default_val, default_size), 0);
+
+	free(actual_val);
+	nvlist_destroy(nvl);
+}
+
+ATF_INIT_TEST_CASES(tp)
+{
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_bool__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_bool__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_number__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_number__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_string__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_string__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_nvlist__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_nvlist__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_binary__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_get_binary__default_value);
+
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_bool__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_bool__empty);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_bool__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_number__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_number__empty);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_number__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_string__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_string__empty);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_string__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_nvlist__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_nvlist__empty);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_nvlist__default_value);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_binary__present);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_binary__empty);
+	ATF_ADD_TEST_CASE(tp, dnvlist_take_binary__default_value);
+}


Property changes on: trunk/lib/libnv/tests/dnv_tests.cc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nv_tests.cc
===================================================================
--- trunk/lib/libnv/tests/nv_tests.cc	                        (rev 0)
+++ trunk/lib/libnv/tests/nv_tests.cc	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,1242 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2014-2015 Sandvine Inc.  All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/lib/libnv/tests/nv_tests.cc 319370 2017-06-01 06:16:57Z ngie $");
+
+#include <atf-c++.hpp>
+#include <nv.h>
+
+#include <errno.h>
+#include <limits>
+#include <set>
+#include <sstream>
+#include <string>
+
+/*
+ * Test that a newly created nvlist has no errors, and is empty.
+ */
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_create__is_empty);
+ATF_TEST_CASE_BODY(nvlist_create__is_empty)
+{
+	nvlist_t *nvl;
+	int type;
+	void *it;
+
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+
+	ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	it = NULL;
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_null__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_null__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key;
+	int type;
+
+	key = "key";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_null(nvl, key);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists_null(nvl, key));
+	ATF_REQUIRE(nvlist_exists_null(nvl, "key"));
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_bool__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_bool__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key;
+	int type;
+
+	key = "name";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_bool(nvl, key, true);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists(nvl, "name"));
+	ATF_REQUIRE(nvlist_exists_bool(nvl, key));
+	ATF_REQUIRE(nvlist_exists_bool(nvl, "name"));
+	ATF_REQUIRE_EQ(nvlist_get_bool(nvl, key), true);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_BOOL);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_number__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_number__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key;
+	uint64_t value;
+	int type;
+
+	key = "foo123";
+	value = 71965;
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_number(nvl, key, value);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists(nvl, "foo123"));
+	ATF_REQUIRE(nvlist_exists_number(nvl, key));
+	ATF_REQUIRE_EQ(nvlist_get_number(nvl, key), value);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_string__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_string__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key;
+	const char *value;
+	int type;
+
+	key = "test";
+	value = "fgjdkgjdk";
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_string(nvl, key, value);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists(nvl, "test"));
+	ATF_REQUIRE(nvlist_exists_string(nvl, key));
+	ATF_REQUIRE(nvlist_exists_string(nvl, "test"));
+	ATF_REQUIRE_EQ(strcmp(nvlist_get_string(nvl, key), value), 0);
+
+	/* nvlist_add_* is required to clone the value, so check for that. */
+	ATF_REQUIRE(nvlist_get_string(nvl, key) != value);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_nvlist__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_nvlist__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key, *subkey;
+	nvlist_t *sublist;
+	const nvlist_t *value;
+	int type;
+
+	key = "test";
+	subkey = "subkey";
+	sublist = nvlist_create(0);
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_null(sublist, subkey);
+	nvlist_add_nvlist(nvl, key, sublist);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists(nvl, "test"));
+	ATF_REQUIRE(nvlist_exists_nvlist(nvl, key));
+	ATF_REQUIRE(nvlist_exists_nvlist(nvl, "test"));
+
+	value = nvlist_get_nvlist(nvl, key);
+	ATF_REQUIRE(nvlist_exists_null(value, subkey));
+
+	/* nvlist_add_* is required to clone the value, so check for that. */
+	ATF_REQUIRE(sublist != value);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(sublist);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_nvlist__child_with_error);
+ATF_TEST_CASE_BODY(nvlist_add_nvlist__child_with_error)
+{
+	nvlist_t *nvl, *parent;
+
+	nvl = nvlist_create(0);
+	parent = nvlist_create(0);
+
+	nvlist_set_error(nvl, EBADF);
+	nvlist_add_nvlist(parent, "test", nvl);
+	ATF_REQUIRE_EQ(nvlist_error(parent), EBADF);
+
+	nvlist_destroy(nvl);
+	nvlist_destroy(parent);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_add_binary__single_insert);
+ATF_TEST_CASE_BODY(nvlist_add_binary__single_insert)
+{
+	nvlist_t *nvl;
+	void *it;
+	const char *key;
+	void *value;
+	const void *ret_value;
+	size_t value_size, ret_size;
+	int type;
+
+	key = "binary";
+	value_size = 13;
+	value = malloc(value_size);
+	memset(value, 0xa5, value_size);
+	nvl = nvlist_create(0);
+
+	ATF_REQUIRE(nvl != NULL);
+	ATF_REQUIRE(!nvlist_exists(nvl, key));
+
+	nvlist_add_binary(nvl, key, value, value_size);
+
+	ATF_REQUIRE(!nvlist_empty(nvl));
+	ATF_REQUIRE(nvlist_exists(nvl, key));
+	ATF_REQUIRE(nvlist_exists(nvl, "binary"));
+	ATF_REQUIRE(nvlist_exists_binary(nvl, key));
+	ATF_REQUIRE(nvlist_exists_binary(nvl, "binary"));
+
+	ret_value = nvlist_get_binary(nvl, key, &ret_size);
+	ATF_REQUIRE_EQ(value_size, ret_size);
+	ATF_REQUIRE_EQ(memcmp(value, ret_value, ret_size), 0);
+
+	/* nvlist_add_* is required to clone the value, so check for that. */
+	ATF_REQUIRE(value != ret_value);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_BINARY);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type,&it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(nvl);
+	free(value);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone__empty_nvlist);
+ATF_TEST_CASE_BODY(nvlist_clone__empty_nvlist)
+{
+	nvlist_t *nvl, *clone;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	clone = nvlist_clone(nvl);
+	ATF_REQUIRE(clone != NULL);
+	ATF_REQUIRE(clone != nvl);
+	ATF_REQUIRE(nvlist_empty(clone));
+
+	nvlist_destroy(clone);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone__nonempty_nvlist);
+ATF_TEST_CASE_BODY(nvlist_clone__nonempty_nvlist)
+{
+	nvlist_t *nvl, *clone;
+	const char *key;
+	void *it;
+	uint64_t value;
+	int type;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	key = "testkey";
+	value = 684874;
+	nvlist_add_number(nvl, key, value);
+
+	clone = nvlist_clone(nvl);
+	ATF_REQUIRE(clone != NULL);
+	ATF_REQUIRE(clone != nvl);
+	ATF_REQUIRE(nvlist_exists_number(clone, key));
+	ATF_REQUIRE_EQ(nvlist_get_number(clone, key), value);
+
+	/* Iterate over the nvlist; ensure that it has only our one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(clone, &type, &it), key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+	ATF_REQUIRE_EQ(nvlist_next(clone, &type, &it), static_cast<const char *>(NULL));
+
+	nvlist_destroy(clone);
+	nvlist_destroy(nvl);
+}
+
+static const char * const test_subnvlist_key = "nvlist";
+
+static const char * const test_string_key = "string";
+static const char * const test_string_val = "59525";
+
+static nvlist_t*
+create_test_nvlist(void)
+{
+	nvlist_t *nvl, *sublist;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	sublist = nvlist_create(0);
+	ATF_REQUIRE(sublist != NULL);
+
+	nvlist_add_string(sublist, test_string_key, test_string_val);
+	nvlist_move_nvlist(nvl, test_subnvlist_key, sublist);
+
+	return (nvl);
+}
+
+static void
+verify_test_nvlist(const nvlist_t *nvl)
+{
+	void *it;
+	const nvlist_t *value;
+	int type;
+
+	ATF_REQUIRE(nvlist_exists_nvlist(nvl, test_subnvlist_key));
+
+	value = nvlist_get_nvlist(nvl, test_subnvlist_key);
+
+	ATF_REQUIRE(nvlist_exists_string(value, test_string_key));
+	ATF_REQUIRE_EQ(strcmp(nvlist_get_string(value, test_string_key), test_string_val), 0);
+	ATF_REQUIRE(nvlist_get_string(value, test_string_key) != test_string_val);
+
+	/* Iterate over both nvlists; ensure that each has only the one key. */
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(value, &type, &it),
+	    test_string_key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+	ATF_REQUIRE_EQ(nvlist_next(value, &type, &it), static_cast<const char *>(NULL));
+
+	it = NULL;
+	ATF_REQUIRE_EQ(strcmp(nvlist_next(nvl, &type, &it),
+	    test_subnvlist_key), 0);
+	ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+	ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &it), static_cast<const char *>(NULL));
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone__nested_nvlist);
+ATF_TEST_CASE_BODY(nvlist_clone__nested_nvlist)
+{
+	nvlist_t *nvl, *clone;
+
+	nvl = create_test_nvlist();
+	clone = nvlist_clone(nvl);
+
+	ATF_REQUIRE(clone != NULL);
+	ATF_REQUIRE(clone != nvl);
+	verify_test_nvlist(clone);
+
+	nvlist_destroy(clone);
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone__error_nvlist);
+ATF_TEST_CASE_BODY(nvlist_clone__error_nvlist)
+{
+	nvlist_t *nvl, *clone;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	nvlist_set_error(nvl, ENOMEM);
+
+	clone = nvlist_clone(nvl);
+	ATF_REQUIRE(clone == NULL);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_pack__empty_nvlist);
+ATF_TEST_CASE_BODY(nvlist_pack__empty_nvlist)
+{
+	nvlist_t *nvl, *unpacked;
+	void *packed;
+	size_t packed_size;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	packed = nvlist_pack(nvl, &packed_size);
+	ATF_REQUIRE(packed != NULL);
+
+	unpacked = nvlist_unpack(packed, packed_size);
+	ATF_REQUIRE(unpacked != NULL);
+	ATF_REQUIRE(unpacked != nvl);
+	ATF_REQUIRE(nvlist_empty(unpacked));
+
+	nvlist_destroy(unpacked);
+	nvlist_destroy(nvl);
+	free(packed);
+}
+
+static void
+verify_null(const nvlist_t *nvl, int type)
+{
+
+	ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+}
+
+static void
+verify_number(const nvlist_t *nvl, const char *name, int type, uint64_t value)
+{
+
+	ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+	ATF_REQUIRE_EQ(nvlist_get_number(nvl, name), value);
+}
+
+static void
+verify_string(const nvlist_t *nvl, const char *name, int type,
+    const char * value)
+{
+
+	ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+	ATF_REQUIRE_EQ(strcmp(nvlist_get_string(nvl, name), value), 0);
+}
+
+static void
+verify_nvlist(const nvlist_t *nvl, const char *name, int type)
+{
+
+	ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+	verify_test_nvlist(nvlist_get_nvlist(nvl, name));
+}
+
+static void
+verify_binary(const nvlist_t *nvl, const char *name, int type,
+    const void * value, size_t size)
+{
+	const void *actual_value;
+	size_t actual_size;
+
+	ATF_REQUIRE_EQ(type, NV_TYPE_BINARY);
+	actual_value = nvlist_get_binary(nvl, name, &actual_size);
+	ATF_REQUIRE_EQ(size, actual_size);
+	ATF_REQUIRE_EQ(memcmp(value, actual_value, size), 0);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_pack__multiple_values);
+ATF_TEST_CASE_BODY(nvlist_pack__multiple_values)
+{
+	std::ostringstream msg;
+	std::set<std::string> keys_seen;
+	nvlist_t *nvl, *unpacked, *nvvalue;
+	const char *nullkey, *numkey, *strkey, *nvkey, *binkey, *name;
+	int numvalue;
+	const char * strvalue;
+	void *binvalue, *packed, *it;
+	size_t binsize, packed_size;
+	int type;
+
+	nvl = nvlist_create(0);
+
+	nullkey = "null";
+	nvlist_add_null(nvl, nullkey);
+
+	numkey = "number";
+	numvalue = 939853984;
+	nvlist_add_number(nvl, numkey, numvalue);
+
+	strkey = "string";
+	strvalue = "jfieutijf";
+	nvlist_add_string(nvl, strkey, strvalue);
+
+	nvkey = "nvlist";
+	nvvalue = create_test_nvlist();
+	nvlist_move_nvlist(nvl, nvkey, nvvalue);
+
+	binkey = "binary";
+	binsize = 4;
+	binvalue = malloc(binsize);
+	memset(binvalue, 'b', binsize);
+	nvlist_move_binary(nvl, binkey, binvalue, binsize);
+
+	packed = nvlist_pack(nvl, &packed_size);
+	ATF_REQUIRE(packed != NULL);
+
+	unpacked = nvlist_unpack(packed, packed_size);
+	ATF_REQUIRE(unpacked != 0);
+
+	it = NULL;
+	while ((name = nvlist_next(unpacked, &type, &it)) != NULL) {
+		/* Ensure that we see every key only once. */
+		ATF_REQUIRE_EQ(keys_seen.count(name), 0);
+
+		if (strcmp(name, nullkey) == 0)
+			verify_null(unpacked, type);
+		else if (strcmp(name, numkey) == 0)
+			verify_number(unpacked, name, type, numvalue);
+		else if (strcmp(name, strkey) == 0)
+			verify_string(unpacked, name, type, strvalue);
+		else if (strcmp(name, nvkey) == 0)
+			verify_nvlist(unpacked, name, type);
+		else if (strcmp(name, binkey) == 0)
+			verify_binary(unpacked, name, type, binvalue, binsize);
+		else {
+			msg << "Unexpected key :'" << name << "'";
+			ATF_FAIL(msg.str().c_str());
+		}
+
+		keys_seen.insert(name);
+	}
+
+	/* Ensure that we saw every key. */
+	ATF_REQUIRE_EQ(keys_seen.size(), 5);
+
+	nvlist_destroy(nvl);
+	nvlist_destroy(unpacked);
+	free(packed);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_pack__error_nvlist);
+ATF_TEST_CASE_BODY(nvlist_pack__error_nvlist)
+{
+	nvlist_t *nvl;
+	void *packed;
+	size_t size;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	nvlist_set_error(nvl, ENOMEM);
+
+	packed = nvlist_pack(nvl, &size);
+	ATF_REQUIRE(packed == NULL);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_unpack__duplicate_key);
+ATF_TEST_CASE_BODY(nvlist_unpack__duplicate_key)
+{
+	nvlist_t *nvl, *unpacked;
+	const char *key1, *key2;
+	void *packed, *keypos;
+	size_t size, keylen;
+
+	nvl = nvlist_create(0);
+
+	key1 = "key1";
+	keylen = strlen(key1);
+	nvlist_add_number(nvl, key1, 5);
+
+	key2 = "key2";
+	ATF_REQUIRE_EQ(keylen, strlen(key2));
+	nvlist_add_number(nvl, key2, 10);
+
+	packed = nvlist_pack(nvl, &size);
+	ATF_REQUIRE(packed != NULL);
+
+	/*
+	 * Mangle the packed nvlist by replacing key1 with key2, creating a
+	 * packed nvlist with a duplicate key.
+	 */
+	keypos = memmem(packed, size, key1, keylen);
+	ATF_REQUIRE(keypos != NULL);
+	memcpy(keypos, key2, keylen);
+
+	unpacked = nvlist_unpack(packed, size);
+	ATF_REQUIRE(nvlist_error(unpacked) != 0);
+
+	free(packed);
+	nvlist_destroy(nvl);
+	nvlist_destroy(unpacked);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_move_string__single_insert);
+ATF_TEST_CASE_BODY(nvlist_move_string__single_insert)
+{
+	nvlist_t *nvl;
+	const char *key;
+	char *value;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	key = "testkey";
+	value = strdup("testval");
+	ATF_REQUIRE(value != NULL);
+
+	nvlist_move_string(nvl, key, value);
+	ATF_REQUIRE_EQ(nvlist_get_string(nvl, key), value);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_move_nvlist__null_child);
+ATF_TEST_CASE_BODY(nvlist_move_nvlist__null_child)
+{
+	nvlist_t *parent;
+
+	parent = nvlist_create(0);
+
+	nvlist_move_nvlist(parent, "test", NULL);
+
+	ATF_REQUIRE(nvlist_error(parent) != 0);
+
+	nvlist_destroy(parent);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_move_nvlist__child_with_error);
+ATF_TEST_CASE_BODY(nvlist_move_nvlist__child_with_error)
+{
+	nvlist_t *nvl, *parent;
+
+	nvl = nvlist_create(0);
+	parent = nvlist_create(0);
+
+	nvlist_set_error(nvl, EBADF);
+	nvlist_move_nvlist(parent, "test", nvl);
+	ATF_REQUIRE_EQ(nvlist_error(parent), EBADF);
+
+	nvlist_destroy(parent);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_move_nvlist__single_insert);
+ATF_TEST_CASE_BODY(nvlist_move_nvlist__single_insert)
+{
+	nvlist_t *nvl;
+	const char *key;
+	nvlist_t *value;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	key = "testkey";
+	value = nvlist_create(0);
+	ATF_REQUIRE(value != NULL);
+
+	nvlist_move_nvlist(nvl, key, value);
+	ATF_REQUIRE_EQ(nvlist_get_nvlist(nvl, key), value);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_move_binary__single_insert);
+ATF_TEST_CASE_BODY(nvlist_move_binary__single_insert)
+{
+	nvlist_t *nvl;
+	const char *key;
+	void *value;
+	size_t size, actual_size;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	key = "testkey";
+	size = 73;
+	value = malloc(size);
+	ATF_REQUIRE(value != NULL);
+
+	nvlist_move_binary(nvl, key, value, size);
+	ATF_REQUIRE_EQ(nvlist_get_binary(nvl, key, &actual_size), value);
+	ATF_REQUIRE_EQ(size, actual_size);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_bool__single_remove);
+ATF_TEST_CASE_BODY(nvlist_take_bool__single_remove)
+{
+	nvlist_t *nvl;
+	const char *testkey;
+	bool testval;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "boolkey";
+	testval = false;
+	nvlist_add_bool(nvl, testkey, testval);
+
+	ATF_REQUIRE_EQ(nvlist_take_bool(nvl, testkey), testval);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_bool__other_keys_unchanged);
+ATF_TEST_CASE_BODY(nvlist_take_bool__other_keys_unchanged)
+{
+	nvlist_t *nvl;
+	const char *testkey, *otherkey1, *otherkey2;
+	bool testval, otherval1;
+	nvlist_t *otherval2;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "boolkey";
+	testval = true;
+	nvlist_add_bool(nvl, testkey, testval);
+
+	otherkey1 = "key1";
+	otherval1 = false;
+	nvlist_add_bool(nvl, otherkey1, otherval1);
+
+	otherkey2 = "key2";
+	otherval2 = create_test_nvlist();
+	nvlist_move_nvlist(nvl, otherkey2, otherval2);
+
+	ATF_REQUIRE_EQ(nvlist_take_bool(nvl, testkey), testval);
+
+	ATF_REQUIRE(nvlist_exists_bool(nvl, otherkey1));
+	ATF_REQUIRE_EQ(nvlist_get_bool(nvl, otherkey1), otherval1);
+
+	ATF_REQUIRE(nvlist_exists_nvlist(nvl, otherkey2));
+	verify_test_nvlist(nvlist_get_nvlist(nvl, otherkey2));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_number__single_remove);
+ATF_TEST_CASE_BODY(nvlist_take_number__single_remove)
+{
+	nvlist_t *nvl;
+	const char *testkey;
+	uint64_t testval;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "numkey";
+	testval = std::numeric_limits<uint64_t>::max();
+	nvlist_add_number(nvl, testkey, testval);
+
+	ATF_REQUIRE_EQ(nvlist_take_number(nvl, testkey), testval);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_number__other_keys_unchanged);
+ATF_TEST_CASE_BODY(nvlist_take_number__other_keys_unchanged)
+{
+	nvlist_t *nvl;
+	const char *testkey, *otherkey1, *otherkey2;
+	uint64_t testval, otherval1;
+	const char *otherval2;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	otherkey1 = "key1";
+	otherval1 = 5;
+	nvlist_add_number(nvl, otherkey1, otherval1);
+
+	testkey = "numkey";
+	testval = 1654;
+	nvlist_add_number(nvl, testkey, testval);
+
+	otherkey2 = "key2";
+	otherval2 = "string";
+	nvlist_add_string(nvl, otherkey2, otherval2);
+
+	ATF_REQUIRE_EQ(nvlist_take_number(nvl, testkey), testval);
+
+	ATF_REQUIRE(nvlist_exists_number(nvl, otherkey1));
+	ATF_REQUIRE_EQ(nvlist_get_number(nvl, otherkey1), otherval1);
+
+	ATF_REQUIRE(nvlist_exists_string(nvl, otherkey2));
+	ATF_REQUIRE_EQ(strcmp(nvlist_get_string(nvl, otherkey2), otherval2), 0);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_string__single_remove);
+ATF_TEST_CASE_BODY(nvlist_take_string__single_remove)
+{
+	nvlist_t *nvl;
+	const char *testkey;
+	const char *testval;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "numkey";
+	testval = "nvlist";
+	nvlist_add_string(nvl, testkey, testval);
+
+	ATF_REQUIRE_EQ(strcmp(nvlist_take_string(nvl, testkey), testval), 0);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_string__other_keys_unchanged);
+ATF_TEST_CASE_BODY(nvlist_take_string__other_keys_unchanged)
+{
+	nvlist_t *nvl;
+	const char *testkey, *otherkey1, *otherkey2;
+	const char *testval, *otherval1;
+	bool otherval2;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	otherkey1 = "key1";
+	otherval1 = "fjdifjdk";
+	nvlist_add_string(nvl, otherkey1, otherval1);
+
+	otherkey2 = "key2";
+	otherval2 = true;
+	nvlist_add_bool(nvl, otherkey2, otherval2);
+
+	testkey = "strkey";
+	testval = "1654";
+	nvlist_add_string(nvl, testkey, testval);
+
+	ATF_REQUIRE_EQ(strcmp(nvlist_take_string(nvl, testkey), testval), 0);
+
+	ATF_REQUIRE(nvlist_exists_string(nvl, otherkey1));
+	ATF_REQUIRE_EQ(strcmp(nvlist_get_string(nvl, otherkey1), otherval1), 0);
+
+	ATF_REQUIRE(nvlist_exists_bool(nvl, otherkey2));
+	ATF_REQUIRE_EQ(nvlist_get_bool(nvl, otherkey2), otherval2);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_nvlist__single_remove);
+ATF_TEST_CASE_BODY(nvlist_take_nvlist__single_remove)
+{
+	nvlist_t *nvl;
+	const char *testkey;
+	nvlist_t *testval;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "numkey";
+	testval = create_test_nvlist();
+	nvlist_move_nvlist(nvl, testkey, testval);
+
+	verify_test_nvlist(nvlist_take_nvlist(nvl, testkey));
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_nvlist__other_keys_unchanged);
+ATF_TEST_CASE_BODY(nvlist_take_nvlist__other_keys_unchanged)
+{
+	nvlist_t *nvl;
+	const char *testkey, *otherkey1, *otherkey2;
+	nvlist_t *testval, *otherval1;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "strkey";
+	testval = create_test_nvlist();
+	nvlist_move_nvlist(nvl, testkey, testval);
+
+	otherkey1 = "key1";
+	otherval1 = nvlist_create(0);
+	nvlist_move_nvlist(nvl, otherkey1, otherval1);
+
+	otherkey2 = "key2";
+	nvlist_add_null(nvl, otherkey2);
+
+	verify_test_nvlist(nvlist_take_nvlist(nvl, testkey));
+
+	ATF_REQUIRE(nvlist_exists_nvlist(nvl, otherkey1));
+	ATF_REQUIRE(nvlist_empty(nvlist_get_nvlist(nvl, otherkey1)));
+
+	ATF_REQUIRE(nvlist_exists_null(nvl, otherkey2));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_binary__single_remove);
+ATF_TEST_CASE_BODY(nvlist_take_binary__single_remove)
+{
+	nvlist_t *nvl;
+	const char *testkey;
+	void *testval;
+	const void *actual_val;
+	size_t testsize, actual_size;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	testkey = "numkey";
+	testsize = 457;
+	testval = malloc(testsize);
+	memset(testval, '5', testsize);
+	nvlist_move_binary(nvl, testkey, testval, testsize);
+
+	actual_val = nvlist_take_binary(nvl, testkey, &actual_size);
+	ATF_REQUIRE_EQ(testsize, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_val, testval, testsize), 0);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_take_binary__other_keys_unchanged);
+ATF_TEST_CASE_BODY(nvlist_take_binary__other_keys_unchanged)
+{
+	nvlist_t *nvl;
+	const char *testkey, *otherkey1, *otherkey2;
+	const void *actual_value;
+	char testval[] = "gjiertj";
+	char otherval1[] = "fdreg";
+	size_t testsize, othersize, actual_size;
+	bool otherval2;
+
+	nvl = nvlist_create(0);
+	ATF_REQUIRE(nvl != NULL);
+
+	otherkey1 = "key1";
+	othersize = sizeof(otherval1);
+	nvlist_add_binary(nvl, otherkey1, otherval1, othersize);
+
+	otherkey2 = "key2";
+	otherval2 = true;
+	nvlist_add_bool(nvl, otherkey2, otherval2);
+
+	testkey = "strkey";
+	testsize = sizeof(testval);
+	nvlist_add_binary(nvl, testkey, testval, testsize);
+
+	actual_value = nvlist_take_binary(nvl, testkey, &actual_size);
+	ATF_REQUIRE_EQ(testsize, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, testval, testsize), 0);
+
+	ATF_REQUIRE(nvlist_exists_binary(nvl, otherkey1));
+	actual_value = nvlist_get_binary(nvl, otherkey1, &actual_size);
+	ATF_REQUIRE_EQ(othersize, actual_size);
+	ATF_REQUIRE_EQ(memcmp(actual_value, otherval1, othersize), 0);
+
+	ATF_REQUIRE(nvlist_exists_bool(nvl, otherkey2));
+	ATF_REQUIRE_EQ(nvlist_get_bool(nvl, otherkey2), otherval2);
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_null);
+ATF_TEST_CASE_BODY(nvlist_free__single_null)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_null(nvl, key);
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_bool);
+ATF_TEST_CASE_BODY(nvlist_free__single_bool)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_bool(nvl, key, true);
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_number);
+ATF_TEST_CASE_BODY(nvlist_free__single_number)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_number(nvl, key, 584);
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_string);
+ATF_TEST_CASE_BODY(nvlist_free__single_string)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_string(nvl, key, "gjkfkjd");
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_nvlist);
+ATF_TEST_CASE_BODY(nvlist_free__single_nvlist)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_nvlist(nvl, key, nvlist_create(0));
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free__single_binary);
+ATF_TEST_CASE_BODY(nvlist_free__single_binary)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_binary(nvl, key, "jgjgfd", 6);
+
+	nvlist_free(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_null__single_null);
+ATF_TEST_CASE_BODY(nvlist_free_null__single_null)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_null(nvl, key);
+
+	nvlist_free_null(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_bool__single_bool);
+ATF_TEST_CASE_BODY(nvlist_free_bool__single_bool)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_bool(nvl, key, true);
+
+	nvlist_free_bool(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_number__single_number);
+ATF_TEST_CASE_BODY(nvlist_free_number__single_number)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_number(nvl, key, 584);
+
+	nvlist_free_number(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_string__single_string);
+ATF_TEST_CASE_BODY(nvlist_free_string__single_string)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_string(nvl, key, "gjkfkjd");
+
+	nvlist_free_string(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_nvlist__single_nvlist);
+ATF_TEST_CASE_BODY(nvlist_free_nvlist__single_nvlist)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_nvlist(nvl, key, nvlist_create(0));
+
+	nvlist_free_nvlist(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_free_binary__single_binary);
+ATF_TEST_CASE_BODY(nvlist_free_binary__single_binary)
+{
+	nvlist_t *nvl;
+	const char *key;
+
+	nvl = nvlist_create(0);
+	key = "test";
+	nvlist_add_binary(nvl, key, "jgjgfd", 6);
+
+	nvlist_free_binary(nvl, key);
+	ATF_REQUIRE(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+}
+
+ATF_INIT_TEST_CASES(tp)
+{
+	ATF_ADD_TEST_CASE(tp, nvlist_create__is_empty);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_null__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_bool__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_number__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_string__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_nvlist__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_nvlist__child_with_error);
+	ATF_ADD_TEST_CASE(tp, nvlist_add_binary__single_insert);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_clone__empty_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_clone__nonempty_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_clone__nested_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_clone__error_nvlist);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_pack__empty_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_pack__multiple_values);
+	ATF_ADD_TEST_CASE(tp, nvlist_pack__error_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_unpack__duplicate_key);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_move_string__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_move_nvlist__single_insert);
+	ATF_ADD_TEST_CASE(tp, nvlist_move_nvlist__null_child);
+	ATF_ADD_TEST_CASE(tp, nvlist_move_nvlist__child_with_error);
+	ATF_ADD_TEST_CASE(tp, nvlist_move_binary__single_insert);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_take_bool__single_remove);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_bool__other_keys_unchanged);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_number__single_remove);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_number__other_keys_unchanged);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_string__single_remove);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_string__other_keys_unchanged);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_nvlist__single_remove);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_nvlist__other_keys_unchanged);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_binary__single_remove);
+	ATF_ADD_TEST_CASE(tp, nvlist_take_binary__other_keys_unchanged);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_null);
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_bool);
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_number);
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_string);
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_free__single_binary);
+
+	ATF_ADD_TEST_CASE(tp, nvlist_free_null__single_null);
+	ATF_ADD_TEST_CASE(tp, nvlist_free_bool__single_bool);
+	ATF_ADD_TEST_CASE(tp, nvlist_free_number__single_number);
+	ATF_ADD_TEST_CASE(tp, nvlist_free_string__single_string);
+	ATF_ADD_TEST_CASE(tp, nvlist_free_nvlist__single_nvlist);
+	ATF_ADD_TEST_CASE(tp, nvlist_free_binary__single_binary);
+}


Property changes on: trunk/lib/libnv/tests/nv_tests.cc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_add_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_add_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_add_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,197 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_add_test.c 269603 2014-08-05 18:41:27Z ngie $
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+int
+main(void)
+{
+	const nvlist_t *cnvl;
+	nvlist_t *nvl;
+
+	printf("1..94\n");
+
+	nvl = nvlist_create(0);
+
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	nvlist_add_null(nvl, "nvlist/null");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true"));
+	nvlist_add_bool(nvl, "nvlist/bool/true", true);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true"));
+
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false"));
+	nvlist_add_bool(nvl, "nvlist/bool/false", false);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/0"));
+	nvlist_add_number(nvl, "nvlist/number/0", 0);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/0"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/1"));
+	nvlist_add_number(nvl, "nvlist/number/1", 1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/1"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1"));
+	nvlist_add_number(nvl, "nvlist/number/-1", -1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/-1"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX"));
+	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN"));
+	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN"));
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX"));
+	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/"));
+	nvlist_add_string(nvl, "nvlist/string/", "");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/x"));
+	nvlist_add_string(nvl, "nvlist/string/x", "x");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/x"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/"));
+	nvlist_add_stringf(nvl, "nvlist/stringf/", "%s", "");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/x"));
+	nvlist_add_stringf(nvl, "nvlist/stringf/x", "%s", "x");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/666Xabc"));
+	nvlist_add_stringf(nvl, "nvlist/stringf/666Xabc", "%d%c%s", 666, 'X', "abc");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc"));
+
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x"));
+
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/0"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/1"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/-1"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/x"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+
+	cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist");
+	CHECK(nvlist_exists_null(cnvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/true"));
+	CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/false"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/0"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/1"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/-1"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/UINT64_MAX"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MIN"));
+	CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MAX"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/string/"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/string/x"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/x"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/666Xabc"));
+	CHECK(nvlist_exists_descriptor(cnvl, "nvlist/descriptor/STDERR_FILENO"));
+	CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x"));
+	CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+
+	nvlist_destroy(nvl);
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_add_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_exists_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_exists_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_exists_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,322 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_exists_test.c 269603 2014-08-05 18:41:27Z ngie $
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+int
+main(void)
+{
+	nvlist_t *nvl;
+
+	printf("1..232\n");
+
+	nvl = nvlist_create(0);
+
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/null"));
+	nvlist_add_null(nvl, "nvlist/null");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/null"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/bool"));
+	nvlist_add_bool(nvl, "nvlist/bool", true);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/bool"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/number"));
+	nvlist_add_number(nvl, "nvlist/number", 0);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/number"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/string"));
+	nvlist_add_string(nvl, "nvlist/string", "test");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/string"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist"));
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor"));
+	nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor"));
+
+	CHECK(!nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary"));
+	nvlist_add_binary(nvl, "nvlist/binary", "test", 4);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	CHECK(nvlist_exists(nvl, "nvlist/null"));
+	CHECK(nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists(nvl, "nvlist/number"));
+	CHECK(nvlist_exists(nvl, "nvlist/string"));
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_null(nvl, "nvlist/null");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists(nvl, "nvlist/number"));
+	CHECK(nvlist_exists(nvl, "nvlist/string"));
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_bool(nvl, "nvlist/bool");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists(nvl, "nvlist/number"));
+	CHECK(nvlist_exists(nvl, "nvlist/string"));
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_number(nvl, "nvlist/number");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(nvlist_exists(nvl, "nvlist/string"));
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_string(nvl, "nvlist/string");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists(nvl, "nvlist/string"));
+	CHECK(nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_nvlist(nvl, "nvlist/nvlist");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_descriptor(nvl, "nvlist/descriptor");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_binary(nvl, "nvlist/binary");
+	CHECK(!nvlist_exists(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists(nvl, "nvlist/binary"));
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	CHECK(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_exists_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_free_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_free_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_free_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,222 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_free_test.c 269603 2014-08-05 18:41:27Z ngie $
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+int
+main(void)
+{
+	nvlist_t *nvl;
+
+	printf("1..114\n");
+
+	nvl = nvlist_create(0);
+
+	nvlist_add_null(nvl, "nvlist/null");
+	nvlist_add_bool(nvl, "nvlist/bool", true);
+	nvlist_add_number(nvl, "nvlist/number", 0);
+	nvlist_add_string(nvl, "nvlist/string", "test");
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+	nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO);
+	nvlist_add_binary(nvl, "nvlist/binary", "test", 4);
+
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_null(nvl, "nvlist/null");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_bool(nvl, "nvlist/bool");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_number(nvl, "nvlist/number");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_string(nvl, "nvlist/string");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_nvlist(nvl, "nvlist/nvlist");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_descriptor(nvl, "nvlist/descriptor");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free_binary(nvl, "nvlist/binary");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	CHECK(nvlist_empty(nvl));
+
+	nvlist_add_null(nvl, "nvlist/null");
+	nvlist_add_bool(nvl, "nvlist/bool", true);
+	nvlist_add_number(nvl, "nvlist/number", 0);
+	nvlist_add_string(nvl, "nvlist/string", "test");
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+	nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO);
+	nvlist_add_binary(nvl, "nvlist/binary", "test", 4);
+
+	CHECK(nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/null");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/bool");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/number");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/string");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/nvlist");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/descriptor");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	nvlist_free(nvl, "nvlist/binary");
+	CHECK(!nvlist_exists_null(nvl, "nvlist/null"));
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool"));
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number"));
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string"));
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor"));
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary"));
+
+	CHECK(nvlist_empty(nvl));
+
+	nvlist_destroy(nvl);
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_free_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_get_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_get_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_get_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,183 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_get_test.c 269603 2014-08-05 18:41:27Z ngie $
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+#define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+int
+main(void)
+{
+	const nvlist_t *cnvl;
+	nvlist_t *nvl;
+	size_t size;
+
+	printf("1..83\n");
+
+	nvl = nvlist_create(0);
+
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true"));
+	nvlist_add_bool(nvl, "nvlist/bool/true", true);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true);
+
+	CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false"));
+	nvlist_add_bool(nvl, "nvlist/bool/false", false);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/0"));
+	nvlist_add_number(nvl, "nvlist/number/0", 0);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/1"));
+	nvlist_add_number(nvl, "nvlist/number/1", 1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1"));
+	nvlist_add_number(nvl, "nvlist/number/-1", -1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX"));
+	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN"));
+	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN);
+
+	CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX"));
+	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX);
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/"));
+	nvlist_add_string(nvl, "nvlist/string/", "");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0);
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/x"));
+	nvlist_add_string(nvl, "nvlist/string/x", "x");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0);
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0);
+
+	CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")));
+
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0);
+	CHECK(size == 1);
+
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+	CHECK(nvlist_error(nvl) == 0);
+	cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist");
+	CHECK(nvlist_get_bool(cnvl, "nvlist/bool/true") == true);
+	CHECK(nvlist_get_bool(cnvl, "nvlist/bool/false") == false);
+	CHECK(nvlist_get_number(cnvl, "nvlist/number/0") == 0);
+	CHECK(nvlist_get_number(cnvl, "nvlist/number/1") == 1);
+	CHECK((int)nvlist_get_number(cnvl, "nvlist/number/-1") == -1);
+	CHECK(nvlist_get_number(cnvl, "nvlist/number/UINT64_MAX") == UINT64_MAX);
+	CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MIN") == INT64_MIN);
+	CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MAX") == INT64_MAX);
+	CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/"), "") == 0);
+	CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/x"), "x") == 0);
+	CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0);
+	/* TODO */
+	CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", NULL), "x", 1) == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", &size), "x", 1) == 0);
+	CHECK(size == 1);
+	CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true);
+	CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1);
+	CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1);
+	CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX);
+	CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN);
+	CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0);
+	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")));
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0);
+	CHECK(size == 1);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	nvlist_destroy(nvl);
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_get_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_move_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_move_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_move_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,162 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_move_test.c 269603 2014-08-05 18:41:27Z ngie $
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+int
+main(void)
+{
+	const nvlist_t *cnvl;
+	nvlist_t *nvl;
+	void *ptr;
+	size_t size;
+	int fd;
+
+	printf("1..52\n");
+
+	nvl = nvlist_create(0);
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/"));
+	ptr = strdup("");
+	CHECK(ptr != NULL);
+	nvlist_move_string(nvl, "nvlist/string/", ptr);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/"));
+	CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/"));
+
+	CHECK(!nvlist_exists_string(nvl, "nvlist/string/x"));
+	ptr = strdup("x");
+	CHECK(ptr != NULL);
+	nvlist_move_string(nvl, "nvlist/string/x", ptr);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/x"));
+	CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/x"));
+
+	CHECK(!nvlist_exists_string(nvl,
+	    "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	ptr = strdup("abcdefghijklmnopqrstuvwxyz");
+	CHECK(ptr != NULL);
+	nvlist_move_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz",
+	    ptr);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_string(nvl,
+	    "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(ptr ==
+	    nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(!nvlist_exists_descriptor(nvl,
+	    "nvlist/descriptor/STDERR_FILENO"));
+	fd = dup(STDERR_FILENO);
+	CHECK(fd >= 0);
+	nvlist_move_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", fd);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+	CHECK(fd ==
+	    nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+
+	CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	ptr = malloc(1);
+	CHECK(ptr != NULL);
+	memcpy(ptr, "x", 1);
+	nvlist_move_binary(nvl, "nvlist/binary/x", ptr, 1);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", NULL));
+	CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", &size));
+	CHECK(size == 1);
+
+	CHECK(!nvlist_exists_binary(nvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	ptr = malloc(sizeof("abcdefghijklmnopqrstuvwxyz"));
+	CHECK(ptr != NULL);
+	memcpy(ptr, "abcdefghijklmnopqrstuvwxyz",
+	    sizeof("abcdefghijklmnopqrstuvwxyz"));
+	nvlist_move_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz",
+	    ptr, sizeof("abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_binary(nvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(ptr == nvlist_get_binary(nvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL));
+	CHECK(ptr == nvlist_get_binary(nvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size));
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	ptr = nvlist_clone(nvl);
+	CHECK(ptr != NULL);
+	nvlist_move_nvlist(nvl, "nvlist/nvlist", ptr);
+	CHECK(nvlist_error(nvl) == 0);
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+	CHECK(ptr == nvlist_get_nvlist(nvl, "nvlist/nvlist"));
+
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/"));
+	CHECK(nvlist_exists_string(nvl, "nvlist/string/x"));
+	CHECK(nvlist_exists_string(nvl,
+	    "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"));
+	CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x"));
+	CHECK(nvlist_exists_binary(nvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist"));
+
+	cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist");
+	CHECK(nvlist_exists_string(cnvl, "nvlist/string/"));
+	CHECK(nvlist_exists_string(cnvl, "nvlist/string/x"));
+	CHECK(nvlist_exists_string(cnvl,
+	    "nvlist/string/abcdefghijklmnopqrstuvwxyz"));
+	CHECK(nvlist_exists_descriptor(cnvl,
+	    "nvlist/descriptor/STDERR_FILENO"));
+	CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x"));
+	CHECK(nvlist_exists_binary(cnvl,
+	    "nvlist/binary/abcdefghijklmnopqrstuvwxyz"));
+
+	nvlist_destroy(nvl);
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_move_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libnv/tests/nvlist_send_recv_test.c
===================================================================
--- trunk/lib/libnv/tests/nvlist_send_recv_test.c	                        (rev 0)
+++ trunk/lib/libnv/tests/nvlist_send_recv_test.c	2018-06-06 23:27:13 UTC (rev 10442)
@@ -0,0 +1,343 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/lib/libnv/tests/nvlist_send_recv_test.c 292634 2015-12-22 23:08:50Z ngie $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <nv.h>
+
+static int ntest = 1;
+
+#define	CHECK(expr)	do {						\
+	if ((expr))							\
+		printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__);	\
+	else								\
+		printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\
+	ntest++;							\
+} while (0)
+
+#define	fd_is_valid(fd)	(fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+static void
+child(int sock)
+{
+	nvlist_t *nvl;
+	nvlist_t *empty;
+
+	nvl = nvlist_create(0);
+	empty = nvlist_create(0);
+
+	nvlist_add_bool(nvl, "nvlist/bool/true", true);
+	nvlist_add_bool(nvl, "nvlist/bool/false", false);
+	nvlist_add_number(nvl, "nvlist/number/0", 0);
+	nvlist_add_number(nvl, "nvlist/number/1", 1);
+	nvlist_add_number(nvl, "nvlist/number/-1", -1);
+	nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX);
+	nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN);
+	nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX);
+	nvlist_add_string(nvl, "nvlist/string/", "");
+	nvlist_add_string(nvl, "nvlist/string/x", "x");
+	nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");
+	nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO);
+	nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
+	nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz"));
+	nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
+	nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+
+	nvlist_send(sock, nvl);
+
+	nvlist_destroy(nvl);
+}
+
+static void
+parent(int sock)
+{
+	nvlist_t *nvl;
+	const nvlist_t *cnvl, *empty;
+	const char *name, *cname;
+	void *cookie, *ccookie;
+	int type, ctype;
+	size_t size;
+
+	nvl = nvlist_recv(sock);
+	CHECK(nvlist_error(nvl) == 0);
+	if (nvlist_error(nvl) != 0)
+		err(1, "nvlist_recv() failed");
+
+	cookie = NULL;
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_BOOL);
+	CHECK(strcmp(name, "nvlist/bool/true") == 0);
+	CHECK(nvlist_get_bool(nvl, name) == true);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_BOOL);
+	CHECK(strcmp(name, "nvlist/bool/false") == 0);
+	CHECK(nvlist_get_bool(nvl, name) == false);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/0") == 0);
+	CHECK(nvlist_get_number(nvl, name) == 0);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/1") == 0);
+	CHECK(nvlist_get_number(nvl, name) == 1);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/-1") == 0);
+	CHECK((int)nvlist_get_number(nvl, name) == -1);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
+	CHECK(nvlist_get_number(nvl, name) == UINT64_MAX);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0);
+	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NUMBER);
+	CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0);
+	CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_STRING);
+	CHECK(strcmp(name, "nvlist/string/") == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_STRING);
+	CHECK(strcmp(name, "nvlist/string/x") == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_STRING);
+	CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
+	CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_DESCRIPTOR);
+	CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
+	CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name)));
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_BINARY);
+	CHECK(strcmp(name, "nvlist/binary/x") == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
+	CHECK(size == 1);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_BINARY);
+	CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NVLIST);
+	CHECK(strcmp(name, "nvlist/nvlist/empty") == 0);
+	cnvl = nvlist_get_nvlist(nvl, name);
+	CHECK(nvlist_empty(cnvl));
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name != NULL);
+	CHECK(type == NV_TYPE_NVLIST);
+	CHECK(strcmp(name, "nvlist/nvlist") == 0);
+	cnvl = nvlist_get_nvlist(nvl, name);
+
+	ccookie = NULL;
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_BOOL);
+	CHECK(strcmp(cname, "nvlist/bool/true") == 0);
+	CHECK(nvlist_get_bool(cnvl, cname) == true);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_BOOL);
+	CHECK(strcmp(cname, "nvlist/bool/false") == 0);
+	CHECK(nvlist_get_bool(cnvl, cname) == false);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/0") == 0);
+	CHECK(nvlist_get_number(cnvl, cname) == 0);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/1") == 0);
+	CHECK(nvlist_get_number(cnvl, cname) == 1);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/-1") == 0);
+	CHECK((int)nvlist_get_number(cnvl, cname) == -1);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
+	CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
+	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NUMBER);
+	CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
+	CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_STRING);
+	CHECK(strcmp(cname, "nvlist/string/") == 0);
+	CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_STRING);
+	CHECK(strcmp(cname, "nvlist/string/x") == 0);
+	CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_STRING);
+	CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0);
+	CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_DESCRIPTOR);
+	CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
+	CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_BINARY);
+	CHECK(strcmp(cname, "nvlist/binary/x") == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
+	CHECK(size == 1);
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_BINARY);
+	CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0);
+	CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz"));
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname != NULL);
+	CHECK(ctype == NV_TYPE_NVLIST);
+	CHECK(strcmp(cname, "nvlist/nvlist/empty") == 0);
+	empty = nvlist_get_nvlist(cnvl, cname);
+	CHECK(nvlist_empty(empty));
+
+	cname = nvlist_next(cnvl, &ctype, &ccookie);
+	CHECK(cname == NULL);
+
+	name = nvlist_next(nvl, &type, &cookie);
+	CHECK(name == NULL);
+}
+
+int
+main(void)
+{
+	int status, socks[2];
+	pid_t pid;
+
+	printf("1..134\n");
+	fflush(stdout);
+
+	if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
+		err(1, "socketpair() failed");
+	pid = fork();
+	switch (pid) {
+	case -1:
+		/* Failure. */
+		err(1, "unable to fork");
+	case 0:
+		/* Child. */
+		close(socks[0]);
+		child(socks[1]);
+		return (0);
+	default:
+		/* Parent. */
+		close(socks[1]);
+		parent(socks[0]);
+		break;
+	}
+
+	if (waitpid(pid, &status, 0) < 0)
+		err(1, "waitpid() failed");
+
+	return (0);
+}


Property changes on: trunk/lib/libnv/tests/nvlist_send_recv_test.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list