]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/zfs-tests/cmd/nvlist_to_lua/nvlist_to_lua.c
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / tests / zfs-tests / cmd / nvlist_to_lua / nvlist_to_lua.c
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
12  *
13  * CDDL HEADER END
14  */
15
16 /*
17  * Copyright (c) 2016 by Delphix. All rights reserved.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <libzfs_core.h>
25 #include <sys/nvpair.h>
26
27 nvlist_t *nvl;
28 const char *pool;
29 boolean_t unexpected_failures;
30
31 static boolean_t
32 nvlist_equal(nvlist_t *nvla, nvlist_t *nvlb)
33 {
34         if (fnvlist_num_pairs(nvla) != fnvlist_num_pairs(nvlb))
35                 return (B_FALSE);
36         /*
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.
40          */
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);
44
45                 if (!nvlist_exists(nvlb, key))
46                         return (B_FALSE);
47
48                 if (nvpair_type(pair) !=
49                     nvpair_type(fnvlist_lookup_nvpair(nvlb, key)))
50                         return (B_FALSE);
51
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)) {
56                                 return (B_FALSE);
57                         }
58                         break;
59                 case DATA_TYPE_STRING:
60                         if (strcmp(fnvpair_value_string(pair),
61                             fnvlist_lookup_string(nvlb, key))) {
62                                 return (B_FALSE);
63                         }
64                         break;
65                 case DATA_TYPE_INT64:
66                         if (fnvpair_value_int64(pair) !=
67                             fnvlist_lookup_int64(nvlb, key)) {
68                                 return (B_FALSE);
69                         }
70                         break;
71                 case DATA_TYPE_NVLIST:
72                         if (!nvlist_equal(fnvpair_value_nvlist(pair),
73                             fnvlist_lookup_nvlist(nvlb, key))) {
74                                 return (B_FALSE);
75                         }
76                         break;
77                 default:
78                         (void) printf("Unexpected type for nvlist_equal\n");
79                         return (B_FALSE);
80                 }
81         }
82         return (B_TRUE);
83 }
84
85 static void
86 test(const char *testname, boolean_t expect_success, boolean_t expect_match)
87 {
88         char *progstr = "input = ...; return {output=input}";
89
90         nvlist_t *outnvl;
91
92         (void) printf("\nrunning test '%s'; input:\n", testname);
93         dump_nvlist(nvl, 4);
94
95         int err = lzc_channel_program(pool, progstr,
96             10 * 1000 * 1000, 10 * 1024 * 1024, nvl, &outnvl);
97
98         (void) printf("lzc_channel_program returned %u\n", err);
99         dump_nvlist(outnvl, 5);
100
101         if (err == 0 && expect_match) {
102                 /*
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.
107                  */
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);
114                 }
115         }
116         if (err != 0 && expect_success) {
117                 unexpected_failures = B_TRUE;
118                 (void) printf("unexpected FAIL of case: %s\n", testname);
119         }
120
121         fnvlist_free(nvl);
122         nvl = fnvlist_alloc();
123 }
124
125 static void
126 run_tests(void)
127 {
128         const char *key = "key";
129
130         /* Note: maximum nvlist key length is 32KB */
131         int len = 1024 * 31;
132         char *bigstring = malloc(len);
133         for (int i = 0; i < len; i++)
134                 bigstring[i] = 'a' + i % 26;
135         bigstring[len - 1] = '\0';
136
137         nvl = fnvlist_alloc();
138
139         fnvlist_add_boolean(nvl, key);
140         test("boolean", B_TRUE, B_FALSE);
141
142         fnvlist_add_boolean_value(nvl, key, B_TRUE);
143         test("boolean_value", B_FALSE, B_FALSE);
144
145         fnvlist_add_byte(nvl, key, 1);
146         test("byte", B_FALSE, B_FALSE);
147
148         fnvlist_add_int8(nvl, key, 1);
149         test("int8", B_FALSE, B_FALSE);
150
151         fnvlist_add_uint8(nvl, key, 1);
152         test("uint8", B_FALSE, B_FALSE);
153
154         fnvlist_add_int16(nvl, key, 1);
155         test("int16", B_FALSE, B_FALSE);
156
157         fnvlist_add_uint16(nvl, key, 1);
158         test("uint16", B_FALSE, B_FALSE);
159
160         fnvlist_add_int32(nvl, key, 1);
161         test("int32", B_FALSE, B_FALSE);
162
163         fnvlist_add_uint32(nvl, key, 1);
164         test("uint32", B_FALSE, B_FALSE);
165
166         fnvlist_add_int64(nvl, key, 1);
167         test("int64", B_TRUE, B_TRUE);
168
169         fnvlist_add_uint64(nvl, key, 1);
170         test("uint64", B_FALSE, B_FALSE);
171
172         fnvlist_add_string(nvl, key, "1");
173         test("string", B_TRUE, B_TRUE);
174
175
176         {
177                 nvlist_t *val = fnvlist_alloc();
178                 fnvlist_add_string(val, "subkey", "subvalue");
179                 fnvlist_add_nvlist(nvl, key, val);
180                 fnvlist_free(val);
181                 test("nvlist", B_TRUE, B_TRUE);
182         }
183         {
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);
187         }
188         {
189                 uchar_t val[2] = { 0, 1 };
190                 fnvlist_add_byte_array(nvl, key, val, 2);
191                 test("byte_array", B_FALSE, B_FALSE);
192         }
193         {
194                 int8_t val[2] = { 0, 1 };
195                 fnvlist_add_int8_array(nvl, key, val, 2);
196                 test("int8_array", B_FALSE, B_FALSE);
197         }
198         {
199                 uint8_t val[2] = { 0, 1 };
200                 fnvlist_add_uint8_array(nvl, key, val, 2);
201                 test("uint8_array", B_FALSE, B_FALSE);
202         }
203         {
204                 int16_t val[2] = { 0, 1 };
205                 fnvlist_add_int16_array(nvl, key, val, 2);
206                 test("int16_array", B_FALSE, B_FALSE);
207         }
208         {
209                 uint16_t val[2] = { 0, 1 };
210                 fnvlist_add_uint16_array(nvl, key, val, 2);
211                 test("uint16_array", B_FALSE, B_FALSE);
212         }
213         {
214                 int32_t val[2] = { 0, 1 };
215                 fnvlist_add_int32_array(nvl, key, val, 2);
216                 test("int32_array", B_FALSE, B_FALSE);
217         }
218         {
219                 uint32_t val[2] = { 0, 1 };
220                 fnvlist_add_uint32_array(nvl, key, val, 2);
221                 test("uint32_array", B_FALSE, B_FALSE);
222         }
223         {
224                 int64_t val[2] = { 0, 1 };
225                 fnvlist_add_int64_array(nvl, key, val, 2);
226                 test("int64_array", B_TRUE, B_FALSE);
227         }
228         {
229                 uint64_t val[2] = { 0, 1 };
230                 fnvlist_add_uint64_array(nvl, key, val, 2);
231                 test("uint64_array", B_FALSE, B_FALSE);
232         }
233         {
234                 char *const val[2] = { "0", "1" };
235                 fnvlist_add_string_array(nvl, key, val, 2);
236                 test("string_array", B_TRUE, B_FALSE);
237         }
238         {
239                 nvlist_t *val[2];
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);
248         }
249         {
250                 fnvlist_add_string(nvl, bigstring, "1");
251                 test("large_key", B_TRUE, B_TRUE);
252         }
253         {
254                 fnvlist_add_string(nvl, key, bigstring);
255                 test("large_value", B_TRUE, B_TRUE);
256         }
257         {
258                 for (int i = 0; i < 1024; i++) {
259                         char buf[32];
260                         (void) snprintf(buf, sizeof (buf), "key-%u", i);
261                         fnvlist_add_int64(nvl, buf, i);
262                 }
263                 test("many_keys", B_TRUE, B_TRUE);
264         }
265 #ifndef __sparc__
266         {
267                 for (int i = 0; i < 10; i++) {
268                         nvlist_t *newval = fnvlist_alloc();
269                         fnvlist_add_nvlist(newval, "key", nvl);
270                         fnvlist_free(nvl);
271                         nvl = newval;
272                 }
273                 test("deeply_nested_pos", B_TRUE, B_TRUE);
274         }
275         {
276                 for (int i = 0; i < 90; i++) {
277                         nvlist_t *newval = fnvlist_alloc();
278                         fnvlist_add_nvlist(newval, "key", nvl);
279                         fnvlist_free(nvl);
280                         nvl = newval;
281                 }
282                 test("deeply_nested_neg", B_FALSE, B_FALSE);
283         }
284 #endif
285         free(bigstring);
286         fnvlist_free(nvl);
287 }
288
289 int
290 main(int argc, const char *argv[])
291 {
292         (void) libzfs_core_init();
293
294         if (argc != 2) {
295                 (void) printf("usage: %s <pool>\n",
296                     argv[0]);
297                 exit(2);
298         }
299         pool = argv[1];
300
301         run_tests();
302
303         libzfs_core_fini();
304         return (unexpected_failures);
305 }