4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
17 * Copyright (c) 2016 by Delphix. All rights reserved.
24 #include <libzfs_core.h>
25 #include <sys/nvpair.h>
29 boolean_t unexpected_failures;
32 nvlist_equal(nvlist_t *nvla, nvlist_t *nvlb)
34 if (fnvlist_num_pairs(nvla) != fnvlist_num_pairs(nvlb))
37 * The nvlists have the same number of pairs and keys are unique, so
38 * if every key in A is also in B and assigned to the same value, the
39 * lists are identical.
41 for (nvpair_t *pair = nvlist_next_nvpair(nvla, NULL);
42 pair != NULL; pair = nvlist_next_nvpair(nvla, pair)) {
43 char *key = nvpair_name(pair);
45 if (!nvlist_exists(nvlb, key))
48 if (nvpair_type(pair) !=
49 nvpair_type(fnvlist_lookup_nvpair(nvlb, key)))
52 switch (nvpair_type(pair)) {
53 case DATA_TYPE_BOOLEAN_VALUE:
54 if (fnvpair_value_boolean_value(pair) !=
55 fnvlist_lookup_boolean_value(nvlb, key)) {
59 case DATA_TYPE_STRING:
60 if (strcmp(fnvpair_value_string(pair),
61 fnvlist_lookup_string(nvlb, key))) {
66 if (fnvpair_value_int64(pair) !=
67 fnvlist_lookup_int64(nvlb, key)) {
71 case DATA_TYPE_NVLIST:
72 if (!nvlist_equal(fnvpair_value_nvlist(pair),
73 fnvlist_lookup_nvlist(nvlb, key))) {
78 (void) printf("Unexpected type for nvlist_equal\n");
86 test(const char *testname, boolean_t expect_success, boolean_t expect_match)
88 char *progstr = "input = ...; return {output=input}";
92 (void) printf("\nrunning test '%s'; input:\n", testname);
95 int err = lzc_channel_program(pool, progstr,
96 10 * 1000 * 1000, 10 * 1024 * 1024, nvl, &outnvl);
98 (void) printf("lzc_channel_program returned %u\n", err);
99 dump_nvlist(outnvl, 5);
101 if (err == 0 && expect_match) {
103 * Verify that outnvl is the same as input nvl, if we expect
104 * them to be. The input and output will never match if the
105 * input contains an array (since arrays are converted to lua
106 * tables), so this is only asserted for some test cases.
108 nvlist_t *real_outnvl = fnvlist_lookup_nvlist(outnvl, "return");
109 real_outnvl = fnvlist_lookup_nvlist(real_outnvl, "output");
110 if (!nvlist_equal(nvl, real_outnvl)) {
111 unexpected_failures = B_TRUE;
112 (void) printf("unexpected input/output mismatch for "
113 "case: %s\n", testname);
116 if (err != 0 && expect_success) {
117 unexpected_failures = B_TRUE;
118 (void) printf("unexpected FAIL of case: %s\n", testname);
122 nvl = fnvlist_alloc();
128 const char *key = "key";
130 /* Note: maximum nvlist key length is 32KB */
132 char *bigstring = malloc(len);
133 for (int i = 0; i < len; i++)
134 bigstring[i] = 'a' + i % 26;
135 bigstring[len - 1] = '\0';
137 nvl = fnvlist_alloc();
139 fnvlist_add_boolean(nvl, key);
140 test("boolean", B_TRUE, B_FALSE);
142 fnvlist_add_boolean_value(nvl, key, B_TRUE);
143 test("boolean_value", B_FALSE, B_FALSE);
145 fnvlist_add_byte(nvl, key, 1);
146 test("byte", B_FALSE, B_FALSE);
148 fnvlist_add_int8(nvl, key, 1);
149 test("int8", B_FALSE, B_FALSE);
151 fnvlist_add_uint8(nvl, key, 1);
152 test("uint8", B_FALSE, B_FALSE);
154 fnvlist_add_int16(nvl, key, 1);
155 test("int16", B_FALSE, B_FALSE);
157 fnvlist_add_uint16(nvl, key, 1);
158 test("uint16", B_FALSE, B_FALSE);
160 fnvlist_add_int32(nvl, key, 1);
161 test("int32", B_FALSE, B_FALSE);
163 fnvlist_add_uint32(nvl, key, 1);
164 test("uint32", B_FALSE, B_FALSE);
166 fnvlist_add_int64(nvl, key, 1);
167 test("int64", B_TRUE, B_TRUE);
169 fnvlist_add_uint64(nvl, key, 1);
170 test("uint64", B_FALSE, B_FALSE);
172 fnvlist_add_string(nvl, key, "1");
173 test("string", B_TRUE, B_TRUE);
177 nvlist_t *val = fnvlist_alloc();
178 fnvlist_add_string(val, "subkey", "subvalue");
179 fnvlist_add_nvlist(nvl, key, val);
181 test("nvlist", B_TRUE, B_TRUE);
184 boolean_t val[2] = { B_FALSE, B_TRUE };
185 fnvlist_add_boolean_array(nvl, key, val, 2);
186 test("boolean_array", B_FALSE, B_FALSE);
189 uchar_t val[2] = { 0, 1 };
190 fnvlist_add_byte_array(nvl, key, val, 2);
191 test("byte_array", B_FALSE, B_FALSE);
194 int8_t val[2] = { 0, 1 };
195 fnvlist_add_int8_array(nvl, key, val, 2);
196 test("int8_array", B_FALSE, B_FALSE);
199 uint8_t val[2] = { 0, 1 };
200 fnvlist_add_uint8_array(nvl, key, val, 2);
201 test("uint8_array", B_FALSE, B_FALSE);
204 int16_t val[2] = { 0, 1 };
205 fnvlist_add_int16_array(nvl, key, val, 2);
206 test("int16_array", B_FALSE, B_FALSE);
209 uint16_t val[2] = { 0, 1 };
210 fnvlist_add_uint16_array(nvl, key, val, 2);
211 test("uint16_array", B_FALSE, B_FALSE);
214 int32_t val[2] = { 0, 1 };
215 fnvlist_add_int32_array(nvl, key, val, 2);
216 test("int32_array", B_FALSE, B_FALSE);
219 uint32_t val[2] = { 0, 1 };
220 fnvlist_add_uint32_array(nvl, key, val, 2);
221 test("uint32_array", B_FALSE, B_FALSE);
224 int64_t val[2] = { 0, 1 };
225 fnvlist_add_int64_array(nvl, key, val, 2);
226 test("int64_array", B_TRUE, B_FALSE);
229 uint64_t val[2] = { 0, 1 };
230 fnvlist_add_uint64_array(nvl, key, val, 2);
231 test("uint64_array", B_FALSE, B_FALSE);
234 char *const val[2] = { "0", "1" };
235 fnvlist_add_string_array(nvl, key, val, 2);
236 test("string_array", B_TRUE, B_FALSE);
240 val[0] = fnvlist_alloc();
241 fnvlist_add_string(val[0], "subkey", "subvalue");
242 val[1] = fnvlist_alloc();
243 fnvlist_add_string(val[1], "subkey2", "subvalue2");
244 fnvlist_add_nvlist_array(nvl, key, val, 2);
245 fnvlist_free(val[0]);
246 fnvlist_free(val[1]);
247 test("nvlist_array", B_FALSE, B_FALSE);
250 fnvlist_add_string(nvl, bigstring, "1");
251 test("large_key", B_TRUE, B_TRUE);
254 fnvlist_add_string(nvl, key, bigstring);
255 test("large_value", B_TRUE, B_TRUE);
258 for (int i = 0; i < 1024; i++) {
260 (void) snprintf(buf, sizeof (buf), "key-%u", i);
261 fnvlist_add_int64(nvl, buf, i);
263 test("many_keys", B_TRUE, B_TRUE);
267 for (int i = 0; i < 10; i++) {
268 nvlist_t *newval = fnvlist_alloc();
269 fnvlist_add_nvlist(newval, "key", nvl);
273 test("deeply_nested_pos", B_TRUE, B_TRUE);
276 for (int i = 0; i < 90; i++) {
277 nvlist_t *newval = fnvlist_alloc();
278 fnvlist_add_nvlist(newval, "key", nvl);
282 test("deeply_nested_neg", B_FALSE, B_FALSE);
290 main(int argc, const char *argv[])
292 (void) libzfs_core_init();
295 (void) printf("usage: %s <pool>\n",
304 return (unexpected_failures);