aboutsummaryrefslogtreecommitdiff
path: root/lib/libnv/tests
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libnv/tests')
-rw-r--r--lib/libnv/tests/Makefile31
-rw-r--r--lib/libnv/tests/Makefile.depend22
-rw-r--r--lib/libnv/tests/cnv_tests.cc1504
-rw-r--r--lib/libnv/tests/dnv_tests.cc571
-rw-r--r--lib/libnv/tests/nv_array_tests.cc1248
-rw-r--r--lib/libnv/tests/nv_tests.cc1275
-rw-r--r--lib/libnv/tests/nvlist_add_test.c193
-rw-r--r--lib/libnv/tests/nvlist_append_test.c118
-rw-r--r--lib/libnv/tests/nvlist_exists_test.c318
-rw-r--r--lib/libnv/tests/nvlist_free_test.c218
-rw-r--r--lib/libnv/tests/nvlist_get_test.c178
-rw-r--r--lib/libnv/tests/nvlist_move_test.c158
-rw-r--r--lib/libnv/tests/nvlist_send_recv_test.c749
13 files changed, 6583 insertions, 0 deletions
diff --git a/lib/libnv/tests/Makefile b/lib/libnv/tests/Makefile
new file mode 100644
index 000000000000..aea416539c4a
--- /dev/null
+++ b/lib/libnv/tests/Makefile
@@ -0,0 +1,31 @@
+.include <src.opts.mk>
+
+ATF_TESTS_C= \
+ nvlist_send_recv_test
+
+.PATH: ${SRCTOP}/lib/libnv
+SRCS.nvlist_send_recv_test= msgio.c nvlist_send_recv_test.c
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/sys/contrib/libnv
+CFLAGS.nvlist_send_recv_test+=-I${SRCTOP}/lib/libnv
+.if ${MK_ASAN} != "yes"
+CFLAGS.nvlist_send_recv_test+=-DNO_ASAN
+.endif
+
+ATF_TESTS_CXX= \
+ cnv_tests \
+ dnv_tests \
+ nv_array_tests \
+ nv_tests
+
+TAP_TESTS_C+= nvlist_add_test
+TAP_TESTS_C+= nvlist_append_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
+
+LIBADD+= nv
+
+WARNS?= 3
+
+.include <bsd.test.mk>
diff --git a/lib/libnv/tests/Makefile.depend b/lib/libnv/tests/Makefile.depend
new file mode 100644
index 000000000000..3da08ae71403
--- /dev/null
+++ b/lib/libnv/tests/Makefile.depend
@@ -0,0 +1,22 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/atf/libatf-c \
+ lib/atf/libatf-c++ \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libnv \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/lib/libnv/tests/cnv_tests.cc b/lib/libnv/tests/cnv_tests.cc
new file mode 100644
index 000000000000..ecd8ba3e98ac
--- /dev/null
+++ b/lib/libnv/tests/cnv_tests.cc
@@ -0,0 +1,1504 @@
+/*-
+ * Copyright (c) 2016 Adam Starak <starak.adam@gmail.com>
+ * 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 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>
+#include <sys/cnv.h>
+#include <sys/nv.h>
+#include <sys/types.h>
+
+#include <atf-c++.hpp>
+#include <fcntl.h>
+#include <errno.h>
+
+#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+/* ATF cnvlist_get tests. */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_bool);
+ATF_TEST_CASE_BODY(cnvlist_get_bool)
+{
+ nvlist_t *nvl;
+ const char *key;
+ bool value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = true;
+
+ nvlist_add_bool(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool(nvl, key));
+
+ ATF_REQUIRE_EQ(cnvlist_get_bool(cookie), value);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_number);
+ATF_TEST_CASE_BODY(cnvlist_get_number)
+{
+ nvlist_t *nvl;
+ const char *key;
+ uint64_t value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = 420;
+
+ nvlist_add_number(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number(nvl, key));
+
+ ATF_REQUIRE_EQ(cnvlist_get_number(cookie), value);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_string);
+ATF_TEST_CASE_BODY(cnvlist_get_string)
+{
+ nvlist_t *nvl;
+ const char *key;
+ const char *value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = "text";
+
+ nvlist_add_string(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string(nvl, key));
+
+ ATF_REQUIRE_EQ(strcmp(cnvlist_get_string(cookie), value), 0);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_nvlist);
+ATF_TEST_CASE_BODY(cnvlist_get_nvlist)
+{
+ nvlist_t *nvl, *value;
+ const nvlist_t *result;
+ const char *key, *subkey;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ value = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ key = "name";
+ subkey = "subname";
+ cookie = NULL;
+
+ /* Add null to 'value' nvlist. */
+ nvlist_add_null(value, subkey);
+ ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(value), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(value));
+ ATF_REQUIRE(nvlist_exists(value, subkey));
+ ATF_REQUIRE(nvlist_exists_null(value, subkey));
+ ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ /* Add 'value' nvlist. */
+ cookie = NULL;
+ nvlist_add_nvlist(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist(nvl, key));
+
+ /*
+ * Assuming nvlist_get_nvlist() is correct check if cnvlist returns
+ * the same pointer.
+ */
+ result = cnvlist_get_nvlist(cookie);
+ ATF_REQUIRE_EQ(result, nvlist_get_nvlist(nvl, key));
+ ATF_REQUIRE(result != value);
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ /* Validate data inside nvlist. */
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(result, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(result), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(result));
+ ATF_REQUIRE(nvlist_exists(result, subkey));
+ ATF_REQUIRE(nvlist_exists_null(result, subkey));
+ ATF_REQUIRE_EQ(nvlist_next(result, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(value);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_descriptor);
+ATF_TEST_CASE_BODY(cnvlist_get_descriptor)
+{
+ nvlist_t *nvl;
+ const char *key;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_descriptor(nvl, key, STDERR_FILENO);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_DESCRIPTOR);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_descriptor(nvl, key));
+
+ ATF_REQUIRE_EQ(fd_is_valid(cnvlist_get_descriptor(cookie)), 1);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_binary);
+ATF_TEST_CASE_BODY(cnvlist_get_binary)
+{
+ nvlist_t *nvl;
+ const char *key;
+ void *in_binary;
+ const void *out_binary;
+ void *cookie;
+ int type;
+ size_t in_size, out_size;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ in_size = 13;
+
+ in_binary = malloc(in_size);
+ ATF_REQUIRE(in_binary != NULL);
+ memset(in_binary, 0xa5, in_size);
+
+ nvlist_add_binary(nvl, key, in_binary, in_size);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BINARY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_binary(nvl, key));
+
+ out_binary = cnvlist_get_binary(cookie, &out_size);
+ ATF_REQUIRE_EQ(out_size, in_size);
+ ATF_REQUIRE_EQ(memcmp(in_binary, out_binary, out_size), 0);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+/* ATF cnvlist_get array tests. */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_bool_array);
+ATF_TEST_CASE_BODY(cnvlist_get_bool_array)
+{
+ nvlist_t *nvl;
+ bool in_array[16];
+ const bool *out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = (i % 2 == 0);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_bool_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+
+ out_array = cnvlist_get_bool_array(cookie, &nitems);
+ ATF_REQUIRE_EQ(nitems, 16);
+ ATF_REQUIRE(out_array != NULL);
+ for (i = 0; i < 16; i++)
+ ATF_REQUIRE_EQ(out_array[i], in_array[i]);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_number_array);
+ATF_TEST_CASE_BODY(cnvlist_get_number_array)
+{
+ nvlist_t *nvl;
+ uint64_t in_array[16];
+ const uint64_t *out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = i;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_number_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+
+ out_array = cnvlist_get_number_array(cookie, &nitems);
+ ATF_REQUIRE(out_array != NULL);
+ ATF_REQUIRE_EQ(nitems, 16);
+ for (i = 0; i < 16; i++)
+ ATF_REQUIRE_EQ(out_array[i], in_array[i]);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_string_array);
+ATF_TEST_CASE_BODY(cnvlist_get_string_array)
+{
+ nvlist_t *nvl;
+ const char *in_array[4] = {"inequality", "sucks", ".", ""};
+ const char * const *out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_string_array(nvl, key, in_array, 4);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+
+ out_array = cnvlist_get_string_array(cookie, &nitems);
+ ATF_REQUIRE_EQ(nitems, 4);
+ ATF_REQUIRE(out_array != NULL);
+ for (i = 0; i < 4; i++) {
+ ATF_REQUIRE(out_array[i] != NULL);
+ ATF_REQUIRE_EQ(strcmp(out_array[i], in_array[i]), 0);
+ }
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_nvlist_array);
+ATF_TEST_CASE_BODY(cnvlist_get_nvlist_array)
+{
+ nvlist_t *nvl;
+ nvlist_t *in_array[6];
+ const nvlist_t * const *out_array;
+ const nvlist_t * const *out_result;
+ void *cookie;
+ const char *key;
+ const char *subkeys;
+ int type, i;
+ size_t nitems;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ subkeys = "123456";
+ for (i = 0; i < 6; i++) {
+ in_array[i] = nvlist_create(0);
+ ATF_REQUIRE(in_array[i] != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(in_array[i]), 0);
+ ATF_REQUIRE(nvlist_empty(in_array[i]));
+
+ cookie = NULL;
+
+ nvlist_add_null(in_array[i], subkeys+i);
+ ATF_REQUIRE_EQ(strcmp(subkeys+i, nvlist_next(in_array[i],
+ &type, &cookie)),0);
+ ATF_REQUIRE_EQ(nvlist_error(in_array[i]), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(in_array[i]));
+ ATF_REQUIRE(nvlist_exists(in_array[i], subkeys+i));
+ ATF_REQUIRE(nvlist_exists_null(in_array[i], subkeys+i));
+ ATF_REQUIRE_EQ(nvlist_next(in_array[i], &type, &cookie),
+ static_cast<const char *>(NULL));
+ }
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_nvlist_array(nvl, key, in_array, 6);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+
+ /* Get nvlist array by cnvlist function. */
+ out_array = cnvlist_get_nvlist_array(cookie, &nitems);
+ ATF_REQUIRE(out_array != NULL);
+ ATF_REQUIRE_EQ(nitems, 6);
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ /* Get nvlist array by nvlist function. */
+ out_result = nvlist_get_nvlist_array(nvl, key, &nitems);
+ ATF_REQUIRE(out_result != NULL);
+ ATF_REQUIRE_EQ(nitems, 6);
+
+ /* Validate assuming that nvlist returned a proper pointer */
+ for (i = 0; i < 6; i++) {
+ ATF_REQUIRE_EQ(out_result[i], out_array[i]);
+ ATF_REQUIRE(out_array[i] != in_array[i]);
+
+ /* Validate data inside nvlist. */
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(subkeys+i, nvlist_next(out_array[i],
+ &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(out_array[i]), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(out_array[i]));
+ ATF_REQUIRE(nvlist_exists(out_array[i], subkeys+i));
+ ATF_REQUIRE(nvlist_exists_null(out_array[i], subkeys+i));
+ ATF_REQUIRE_EQ(nvlist_next(out_array[i], &type, &cookie),
+ static_cast<const char *>(NULL));
+ }
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_get_descriptor_array);
+ATF_TEST_CASE_BODY(cnvlist_get_descriptor_array)
+{
+ nvlist_t *nvl;
+ size_t count, i, nitems;
+ const int *out_array;
+ int *in_array, type;
+ const char *key;
+ void *cookie;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ count = 50;
+
+ in_array = static_cast<int *>(malloc(sizeof(*in_array)*count));
+ ATF_REQUIRE(in_array != NULL);
+ for (i = 0; i < count; i++) {
+ in_array[i] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fd_is_valid(in_array[i]));
+ }
+
+ nvlist_add_descriptor_array(nvl, key, in_array, count);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_DESCRIPTOR_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key));
+
+ out_array = cnvlist_get_descriptor_array(cookie, &nitems);
+ ATF_REQUIRE_EQ(nitems, count);
+ ATF_REQUIRE(out_array != NULL);
+ for (i = 0; i < count; i++)
+ ATF_REQUIRE_EQ(fd_is_valid(out_array[i]), 1);
+
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+/* ATF cnvlist_take tests. */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_bool);
+ATF_TEST_CASE_BODY(cnvlist_take_bool)
+{
+ nvlist_t *nvl;
+ const char *key;
+ bool value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = true;
+
+ nvlist_add_bool(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(cnvlist_take_bool(cookie), value);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_bool(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_number);
+ATF_TEST_CASE_BODY(cnvlist_take_number)
+{
+ nvlist_t *nvl;
+ const char *key;
+ uint64_t value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = 69;
+
+ nvlist_add_number(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(cnvlist_take_number(cookie), value);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_number(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_string);
+ATF_TEST_CASE_BODY(cnvlist_take_string)
+{
+ nvlist_t *nvl;
+ const char *key;
+ const char *value;
+ char *out_string;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = "text";
+
+ nvlist_add_string(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ out_string = cnvlist_take_string(cookie);
+ ATF_REQUIRE(out_string != NULL);
+ ATF_REQUIRE_EQ(strcmp(out_string, value), 0);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_string(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ free(out_string);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_nvlist);
+ATF_TEST_CASE_BODY(cnvlist_take_nvlist)
+{
+ nvlist_t *nvl, *value, *result;
+ const char *key, *subkey;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ value = nvlist_create(0);
+ ATF_REQUIRE(value != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(value), 0);
+ ATF_REQUIRE(nvlist_empty(value));
+
+ key = "name";
+ subkey = "subname";
+ cookie = NULL;
+
+ /* Add null to 'value' nvlist. */
+ nvlist_add_null(value, subkey);
+ ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(value), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(value));
+ ATF_REQUIRE(nvlist_exists(value, subkey));
+ ATF_REQUIRE(nvlist_exists_null(value, subkey));
+ ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ /* Add 'value' nvlist. */
+ cookie = NULL;
+ nvlist_move_nvlist(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ result = cnvlist_take_nvlist(cookie);
+ ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key));
+ ATF_REQUIRE(result == value);
+
+ /* Validate data inside nvlist. */
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(result, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(value), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(value));
+ ATF_REQUIRE(nvlist_exists(value, subkey));
+ ATF_REQUIRE(nvlist_exists_null(value, subkey));
+ ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(value);
+}
+
+/* ATF cnvlist_take array tests */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_bool_array);
+ATF_TEST_CASE_BODY(cnvlist_take_bool_array)
+{
+ nvlist_t *nvl;
+ bool in_array[16];
+ const bool *out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = (i % 2 == 0);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_bool_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ out_array = cnvlist_take_bool_array(cookie, &nitems);
+ ATF_REQUIRE_EQ(nitems, 16);
+ ATF_REQUIRE(out_array != NULL);
+ for (i = 0; i < 16; i++)
+ ATF_REQUIRE_EQ(out_array[i], in_array[i]);
+
+ cookie = NULL;
+ ATF_REQUIRE(!nvlist_exists_bool_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_number_array);
+ATF_TEST_CASE_BODY(cnvlist_take_number_array)
+{
+ nvlist_t *nvl;
+ uint64_t in_array[16];
+ const uint64_t *out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = i;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_number_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ out_array = cnvlist_take_number_array(cookie, &nitems);
+
+ ATF_REQUIRE(out_array != NULL);
+ ATF_REQUIRE_EQ(nitems, 16);
+ for (i = 0; i < 16; i++)
+ ATF_REQUIRE_EQ(out_array[i], in_array[i]);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_string_array);
+ATF_TEST_CASE_BODY(cnvlist_take_string_array)
+{
+ nvlist_t *nvl;
+ const char *in_array[4] = {"inequality", "sks", ".", ""};
+ char **out_array;
+ const char *key;
+ void *cookie;
+ int type, i;
+ size_t nitems;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_string_array(nvl, key, in_array, 4);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ out_array = cnvlist_take_string_array(cookie, &nitems);
+ ATF_REQUIRE_EQ(nitems, 4);
+ for (i = 0; i < 4; i++) {
+ ATF_REQUIRE(out_array[i] != NULL);
+ ATF_REQUIRE_EQ(strcmp(out_array[i], in_array[i]), 0);
+ }
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ free(out_array);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_nvlist_array);
+ATF_TEST_CASE_BODY(cnvlist_take_nvlist_array)
+{
+ nvlist_t *testnvl[8];
+ nvlist_t **result;
+ nvlist_t *nvl;
+ void *cookie;
+ size_t num_items;
+ unsigned int i;
+ int type;
+ const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" };
+ const char *key;
+
+ for (i = 0; i < 8; i++) {
+ testnvl[i] = nvlist_create(0);
+ ATF_REQUIRE(testnvl[i] != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE(nvlist_empty(testnvl[i]));
+ nvlist_add_string(testnvl[i], "nvl/string", somestr[i]);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp("nvl/string", nvlist_next(testnvl[i],
+ &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+ ATF_REQUIRE(!nvlist_empty(testnvl[i]));
+ ATF_REQUIRE(nvlist_exists(testnvl[i], "nvl/string"));
+ ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string"));
+ ATF_REQUIRE_EQ(nvlist_next(testnvl[i], &type, &cookie),
+ static_cast<const char *>(NULL));
+ }
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ key = "nvl/nvlist";
+ cookie = NULL;
+
+ nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ result = cnvlist_take_nvlist_array(cookie, &num_items);
+
+ ATF_REQUIRE(result != NULL);
+ ATF_REQUIRE_EQ(num_items, 8);
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(nvlist_error(result[i]), 0);
+ ATF_REQUIRE(nvlist_get_array_next(result[i]) == NULL);
+ }
+
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ for (i = 0; i < 8; i++) {
+ nvlist_destroy(result[i]);
+ nvlist_destroy(testnvl[i]);
+ }
+
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_take_binary);
+ATF_TEST_CASE_BODY(cnvlist_take_binary)
+{
+ nvlist_t *nvl;
+ const char *key;
+ void *in_binary;
+ const void *out_binary;
+ void *cookie;
+ int type;
+ size_t in_size, out_size;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ in_size = 13;
+ in_binary = malloc(in_size);
+ ATF_REQUIRE(in_binary != NULL);
+ memset(in_binary, 0xa5, in_size);
+
+ nvlist_add_binary(nvl, key, in_binary, in_size);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BINARY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_binary(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ out_binary = cnvlist_take_binary(cookie, &out_size);
+ ATF_REQUIRE_EQ(out_size, in_size);
+ ATF_REQUIRE_EQ(memcmp(in_binary, out_binary, out_size), 0);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_binary(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+/* ATF cnvlist_free tests. */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_bool);
+ATF_TEST_CASE_BODY(cnvlist_free_bool)
+{
+ nvlist_t *nvl;
+ const char *key;
+ bool value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = true;
+
+ nvlist_add_bool(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_bool(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_bool(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_number);
+ATF_TEST_CASE_BODY(cnvlist_free_number)
+{
+ nvlist_t *nvl;
+ const char *key;
+ uint64_t value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = 69;
+
+ nvlist_add_number(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_number(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_number(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_string);
+ATF_TEST_CASE_BODY(cnvlist_free_string)
+{
+ nvlist_t *nvl;
+ const char *key;
+ const char *value;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ value = "text";
+
+ nvlist_add_string(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_string(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_string(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_nvlist);
+ATF_TEST_CASE_BODY(cnvlist_free_nvlist)
+{
+ nvlist_t *nvl, *value;
+ const char *key, *subkey;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ value = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ key = "name";
+ subkey = "subname";
+ cookie = NULL;
+
+ /* Add null to 'value' nvlist. */
+ nvlist_add_null(value, subkey);
+ ATF_REQUIRE_EQ(strcmp(subkey, nvlist_next(value, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(value), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NULL);
+ ATF_REQUIRE(!nvlist_empty(value));
+ ATF_REQUIRE(nvlist_exists(value, subkey));
+ ATF_REQUIRE(nvlist_exists_null(value, subkey));
+ ATF_REQUIRE_EQ(nvlist_next(value, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ /* Add 'value' nvlist. */
+ cookie = NULL;
+ nvlist_move_nvlist(nvl, key, value);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_nvlist(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_binary);
+ATF_TEST_CASE_BODY(cnvlist_free_binary)
+{
+ nvlist_t *nvl;
+ const char *key;
+ void *in_binary;
+ void *cookie;
+ int type;
+ size_t in_size;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+ in_size = 13;
+ in_binary = malloc(in_size);
+ ATF_REQUIRE(in_binary != NULL);
+ memset(in_binary, 0xa5, in_size);
+
+ nvlist_add_binary(nvl, key, in_binary, in_size);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BINARY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_binary(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_binary(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_nvlist(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+/* ATF cnvlist_free array tests. */
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_bool_array);
+ATF_TEST_CASE_BODY(cnvlist_free_bool_array)
+{
+ nvlist_t *nvl;
+ bool in_array[16];
+ const char *key;
+ void *cookie;
+ int type, i;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = (i % 2 == 0);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_bool_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_BOOL_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_bool_array(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_bool(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_number_array);
+ATF_TEST_CASE_BODY(cnvlist_free_number_array)
+{
+ nvlist_t *nvl;
+ uint64_t in_array[16];
+ const char *key;
+ void *cookie;
+ int type, i;
+
+ for (i = 0; i < 16; i++)
+ in_array[i] = i;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_number_array(nvl, key, in_array, 16);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NUMBER_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_number_array(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_string_array);
+ATF_TEST_CASE_BODY(cnvlist_free_string_array)
+{
+ nvlist_t *nvl;
+ const char *in_array[4] = {"inequality", "sucks", ".", ""};
+ const char *key;
+ void *cookie;
+ int type;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ cookie = NULL;
+ key = "name";
+
+ nvlist_add_string_array(nvl, key, in_array, 4);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_string_array(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(cnvlist_free_nvlist_array);
+ATF_TEST_CASE_BODY(cnvlist_free_nvlist_array)
+{
+ nvlist_t *testnvl[8];
+ nvlist_t *nvl;
+ void *cookie;
+ unsigned int i;
+ int type;
+ const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" };
+ const char *key;
+
+ for (i = 0; i < 8; i++) {
+ testnvl[i] = nvlist_create(0);
+ ATF_REQUIRE(testnvl[i] != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE(nvlist_empty(testnvl[i]));
+ nvlist_add_string(testnvl[i], "nvl/string", somestr[i]);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp("nvl/string", nvlist_next(testnvl[i],
+ &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_STRING);
+ ATF_REQUIRE(!nvlist_empty(testnvl[i]));
+ ATF_REQUIRE(nvlist_exists(testnvl[i], "nvl/string"));
+ ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string"));
+ ATF_REQUIRE_EQ(nvlist_next(testnvl[i], &type, &cookie),
+ static_cast<const char *>(NULL));
+ }
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ key = "nvl/nvlist";
+ cookie = NULL;
+
+ nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8);
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE_EQ(type, NV_TYPE_NVLIST_ARRAY);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(strcmp(key, nvlist_next(nvl, &type, &cookie)), 0);
+ cnvlist_free_nvlist_array(cookie);
+
+ cookie = NULL;
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists(nvl, key));
+ ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE_EQ(nvlist_next(nvl, &type, &cookie),
+ static_cast<const char *>(NULL));
+
+ for (i = 0; i < 8; i++)
+ nvlist_destroy(testnvl[i]);
+ nvlist_destroy(nvl);
+}
+
+ATF_INIT_TEST_CASES(tp)
+{
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_bool);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_bool_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_number);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_string);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_nvlist);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_descriptor);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_binary);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_number_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_string_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_nvlist_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_get_descriptor_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_bool);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_number);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_string);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_nvlist);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_binary);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_bool_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_number_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_string_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_take_nvlist_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_bool);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_number);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_string);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_nvlist);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_binary);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_bool_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_number_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_string_array);
+ ATF_ADD_TEST_CASE(tp, cnvlist_free_nvlist_array);
+}
diff --git a/lib/libnv/tests/dnv_tests.cc b/lib/libnv/tests/dnv_tests.cc
new file mode 100644
index 000000000000..cf478f1bd2a2
--- /dev/null
+++ b/lib/libnv/tests/dnv_tests.cc
@@ -0,0 +1,571 @@
+/*-
+ * 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/types.h>
+#include <sys/dnv.h>
+#include <sys/nv.h>
+
+#include <atf-c++.hpp>
+
+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);
+ free(default_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);
+ free(default_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);
+ free(value);
+ 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);
+ free(default_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);
+ free(default_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);
+}
diff --git a/lib/libnv/tests/nv_array_tests.cc b/lib/libnv/tests/nv_array_tests.cc
new file mode 100644
index 000000000000..9acbaef67eba
--- /dev/null
+++ b/lib/libnv/tests/nv_array_tests.cc
@@ -0,0 +1,1248 @@
+/*-
+ * Copyright (c) 2015-2024 Mariusz Zaborski <oshogbo@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 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/param.h>
+#include <sys/types.h>
+#include <sys/nv.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+
+#include <atf-c++.hpp>
+
+#include <cstdio>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits>
+#include <set>
+#include <sstream>
+#include <string>
+
+#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__basic);
+ATF_TEST_CASE_BODY(nvlist_bool_array__basic)
+{
+ bool testbool[16];
+ const bool *const_result;
+ bool *result;
+ nvlist_t *nvl;
+ size_t num_items;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/bool";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ for (i = 0; i < 16; i++)
+ testbool[i] = (i % 2 == 0);
+
+ nvlist_add_bool_array(nvl, key, testbool, 16);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, "nvl/bool"));
+
+ const_result = nvlist_get_bool_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, 16);
+ ATF_REQUIRE(const_result != NULL);
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(const_result[i], testbool[i]);
+
+ result = nvlist_take_bool_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, 16);
+ ATF_REQUIRE(const_result != NULL);
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(result[i], testbool[i]);
+
+ ATF_REQUIRE(!nvlist_exists_bool_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__basic);
+ATF_TEST_CASE_BODY(nvlist_string_array__basic)
+{
+ const char * const *const_result;
+ char **result;
+ nvlist_t *nvl;
+ size_t num_items;
+ unsigned int i;
+ const char *key;
+ const char *string_arr[8] = { "a", "b", "kot", "foo",
+ "tests", "nice test", "", "abcdef" };
+
+ key = "nvl/string";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_string_array(nvl, key, string_arr, nitems(string_arr));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, "nvl/string"));
+
+ const_result = nvlist_get_string_array(nvl, key, &num_items);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(num_items == nitems(string_arr));
+ for (i = 0; i < num_items; i++) {
+ if (string_arr[i] != NULL) {
+ ATF_REQUIRE(strcmp(const_result[i],
+ string_arr[i]) == 0);
+ } else {
+ ATF_REQUIRE(const_result[i] == string_arr[i]);
+ }
+ }
+
+ result = nvlist_take_string_array(nvl, key, &num_items);
+ ATF_REQUIRE(result != NULL);
+ ATF_REQUIRE_EQ(num_items, nitems(string_arr));
+ for (i = 0; i < num_items; i++) {
+ if (string_arr[i] != NULL) {
+ ATF_REQUIRE_EQ(strcmp(result[i], string_arr[i]), 0);
+ } else {
+ ATF_REQUIRE_EQ(result[i], string_arr[i]);
+ }
+ }
+
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ for (i = 0; i < num_items; i++)
+ free(result[i]);
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__basic);
+ATF_TEST_CASE_BODY(nvlist_descriptor_array__basic)
+{
+ int fd[32], *result;
+ const int *const_result;
+ nvlist_t *nvl;
+ size_t num_items;
+ unsigned int i;
+ const char *key;
+
+ for (i = 0; i < nitems(fd); i++) {
+ fd[i] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fd_is_valid(fd[i]));
+ }
+
+ key = "nvl/descriptor";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_descriptor_array(nvl, key));
+
+ nvlist_add_descriptor_array(nvl, key, fd, nitems(fd));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, "nvl/descriptor"));
+
+ const_result = nvlist_get_descriptor_array(nvl, key, &num_items);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(num_items == nitems(fd));
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE(fd_is_valid(const_result[i]));
+ if (i > 0)
+ ATF_REQUIRE(const_result[i] != const_result[i - 1]);
+ }
+
+ result = nvlist_take_descriptor_array(nvl, key, &num_items);
+ ATF_REQUIRE(result != NULL);
+ ATF_REQUIRE_EQ(num_items, nitems(fd));
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE(fd_is_valid(result[i]));
+ if (i > 0)
+ ATF_REQUIRE(const_result[i] != const_result[i - 1]);
+ }
+
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ for (i = 0; i < num_items; i++) {
+ close(result[i]);
+ close(fd[i]);
+ }
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__basic);
+ATF_TEST_CASE_BODY(nvlist_number_array__basic)
+{
+ const uint64_t *const_result;
+ uint64_t *result;
+ nvlist_t *nvl;
+ size_t num_items;
+ unsigned int i;
+ const char *key;
+ const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90,
+ 100000, 8, 1 };
+
+ key = "nvl/number";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_number_array(nvl, key, number, nitems(number));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, "nvl/number"));
+
+ const_result = nvlist_get_number_array(nvl, key, &num_items);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(num_items == nitems(number));
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(const_result[i], number[i]);
+
+ result = nvlist_take_number_array(nvl, key, &num_items);
+ ATF_REQUIRE(result != NULL);
+ ATF_REQUIRE_EQ(num_items, nitems(number));
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(result[i], number[i]);
+
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__basic);
+ATF_TEST_CASE_BODY(nvlist_nvlist_array__basic)
+{
+ nvlist_t *testnvl[8];
+ const nvlist_t * const *const_result;
+ nvlist_t **result;
+ nvlist_t *nvl;
+ size_t num_items;
+ unsigned int i;
+ const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" };
+ const char *key;
+
+ for (i = 0; i < 8; i++) {
+ testnvl[i] = nvlist_create(0);
+ ATF_REQUIRE(testnvl[i] != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ nvlist_add_string(testnvl[i], "nvl/string", somestr[i]);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string"));
+ }
+
+ key = "nvl/nvlist";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, "nvl/nvlist"));
+
+ const_result = nvlist_get_nvlist_array(nvl, key, &num_items);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(num_items == nitems(testnvl));
+
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0);
+ if (i < num_items - 1) {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ const_result[i + 1]);
+ } else {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ NULL);
+ }
+ ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == nvl);
+ ATF_REQUIRE(nvlist_in_array(const_result[i]));
+ ATF_REQUIRE(nvlist_exists_string(const_result[i],
+ "nvl/string"));
+ ATF_REQUIRE(strcmp(nvlist_get_string(const_result[i],
+ "nvl/string"), somestr[i]) == 0);
+ }
+
+ result = nvlist_take_nvlist_array(nvl, key, &num_items);
+ ATF_REQUIRE(result != NULL);
+ ATF_REQUIRE_EQ(num_items, 8);
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(nvlist_error(result[i]), 0);
+ ATF_REQUIRE(nvlist_get_array_next(result[i]) == NULL);
+ ATF_REQUIRE(nvlist_get_parent(result[i], NULL) == NULL);
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) == NULL);
+ ATF_REQUIRE(!nvlist_in_array(const_result[i]));
+ }
+
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ for (i = 0; i < 8; i++) {
+ nvlist_destroy(result[i]);
+ nvlist_destroy(testnvl[i]);
+ }
+
+ free(result);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone_array);
+ATF_TEST_CASE_BODY(nvlist_clone_array)
+{
+ nvlist_t *testnvl[8];
+ nvlist_t *src, *dst;
+ const nvlist_t *nvl;
+ bool testbool[16];
+ int testfd[16];
+ size_t i, num_items;
+ const char *string_arr[8] = { "a", "b", "kot", "foo",
+ "tests", "nice test", "", "abcdef" };
+ const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" };
+ const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90,
+ 100000, 8, 1 };
+
+ for (i = 0; i < nitems(testfd); i++) {
+ testbool[i] = (i % 2 == 0);
+ testfd[i] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fd_is_valid(testfd[i]));
+ }
+ for (i = 0; i < nitems(testnvl); i++) {
+ testnvl[i] = nvlist_create(0);
+ ATF_REQUIRE(nvlist_error(testnvl[i]) == 0);
+ nvlist_add_string(testnvl[i], "nvl/nvl/teststr", somestr[i]);
+ ATF_REQUIRE(nvlist_error(testnvl[i]) == 0);
+ }
+
+ src = nvlist_create(0);
+ ATF_REQUIRE(nvlist_error(src) == 0);
+
+ ATF_REQUIRE(!nvlist_exists_bool_array(src, "nvl/bool"));
+ nvlist_add_bool_array(src, "nvl/bool", testbool, nitems(testbool));
+ ATF_REQUIRE_EQ(nvlist_error(src), 0);
+ ATF_REQUIRE(nvlist_exists_bool_array(src, "nvl/bool"));
+
+ ATF_REQUIRE(!nvlist_exists_string_array(src, "nvl/string"));
+ nvlist_add_string_array(src, "nvl/string", string_arr,
+ nitems(string_arr));
+ ATF_REQUIRE_EQ(nvlist_error(src), 0);
+ ATF_REQUIRE(nvlist_exists_string_array(src, "nvl/string"));
+
+ ATF_REQUIRE(!nvlist_exists_descriptor_array(src, "nvl/fd"));
+ nvlist_add_descriptor_array(src, "nvl/fd", testfd, nitems(testfd));
+ ATF_REQUIRE_EQ(nvlist_error(src), 0);
+ ATF_REQUIRE(nvlist_exists_descriptor_array(src, "nvl/fd"));
+
+ ATF_REQUIRE(!nvlist_exists_number_array(src, "nvl/number"));
+ nvlist_add_number_array(src, "nvl/number", number,
+ nitems(number));
+ ATF_REQUIRE_EQ(nvlist_error(src), 0);
+ ATF_REQUIRE(nvlist_exists_number_array(src, "nvl/number"));
+
+ ATF_REQUIRE(!nvlist_exists_nvlist_array(src, "nvl/array"));
+ nvlist_add_nvlist_array(src, "nvl/array",
+ (const nvlist_t * const *)testnvl, nitems(testnvl));
+ ATF_REQUIRE_EQ(nvlist_error(src), 0);
+ ATF_REQUIRE(nvlist_exists_nvlist_array(src, "nvl/array"));
+
+ dst = nvlist_clone(src);
+ ATF_REQUIRE(dst != NULL);
+
+ ATF_REQUIRE(nvlist_exists_bool_array(dst, "nvl/bool"));
+ (void) nvlist_get_bool_array(dst, "nvl/bool", &num_items);
+ ATF_REQUIRE_EQ(num_items, nitems(testbool));
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE(
+ nvlist_get_bool_array(dst, "nvl/bool", &num_items)[i] ==
+ nvlist_get_bool_array(src, "nvl/bool", &num_items)[i]);
+ }
+
+ ATF_REQUIRE(nvlist_exists_string_array(dst, "nvl/string"));
+ (void) nvlist_get_string_array(dst, "nvl/string", &num_items);
+ ATF_REQUIRE_EQ(num_items, nitems(string_arr));
+ for (i = 0; i < num_items; i++) {
+ if (nvlist_get_string_array(dst, "nvl/string",
+ &num_items)[i] == NULL) {
+ ATF_REQUIRE(nvlist_get_string_array(dst, "nvl/string",
+ &num_items)[i] == nvlist_get_string_array(src,
+ "nvl/string", &num_items)[i]);
+ } else {
+ ATF_REQUIRE(strcmp(nvlist_get_string_array(dst,
+ "nvl/string", &num_items)[i], nvlist_get_string_array(
+ src, "nvl/string", &num_items)[i]) == 0);
+ }
+ }
+
+ ATF_REQUIRE(nvlist_exists_descriptor_array(dst, "nvl/fd"));
+ (void) nvlist_get_descriptor_array(dst, "nvl/fd", &num_items);
+ ATF_REQUIRE_EQ(num_items, nitems(testfd));
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE(fd_is_valid(
+ nvlist_get_descriptor_array(dst, "nvl/fd", &num_items)[i]));
+ }
+ ATF_REQUIRE(nvlist_exists_number_array(dst, "nvl/number"));
+ (void) nvlist_get_number_array(dst, "nvl/number", &num_items);
+ ATF_REQUIRE_EQ(num_items, nitems(number));
+
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE(
+ nvlist_get_number_array(dst, "nvl/number", &num_items)[i] ==
+ nvlist_get_number_array(src, "nvl/number", &num_items)[i]);
+ }
+
+ ATF_REQUIRE(nvlist_exists_nvlist_array(dst, "nvl/array"));
+ (void) nvlist_get_nvlist_array(dst, "nvl/array", &num_items);
+ ATF_REQUIRE_EQ(num_items, nitems(testnvl));
+ for (i = 0; i < num_items; i++) {
+ nvl = nvlist_get_nvlist_array(dst, "nvl/array", &num_items)[i];
+ ATF_REQUIRE(nvlist_exists_string(nvl, "nvl/nvl/teststr"));
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, "nvl/nvl/teststr"),
+ somestr[i]) == 0);
+ }
+
+ for (i = 0; i < nitems(testfd); i++) {
+ close(testfd[i]);
+ }
+ for (i = 0; i < nitems(testnvl); i++) {
+ nvlist_destroy(testnvl[i]);
+ }
+ nvlist_destroy(src);
+ nvlist_destroy(dst);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__move);
+ATF_TEST_CASE_BODY(nvlist_bool_array__move)
+{
+ bool *testbool;
+ const bool *const_result;
+ nvlist_t *nvl;
+ size_t num_items, count;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/bool";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ count = 16;
+ testbool = (bool*)malloc(sizeof(*testbool) * count);
+ ATF_REQUIRE(testbool != NULL);
+ for (i = 0; i < count; i++)
+ testbool[i] = (i % 2 == 0);
+
+ nvlist_move_bool_array(nvl, key, testbool, count);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+
+ const_result = nvlist_get_bool_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, count);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(const_result == testbool);
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(const_result[i], (i % 2 == 0));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__move);
+ATF_TEST_CASE_BODY(nvlist_string_array__move)
+{
+ char **teststr;
+ const char * const *const_result;
+ nvlist_t *nvl;
+ size_t num_items, count;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/string";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ count = 26;
+ teststr = (char**)malloc(sizeof(*teststr) * count);
+ ATF_REQUIRE(teststr != NULL);
+ for (i = 0; i < count; i++) {
+ teststr[i] = (char*)malloc(sizeof(**teststr) * 2);
+ ATF_REQUIRE(teststr[i] != NULL);
+ teststr[i][0] = 'a' + i;
+ teststr[i][1] = '\0';
+ }
+
+ nvlist_move_string_array(nvl, key, teststr, count);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+
+ const_result = nvlist_get_string_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, count);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE((intptr_t)const_result == (intptr_t)teststr);
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(const_result[i][0], (char)('a' + i));
+ ATF_REQUIRE_EQ(const_result[i][1], '\0');
+ }
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__move);
+ATF_TEST_CASE_BODY(nvlist_nvlist_array__move)
+{
+ nvlist **testnv;
+ const nvlist * const *const_result;
+ nvlist_t *nvl;
+ size_t num_items, count;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/nvlist";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_nvlist_array(nvl, key));
+
+ count = 26;
+ testnv = (nvlist**)malloc(sizeof(*testnv) * count);
+ ATF_REQUIRE(testnv != NULL);
+ for (i = 0; i < count; i++) {
+ testnv[i] = nvlist_create(0);
+ ATF_REQUIRE(testnv[i] != NULL);
+ }
+
+ nvlist_move_nvlist_array(nvl, key, testnv, count);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+
+ const_result = nvlist_get_nvlist_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, count);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE((intptr_t)const_result == (intptr_t)testnv);
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0);
+ ATF_REQUIRE(nvlist_empty(const_result[i]));
+ if (i < num_items - 1) {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ const_result[i + 1]);
+ } else {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ NULL);
+ }
+ ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == nvl);
+ ATF_REQUIRE(nvlist_in_array(const_result[i]));
+ }
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__move);
+ATF_TEST_CASE_BODY(nvlist_number_array__move)
+{
+ uint64_t *testnumber;
+ const uint64_t *const_result;
+ nvlist_t *nvl;
+ size_t num_items, count;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/number";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ count = 1000;
+ testnumber = (uint64_t*)malloc(sizeof(*testnumber) * count);
+ ATF_REQUIRE(testnumber != NULL);
+ for (i = 0; i < count; i++)
+ testnumber[i] = i;
+
+ nvlist_move_number_array(nvl, key, testnumber, count);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+
+ const_result = nvlist_get_number_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, count);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(const_result == testnumber);
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE_EQ(const_result[i], i);
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__move);
+ATF_TEST_CASE_BODY(nvlist_descriptor_array__move)
+{
+ int *testfd;
+ const int *const_result;
+ nvlist_t *nvl;
+ size_t num_items, count;
+ unsigned int i;
+ const char *key;
+
+ key = "nvl/fd";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ count = 50;
+ testfd = (int*)malloc(sizeof(*testfd) * count);
+ ATF_REQUIRE(testfd != NULL);
+ for (i = 0; i < count; i++) {
+ testfd[i] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fd_is_valid(testfd[i]));
+ }
+
+ nvlist_move_descriptor_array(nvl, key, testfd, count);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key));
+
+ const_result = nvlist_get_descriptor_array(nvl, key, &num_items);
+ ATF_REQUIRE_EQ(num_items, count);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE(const_result == testfd);
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE(fd_is_valid(const_result[i]));
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_arrays__error_null);
+ATF_TEST_CASE_BODY(nvlist_arrays__error_null)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_number_array(nvl, "nvl/number", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_number_array(nvl, "nvl/number", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_descriptor_array(nvl, "nvl/fd", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_descriptor_array(nvl, "nvl/fd", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_string_array(nvl, "nvl/string", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_string_array(nvl, "nvl/string", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_nvlist_array(nvl, "nvl/nvlist", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_nvlist_array(nvl, "nvl/nvlist", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_bool_array(nvl, "nvl/bool", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_bool_array(nvl, "nvl/bool", NULL, 0);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_arrays__bad_value);
+ATF_TEST_CASE_BODY(nvlist_arrays__bad_value)
+{
+ nvlist_t *nvl, *nvladd[1], **nvlmove;
+ int fdadd[1], *fdmove;
+
+ nvladd[0] = NULL;
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_nvlist_array(nvl, "nvl/nvlist", nvladd, 1);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ nvlmove = (nvlist_t**)malloc(sizeof(*nvlmove));
+ ATF_REQUIRE(nvlmove != NULL);
+ nvlmove[0] = NULL;
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_nvlist_array(nvl, "nvl/nvlist", nvlmove, 1);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ fdadd[0] = -2;
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_descriptor_array(nvl, "nvl/fd", fdadd, 1);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+
+ fdmove = (int*)malloc(sizeof(*fdmove));
+ ATF_REQUIRE(fdmove != NULL);
+ fdmove[0] = -2;
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_move_descriptor_array(nvl, "nvl/fd", fdmove, 1);
+ ATF_REQUIRE(nvlist_error(nvl) != 0);
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__travel);
+ATF_TEST_CASE_BODY(nvlist_nvlist_array__travel)
+{
+ nvlist_t *nvl, *test[5], *nasted;
+ const nvlist_t *travel;
+ const char *name;
+ void *cookie;
+ int type;
+ unsigned int i, index;
+
+ for (i = 0; i < nitems(test); i++) {
+ test[i] = nvlist_create(0);
+ ATF_REQUIRE(test[i] != NULL);
+ nvlist_add_number(test[i], "nvl/number", i);
+ ATF_REQUIRE(nvlist_error(test[i]) == 0);
+ }
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_nvlist_array(nvl, "nvl/nvlist_array", test, nitems(test));
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+ nasted = nvlist_create(0);
+ ATF_REQUIRE(nasted != NULL);
+ nvlist_add_nvlist_array(nasted, "nvl/nvl/nvlist_array", test,
+ nitems(test));
+ ATF_REQUIRE(nvlist_error(nasted) == 0);
+ nvlist_move_nvlist(nvl, "nvl/nvl", nasted);
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+ nvlist_add_string(nvl, "nvl/string", "END");
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+
+ cookie = NULL;
+ index = 0;
+ travel = nvl;
+ do {
+ while ((name = nvlist_next(travel, &type, &cookie)) != NULL) {
+ if (index == 0) {
+ ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY);
+ } else if (index >= 1 && index <= nitems(test)) {
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ } else if (index == nitems(test) + 1) {
+ ATF_REQUIRE(type == NV_TYPE_NVLIST);
+ } else if (index == nitems(test) + 2) {
+ ATF_REQUIRE(type == NV_TYPE_NVLIST_ARRAY);
+ } else if (index >= nitems(test) + 3 &&
+ index <= 2 * nitems(test) + 2) {
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ } else if (index == 2 * nitems(test) + 3) {
+ ATF_REQUIRE(type == NV_TYPE_STRING);
+ }
+
+ if (type == NV_TYPE_NVLIST) {
+ travel = nvlist_get_nvlist(travel, name);
+ cookie = NULL;
+ } else if (type == NV_TYPE_NVLIST_ARRAY) {
+ travel = nvlist_get_nvlist_array(travel, name,
+ NULL)[0];
+ cookie = NULL;
+ }
+ index ++;
+ }
+ } while ((travel = nvlist_get_pararr(travel, &cookie)) != NULL);
+
+ for (i = 0; i < nitems(test); i++)
+ nvlist_destroy(test[i]);
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__travel_alternative);
+ATF_TEST_CASE_BODY(nvlist_nvlist_array__travel_alternative)
+{
+ nvlist_t *nvl, *test[5], *nasted;
+ const nvlist_t *travel, *tmp;
+ void *cookie;
+ int index, i, type;
+ const char *name;
+
+ for (i = 0; i < 5; i++) {
+ test[i] = nvlist_create(0);
+ ATF_REQUIRE(test[i] != NULL);
+ nvlist_add_number(test[i], "nvl/number", i);
+ ATF_REQUIRE(nvlist_error(test[i]) == 0);
+ }
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_nvlist_array(nvl, "nvl/nvlist_array", test, 5);
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+ nasted = nvlist_create(0);
+ ATF_REQUIRE(nasted != NULL);
+ nvlist_add_nvlist_array(nasted, "nvl/nvl/nvlist_array", test, 5);
+ ATF_REQUIRE(nvlist_error(nasted) == 0);
+ nvlist_move_nvlist(nvl, "nvl/nvl", nasted);
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+ nvlist_add_string(nvl, "nvl/string", "END");
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+
+ cookie = NULL;
+ index = 0;
+ tmp = travel = nvl;
+ do {
+ do {
+ travel = tmp;
+ while ((name = nvlist_next(travel, &type, &cookie)) !=
+ NULL) {
+ if (index == 0) {
+ ATF_REQUIRE(type ==
+ NV_TYPE_NVLIST_ARRAY);
+ } else if (index >= 1 && index <= 5) {
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ } else if (index == 6) {
+ ATF_REQUIRE(type == NV_TYPE_NVLIST);
+ } else if (index == 7) {
+ ATF_REQUIRE(type ==
+ NV_TYPE_NVLIST_ARRAY);
+ } else if (index >= 8 && index <= 12) {
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ } else if (index == 13) {
+ ATF_REQUIRE(type == NV_TYPE_STRING);
+ }
+
+ if (type == NV_TYPE_NVLIST) {
+ travel = nvlist_get_nvlist(travel,
+ name);
+ cookie = NULL;
+ } else if (type == NV_TYPE_NVLIST_ARRAY) {
+ travel = nvlist_get_nvlist_array(travel,
+ name, NULL)[0];
+ cookie = NULL;
+ }
+ index ++;
+ }
+ cookie = NULL;
+ } while ((tmp = nvlist_get_array_next(travel)) != NULL);
+ } while ((tmp = nvlist_get_parent(travel, &cookie)) != NULL);
+
+ for (i = 0; i < 5; i++)
+ nvlist_destroy(test[i]);
+
+ nvlist_destroy(nvl);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_bool_array__pack);
+ATF_TEST_CASE_BODY(nvlist_bool_array__pack)
+{
+ nvlist_t *nvl, *unpacked;
+ const char *key;
+ size_t packed_size, count;
+ void *packed;
+ unsigned int i;
+ const bool *const_result;
+ bool testbool[16];
+
+ for (i = 0; i < nitems(testbool); i++)
+ testbool[i] = (i % 2 == 0);
+
+ key = "nvl/bool";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_bool_array(nvl, key, testbool, nitems(testbool));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_bool_array(nvl, key));
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, 0);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(unpacked), 0);
+ ATF_REQUIRE(nvlist_exists_bool_array(unpacked, key));
+
+ const_result = nvlist_get_bool_array(unpacked, key, &count);
+ ATF_REQUIRE_EQ(count, nitems(testbool));
+ for (i = 0; i < count; i++) {
+ ATF_REQUIRE_EQ(testbool[i], const_result[i]);
+ }
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(unpacked);
+ free(packed);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_number_array__pack);
+ATF_TEST_CASE_BODY(nvlist_number_array__pack)
+{
+ nvlist_t *nvl, *unpacked;
+ const char *key;
+ size_t packed_size, count;
+ void *packed;
+ unsigned int i;
+ const uint64_t *const_result;
+ const uint64_t number[8] = { 0, UINT_MAX, 7, 123, 90,
+ 100000, 8, 1 };
+
+ key = "nvl/number";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_number_array(nvl, key, number, 8);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_number_array(nvl, key));
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, 0);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(unpacked), 0);
+ ATF_REQUIRE(nvlist_exists_number_array(unpacked, key));
+
+ const_result = nvlist_get_number_array(unpacked, key, &count);
+ ATF_REQUIRE_EQ(count, nitems(number));
+ for (i = 0; i < count; i++) {
+ ATF_REQUIRE_EQ(number[i], const_result[i]);
+ }
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(unpacked);
+ free(packed);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_descriptor_array__pack);
+ATF_TEST_CASE_BODY(nvlist_descriptor_array__pack)
+{
+ nvlist_t *nvl;
+ const char *key;
+ size_t num_items;
+ unsigned int i;
+ const int *const_result;
+ int desc[32], fd, socks[2];
+ pid_t pid;
+
+ key = "nvl/descriptor";
+
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
+
+ pid = atf::utils::fork();
+ ATF_REQUIRE(pid >= 0);
+ if (pid == 0) {
+ /* Child. */
+ fd = socks[0];
+ close(socks[1]);
+ for (i = 0; i < nitems(desc); i++) {
+ desc[i] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fd_is_valid(desc[i]));
+ }
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_descriptor_array(nvl, key));
+
+ nvlist_add_descriptor_array(nvl, key, desc, nitems(desc));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key));
+
+ ATF_REQUIRE(nvlist_send(fd, nvl) >= 0);
+
+ for (i = 0; i < nitems(desc); i++)
+ close(desc[i]);
+ } else {
+ /* Parent */
+ fd = socks[1];
+ close(socks[0]);
+
+ errno = 0;
+ nvl = nvlist_recv(fd, 0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(nvlist_exists_descriptor_array(nvl, key));
+
+ const_result = nvlist_get_descriptor_array(nvl, key, &num_items);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE_EQ(num_items, nitems(desc));
+ for (i = 0; i < num_items; i++)
+ ATF_REQUIRE(fd_is_valid(const_result[i]));
+
+ atf::utils::wait(pid, 0, "", "");
+ }
+
+ nvlist_destroy(nvl);
+ close(fd);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array__pack);
+ATF_TEST_CASE_BODY(nvlist_string_array__pack)
+{
+ nvlist_t *nvl, *unpacked;
+ const char *key;
+ size_t packed_size, count;
+ void *packed;
+ unsigned int i;
+ const char * const *const_result;
+ const char *string_arr[8] = { "a", "b", "kot", "foo",
+ "tests", "nice test", "", "abcdef" };
+
+ key = "nvl/string";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_string_array(nvl, key, string_arr, nitems(string_arr));
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_string_array(nvl, key));
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, 0);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(unpacked), 0);
+ ATF_REQUIRE(nvlist_exists_string_array(unpacked, key));
+
+ const_result = nvlist_get_string_array(unpacked, key, &count);
+ ATF_REQUIRE_EQ(count, nitems(string_arr));
+ for (i = 0; i < count; i++) {
+ ATF_REQUIRE_EQ(strcmp(string_arr[i], const_result[i]), 0);
+ }
+
+ nvlist_destroy(nvl);
+ nvlist_destroy(unpacked);
+ free(packed);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_nvlist_array__pack);
+ATF_TEST_CASE_BODY(nvlist_nvlist_array__pack)
+{
+ nvlist_t *testnvl[8], *unpacked;
+ const nvlist_t * const *const_result;
+ nvlist_t *nvl;
+ size_t num_items, packed_size;
+ unsigned int i;
+ void *packed;
+ const char *somestr[8] = { "a", "b", "c", "d", "e", "f", "g", "h" };
+ const char *key;
+
+ for (i = 0; i < nitems(testnvl); i++) {
+ testnvl[i] = nvlist_create(0);
+ ATF_REQUIRE(testnvl[i] != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ nvlist_add_string(testnvl[i], "nvl/string", somestr[i]);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl[i]), 0);
+ ATF_REQUIRE(nvlist_exists_string(testnvl[i], "nvl/string"));
+ }
+
+ key = "nvl/nvlist";
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+ ATF_REQUIRE(!nvlist_exists_string_array(nvl, key));
+
+ nvlist_add_nvlist_array(nvl, key, (const nvlist_t * const *)testnvl, 8);
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, key));
+ ATF_REQUIRE(nvlist_exists_nvlist_array(nvl, "nvl/nvlist"));
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, 0);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(unpacked), 0);
+ ATF_REQUIRE(nvlist_exists_nvlist_array(unpacked, key));
+
+ const_result = nvlist_get_nvlist_array(unpacked, key, &num_items);
+ ATF_REQUIRE(const_result != NULL);
+ ATF_REQUIRE_EQ(num_items, nitems(testnvl));
+ for (i = 0; i < num_items; i++) {
+ ATF_REQUIRE_EQ(nvlist_error(const_result[i]), 0);
+ if (i < num_items - 1) {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ const_result[i + 1]);
+ } else {
+ ATF_REQUIRE(nvlist_get_array_next(const_result[i]) ==
+ NULL);
+ }
+ ATF_REQUIRE(nvlist_get_parent(const_result[i], NULL) == unpacked);
+ ATF_REQUIRE(nvlist_in_array(const_result[i]));
+ ATF_REQUIRE(nvlist_exists_string(const_result[i],
+ "nvl/string"));
+ ATF_REQUIRE(strcmp(nvlist_get_string(const_result[i],
+ "nvl/string"), somestr[i]) == 0);
+ }
+
+ for (i = 0; i < nitems(testnvl); i++)
+ nvlist_destroy(testnvl[i]);
+ nvlist_destroy(nvl);
+ nvlist_destroy(unpacked);
+ free(packed);
+}
+
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_string_array_nonull__pack);
+ATF_TEST_CASE_BODY(nvlist_string_array_nonull__pack)
+{
+ nvlist_t *testnvl, *unpacked;
+ const char *somestr[3] = { "a", "b", "XXX" };
+ uint8_t *packed, *twopages, *dataptr, *secondpage;
+ size_t packed_size, page_size;
+ bool found;
+
+ page_size = sysconf(_SC_PAGESIZE);
+ testnvl = nvlist_create(0);
+ ATF_REQUIRE(testnvl != NULL);
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
+ nvlist_add_string_array(testnvl, "nvl/string", somestr,
+ nitems(somestr));
+ ATF_REQUIRE_EQ(nvlist_error(testnvl), 0);
+
+ packed = (uint8_t *)nvlist_pack(testnvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ twopages = (uint8_t *)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ATF_REQUIRE(twopages != MAP_FAILED);
+ dataptr = &twopages[page_size - packed_size];
+ secondpage = &twopages[page_size];
+
+ memset(twopages, 'A', page_size * 2);
+
+ mprotect(secondpage, page_size, PROT_NONE);
+ memcpy(dataptr, packed, packed_size);
+
+ found = false;
+ for (size_t i = 0; i < packed_size - 3; i++) {
+ if (dataptr[i] == 'X' && dataptr[i + 1] == 'X' &&
+ dataptr[i + 2] == 'X' && dataptr[i + 3] == '\0') {
+ dataptr[i + 3] = 'X';
+ found = true;
+ break;
+ }
+ }
+ ATF_REQUIRE(found == true);
+
+ unpacked = nvlist_unpack(dataptr, packed_size, 0);
+ ATF_REQUIRE(unpacked == NULL);
+
+ nvlist_destroy(testnvl);
+ free(packed);
+ munmap(twopages, page_size * 2);
+}
+
+
+ATF_INIT_TEST_CASES(tp)
+{
+
+ ATF_ADD_TEST_CASE(tp, nvlist_bool_array__basic);
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array__basic);
+ ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__basic);
+ ATF_ADD_TEST_CASE(tp, nvlist_number_array__basic);
+ ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__basic)
+
+ ATF_ADD_TEST_CASE(tp, nvlist_clone_array)
+
+ ATF_ADD_TEST_CASE(tp, nvlist_bool_array__move);
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array__move);
+ ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__move);
+ ATF_ADD_TEST_CASE(tp, nvlist_number_array__move);
+ ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__move);
+
+ ATF_ADD_TEST_CASE(tp, nvlist_arrays__error_null);
+
+ ATF_ADD_TEST_CASE(tp, nvlist_arrays__bad_value)
+
+ ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__travel)
+ ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__travel_alternative)
+
+ ATF_ADD_TEST_CASE(tp, nvlist_bool_array__pack)
+ ATF_ADD_TEST_CASE(tp, nvlist_number_array__pack)
+ ATF_ADD_TEST_CASE(tp, nvlist_descriptor_array__pack)
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array__pack)
+ ATF_ADD_TEST_CASE(tp, nvlist_nvlist_array__pack)
+
+ ATF_ADD_TEST_CASE(tp, nvlist_string_array_nonull__pack)
+}
+
diff --git a/lib/libnv/tests/nv_tests.cc b/lib/libnv/tests/nv_tests.cc
new file mode 100644
index 000000000000..c784f6caa232
--- /dev/null
+++ b/lib/libnv/tests/nv_tests.cc
@@ -0,0 +1,1275 @@
+/*-
+ * 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>
+#include <sys/nv.h>
+
+#include <atf-c++.hpp>
+
+#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, 0);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE(unpacked != nvl);
+ ATF_REQUIRE(nvlist_empty(unpacked));
+
+ nvlist_destroy(unpacked);
+ nvlist_destroy(nvl);
+ free(packed);
+}
+
+ATF_TEST_CASE_WITHOUT_HEAD(nvlist_unpack__flags_nvlist);
+ATF_TEST_CASE_BODY(nvlist_unpack__flags_nvlist)
+{
+ nvlist_t *nvl, *unpacked;
+ void *packed;
+ size_t packed_size;
+
+ nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
+ ATF_REQUIRE(nvl != NULL);
+
+ nvlist_add_bool(nvl, "name", true);
+ ATF_REQUIRE(!nvlist_empty(nvl));
+ ATF_REQUIRE(nvlist_exists_bool(nvl, "name"));
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, 0);
+ ATF_REQUIRE(unpacked == NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, NV_FLAG_IGNORE_CASE);
+ ATF_REQUIRE(unpacked == NULL);
+
+ unpacked = nvlist_unpack(packed, packed_size, NV_FLAG_NO_UNIQUE);
+ ATF_REQUIRE(unpacked != NULL);
+ ATF_REQUIRE(unpacked != nvl);
+ ATF_REQUIRE(!nvlist_empty(unpacked));
+ ATF_REQUIRE(nvlist_exists_bool(unpacked, "name"));
+
+ 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, 0);
+ 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, 0);
+ 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_unpack__flags_nvlist);
+
+ 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);
+}
diff --git a/lib/libnv/tests/nvlist_add_test.c b/lib/libnv/tests/nvlist_add_test.c
new file mode 100644
index 000000000000..28f2b6f45446
--- /dev/null
+++ b/lib/libnv/tests/nvlist_add_test.c
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/nv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.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_append_test.c b/lib/libnv/tests/nvlist_append_test.c
new file mode 100644
index 000000000000..27038cc4fa98
--- /dev/null
+++ b/lib/libnv/tests/nvlist_append_test.c
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/nv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.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 bool *bool_result;
+ const char * const *string_result;
+ const nvlist_t * const *nvl_result;
+ nvlist_t *nvl, *nvl1, *nvl2, **items;
+ unsigned int i;
+ size_t nitems;
+
+ printf("1..32\n");
+
+ nvl = nvlist_create(0);
+
+ for (i = 0; i < 16; i++)
+ nvlist_append_bool_array(nvl, "nvl/bool", i % 2 == 0);
+
+ CHECK(nvlist_error(nvl) == 0);
+ CHECK(!nvlist_empty(nvl));
+ CHECK(nvlist_exists_bool_array(nvl, "nvl/bool"));
+
+ bool_result = nvlist_get_bool_array(nvl, "nvl/bool", &nitems);
+ CHECK(nitems == 16);
+ CHECK(bool_result != NULL);
+ for (i = 0; i < nitems; i++)
+ CHECK(bool_result[i] == (i % 2 == 0));
+
+
+ nvlist_append_string_array(nvl, "nvl/string", "a");
+ nvlist_append_string_array(nvl, "nvl/string", "abc");
+ string_result = nvlist_get_string_array(nvl, "nvl/string", &nitems);
+ CHECK(nitems == 2);
+ CHECK(strcmp(string_result[0], "a") == 0);
+ CHECK(strcmp(string_result[1], "abc") == 0);
+
+
+ nvl1 = nvlist_create(0);
+ nvlist_add_string(nvl1, "key1", "test1");
+ nvlist_append_nvlist_array(nvl, "nvl/nvl", nvl1);
+ nvlist_destroy(nvl1);
+
+ nvl2 = nvlist_create(0);
+ nvlist_add_string(nvl2, "key2", "test2");
+ nvlist_append_nvlist_array(nvl, "nvl/nvl", nvl2);
+ nvlist_destroy(nvl2);
+
+ nvl_result = nvlist_get_nvlist_array(nvl, "nvl/nvl", &nitems);
+ CHECK(nitems == 2);
+ CHECK(strcmp(nvlist_get_string(nvl_result[0], "key1"), "test1") == 0);
+ CHECK(strcmp(nvlist_get_string(nvl_result[1], "key2"), "test2") == 0);
+
+ nvl1 = nvlist_create(0);
+ nvlist_add_number(nvl1, "key1", 10);
+ nvlist_append_nvlist_array(nvl, "nvl/nvl_array", nvl1);
+ nvlist_destroy(nvl1);
+
+ nvl2 = nvlist_create(0);
+ nvlist_add_number(nvl2, "key1", 20);
+ nvlist_append_nvlist_array(nvl, "nvl/nvl_array", nvl2);
+ nvlist_destroy(nvl2);
+
+ items = nvlist_take_nvlist_array(nvl, "nvl/nvl_array", &nitems);
+ CHECK(nvlist_get_number(items[0], "key1") == 10);
+ CHECK(nvlist_get_number(items[1], "key1") == 20);
+ CHECK(nvlist_error(items[0]) == 0);
+ CHECK(nvlist_error(items[1]) == 0);
+
+ nvlist_move_nvlist_array(nvl, "nvl/nvl_new_array", items, nitems);
+ CHECK(nvlist_error(nvl) == 0);
+
+ 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 000000000000..808692feb85b
--- /dev/null
+++ b/lib/libnv/tests/nvlist_exists_test.c
@@ -0,0 +1,318 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/nv.h>
+
+#include <stdio.h>
+#include <unistd.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 000000000000..bb5eeaf7d04c
--- /dev/null
+++ b/lib/libnv/tests/nvlist_free_test.c
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/nv.h>
+
+#include <stdio.h>
+#include <unistd.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 000000000000..f06be569c90d
--- /dev/null
+++ b/lib/libnv/tests/nvlist_get_test.c
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/nv.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.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 000000000000..2ef7ca4de384
--- /dev/null
+++ b/lib/libnv/tests/nvlist_move_test.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/nv.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.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 000000000000..79297dfe2043
--- /dev/null
+++ b/lib/libnv/tests/nvlist_send_recv_test.c
@@ -0,0 +1,749 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ *
+ * 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/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <sys/nv.h>
+
+#include <stdlib.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include <nv_impl.h>
+#include <msgio.h>
+
+#define ALPHABET "abcdefghijklmnopqrstuvwxyz"
+#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
+
+static void
+send_nvlist_child(int sock)
+{
+ nvlist_t *nvl;
+ nvlist_t *empty;
+ int pfd[2];
+
+ 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/" ALPHABET, ALPHABET);
+
+ nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO",
+ STDERR_FILENO);
+ if (pipe(pfd) == -1)
+ err(EXIT_FAILURE, "pipe");
+ if (write(pfd[1], "test", 4) != 4)
+ err(EXIT_FAILURE, "write");
+ close(pfd[1]);
+ nvlist_add_descriptor(nvl, "nvlist/descriptor/pipe_rd", pfd[0]);
+ close(pfd[0]);
+
+ nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1);
+ nvlist_add_binary(nvl, "nvlist/binary/" ALPHABET, ALPHABET,
+ sizeof(ALPHABET));
+ nvlist_move_nvlist(nvl, "nvlist/nvlist/empty", empty);
+ nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl);
+
+ nvlist_send(sock, nvl);
+
+ nvlist_destroy(nvl);
+}
+
+static void
+send_nvlist_parent(int sock)
+{
+ nvlist_t *nvl;
+ const nvlist_t *cnvl, *empty;
+ const char *name, *cname;
+ void *cookie, *ccookie;
+ int type, ctype, fd;
+ size_t size;
+ char buf[4];
+
+ nvl = nvlist_recv(sock, 0);
+ ATF_REQUIRE(nvlist_error(nvl) == 0);
+ if (nvlist_error(nvl) != 0)
+ err(1, "nvlist_recv() failed");
+
+ cookie = NULL;
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_BOOL);
+ ATF_REQUIRE(strcmp(name, "nvlist/bool/true") == 0);
+ ATF_REQUIRE(nvlist_get_bool(nvl, name) == true);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_BOOL);
+ ATF_REQUIRE(strcmp(name, "nvlist/bool/false") == 0);
+ ATF_REQUIRE(nvlist_get_bool(nvl, name) == false);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/0") == 0);
+ ATF_REQUIRE(nvlist_get_number(nvl, name) == 0);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/1") == 0);
+ ATF_REQUIRE(nvlist_get_number(nvl, name) == 1);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/-1") == 0);
+ ATF_REQUIRE((int)nvlist_get_number(nvl, name) == -1);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/UINT64_MAX") == 0);
+ ATF_REQUIRE(nvlist_get_number(nvl, name) == UINT64_MAX);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MIN") == 0);
+ ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MIN);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(name, "nvlist/number/INT64_MAX") == 0);
+ ATF_REQUIRE((int64_t)nvlist_get_number(nvl, name) == INT64_MAX);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(name, "nvlist/string/") == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "") == 0);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(name, "nvlist/string/x") == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), "x") == 0);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(name, "nvlist/string/" ALPHABET) == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(nvl, name), ALPHABET) == 0);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
+ ATF_REQUIRE(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0);
+ ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(nvl, name)));
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_DESCRIPTOR);
+ ATF_REQUIRE(strcmp(name, "nvlist/descriptor/pipe_rd") == 0);
+ fd = nvlist_get_descriptor(nvl, name);
+ ATF_REQUIRE(fd_is_valid(fd));
+ ATF_REQUIRE(read(fd, buf, sizeof(buf)) == 4);
+ ATF_REQUIRE(strncmp(buf, "test", sizeof(buf)) == 0);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_BINARY);
+ ATF_REQUIRE(strcmp(name, "nvlist/binary/x") == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0);
+ ATF_REQUIRE(size == 1);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_BINARY);
+ ATF_REQUIRE(strcmp(name, "nvlist/binary/" ALPHABET) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, NULL), ALPHABET,
+ sizeof(ALPHABET)) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(nvl, name, &size), ALPHABET,
+ sizeof(ALPHABET)) == 0);
+ ATF_REQUIRE(size == sizeof(ALPHABET));
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NVLIST);
+ ATF_REQUIRE(strcmp(name, "nvlist/nvlist/empty") == 0);
+ cnvl = nvlist_get_nvlist(nvl, name);
+ ATF_REQUIRE(nvlist_empty(cnvl));
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name != NULL);
+ ATF_REQUIRE(type == NV_TYPE_NVLIST);
+ ATF_REQUIRE(strcmp(name, "nvlist/nvlist") == 0);
+ cnvl = nvlist_get_nvlist(nvl, name);
+
+ ccookie = NULL;
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_BOOL);
+ ATF_REQUIRE(strcmp(cname, "nvlist/bool/true") == 0);
+ ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == true);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_BOOL);
+ ATF_REQUIRE(strcmp(cname, "nvlist/bool/false") == 0);
+ ATF_REQUIRE(nvlist_get_bool(cnvl, cname) == false);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/0") == 0);
+ ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 0);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/1") == 0);
+ ATF_REQUIRE(nvlist_get_number(cnvl, cname) == 1);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/-1") == 0);
+ ATF_REQUIRE((int)nvlist_get_number(cnvl, cname) == -1);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/UINT64_MAX") == 0);
+ ATF_REQUIRE(nvlist_get_number(cnvl, cname) == UINT64_MAX);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MIN") == 0);
+ ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NUMBER);
+ ATF_REQUIRE(strcmp(cname, "nvlist/number/INT64_MAX") == 0);
+ ATF_REQUIRE((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(cname, "nvlist/string/") == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "") == 0);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(cname, "nvlist/string/x") == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), "x") == 0);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_STRING);
+ ATF_REQUIRE(strcmp(cname, "nvlist/string/" ALPHABET) == 0);
+ ATF_REQUIRE(strcmp(nvlist_get_string(cnvl, cname), ALPHABET) == 0);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
+ ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0);
+ ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_DESCRIPTOR);
+ ATF_REQUIRE(strcmp(cname, "nvlist/descriptor/pipe_rd") == 0);
+ ATF_REQUIRE(fd_is_valid(nvlist_get_descriptor(cnvl, cname)));
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_BINARY);
+ ATF_REQUIRE(strcmp(cname, "nvlist/binary/x") == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0);
+ ATF_REQUIRE(size == 1);
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_BINARY);
+ ATF_REQUIRE(strcmp(cname, "nvlist/binary/" ALPHABET) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, NULL), ALPHABET,
+ sizeof(ALPHABET)) == 0);
+ ATF_REQUIRE(memcmp(nvlist_get_binary(cnvl, cname, &size), ALPHABET,
+ sizeof(ALPHABET)) == 0);
+ ATF_REQUIRE(size == sizeof(ALPHABET));
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname != NULL);
+ ATF_REQUIRE(ctype == NV_TYPE_NVLIST);
+ ATF_REQUIRE(strcmp(cname, "nvlist/nvlist/empty") == 0);
+ empty = nvlist_get_nvlist(cnvl, cname);
+ ATF_REQUIRE(nvlist_empty(empty));
+
+ cname = nvlist_next(cnvl, &ctype, &ccookie);
+ ATF_REQUIRE(cname == NULL);
+
+ name = nvlist_next(nvl, &type, &cookie);
+ ATF_REQUIRE(name == NULL);
+
+ nvlist_destroy(nvl);
+}
+
+static void
+nvlist_send_recv__send_nvlist(short sotype)
+{
+ int socks[2], status;
+ pid_t pid;
+
+ ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+ if (pid == 0) {
+ /* Child. */
+ (void)close(socks[0]);
+ send_nvlist_child(socks[1]);
+ _exit(0);
+ }
+
+ (void)close(socks[1]);
+ send_nvlist_parent(socks[0]);
+
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
+ ATF_REQUIRE(status == 0);
+}
+
+static void
+nvlist_send_recv__send_closed_fd(short sotype)
+{
+ nvlist_t *nvl;
+ int socks[2];
+
+ ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ nvlist_add_descriptor(nvl, "fd", 12345);
+ ATF_REQUIRE(nvlist_error(nvl) == EBADF);
+
+ ATF_REQUIRE_ERRNO(EBADF, nvlist_send(socks[1], nvl) != 0);
+}
+
+static int
+nopenfds(void)
+{
+ size_t len;
+ int error, mib[4], n;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_NFDS;
+ mib[3] = 0;
+
+ len = sizeof(n);
+ error = sysctl(mib, nitems(mib), &n, &len, NULL, 0);
+ if (error != 0)
+ return (-1);
+ return (n);
+}
+
+#define NFDS 512
+
+static void
+send_many_fds_child(int sock)
+{
+ char name[16];
+ nvlist_t *nvl;
+ int anfds, bnfds, fd, i, j;
+
+ fd = open(_PATH_DEVNULL, O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ for (i = 1; i < NFDS; i++) {
+ nvl = nvlist_create(0);
+ bnfds = nopenfds();
+ if (bnfds == -1)
+ err(EXIT_FAILURE, "sysctl");
+
+ for (j = 0; j < i; j++) {
+ snprintf(name, sizeof(name), "fd%d", j);
+ nvlist_add_descriptor(nvl, name, fd);
+ }
+ nvlist_send(sock, nvl);
+ nvlist_destroy(nvl);
+
+ anfds = nopenfds();
+ if (anfds == -1)
+ err(EXIT_FAILURE, "sysctl");
+ if (anfds != bnfds)
+ errx(EXIT_FAILURE, "fd count mismatch");
+ }
+}
+
+static void
+nvlist_send_recv__send_many_fds(short sotype)
+{
+ char name[16];
+ nvlist_t *nvl;
+ int anfds, bnfds, fd, i, j, socks[2], status;
+ pid_t pid;
+
+ ATF_REQUIRE(socketpair(PF_UNIX, sotype, 0, socks) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+ if (pid == 0) {
+ /* Child. */
+ (void)close(socks[0]);
+ send_many_fds_child(socks[1]);
+ _exit(0);
+ }
+
+ (void)close(socks[1]);
+
+ for (i = 1; i < NFDS; i++) {
+ bnfds = nopenfds();
+ ATF_REQUIRE(bnfds != -1);
+
+ nvl = nvlist_recv(socks[0], 0);
+ ATF_REQUIRE(nvl != NULL);
+ for (j = 0; j < i; j++) {
+ snprintf(name, sizeof(name), "fd%d", j);
+ fd = nvlist_take_descriptor(nvl, name);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+ nvlist_destroy(nvl);
+
+ anfds = nopenfds();
+ ATF_REQUIRE(anfds != -1);
+ ATF_REQUIRE(anfds == bnfds);
+ }
+
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
+ ATF_REQUIRE(status == 0);
+}
+
+/*
+ * This test needs to tune the following sysctl's:
+ * net.local.dgram.maxdgram
+ * net.local.dgram.recvspace
+ */
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__dgram);
+ATF_TC_BODY(nvlist_send_recv__send_many_fds__dgram, tc)
+{
+ u_long maxdgram, recvspace, temp_maxdgram, temp_recvspace;
+ size_t len;
+ int error;
+
+ atf_tc_skip("https://bugs.freebsd.org/260891");
+
+ /* size of the largest datagram to send */
+ temp_maxdgram = 16772;
+ len = sizeof(maxdgram);
+ error = sysctlbyname("net.local.dgram.maxdgram", &maxdgram,
+ &len, &temp_maxdgram, sizeof(temp_maxdgram));
+ if (error != 0)
+ atf_tc_skip("cannot set net.local.dgram.maxdgram: %s", strerror(errno));
+
+ /*
+ * The receive queue fills up quicker than it's being emptied,
+ * bump it to a sufficiently large enough value, 1M.
+ */
+ temp_recvspace = 1048576;
+ len = sizeof(recvspace);
+ error = sysctlbyname("net.local.dgram.recvspace", &recvspace,
+ &len, &temp_recvspace, sizeof(temp_recvspace));
+ if (error != 0)
+ atf_tc_skip("cannot set net.local.dgram.recvspace: %s", strerror(errno));
+
+ nvlist_send_recv__send_many_fds(SOCK_DGRAM);
+
+ /* restore original values */
+ error = sysctlbyname("net.local.dgram.maxdgram", NULL, NULL, &maxdgram, sizeof(maxdgram));
+ if (error != 0)
+ warn("failed to restore net.local.dgram.maxdgram");
+
+ error = sysctlbyname("net.local.dgram.recvspace", NULL, NULL, &recvspace, sizeof(recvspace));
+ if (error != 0)
+ warn("failed to restore net.local.dgram.recvspace");
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_many_fds__stream);
+ATF_TC_BODY(nvlist_send_recv__send_many_fds__stream, tc)
+{
+ nvlist_send_recv__send_many_fds(SOCK_STREAM);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__dgram);
+ATF_TC_BODY(nvlist_send_recv__send_nvlist__dgram, tc)
+{
+ nvlist_send_recv__send_nvlist(SOCK_DGRAM);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_nvlist__stream);
+ATF_TC_BODY(nvlist_send_recv__send_nvlist__stream, tc)
+{
+ nvlist_send_recv__send_nvlist(SOCK_STREAM);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__dgram);
+ATF_TC_BODY(nvlist_send_recv__send_closed_fd__dgram, tc)
+{
+ nvlist_send_recv__send_closed_fd(SOCK_DGRAM);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__send_closed_fd__stream);
+ATF_TC_BODY(nvlist_send_recv__send_closed_fd__stream, tc)
+{
+ nvlist_send_recv__send_closed_fd(SOCK_STREAM);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_header_size);
+ATF_TC_BODY(nvlist_send_recv__overflow_header_size, tc)
+{
+ nvlist_t *nvl;
+ void *packed;
+ size_t packed_size;
+ struct nvlist_header *header;
+ int fd, socks[2], status;
+ pid_t pid;
+
+#ifdef NO_ASAN
+ atf_tc_skip("This test requires ASAN");
+#endif
+
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ /* Child. */
+ fd = socks[0];
+ close(socks[1]);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
+
+ header = (struct nvlist_header *)packed;
+ header->nvlh_size = SIZE_MAX - sizeof(struct nvlist_header) + 2;
+
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
+ (ssize_t)sizeof(struct nvlist_header));
+
+ nvlist_destroy(nvl);
+ free(packed);
+
+ exit(0);
+ } else {
+ /* Parent */
+ fd = socks[1];
+ close(socks[0]);
+
+ errno = 0;
+ nvl = nvlist_recv(fd, 0);
+ ATF_REQUIRE(nvl == NULL);
+
+ /*
+ * Make sure it has failed on EINVAL, and not on
+ * errors returned by malloc or recv.
+ */
+ ATF_REQUIRE(errno == EINVAL);
+
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
+ ATF_REQUIRE(status == 0);
+ close(fd);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__invalid_fd_size);
+ATF_TC_BODY(nvlist_send_recv__invalid_fd_size, tc)
+{
+ nvlist_t *nvl;
+ void *packed;
+ size_t packed_size;
+ struct nvlist_header *header;
+ int fd, socks[2], status;
+ pid_t pid;
+
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ /* Child. */
+ fd = socks[0];
+ close(socks[1]);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ nvlist_add_string(nvl, "nvl/string", "test");
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
+
+ header = (struct nvlist_header *)packed;
+ header->nvlh_descriptors = 0x20;
+
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
+ (ssize_t)packed_size);
+
+ nvlist_destroy(nvl);
+ free(packed);
+
+ exit(0);
+ } else {
+ /* Parent */
+ fd = socks[1];
+ close(socks[0]);
+
+ nvl = nvlist_recv(fd, 0);
+ ATF_REQUIRE(nvl == NULL);
+
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
+ ATF_REQUIRE(status == 0);
+ }
+
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(nvlist_send_recv__overflow_fd_size);
+ATF_TC_BODY(nvlist_send_recv__overflow_fd_size, tc)
+{
+ nvlist_t *nvl;
+ void *packed;
+ size_t packed_size;
+ struct nvlist_header *header;
+ int fd, socks[2], fds[1], status;
+ pid_t pid;
+
+ ATF_REQUIRE_EQ(socketpair(PF_UNIX, SOCK_STREAM, 0, socks), 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ /* Child. */
+ fd = socks[0];
+ close(socks[1]);
+
+ nvl = nvlist_create(0);
+ ATF_REQUIRE(nvl != NULL);
+ ATF_REQUIRE(nvlist_empty(nvl));
+
+ nvlist_add_string(nvl, "nvl/string", "test");
+ ATF_REQUIRE_EQ(nvlist_error(nvl), 0);
+
+ packed = nvlist_pack(nvl, &packed_size);
+ ATF_REQUIRE(packed != NULL);
+ ATF_REQUIRE(packed_size >= sizeof(struct nvlist_header));
+
+ header = (struct nvlist_header *)packed;
+ header->nvlh_descriptors = 0x4000000000000002;
+
+ ATF_REQUIRE_EQ(write(fd, packed, packed_size),
+ (ssize_t)packed_size);
+
+ fds[0] = dup(STDERR_FILENO);
+ ATF_REQUIRE(fds[0] >= 0);
+ ATF_REQUIRE_EQ(fd_send(fd, fds, 1), 0);
+
+ nvlist_destroy(nvl);
+ free(packed);
+
+ close(fds[0]);
+ close(fd);
+
+ exit(0);
+ } else {
+ /* Parent */
+ fd = socks[1];
+ close(socks[0]);
+
+ nvl = nvlist_recv(fd, 0);
+ ATF_REQUIRE(nvl == NULL);
+
+ /* Make sure that fd was not parsed by nvlist */
+ ATF_REQUIRE(fd_recv(fd, fds, 1) == 0);
+
+ ATF_REQUIRE(waitpid(pid, &status, 0) == pid);
+ ATF_REQUIRE(status == 0);
+
+ close(fds[0]);
+ close(fd);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__dgram);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_nvlist__stream);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__dgram);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_closed_fd__stream);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__dgram);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__send_many_fds__stream);
+
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_header_size);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__invalid_fd_size);
+ ATF_TP_ADD_TC(tp, nvlist_send_recv__overflow_fd_size);
+
+ return (atf_no_error());
+}