Fix readonly check for vdev user properties
[zfs.git] / tests / zfs-tests / cmd / nvlist_to_lua.c
blob57a8f51e1cc03932612dc0a2c542940f58911cd0
1 /*
2 * CDDL HEADER START
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
7 * 1.0 of the CDDL.
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.
13 * CDDL HEADER END
17 * Copyright (c) 2016 by Delphix. All rights reserved.
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <libzfs_core.h>
24 #include <sys/nvpair.h>
26 static nvlist_t *nvl;
27 static const char *pool;
28 static boolean_t unexpected_failures;
30 static boolean_t
31 nvlist_equal(nvlist_t *nvla, nvlist_t *nvlb)
33 if (fnvlist_num_pairs(nvla) != fnvlist_num_pairs(nvlb))
34 return (B_FALSE);
36 * The nvlists have the same number of pairs and keys are unique, so
37 * if every key in A is also in B and assigned to the same value, the
38 * lists are identical.
40 for (nvpair_t *pair = nvlist_next_nvpair(nvla, NULL);
41 pair != NULL; pair = nvlist_next_nvpair(nvla, pair)) {
42 const char *key = nvpair_name(pair);
44 if (!nvlist_exists(nvlb, key))
45 return (B_FALSE);
47 if (nvpair_type(pair) !=
48 nvpair_type(fnvlist_lookup_nvpair(nvlb, key)))
49 return (B_FALSE);
51 switch (nvpair_type(pair)) {
52 case DATA_TYPE_BOOLEAN_VALUE:
53 if (fnvpair_value_boolean_value(pair) !=
54 fnvlist_lookup_boolean_value(nvlb, key)) {
55 return (B_FALSE);
57 break;
58 case DATA_TYPE_STRING:
59 if (strcmp(fnvpair_value_string(pair),
60 fnvlist_lookup_string(nvlb, key))) {
61 return (B_FALSE);
63 break;
64 case DATA_TYPE_INT64:
65 if (fnvpair_value_int64(pair) !=
66 fnvlist_lookup_int64(nvlb, key)) {
67 return (B_FALSE);
69 break;
70 case DATA_TYPE_NVLIST:
71 if (!nvlist_equal(fnvpair_value_nvlist(pair),
72 fnvlist_lookup_nvlist(nvlb, key))) {
73 return (B_FALSE);
75 break;
76 default:
77 (void) printf("Unexpected type for nvlist_equal\n");
78 return (B_FALSE);
81 return (B_TRUE);
84 static void
85 test(const char *testname, boolean_t expect_success, boolean_t expect_match)
87 const char *progstr = "input = ...; return {output=input}";
89 nvlist_t *outnvl;
91 (void) printf("\nrunning test '%s'; input:\n", testname);
92 dump_nvlist(nvl, 4);
94 int err = lzc_channel_program(pool, progstr,
95 10 * 1000 * 1000, 10 * 1024 * 1024, nvl, &outnvl);
97 (void) printf("lzc_channel_program returned %u\n", err);
98 dump_nvlist(outnvl, 5);
100 if (err == 0 && expect_match) {
102 * Verify that outnvl is the same as input nvl, if we expect
103 * them to be. The input and output will never match if the
104 * input contains an array (since arrays are converted to lua
105 * tables), so this is only asserted for some test cases.
107 nvlist_t *real_outnvl = fnvlist_lookup_nvlist(outnvl, "return");
108 real_outnvl = fnvlist_lookup_nvlist(real_outnvl, "output");
109 if (!nvlist_equal(nvl, real_outnvl)) {
110 unexpected_failures = B_TRUE;
111 (void) printf("unexpected input/output mismatch for "
112 "case: %s\n", testname);
115 if (err != 0 && expect_success) {
116 unexpected_failures = B_TRUE;
117 (void) printf("unexpected FAIL of case: %s\n", testname);
120 fnvlist_free(nvl);
121 nvl = fnvlist_alloc();
124 static void
125 run_tests(void)
127 const char *key = "key";
129 /* Note: maximum nvlist key length is 32KB */
130 int len = 1024 * 31;
131 char *bigstring = malloc(len);
132 if (bigstring == NULL) {
133 perror("malloc");
134 exit(EXIT_FAILURE);
137 for (int i = 0; i < len; i++)
138 bigstring[i] = 'a' + i % 26;
139 bigstring[len - 1] = '\0';
141 nvl = fnvlist_alloc();
143 fnvlist_add_boolean(nvl, key);
144 test("boolean", B_TRUE, B_FALSE);
146 fnvlist_add_boolean_value(nvl, key, B_TRUE);
147 test("boolean_value", B_FALSE, B_FALSE);
149 fnvlist_add_byte(nvl, key, 1);
150 test("byte", B_FALSE, B_FALSE);
152 fnvlist_add_int8(nvl, key, 1);
153 test("int8", B_FALSE, B_FALSE);
155 fnvlist_add_uint8(nvl, key, 1);
156 test("uint8", B_FALSE, B_FALSE);
158 fnvlist_add_int16(nvl, key, 1);
159 test("int16", B_FALSE, B_FALSE);
161 fnvlist_add_uint16(nvl, key, 1);
162 test("uint16", B_FALSE, B_FALSE);
164 fnvlist_add_int32(nvl, key, 1);
165 test("int32", B_FALSE, B_FALSE);
167 fnvlist_add_uint32(nvl, key, 1);
168 test("uint32", B_FALSE, B_FALSE);
170 fnvlist_add_int64(nvl, key, 1);
171 test("int64", B_TRUE, B_TRUE);
173 fnvlist_add_uint64(nvl, key, 1);
174 test("uint64", B_FALSE, B_FALSE);
176 fnvlist_add_string(nvl, key, "1");
177 test("string", B_TRUE, B_TRUE);
181 nvlist_t *val = fnvlist_alloc();
182 fnvlist_add_string(val, "subkey", "subvalue");
183 fnvlist_add_nvlist(nvl, key, val);
184 fnvlist_free(val);
185 test("nvlist", B_TRUE, B_TRUE);
188 boolean_t val[2] = { B_FALSE, B_TRUE };
189 fnvlist_add_boolean_array(nvl, key, val, 2);
190 test("boolean_array", B_FALSE, B_FALSE);
193 uchar_t val[2] = { 0, 1 };
194 fnvlist_add_byte_array(nvl, key, val, 2);
195 test("byte_array", B_FALSE, B_FALSE);
198 int8_t val[2] = { 0, 1 };
199 fnvlist_add_int8_array(nvl, key, val, 2);
200 test("int8_array", B_FALSE, B_FALSE);
203 uint8_t val[2] = { 0, 1 };
204 fnvlist_add_uint8_array(nvl, key, val, 2);
205 test("uint8_array", B_FALSE, B_FALSE);
208 int16_t val[2] = { 0, 1 };
209 fnvlist_add_int16_array(nvl, key, val, 2);
210 test("int16_array", B_FALSE, B_FALSE);
213 uint16_t val[2] = { 0, 1 };
214 fnvlist_add_uint16_array(nvl, key, val, 2);
215 test("uint16_array", B_FALSE, B_FALSE);
218 int32_t val[2] = { 0, 1 };
219 fnvlist_add_int32_array(nvl, key, val, 2);
220 test("int32_array", B_FALSE, B_FALSE);
223 uint32_t val[2] = { 0, 1 };
224 fnvlist_add_uint32_array(nvl, key, val, 2);
225 test("uint32_array", B_FALSE, B_FALSE);
228 int64_t val[2] = { 0, 1 };
229 fnvlist_add_int64_array(nvl, key, val, 2);
230 test("int64_array", B_TRUE, B_FALSE);
233 uint64_t val[2] = { 0, 1 };
234 fnvlist_add_uint64_array(nvl, key, val, 2);
235 test("uint64_array", B_FALSE, B_FALSE);
238 const char *val[2] = { "0", "1" };
239 fnvlist_add_string_array(nvl, key, val, 2);
240 test("string_array", B_TRUE, B_FALSE);
243 nvlist_t *val[2];
244 val[0] = fnvlist_alloc();
245 fnvlist_add_string(val[0], "subkey", "subvalue");
246 val[1] = fnvlist_alloc();
247 fnvlist_add_string(val[1], "subkey2", "subvalue2");
248 fnvlist_add_nvlist_array(nvl, key, (const nvlist_t **)val, 2);
249 fnvlist_free(val[0]);
250 fnvlist_free(val[1]);
251 test("nvlist_array", B_FALSE, B_FALSE);
254 fnvlist_add_string(nvl, bigstring, "1");
255 test("large_key", B_TRUE, B_TRUE);
258 fnvlist_add_string(nvl, key, bigstring);
259 test("large_value", B_TRUE, B_TRUE);
262 for (int i = 0; i < 1024; i++) {
263 char buf[32];
264 (void) snprintf(buf, sizeof (buf), "key-%u", i);
265 fnvlist_add_int64(nvl, buf, i);
267 test("many_keys", B_TRUE, B_TRUE);
269 #ifndef __sparc__
271 for (int i = 0; i < 10; i++) {
272 nvlist_t *newval = fnvlist_alloc();
273 fnvlist_add_nvlist(newval, "key", nvl);
274 fnvlist_free(nvl);
275 nvl = newval;
277 test("deeply_nested_pos", B_TRUE, B_TRUE);
280 for (int i = 0; i < 90; i++) {
281 nvlist_t *newval = fnvlist_alloc();
282 fnvlist_add_nvlist(newval, "key", nvl);
283 fnvlist_free(nvl);
284 nvl = newval;
286 test("deeply_nested_neg", B_FALSE, B_FALSE);
288 #endif
289 free(bigstring);
290 fnvlist_free(nvl);
294 main(int argc, const char *argv[])
296 (void) libzfs_core_init();
298 if (argc != 2) {
299 (void) printf("usage: %s <pool>\n",
300 argv[0]);
301 exit(2);
303 pool = argv[1];
305 run_tests();
307 libzfs_core_fini();
308 return (unexpected_failures);