summaryrefslogtreecommitdiffstats
path: root/lib/libnv
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2014-11-19 01:07:58 +0000
committersjg <sjg@FreeBSD.org>2014-11-19 01:07:58 +0000
commitb137080f19736ee33fede2e88bb54438604cf86b (patch)
tree377ac0ac449528621eb192cd245adadb5fd53668 /lib/libnv
parentab21a29eb607d4dfe389b965fbdee27558e791aa (diff)
parent4a8d07956d121238d006d34ffe7d6269744e8b1a (diff)
downloadFreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.zip
FreeBSD-src-b137080f19736ee33fede2e88bb54438604cf86b.tar.gz
Merge from head@274682
Diffstat (limited to 'lib/libnv')
-rw-r--r--lib/libnv/Makefile11
-rw-r--r--lib/libnv/msgio.c113
-rw-r--r--lib/libnv/nv.38
-rw-r--r--lib/libnv/nv.h2
-rw-r--r--lib/libnv/nv_impl.h4
-rw-r--r--lib/libnv/nvlist.c255
-rw-r--r--lib/libnv/nvlist_impl.h4
-rw-r--r--lib/libnv/nvpair.c217
-rw-r--r--lib/libnv/nvpair_impl.h44
-rw-r--r--lib/libnv/tests/Makefile17
-rw-r--r--lib/libnv/tests/nvlist_add_test.c196
-rw-r--r--lib/libnv/tests/nvlist_exists_test.c321
-rw-r--r--lib/libnv/tests/nvlist_free_test.c221
-rw-r--r--lib/libnv/tests/nvlist_get_test.c182
-rw-r--r--lib/libnv/tests/nvlist_move_test.c161
-rw-r--r--lib/libnv/tests/nvlist_send_recv_test.c325
16 files changed, 1865 insertions, 216 deletions
diff --git a/lib/libnv/Makefile b/lib/libnv/Makefile
index 710c295..e9371bc 100644
--- a/lib/libnv/Makefile
+++ b/lib/libnv/Makefile
@@ -1,7 +1,10 @@
# $FreeBSD$
-LIB= nv
SHLIBDIR?= /lib
+
+.include <src.opts.mk>
+
+LIB= nv
SHLIB_MAJOR= 0
SRCS= dnvlist.c
@@ -146,7 +149,7 @@ MLINKS+=nv.3 nvlist_existsv.3 \
nv.3 nvlist_takev_nvlist.3 \
nv.3 nvlist_takev_descriptor.3 \
nv.3 nvlist_takev_binary.3 \
- nv.3 nvlist_freef.3 \
+ nv.3 nvlist_freev.3 \
nv.3 nvlist_freev_type.3 \
nv.3 nvlist_freev_null.3 \
nv.3 nvlist_freev_bool.3 \
@@ -158,4 +161,8 @@ MLINKS+=nv.3 nvlist_existsv.3 \
WARNS?= 6
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.lib.mk>
diff --git a/lib/libnv/msgio.c b/lib/libnv/msgio.c
index 41292aa..27620a1 100644
--- a/lib/libnv/msgio.c
+++ b/lib/libnv/msgio.c
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <errno.h>
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
#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)
{
@@ -234,22 +236,31 @@ cred_recv(int sock, struct cmsgcred *cred)
return (0);
}
-int
-fd_send(int sock, const int *fds, size_t nfds)
+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;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(fds != NULL);
+ PJDLOG_ASSERT(nfds > 0);
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+
+ /*
+ * 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)
@@ -274,22 +285,32 @@ end:
return (ret);
}
-int
-fd_recv(int sock, int *fds, size_t nfds)
+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;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(nfds > 0);
+ PJDLOG_ASSERT(fds != NULL);
+ i = 0;
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+ 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)
@@ -333,6 +354,64 @@ end:
}
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;
diff --git a/lib/libnv/nv.3 b/lib/libnv/nv.3
index 63c8e8b..29ba744 100644
--- a/lib/libnv/nv.3
+++ b/lib/libnv/nv.3
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 21, 2014
+.Dd September 25, 2014
.Dt NV 3
.Os
.Sh NAME
@@ -150,6 +150,8 @@
.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"
.\"
.Ft bool
.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
@@ -437,6 +439,10 @@ 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 ,
diff --git a/lib/libnv/nv.h b/lib/libnv/nv.h
index e2d7030..1b55be1 100644
--- a/lib/libnv/nv.h
+++ b/lib/libnv/nv.h
@@ -83,6 +83,8 @@ nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl);
const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep);
+const nvlist_t *nvlist_get_parent(const nvlist_t *nvl);
+
/*
* The nvlist_exists functions check if the given name (optionally of the given
* type) exists on nvlist.
diff --git a/lib/libnv/nv_impl.h b/lib/libnv/nv_impl.h
index 3206006..3ed45b3 100644
--- a/lib/libnv/nv_impl.h
+++ b/lib/libnv/nv_impl.h
@@ -39,6 +39,8 @@ struct nvpair;
typedef struct nvpair nvpair_t;
#endif
+#define NV_TYPE_NVLIST_UP 255
+
#define NV_TYPE_FIRST NV_TYPE_NULL
#define NV_TYPE_LAST NV_TYPE_BINARY
@@ -55,6 +57,8 @@ void nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp);
void nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp);
+void nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent);
+
const nvpair_t *nvlist_get_nvpair(const nvlist_t *nvl, const char *name);
nvpair_t *nvlist_take_nvpair(nvlist_t *nvl, const char *name);
diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c
index 929ba48..b495441 100644
--- a/lib/libnv/nvlist.c
+++ b/lib/libnv/nvlist.c
@@ -73,10 +73,11 @@ __FBSDID("$FreeBSD$");
#define NVLIST_MAGIC 0x6e766c /* "nvl" */
struct nvlist {
- int nvl_magic;
- int nvl_error;
- int nvl_flags;
- struct nvl_head nvl_head;
+ int nvl_magic;
+ int nvl_error;
+ int nvl_flags;
+ nvpair_t *nvl_parent;
+ struct nvl_head nvl_head;
};
#define NVLIST_ASSERT(nvl) do { \
@@ -106,6 +107,7 @@ nvlist_create(int flags)
nvl = malloc(sizeof(*nvl));
nvl->nvl_error = 0;
nvl->nvl_flags = flags;
+ nvl->nvl_parent = NULL;
TAILQ_INIT(&nvl->nvl_head);
nvl->nvl_magic = NVLIST_MAGIC;
@@ -147,6 +149,36 @@ nvlist_error(const nvlist_t *nvl)
return (nvl->nvl_error);
}
+nvpair_t *
+nvlist_get_nvpair_parent(const nvlist_t *nvl)
+{
+
+ NVLIST_ASSERT(nvl);
+
+ return (nvl->nvl_parent);
+}
+
+const nvlist_t *
+nvlist_get_parent(const nvlist_t *nvl)
+{
+
+ NVLIST_ASSERT(nvl);
+
+ if (nvl->nvl_parent == NULL)
+ return (NULL);
+
+ return (nvpair_nvlist(nvl->nvl_parent));
+}
+
+void
+nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
+{
+
+ NVLIST_ASSERT(nvl);
+
+ nvl->nvl_parent = parent;
+}
+
bool
nvlist_empty(const nvlist_t *nvl)
{
@@ -301,24 +333,34 @@ nvlist_clone(const nvlist_t *nvl)
return (newnvl);
}
+static bool
+nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
+{
+
+ if (nvlist_error(nvl) != 0) {
+ dprintf(fd, "%*serror: %d\n", level * 4, "",
+ nvlist_error(nvl));
+ return (true);
+ }
+
+ return (false);
+}
+
/*
* Dump content of nvlist.
*/
-static void
-nvlist_xdump(const nvlist_t *nvl, int fd, int level)
+void
+nvlist_dump(const nvlist_t *nvl, int fd)
{
nvpair_t *nvp;
+ int level;
- PJDLOG_ASSERT(level < 3);
-
- if (nvlist_error(nvl) != 0) {
- dprintf(fd, "%*serror: %d\n", level * 4, "",
- nvlist_error(nvl));
+ level = 0;
+ if (nvlist_dump_error_check(nvl, fd, level))
return;
- }
- for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
- nvp = nvlist_next_nvpair(nvl, nvp)) {
+ nvp = nvlist_first_nvpair(nvl);
+ while (nvp != NULL) {
dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
nvpair_type_string(nvpair_type(nvp)));
switch (nvpair_type(nvp)) {
@@ -340,8 +382,14 @@ nvlist_xdump(const nvlist_t *nvl, int fd, int level)
break;
case NV_TYPE_NVLIST:
dprintf(fd, "\n");
- nvlist_xdump(nvpair_get_nvlist(nvp), fd, level + 1);
- break;
+ nvl = nvpair_get_nvlist(nvp);
+ if (nvlist_dump_error_check(nvl, fd, level + 1)) {
+ nvl = nvlist_get_parent(nvl);
+ break;
+ }
+ level += 1;
+ nvp = nvlist_first_nvpair(nvl);
+ continue;
case NV_TYPE_DESCRIPTOR:
dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
break;
@@ -361,14 +409,15 @@ nvlist_xdump(const nvlist_t *nvl, int fd, int level)
default:
PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
}
- }
-}
-void
-nvlist_dump(const nvlist_t *nvl, int fd)
-{
-
- nvlist_xdump(nvl, fd, 0);
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+ nvp = nvlist_get_nvpair_parent(nvl);
+ if (nvp == NULL)
+ return;
+ nvl = nvlist_get_parent(nvl);
+ level --;
+ }
+ }
}
void
@@ -381,41 +430,44 @@ nvlist_fdump(const nvlist_t *nvl, FILE *fp)
/*
* The function obtains size of the nvlist after nvlist_pack().
- * Additional argument 'level' allows to track how deep are we as we obtain
- * size of the NV_TYPE_NVLIST elements using recursion. We allow at most
- * three levels of recursion.
*/
-static size_t
-nvlist_xsize(const nvlist_t *nvl, int level)
+size_t
+nvlist_size(const nvlist_t *nvl)
{
const nvpair_t *nvp;
size_t size;
NVLIST_ASSERT(nvl);
PJDLOG_ASSERT(nvl->nvl_error == 0);
- PJDLOG_ASSERT(level < 3);
size = sizeof(struct nvlist_header);
- for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
- nvp = nvlist_next_nvpair(nvl, nvp)) {
+ nvp = nvlist_first_nvpair(nvl);
+ while (nvp != NULL) {
size += nvpair_header_size();
size += strlen(nvpair_name(nvp)) + 1;
- if (nvpair_type(nvp) == NV_TYPE_NVLIST)
- size += nvlist_xsize(nvpair_get_nvlist(nvp), level + 1);
- else
+ if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
+ size += sizeof(struct nvlist_header);
+ size += nvpair_header_size() + 1;
+ nvl = nvpair_get_nvlist(nvp);
+ PJDLOG_ASSERT(nvl->nvl_error == 0);
+ nvp = nvlist_first_nvpair(nvl);
+ continue;
+ } else {
size += nvpair_size(nvp);
+ }
+
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+ nvp = nvlist_get_nvpair_parent(nvl);
+ if (nvp == NULL)
+ goto out;
+ nvl = nvlist_get_parent(nvl);
+ }
}
+out:
return (size);
}
-size_t
-nvlist_size(const nvlist_t *nvl)
-{
-
- return (nvlist_xsize(nvl, 0));
-}
-
static int *
nvlist_xdescriptors(const nvlist_t *nvl, int *descs, int level)
{
@@ -541,15 +593,59 @@ nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
ptr = nvlist_pack_header(nvl, ptr, &left);
- for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
- nvp = nvlist_next_nvpair(nvl, nvp)) {
- ptr = nvpair_pack(nvp, ptr, fdidxp, &left);
+ nvp = nvlist_first_nvpair(nvl);
+ while (nvp != NULL) {
+ NVPAIR_ASSERT(nvp);
+
+ nvpair_init_datasize(nvp);
+ ptr = nvpair_pack_header(nvp, ptr, &left);
if (ptr == NULL) {
free(buf);
return (NULL);
}
+ switch (nvpair_type(nvp)) {
+ case NV_TYPE_NULL:
+ ptr = nvpair_pack_null(nvp, ptr, &left);
+ break;
+ case NV_TYPE_BOOL:
+ ptr = nvpair_pack_bool(nvp, ptr, &left);
+ break;
+ case NV_TYPE_NUMBER:
+ ptr = nvpair_pack_number(nvp, ptr, &left);
+ break;
+ case NV_TYPE_STRING:
+ ptr = nvpair_pack_string(nvp, ptr, &left);
+ break;
+ case NV_TYPE_NVLIST:
+ nvl = nvpair_get_nvlist(nvp);
+ nvp = nvlist_first_nvpair(nvl);
+ ptr = nvlist_pack_header(nvl, ptr, &left);
+ continue;
+ case NV_TYPE_DESCRIPTOR:
+ ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
+ break;
+ case NV_TYPE_BINARY:
+ ptr = nvpair_pack_binary(nvp, ptr, &left);
+ break;
+ default:
+ PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
+ }
+ if (ptr == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
+ nvp = nvlist_get_nvpair_parent(nvl);
+ if (nvp == NULL)
+ goto out;
+ ptr = nvpair_pack_nvlist_up(ptr, &left);
+ if (ptr == NULL)
+ goto out;
+ nvl = nvlist_get_parent(nvl);
+ }
}
+out:
if (sizep != NULL)
*sizep = size;
return (buf);
@@ -600,9 +696,9 @@ nvlist_check_header(struct nvlist_header *nvlhdrp)
return (true);
}
-static const unsigned char *
+const unsigned char *
nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
- int *flagsp, size_t *leftp)
+ bool *isbep, size_t *leftp)
{
struct nvlist_header nvlhdr;
@@ -629,7 +725,8 @@ nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
ptr += sizeof(nvlhdr);
- *flagsp = (int)nvlhdr.nvlh_flags;
+ if (isbep != NULL)
+ *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
*leftp -= sizeof(nvlhdr);
return (ptr);
@@ -642,32 +739,72 @@ nvlist_t *
nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
{
const unsigned char *ptr;
- nvlist_t *nvl;
+ nvlist_t *nvl, *retnvl, *tmpnvl;
nvpair_t *nvp;
size_t left;
- int flags;
+ bool isbe;
left = size;
ptr = buf;
- nvl = nvlist_create(0);
+ tmpnvl = NULL;
+ nvl = retnvl = nvlist_create(0);
if (nvl == NULL)
goto failed;
- ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
+ ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
if (ptr == NULL)
goto failed;
while (left > 0) {
- ptr = nvpair_unpack(flags, ptr, &left, fds, nfds, &nvp);
+ ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
+ if (ptr == NULL)
+ goto failed;
+ switch (nvpair_type(nvp)) {
+ case NV_TYPE_NULL:
+ ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_BOOL:
+ ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NUMBER:
+ ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_STRING:
+ ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NVLIST:
+ ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
+ &tmpnvl);
+ nvlist_set_parent(tmpnvl, nvp);
+ break;
+ case NV_TYPE_DESCRIPTOR:
+ ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
+ fds, nfds);
+ break;
+ case NV_TYPE_BINARY:
+ ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
+ break;
+ case NV_TYPE_NVLIST_UP:
+ if (nvl->nvl_parent == NULL)
+ goto failed;
+ nvl = nvpair_nvlist(nvl->nvl_parent);
+ continue;
+ default:
+ PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
+ }
if (ptr == NULL)
goto failed;
nvlist_move_nvpair(nvl, nvp);
+ if (tmpnvl != NULL) {
+ nvl = tmpnvl;
+ tmpnvl = NULL;
+ }
}
- return (nvl);
+ return (retnvl);
failed:
- nvlist_destroy(nvl);
+ nvlist_destroy(retnvl);
return (NULL);
}
@@ -727,7 +864,7 @@ nvlist_recv(int sock)
struct nvlist_header nvlhdr;
nvlist_t *nvl, *ret;
unsigned char *buf;
- size_t nfds, size;
+ size_t nfds, size, i;
int serrno, *fds;
if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
@@ -760,8 +897,11 @@ nvlist_recv(int sock)
}
nvl = nvlist_xunpack(buf, size, fds, nfds);
- if (nvl == NULL)
+ if (nvl == NULL) {
+ for (i = 0; i < nfds; i++)
+ close(fds[i]);
goto out;
+ }
ret = nvl;
out:
@@ -1328,7 +1468,8 @@ nvlist_movev_nvlist(nvlist_t *nvl, nvlist_t *value, const char *namefmt,
nvpair_t *nvp;
if (nvlist_error(nvl) != 0) {
- nvlist_destroy(value);
+ if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
+ nvlist_destroy(value);
errno = nvlist_error(nvl);
return;
}
diff --git a/lib/libnv/nvlist_impl.h b/lib/libnv/nvlist_impl.h
index 43a7bb0..ef32dea 100644
--- a/lib/libnv/nvlist_impl.h
+++ b/lib/libnv/nvlist_impl.h
@@ -40,4 +40,8 @@ void *nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep);
nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds,
size_t nfds);
+nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl);
+const unsigned char *nvlist_unpack_header(nvlist_t *nvl,
+ const unsigned char *ptr, size_t nfds, bool *isbep, size_t *leftp);
+
#endif /* !_NVLIST_IMPL_H_ */
diff --git a/lib/libnv/nvpair.c b/lib/libnv/nvpair.c
index 916444f..4f0bd72 100644
--- a/lib/libnv/nvpair.c
+++ b/lib/libnv/nvpair.c
@@ -67,7 +67,7 @@ struct nvpair {
int nvp_type;
uint64_t nvp_data;
size_t nvp_datasize;
- nvlist_t *nvp_list; /* Used for sanity checks. */
+ nvlist_t *nvp_list;
TAILQ_ENTRY(nvpair) nvp_next;
};
@@ -90,7 +90,7 @@ nvpair_assert(const nvpair_t *nvp)
NVPAIR_ASSERT(nvp);
}
-const nvlist_t *
+nvlist_t *
nvpair_nvlist(const nvpair_t *nvp)
{
@@ -131,6 +131,17 @@ nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
nvp->nvp_list = nvl;
}
+static void
+nvpair_remove_nvlist(nvpair_t *nvp)
+{
+ nvlist_t *nvl;
+
+ /* XXX: DECONST is bad, mkay? */
+ nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
+ PJDLOG_ASSERT(nvl != NULL);
+ nvlist_set_parent(nvl, NULL);
+}
+
void
nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
{
@@ -138,6 +149,9 @@ nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
NVPAIR_ASSERT(nvp);
PJDLOG_ASSERT(nvp->nvp_list == nvl);
+ if (nvpair_type(nvp) == NV_TYPE_NVLIST)
+ nvpair_remove_nvlist(nvp);
+
TAILQ_REMOVE(head, nvp, nvp_next);
nvp->nvp_list = NULL;
}
@@ -201,7 +215,7 @@ nvpair_size(const nvpair_t *nvp)
return (nvp->nvp_datasize);
}
-static unsigned char *
+unsigned char *
nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
{
struct nvpair_header nvphdr;
@@ -227,7 +241,7 @@ nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
size_t *leftp __unused)
{
@@ -238,7 +252,7 @@ nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
{
uint8_t value;
@@ -256,7 +270,7 @@ nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
{
uint64_t value;
@@ -274,7 +288,7 @@ nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
{
@@ -289,37 +303,31 @@ nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
return (ptr);
}
-static unsigned char *
-nvpair_pack_nvlist(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
- size_t *leftp)
+unsigned char *
+nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
{
- unsigned char *data;
- size_t size;
-
- NVPAIR_ASSERT(nvp);
- PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
-
- if (nvp->nvp_datasize == 0)
- return (ptr);
-
- data = nvlist_xpack((const nvlist_t *)(intptr_t)nvp->nvp_data, fdidxp,
- &size);
- if (data == NULL)
- return (NULL);
-
- PJDLOG_ASSERT(size == nvp->nvp_datasize);
- PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
+ struct nvpair_header nvphdr;
+ size_t namesize;
+ const char *name = "";
- memcpy(ptr, data, nvp->nvp_datasize);
- free(data);
+ namesize = 1;
+ nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
+ nvphdr.nvph_namesize = namesize;
+ nvphdr.nvph_datasize = 0;
+ PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
+ memcpy(ptr, &nvphdr, sizeof(nvphdr));
+ ptr += sizeof(nvphdr);
+ *leftp -= sizeof(nvphdr);
- ptr += nvp->nvp_datasize;
- *leftp -= nvp->nvp_datasize;
+ PJDLOG_ASSERT(*leftp >= namesize);
+ memcpy(ptr, name, namesize);
+ ptr += namesize;
+ *leftp -= namesize;
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
size_t *leftp)
{
@@ -349,7 +357,7 @@ nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
return (ptr);
}
-static unsigned char *
+unsigned char *
nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
{
@@ -364,17 +372,12 @@ nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
return (ptr);
}
-unsigned char *
-nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp)
+void
+nvpair_init_datasize(nvpair_t *nvp)
{
NVPAIR_ASSERT(nvp);
- /*
- * We have to update datasize for NV_TYPE_NVLIST on every pack,
- * so that proper datasize is placed into nvpair_header
- * during the nvpair_pack_header() call below.
- */
if (nvp->nvp_type == NV_TYPE_NVLIST) {
if (nvp->nvp_data == 0) {
nvp->nvp_datasize = 0;
@@ -383,42 +386,10 @@ nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp, size_t *leftp)
nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
}
}
-
- ptr = nvpair_pack_header(nvp, ptr, leftp);
- if (ptr == NULL)
- return (NULL);
-
- switch (nvp->nvp_type) {
- case NV_TYPE_NULL:
- ptr = nvpair_pack_null(nvp, ptr, leftp);
- break;
- case NV_TYPE_BOOL:
- ptr = nvpair_pack_bool(nvp, ptr, leftp);
- break;
- case NV_TYPE_NUMBER:
- ptr = nvpair_pack_number(nvp, ptr, leftp);
- break;
- case NV_TYPE_STRING:
- ptr = nvpair_pack_string(nvp, ptr, leftp);
- break;
- case NV_TYPE_NVLIST:
- ptr = nvpair_pack_nvlist(nvp, ptr, fdidxp, leftp);
- break;
- case NV_TYPE_DESCRIPTOR:
- ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, leftp);
- break;
- case NV_TYPE_BINARY:
- ptr = nvpair_pack_binary(nvp, ptr, leftp);
- break;
- default:
- PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
- }
-
- return (ptr);
}
-static const unsigned char *
-nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
struct nvpair_header nvphdr;
@@ -434,16 +405,18 @@ nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
if (nvphdr.nvph_type < NV_TYPE_FIRST)
goto failed;
#endif
- if (nvphdr.nvph_type > NV_TYPE_LAST)
+ if (nvphdr.nvph_type > NV_TYPE_LAST &&
+ nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
goto failed;
+ }
#if BYTE_ORDER == BIG_ENDIAN
- if ((flags & NV_FLAG_BIG_ENDIAN) == 0) {
+ if (!isbe) {
nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
}
#else
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0) {
+ if (isbe) {
nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
}
@@ -477,8 +450,8 @@ failed:
return (NULL);
}
-static const unsigned char *
-nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp __unused)
{
@@ -492,8 +465,8 @@ nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
uint8_t value;
@@ -523,9 +496,9 @@ nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
- size_t *leftp)
+const unsigned char *
+nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
+ size_t *leftp)
{
PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
@@ -539,7 +512,7 @@ nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (NULL);
}
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
+ if (isbe)
nvp->nvp_data = be64dec(ptr);
else
nvp->nvp_data = le64dec(ptr);
@@ -549,8 +522,8 @@ nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
+const unsigned char *
+nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp)
{
@@ -577,9 +550,9 @@ nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp,
- const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds)
+const unsigned char *
+nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
{
nvlist_t *value;
@@ -590,20 +563,22 @@ nvpair_unpack_nvlist(int flags __unused, nvpair_t *nvp,
return (NULL);
}
- value = nvlist_xunpack(ptr, nvp->nvp_datasize, fds, nfds);
+ value = nvlist_create(0);
if (value == NULL)
return (NULL);
- nvp->nvp_data = (uint64_t)(uintptr_t)value;
+ ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
+ if (ptr == NULL)
+ return (NULL);
- ptr += nvp->nvp_datasize;
- *leftp -= nvp->nvp_datasize;
+ nvp->nvp_data = (uint64_t)(uintptr_t)value;
+ *child = value;
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
+const unsigned char *
+nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp, const int *fds, size_t nfds)
{
int64_t idx;
@@ -619,7 +594,7 @@ nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (NULL);
}
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
+ if (isbe)
idx = be64dec(ptr);
else
idx = le64dec(ptr);
@@ -642,8 +617,8 @@ nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (ptr);
}
-static const unsigned char *
-nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
+const unsigned char *
+nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp)
{
void *value;
@@ -669,8 +644,8 @@ nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
}
const unsigned char *
-nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
- const int *fds, size_t nfds, nvpair_t **nvpp)
+nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
+ nvpair_t **nvpp)
{
nvpair_t *nvp, *tmp;
@@ -679,47 +654,17 @@ nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
return (NULL);
nvp->nvp_name = (char *)(nvp + 1);
- ptr = nvpair_unpack_header(flags, nvp, ptr, leftp);
+ ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
if (ptr == NULL)
goto failed;
tmp = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
if (tmp == NULL)
goto failed;
nvp = tmp;
+
/* Update nvp_name after realloc(). */
nvp->nvp_name = (char *)(nvp + 1);
-
- switch (nvp->nvp_type) {
- case NV_TYPE_NULL:
- ptr = nvpair_unpack_null(flags, nvp, ptr, leftp);
- break;
- case NV_TYPE_BOOL:
- ptr = nvpair_unpack_bool(flags, nvp, ptr, leftp);
- break;
- case NV_TYPE_NUMBER:
- ptr = nvpair_unpack_number(flags, nvp, ptr, leftp);
- break;
- case NV_TYPE_STRING:
- ptr = nvpair_unpack_string(flags, nvp, ptr, leftp);
- break;
- case NV_TYPE_NVLIST:
- ptr = nvpair_unpack_nvlist(flags, nvp, ptr, leftp, fds,
- nfds);
- break;
- case NV_TYPE_DESCRIPTOR:
- ptr = nvpair_unpack_descriptor(flags, nvp, ptr, leftp, fds,
- nfds);
- break;
- case NV_TYPE_BINARY:
- ptr = nvpair_unpack_binary(flags, nvp, ptr, leftp);
- break;
- default:
- PJDLOG_ABORT("Invalid type (%d).", nvp->nvp_type);
- }
-
- if (ptr == NULL)
- goto failed;
-
+ nvp->nvp_data = 0x00;
nvp->nvp_magic = NVPAIR_MAGIC;
*nvpp = nvp;
return (ptr);
@@ -1018,6 +963,8 @@ nvpair_createv_nvlist(const nvlist_t *value, const char *namefmt,
namefmt, nameap);
if (nvp == NULL)
nvlist_destroy(nvl);
+ else
+ nvlist_set_parent(nvl, nvp);
return (nvp);
}
@@ -1172,7 +1119,7 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap)
{
nvpair_t *nvp;
- if (value == NULL) {
+ if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
errno = EINVAL;
return (NULL);
}
@@ -1181,6 +1128,8 @@ nvpair_movev_nvlist(nvlist_t *value, const char *namefmt, va_list nameap)
namefmt, nameap);
if (nvp == NULL)
nvlist_destroy(value);
+ else
+ nvlist_set_parent(value, nvp);
return (nvp);
}
diff --git a/lib/libnv/nvpair_impl.h b/lib/libnv/nvpair_impl.h
index aa4046c..a72000b 100644
--- a/lib/libnv/nvpair_impl.h
+++ b/lib/libnv/nvpair_impl.h
@@ -41,18 +41,52 @@
TAILQ_HEAD(nvl_head, nvpair);
void nvpair_assert(const nvpair_t *nvp);
-const nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
+nvlist_t *nvpair_nvlist(const nvpair_t *nvp);
nvpair_t *nvpair_next(const nvpair_t *nvp);
nvpair_t *nvpair_prev(const nvpair_t *nvp);
void nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl);
void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl);
size_t nvpair_header_size(void);
size_t nvpair_size(const nvpair_t *nvp);
-unsigned char *nvpair_pack(nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
- size_t *leftp);
-const unsigned char *nvpair_unpack(int flags, const unsigned char *ptr,
- size_t *leftp, const int *fds, size_t nfds, nvpair_t **nvpp);
+const unsigned char *nvpair_unpack(bool isbe, const unsigned char *ptr,
+ size_t *leftp, nvpair_t **nvpp);
void nvpair_free_structure(nvpair_t *nvp);
+void nvpair_init_datasize(nvpair_t *nvp);
const char *nvpair_type_string(int type);
+/* Pack functions. */
+unsigned char *nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr,
+ int64_t *fdidxp, size_t *leftp);
+unsigned char *nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr,
+ size_t *leftp);
+unsigned char *nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp);
+
+/* Unpack data functions. */
+const unsigned char *nvpair_unpack_header(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_null(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_bool(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_number(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_string(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+const unsigned char *nvpair_unpack_nvlist(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child);
+const unsigned char *nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds);
+const unsigned char *nvpair_unpack_binary(bool isbe, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp);
+
#endif /* !_NVPAIR_IMPL_H_ */
diff --git a/lib/libnv/tests/Makefile b/lib/libnv/tests/Makefile
new file mode 100644
index 0000000..df10549
--- /dev/null
+++ b/lib/libnv/tests/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libnv
+
+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?= 6
+
+.include <bsd.test.mk>
diff --git a/lib/libnv/tests/nvlist_add_test.c b/lib/libnv/tests/nvlist_add_test.c
new file mode 100644
index 0000000..06bcc63
--- /dev/null
+++ b/lib/libnv/tests/nvlist_add_test.c
@@ -0,0 +1,196 @@
+/*-
+ * 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$
+ */
+
+#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);
+}
diff --git a/lib/libnv/tests/nvlist_exists_test.c b/lib/libnv/tests/nvlist_exists_test.c
new file mode 100644
index 0000000..cb595d7
--- /dev/null
+++ b/lib/libnv/tests/nvlist_exists_test.c
@@ -0,0 +1,321 @@
+/*-
+ * 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$
+ */
+
+#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);
+}
diff --git a/lib/libnv/tests/nvlist_free_test.c b/lib/libnv/tests/nvlist_free_test.c
new file mode 100644
index 0000000..4417a44
--- /dev/null
+++ b/lib/libnv/tests/nvlist_free_test.c
@@ -0,0 +1,221 @@
+/*-
+ * 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$
+ */
+
+#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);
+}
diff --git a/lib/libnv/tests/nvlist_get_test.c b/lib/libnv/tests/nvlist_get_test.c
new file mode 100644
index 0000000..b4468db
--- /dev/null
+++ b/lib/libnv/tests/nvlist_get_test.c
@@ -0,0 +1,182 @@
+/*-
+ * 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$
+ */
+
+#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);
+}
diff --git a/lib/libnv/tests/nvlist_move_test.c b/lib/libnv/tests/nvlist_move_test.c
new file mode 100644
index 0000000..760399d
--- /dev/null
+++ b/lib/libnv/tests/nvlist_move_test.c
@@ -0,0 +1,161 @@
+/*-
+ * 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$
+ */
+
+#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);
+}
diff --git a/lib/libnv/tests/nvlist_send_recv_test.c b/lib/libnv/tests/nvlist_send_recv_test.c
new file mode 100644
index 0000000..c751bf7
--- /dev/null
+++ b/lib/libnv/tests/nvlist_send_recv_test.c
@@ -0,0 +1,325 @@
+/*-
+ * 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$
+ */
+
+#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;
+
+ nvl = 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_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;
+ 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") == 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);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ CHECK(name == NULL);
+}
+
+int
+main(void)
+{
+ int status, socks[2];
+ pid_t pid;
+
+ printf("1..126\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);
+}
OpenPOWER on IntegriCloud