]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/test/unit/lib/json/json_parse.c/json_parse_ut.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / test / unit / lib / json / json_parse.c / json_parse_ut.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35
36 #include "spdk_cunit.h"
37
38 #include "json/json_parse.c"
39
40 static uint8_t g_buf[1000];
41 static void *g_end;
42 static struct spdk_json_val g_vals[100];
43 static int g_cur_val;
44
45 /* Fill buf with raw data */
46 #define BUF_SETUP(in) \
47 memset(g_buf, 0, sizeof(g_buf)); \
48 if (sizeof(in) > 1) { \
49 memcpy(g_buf, in, sizeof(in) - 1); \
50 } \
51 g_end = NULL
52
53 /*
54 * Do two checks - first pass NULL for values to ensure the count is correct,
55 * then pass g_vals to get the actual values.
56 */
57 #define PARSE_PASS_FLAGS(in, num_vals, trailing, flags) \
58 BUF_SETUP(in); \
59 CU_ASSERT(spdk_json_parse(g_buf, sizeof(in) - 1, NULL, 0, &g_end, flags) == num_vals); \
60 memset(g_vals, 0, sizeof(g_vals)); \
61 CU_ASSERT(spdk_json_parse(g_buf, sizeof(in) - 1, g_vals, sizeof(g_vals), &g_end, flags | SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE) == num_vals); \
62 CU_ASSERT(g_end == g_buf + sizeof(in) - sizeof(trailing)); \
63 CU_ASSERT(memcmp(g_end, trailing, sizeof(trailing) - 1) == 0); \
64 g_cur_val = 0
65
66 #define PARSE_PASS(in, num_vals, trailing) \
67 PARSE_PASS_FLAGS(in, num_vals, trailing, 0)
68
69 #define PARSE_FAIL_FLAGS(in, retval, flags) \
70 BUF_SETUP(in); \
71 CU_ASSERT(spdk_json_parse(g_buf, sizeof(in) - 1, NULL, 0, &g_end, flags) == retval)
72
73 #define PARSE_FAIL(in, retval) \
74 PARSE_FAIL_FLAGS(in, retval, 0)
75
76 #define VAL_STRING_MATCH(str, var_type) \
77 CU_ASSERT(g_vals[g_cur_val].type == var_type); \
78 CU_ASSERT(g_vals[g_cur_val].len == sizeof(str) - 1); \
79 if (g_vals[g_cur_val].len == sizeof(str) - 1 && sizeof(str) > 1) { \
80 CU_ASSERT(memcmp(g_vals[g_cur_val].start, str, g_vals[g_cur_val].len) == 0); \
81 } \
82 g_cur_val++
83
84 #define VAL_STRING(str) VAL_STRING_MATCH(str, SPDK_JSON_VAL_STRING)
85 #define VAL_NAME(str) VAL_STRING_MATCH(str, SPDK_JSON_VAL_NAME)
86 #define VAL_NUMBER(num) VAL_STRING_MATCH(num, SPDK_JSON_VAL_NUMBER)
87
88 #define VAL_LITERAL(str, val_type) \
89 CU_ASSERT(g_vals[g_cur_val].type == val_type); \
90 CU_ASSERT(g_vals[g_cur_val].len == strlen(str)); \
91 if (g_vals[g_cur_val].len == strlen(str)) { \
92 CU_ASSERT(memcmp(g_vals[g_cur_val].start, str, g_vals[g_cur_val].len) == 0); \
93 } \
94 g_cur_val++
95
96 #define VAL_TRUE() VAL_LITERAL("true", SPDK_JSON_VAL_TRUE)
97 #define VAL_FALSE() VAL_LITERAL("false", SPDK_JSON_VAL_FALSE)
98 #define VAL_NULL() VAL_LITERAL("null", SPDK_JSON_VAL_NULL)
99
100 #define VAL_ARRAY_BEGIN(count) \
101 CU_ASSERT(g_vals[g_cur_val].type == SPDK_JSON_VAL_ARRAY_BEGIN); \
102 CU_ASSERT(g_vals[g_cur_val].len == count); \
103 g_cur_val++
104
105 #define VAL_ARRAY_END() \
106 CU_ASSERT(g_vals[g_cur_val].type == SPDK_JSON_VAL_ARRAY_END); \
107 g_cur_val++
108
109 #define VAL_OBJECT_BEGIN(count) \
110 CU_ASSERT(g_vals[g_cur_val].type == SPDK_JSON_VAL_OBJECT_BEGIN); \
111 CU_ASSERT(g_vals[g_cur_val].len == count); \
112 g_cur_val++
113
114 #define VAL_OBJECT_END() \
115 CU_ASSERT(g_vals[g_cur_val].type == SPDK_JSON_VAL_OBJECT_END); \
116 g_cur_val++
117
118 /* Simplified macros for string-only testing */
119 #define STR_PASS(in, out) \
120 PARSE_PASS("\"" in "\"", 1, ""); \
121 VAL_STRING(out)
122
123 #define STR_FAIL(in, retval) \
124 PARSE_FAIL("\"" in "\"", retval)
125
126 /* Simplified macros for number-only testing (no whitespace allowed) */
127 #define NUM_PASS(in) \
128 PARSE_PASS(in, 1, ""); \
129 VAL_NUMBER(in)
130
131 #define NUM_FAIL(in, retval) \
132 PARSE_FAIL(in, retval)
133
134 static void
135 test_parse_literal(void)
136 {
137 PARSE_PASS("true", 1, "");
138 VAL_TRUE();
139
140 PARSE_PASS(" true ", 1, "");
141 VAL_TRUE();
142
143 PARSE_PASS("false", 1, "");
144 VAL_FALSE();
145
146 PARSE_PASS("null", 1, "");
147 VAL_NULL();
148
149 PARSE_PASS("trueaaa", 1, "aaa");
150 VAL_TRUE();
151
152 PARSE_PASS("truefalse", 1, "false");
153 VAL_TRUE();
154
155 PARSE_PASS("true false", 1, "false");
156 VAL_TRUE();
157
158 PARSE_PASS("true,false", 1, ",false");
159 VAL_TRUE();
160
161 PARSE_PASS("true,", 1, ",");
162 VAL_TRUE();
163
164 PARSE_FAIL("True", SPDK_JSON_PARSE_INVALID);
165 PARSE_FAIL("abcdef", SPDK_JSON_PARSE_INVALID);
166
167 PARSE_FAIL("t", SPDK_JSON_PARSE_INCOMPLETE);
168 PARSE_FAIL("tru", SPDK_JSON_PARSE_INCOMPLETE);
169 PARSE_FAIL("f", SPDK_JSON_PARSE_INCOMPLETE);
170 PARSE_FAIL("fals", SPDK_JSON_PARSE_INCOMPLETE);
171 PARSE_FAIL("n", SPDK_JSON_PARSE_INCOMPLETE);
172 PARSE_FAIL("nul", SPDK_JSON_PARSE_INCOMPLETE);
173
174 PARSE_FAIL("taaaaa", SPDK_JSON_PARSE_INVALID);
175 PARSE_FAIL("faaaaa", SPDK_JSON_PARSE_INVALID);
176 PARSE_FAIL("naaaaa", SPDK_JSON_PARSE_INVALID);
177 }
178
179 static void
180 test_parse_string_simple(void)
181 {
182 PARSE_PASS("\"\"", 1, "");
183 VAL_STRING("");
184
185 PARSE_PASS("\"hello world\"", 1, "");
186 VAL_STRING("hello world");
187
188 PARSE_PASS(" \"hello world\" ", 1, "");
189 VAL_STRING("hello world");
190
191 /* Unterminated string */
192 PARSE_FAIL("\"hello world", SPDK_JSON_PARSE_INCOMPLETE);
193
194 /* Trailing comma */
195 PARSE_PASS("\"hello world\",", 1, ",");
196 VAL_STRING("hello world");
197 }
198
199 static void
200 test_parse_string_control_chars(void)
201 {
202 /* U+0000 through U+001F must be escaped */
203 STR_FAIL("\x00", SPDK_JSON_PARSE_INVALID);
204 STR_FAIL("\x01", SPDK_JSON_PARSE_INVALID);
205 STR_FAIL("\x02", SPDK_JSON_PARSE_INVALID);
206 STR_FAIL("\x03", SPDK_JSON_PARSE_INVALID);
207 STR_FAIL("\x04", SPDK_JSON_PARSE_INVALID);
208 STR_FAIL("\x05", SPDK_JSON_PARSE_INVALID);
209 STR_FAIL("\x06", SPDK_JSON_PARSE_INVALID);
210 STR_FAIL("\x07", SPDK_JSON_PARSE_INVALID);
211 STR_FAIL("\x08", SPDK_JSON_PARSE_INVALID);
212 STR_FAIL("\x09", SPDK_JSON_PARSE_INVALID);
213 STR_FAIL("\x0A", SPDK_JSON_PARSE_INVALID);
214 STR_FAIL("\x0B", SPDK_JSON_PARSE_INVALID);
215 STR_FAIL("\x0C", SPDK_JSON_PARSE_INVALID);
216 STR_FAIL("\x0D", SPDK_JSON_PARSE_INVALID);
217 STR_FAIL("\x0E", SPDK_JSON_PARSE_INVALID);
218 STR_FAIL("\x0F", SPDK_JSON_PARSE_INVALID);
219 STR_FAIL("\x10", SPDK_JSON_PARSE_INVALID);
220 STR_FAIL("\x11", SPDK_JSON_PARSE_INVALID);
221 STR_FAIL("\x12", SPDK_JSON_PARSE_INVALID);
222 STR_FAIL("\x13", SPDK_JSON_PARSE_INVALID);
223 STR_FAIL("\x14", SPDK_JSON_PARSE_INVALID);
224 STR_FAIL("\x15", SPDK_JSON_PARSE_INVALID);
225 STR_FAIL("\x16", SPDK_JSON_PARSE_INVALID);
226 STR_FAIL("\x17", SPDK_JSON_PARSE_INVALID);
227 STR_FAIL("\x18", SPDK_JSON_PARSE_INVALID);
228 STR_FAIL("\x19", SPDK_JSON_PARSE_INVALID);
229 STR_FAIL("\x1A", SPDK_JSON_PARSE_INVALID);
230 STR_FAIL("\x1B", SPDK_JSON_PARSE_INVALID);
231 STR_FAIL("\x1C", SPDK_JSON_PARSE_INVALID);
232 STR_FAIL("\x1D", SPDK_JSON_PARSE_INVALID);
233 STR_FAIL("\x1E", SPDK_JSON_PARSE_INVALID);
234 STR_FAIL("\x1F", SPDK_JSON_PARSE_INVALID);
235 STR_PASS(" ", " "); /* \x20 (first valid unescaped char) */
236
237 /* Test control chars in the middle of a string */
238 STR_FAIL("abc\ndef", SPDK_JSON_PARSE_INVALID);
239 STR_FAIL("abc\tdef", SPDK_JSON_PARSE_INVALID);
240 }
241
242 static void
243 test_parse_string_utf8(void)
244 {
245 /* Valid one-, two-, three-, and four-byte sequences */
246 STR_PASS("\x41", "A");
247 STR_PASS("\xC3\xB6", "\xC3\xB6");
248 STR_PASS("\xE2\x88\x9A", "\xE2\x88\x9A");
249 STR_PASS("\xF0\xA0\x9C\x8E", "\xF0\xA0\x9C\x8E");
250
251 /* Examples from RFC 3629 */
252 STR_PASS("\x41\xE2\x89\xA2\xCE\x91\x2E", "\x41\xE2\x89\xA2\xCE\x91\x2E");
253 STR_PASS("\xED\x95\x9C\xEA\xB5\xAD\xEC\x96\xB4", "\xED\x95\x9C\xEA\xB5\xAD\xEC\x96\xB4");
254 STR_PASS("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E", "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E");
255 STR_PASS("\xEF\xBB\xBF\xF0\xA3\x8E\xB4", "\xEF\xBB\xBF\xF0\xA3\x8E\xB4");
256
257 /* Edge cases */
258 STR_PASS("\x7F", "\x7F");
259 STR_FAIL("\x80", SPDK_JSON_PARSE_INVALID);
260 STR_FAIL("\xC1", SPDK_JSON_PARSE_INVALID);
261 STR_FAIL("\xC2", SPDK_JSON_PARSE_INVALID);
262 STR_PASS("\xC2\x80", "\xC2\x80");
263 STR_PASS("\xC2\xBF", "\xC2\xBF");
264 STR_PASS("\xDF\x80", "\xDF\x80");
265 STR_PASS("\xDF\xBF", "\xDF\xBF");
266 STR_FAIL("\xDF", SPDK_JSON_PARSE_INVALID);
267 STR_FAIL("\xE0\x80", SPDK_JSON_PARSE_INVALID);
268 STR_FAIL("\xE0\x1F", SPDK_JSON_PARSE_INVALID);
269 STR_FAIL("\xE0\x1F\x80", SPDK_JSON_PARSE_INVALID);
270 STR_FAIL("\xE0", SPDK_JSON_PARSE_INVALID);
271 STR_FAIL("\xE0\xA0", SPDK_JSON_PARSE_INVALID);
272 STR_PASS("\xE0\xA0\x80", "\xE0\xA0\x80");
273 STR_PASS("\xE0\xA0\xBF", "\xE0\xA0\xBF");
274 STR_FAIL("\xE0\xA0\xC0", SPDK_JSON_PARSE_INVALID);
275 STR_PASS("\xE0\xBF\x80", "\xE0\xBF\x80");
276 STR_PASS("\xE0\xBF\xBF", "\xE0\xBF\xBF");
277 STR_FAIL("\xE0\xC0\x80", SPDK_JSON_PARSE_INVALID);
278 STR_FAIL("\xE1", SPDK_JSON_PARSE_INVALID);
279 STR_FAIL("\xE1\x80", SPDK_JSON_PARSE_INVALID);
280 STR_FAIL("\xE1\x7F\x80", SPDK_JSON_PARSE_INVALID);
281 STR_FAIL("\xE1\x80\x7F", SPDK_JSON_PARSE_INVALID);
282 STR_PASS("\xE1\x80\x80", "\xE1\x80\x80");
283 STR_PASS("\xE1\x80\xBF", "\xE1\x80\xBF");
284 STR_PASS("\xE1\xBF\x80", "\xE1\xBF\x80");
285 STR_PASS("\xE1\xBF\xBF", "\xE1\xBF\xBF");
286 STR_FAIL("\xE1\xC0\x80", SPDK_JSON_PARSE_INVALID);
287 STR_FAIL("\xE1\x80\xC0", SPDK_JSON_PARSE_INVALID);
288 STR_PASS("\xEF\x80\x80", "\xEF\x80\x80");
289 STR_PASS("\xEF\xBF\xBF", "\xEF\xBF\xBF");
290 STR_FAIL("\xF0", SPDK_JSON_PARSE_INVALID);
291 STR_FAIL("\xF0\x90", SPDK_JSON_PARSE_INVALID);
292 STR_FAIL("\xF0\x90\x80", SPDK_JSON_PARSE_INVALID);
293 STR_FAIL("\xF0\x80\x80\x80", SPDK_JSON_PARSE_INVALID);
294 STR_FAIL("\xF0\x8F\x80\x80", SPDK_JSON_PARSE_INVALID);
295 STR_PASS("\xF0\x90\x80\x80", "\xF0\x90\x80\x80");
296 STR_PASS("\xF0\x90\x80\xBF", "\xF0\x90\x80\xBF");
297 STR_PASS("\xF0\x90\xBF\x80", "\xF0\x90\xBF\x80");
298 STR_PASS("\xF0\xBF\x80\x80", "\xF0\xBF\x80\x80");
299 STR_FAIL("\xF0\xC0\x80\x80", SPDK_JSON_PARSE_INVALID);
300 STR_FAIL("\xF1", SPDK_JSON_PARSE_INVALID);
301 STR_FAIL("\xF1\x80", SPDK_JSON_PARSE_INVALID);
302 STR_FAIL("\xF1\x80\x80", SPDK_JSON_PARSE_INVALID);
303 STR_FAIL("\xF1\x80\x80\x7F", SPDK_JSON_PARSE_INVALID);
304 STR_PASS("\xF1\x80\x80\x80", "\xF1\x80\x80\x80");
305 STR_PASS("\xF1\x80\x80\xBF", "\xF1\x80\x80\xBF");
306 STR_PASS("\xF1\x80\xBF\x80", "\xF1\x80\xBF\x80");
307 STR_PASS("\xF1\xBF\x80\x80", "\xF1\xBF\x80\x80");
308 STR_PASS("\xF3\x80\x80\x80", "\xF3\x80\x80\x80");
309 STR_FAIL("\xF3\xC0\x80\x80", SPDK_JSON_PARSE_INVALID);
310 STR_FAIL("\xF3\x80\xC0\x80", SPDK_JSON_PARSE_INVALID);
311 STR_FAIL("\xF3\x80\x80\xC0", SPDK_JSON_PARSE_INVALID);
312 STR_FAIL("\xF4", SPDK_JSON_PARSE_INVALID);
313 STR_FAIL("\xF4\x80", SPDK_JSON_PARSE_INVALID);
314 STR_FAIL("\xF4\x80\x80", SPDK_JSON_PARSE_INVALID);
315 STR_PASS("\xF4\x80\x80\x80", "\xF4\x80\x80\x80");
316 STR_PASS("\xF4\x8F\x80\x80", "\xF4\x8F\x80\x80");
317 STR_PASS("\xF4\x8F\xBF\xBF", "\xF4\x8F\xBF\xBF");
318 STR_FAIL("\xF4\x90\x80\x80", SPDK_JSON_PARSE_INVALID);
319 STR_FAIL("\xF5", SPDK_JSON_PARSE_INVALID);
320 STR_FAIL("\xF5\x80", SPDK_JSON_PARSE_INVALID);
321 STR_FAIL("\xF5\x80\x80", SPDK_JSON_PARSE_INVALID);
322 STR_FAIL("\xF5\x80\x80\x80", SPDK_JSON_PARSE_INVALID);
323 STR_FAIL("\xF5\x80\x80\x80\x80", SPDK_JSON_PARSE_INVALID);
324
325 /* Overlong encodings */
326 STR_FAIL("\xC0\x80", SPDK_JSON_PARSE_INVALID);
327
328 /* Surrogate pairs */
329 STR_FAIL("\xED\xA0\x80", SPDK_JSON_PARSE_INVALID); /* U+D800 First high surrogate */
330 STR_FAIL("\xED\xAF\xBF", SPDK_JSON_PARSE_INVALID); /* U+DBFF Last high surrogate */
331 STR_FAIL("\xED\xB0\x80", SPDK_JSON_PARSE_INVALID); /* U+DC00 First low surrogate */
332 STR_FAIL("\xED\xBF\xBF", SPDK_JSON_PARSE_INVALID); /* U+DFFF Last low surrogate */
333 STR_FAIL("\xED\xA1\x8C\xED\xBE\xB4",
334 SPDK_JSON_PARSE_INVALID); /* U+233B4 (invalid surrogate pair encoding) */
335 }
336
337 static void
338 test_parse_string_escapes_twochar(void)
339 {
340 STR_PASS("\\\"", "\"");
341 STR_PASS("\\\\", "\\");
342 STR_PASS("\\/", "/");
343 STR_PASS("\\b", "\b");
344 STR_PASS("\\f", "\f");
345 STR_PASS("\\n", "\n");
346 STR_PASS("\\r", "\r");
347 STR_PASS("\\t", "\t");
348
349 STR_PASS("abc\\tdef", "abc\tdef");
350 STR_PASS("abc\\\"def", "abc\"def");
351
352 /* Backslash at end of string (will be treated as escaped quote) */
353 STR_FAIL("\\", SPDK_JSON_PARSE_INCOMPLETE);
354 STR_FAIL("abc\\", SPDK_JSON_PARSE_INCOMPLETE);
355
356 /* Invalid C-like escapes */
357 STR_FAIL("\\a", SPDK_JSON_PARSE_INVALID);
358 STR_FAIL("\\v", SPDK_JSON_PARSE_INVALID);
359 STR_FAIL("\\'", SPDK_JSON_PARSE_INVALID);
360 STR_FAIL("\\?", SPDK_JSON_PARSE_INVALID);
361 STR_FAIL("\\0", SPDK_JSON_PARSE_INVALID);
362 STR_FAIL("\\x00", SPDK_JSON_PARSE_INVALID);
363
364 /* Other invalid escapes */
365 STR_FAIL("\\B", SPDK_JSON_PARSE_INVALID);
366 STR_FAIL("\\z", SPDK_JSON_PARSE_INVALID);
367 }
368
369 static void
370 test_parse_string_escapes_unicode(void)
371 {
372 STR_PASS("\\u0000", "\0");
373 STR_PASS("\\u0001", "\1");
374 STR_PASS("\\u0041", "A");
375 STR_PASS("\\uAAAA", "\xEA\xAA\xAA");
376 STR_PASS("\\uaaaa", "\xEA\xAA\xAA");
377 STR_PASS("\\uAaAa", "\xEA\xAA\xAA");
378
379 STR_FAIL("\\u", SPDK_JSON_PARSE_INVALID);
380 STR_FAIL("\\u0", SPDK_JSON_PARSE_INVALID);
381 STR_FAIL("\\u00", SPDK_JSON_PARSE_INVALID);
382 STR_FAIL("\\u000", SPDK_JSON_PARSE_INVALID);
383 STR_FAIL("\\u000g", SPDK_JSON_PARSE_INVALID);
384 STR_FAIL("\\U", SPDK_JSON_PARSE_INVALID);
385 STR_FAIL("\\U0000", SPDK_JSON_PARSE_INVALID);
386
387 PARSE_FAIL("\"\\u", SPDK_JSON_PARSE_INCOMPLETE);
388 PARSE_FAIL("\"\\u0", SPDK_JSON_PARSE_INCOMPLETE);
389 PARSE_FAIL("\"\\u00", SPDK_JSON_PARSE_INCOMPLETE);
390 PARSE_FAIL("\"\\u000", SPDK_JSON_PARSE_INCOMPLETE);
391
392 /* Surrogate pair */
393 STR_PASS("\\uD834\\uDD1E", "\xF0\x9D\x84\x9E");
394
395 /* Low surrogate without high */
396 STR_FAIL("\\uDC00", SPDK_JSON_PARSE_INVALID);
397 STR_FAIL("\\uDC00\\uDC00", SPDK_JSON_PARSE_INVALID);
398 STR_FAIL("\\uDC00abcdef", SPDK_JSON_PARSE_INVALID);
399 STR_FAIL("\\uDEAD", SPDK_JSON_PARSE_INVALID);
400 PARSE_FAIL("\"\\uD834", SPDK_JSON_PARSE_INCOMPLETE);
401 PARSE_FAIL("\"\\uD834\\", SPDK_JSON_PARSE_INCOMPLETE);
402 PARSE_FAIL("\"\\uD834\\u", SPDK_JSON_PARSE_INCOMPLETE);
403 PARSE_FAIL("\"\\uD834\\uD", SPDK_JSON_PARSE_INCOMPLETE);
404 PARSE_FAIL("\"\\uD834\\uDD1", SPDK_JSON_PARSE_INCOMPLETE);
405
406 /* High surrogate without low */
407 STR_FAIL("\\uD800", SPDK_JSON_PARSE_INVALID);
408 STR_FAIL("\\uD800abcdef", SPDK_JSON_PARSE_INVALID);
409
410 /* High surrogate followed by high surrogate */
411 STR_FAIL("\\uD800\\uD800", SPDK_JSON_PARSE_INVALID);
412 }
413
414 static void
415 test_parse_number(void)
416 {
417 NUM_PASS("0");
418 NUM_PASS("1");
419 NUM_PASS("100");
420 NUM_PASS("-1");
421 NUM_PASS("-0");
422 NUM_PASS("3.0");
423 NUM_PASS("3.00");
424 NUM_PASS("3.001");
425 NUM_PASS("3.14159");
426 NUM_PASS("3.141592653589793238462643383279");
427 NUM_PASS("1e400");
428 NUM_PASS("1E400");
429 NUM_PASS("0e10");
430 NUM_PASS("0e0");
431 NUM_PASS("-0e0");
432 NUM_PASS("-0e+0");
433 NUM_PASS("-0e-0");
434 NUM_PASS("1e+400");
435 NUM_PASS("1e-400");
436 NUM_PASS("6.022e23");
437 NUM_PASS("-1.234e+56");
438 NUM_PASS("1.23e+56");
439 NUM_PASS("-1.23e-56");
440 NUM_PASS("1.23e-56");
441 NUM_PASS("1e04");
442
443 /* Trailing garbage */
444 PARSE_PASS("0A", 1, "A");
445 VAL_NUMBER("0");
446
447 PARSE_PASS("0,", 1, ",");
448 VAL_NUMBER("0");
449
450 PARSE_PASS("0true", 1, "true");
451 VAL_NUMBER("0");
452
453 PARSE_PASS("00", 1, "0");
454 VAL_NUMBER("0");
455 PARSE_FAIL("[00", SPDK_JSON_PARSE_INVALID);
456
457 PARSE_PASS("007", 1, "07");
458 VAL_NUMBER("0");
459 PARSE_FAIL("[007]", SPDK_JSON_PARSE_INVALID);
460
461 PARSE_PASS("345.678.1", 1, ".1");
462 VAL_NUMBER("345.678");
463 PARSE_FAIL("[345.678.1]", SPDK_JSON_PARSE_INVALID);
464
465 PARSE_PASS("3.2e-4+5", 1, "+5");
466 VAL_NUMBER("3.2e-4");
467 PARSE_FAIL("[3.2e-4+5]", SPDK_JSON_PARSE_INVALID);
468
469 PARSE_PASS("3.4.5", 1, ".5");
470 VAL_NUMBER("3.4");
471 PARSE_FAIL("[3.4.5]", SPDK_JSON_PARSE_INVALID);
472
473 NUM_FAIL("345.", SPDK_JSON_PARSE_INCOMPLETE);
474 NUM_FAIL("+1", SPDK_JSON_PARSE_INVALID);
475 NUM_FAIL("--1", SPDK_JSON_PARSE_INVALID);
476 NUM_FAIL("3.", SPDK_JSON_PARSE_INCOMPLETE);
477 NUM_FAIL("3.+4", SPDK_JSON_PARSE_INVALID);
478 NUM_FAIL("3.2e+-4", SPDK_JSON_PARSE_INVALID);
479 NUM_FAIL("3.2e-+4", SPDK_JSON_PARSE_INVALID);
480 NUM_FAIL("3e+", SPDK_JSON_PARSE_INCOMPLETE);
481 NUM_FAIL("3e-", SPDK_JSON_PARSE_INCOMPLETE);
482 NUM_FAIL("3.e4", SPDK_JSON_PARSE_INVALID);
483 NUM_FAIL("3.2eX", SPDK_JSON_PARSE_INVALID);
484 NUM_FAIL("-", SPDK_JSON_PARSE_INCOMPLETE);
485 NUM_FAIL("NaN", SPDK_JSON_PARSE_INVALID);
486 NUM_FAIL(".123", SPDK_JSON_PARSE_INVALID);
487 }
488
489 static void
490 test_parse_array(void)
491 {
492 char buffer[SPDK_JSON_MAX_NESTING_DEPTH + 2] = {0};
493
494 PARSE_PASS("[]", 2, "");
495 VAL_ARRAY_BEGIN(0);
496 VAL_ARRAY_END();
497
498 PARSE_PASS("[true]", 3, "");
499 VAL_ARRAY_BEGIN(1);
500 VAL_TRUE();
501 VAL_ARRAY_END();
502
503 PARSE_PASS("[true, false]", 4, "");
504 VAL_ARRAY_BEGIN(2);
505 VAL_TRUE();
506 VAL_FALSE();
507 VAL_ARRAY_END();
508
509 PARSE_PASS("[\"hello\"]", 3, "");
510 VAL_ARRAY_BEGIN(1);
511 VAL_STRING("hello");
512 VAL_ARRAY_END();
513
514 PARSE_PASS("[[]]", 4, "");
515 VAL_ARRAY_BEGIN(2);
516 VAL_ARRAY_BEGIN(0);
517 VAL_ARRAY_END();
518 VAL_ARRAY_END();
519
520 PARSE_PASS("[\"hello\", \"world\"]", 4, "");
521 VAL_ARRAY_BEGIN(2);
522 VAL_STRING("hello");
523 VAL_STRING("world");
524 VAL_ARRAY_END();
525
526 PARSE_PASS("[],", 2, ",");
527 VAL_ARRAY_BEGIN(0);
528 VAL_ARRAY_END();
529
530 PARSE_FAIL("]", SPDK_JSON_PARSE_INVALID);
531 PARSE_FAIL("[", SPDK_JSON_PARSE_INCOMPLETE);
532 PARSE_FAIL("[true", SPDK_JSON_PARSE_INCOMPLETE);
533 PARSE_FAIL("[\"hello", SPDK_JSON_PARSE_INCOMPLETE);
534 PARSE_FAIL("[\"hello\"", SPDK_JSON_PARSE_INCOMPLETE);
535 PARSE_FAIL("[true,]", SPDK_JSON_PARSE_INVALID);
536 PARSE_FAIL("[,]", SPDK_JSON_PARSE_INVALID);
537 PARSE_FAIL("[,true]", SPDK_JSON_PARSE_INVALID);
538 PARSE_FAIL("[true}", SPDK_JSON_PARSE_INVALID);
539 PARSE_FAIL("[true,,true]", SPDK_JSON_PARSE_INVALID);
540
541 /* Nested arrays exactly up to the allowed nesting depth */
542 memset(buffer, '[', SPDK_JSON_MAX_NESTING_DEPTH);
543 buffer[SPDK_JSON_MAX_NESTING_DEPTH] = ' ';
544 PARSE_FAIL(buffer, SPDK_JSON_PARSE_INCOMPLETE);
545
546 /* Nested arrays exceeding the maximum allowed nesting depth for this implementation */
547 buffer[SPDK_JSON_MAX_NESTING_DEPTH] = '[';
548 PARSE_FAIL(buffer, SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED);
549 }
550
551 static void
552 test_parse_object(void)
553 {
554 PARSE_PASS("{}", 2, "");
555 VAL_OBJECT_BEGIN(0);
556 VAL_OBJECT_END();
557
558 PARSE_PASS("{\"a\": true}", 4, "");
559 VAL_OBJECT_BEGIN(2);
560 VAL_NAME("a");
561 VAL_TRUE();
562 VAL_OBJECT_END();
563
564 PARSE_PASS("{\"abc\": \"def\"}", 4, "");
565 VAL_OBJECT_BEGIN(2);
566 VAL_NAME("abc");
567 VAL_STRING("def");
568 VAL_OBJECT_END();
569
570 PARSE_PASS("{\"a\": true, \"b\": false}", 6, "");
571 VAL_OBJECT_BEGIN(4);
572 VAL_NAME("a");
573 VAL_TRUE();
574 VAL_NAME("b");
575 VAL_FALSE();
576 VAL_OBJECT_END();
577
578 PARSE_PASS("{\"a\": { \"b\": true } }", 7, "");
579 VAL_OBJECT_BEGIN(5);
580 VAL_NAME("a");
581 VAL_OBJECT_BEGIN(2);
582 VAL_NAME("b");
583 VAL_TRUE();
584 VAL_OBJECT_END();
585 VAL_OBJECT_END();
586
587 PARSE_PASS("{\"{test\": 0}", 4, "");
588 VAL_OBJECT_BEGIN(2);
589 VAL_NAME("{test");
590 VAL_NUMBER("0");
591 VAL_OBJECT_END();
592
593 PARSE_PASS("{\"test}\": 1}", 4, "");
594 VAL_OBJECT_BEGIN(2);
595 VAL_NAME("test}");
596 VAL_NUMBER("1");
597 VAL_OBJECT_END();
598
599 PARSE_PASS("{\"\\\"\": 2}", 4, "");
600 VAL_OBJECT_BEGIN(2);
601 VAL_NAME("\"");
602 VAL_NUMBER("2");
603 VAL_OBJECT_END();
604
605 PARSE_PASS("{\"a\":true},", 4, ",");
606 VAL_OBJECT_BEGIN(2);
607 VAL_NAME("a");
608 VAL_TRUE();
609 VAL_OBJECT_END();
610
611 /* Object end without object begin (trailing garbage) */
612 PARSE_PASS("true}", 1, "}");
613 VAL_TRUE();
614
615 PARSE_PASS("0}", 1, "}");
616 VAL_NUMBER("0");
617
618 PARSE_PASS("\"a\"}", 1, "}");
619 VAL_STRING("a");
620
621 PARSE_FAIL("}", SPDK_JSON_PARSE_INVALID);
622 PARSE_FAIL("{", SPDK_JSON_PARSE_INCOMPLETE);
623 PARSE_FAIL("{\"a", SPDK_JSON_PARSE_INCOMPLETE);
624 PARSE_FAIL("{\"a\"", SPDK_JSON_PARSE_INCOMPLETE);
625 PARSE_FAIL("{\"a\":", SPDK_JSON_PARSE_INCOMPLETE);
626 PARSE_FAIL("{\"a\":true", SPDK_JSON_PARSE_INCOMPLETE);
627 PARSE_FAIL("{\"a\":true,", SPDK_JSON_PARSE_INCOMPLETE);
628 PARSE_FAIL("{\"a\":true]", SPDK_JSON_PARSE_INVALID);
629 PARSE_FAIL("{\"a\":true,}", SPDK_JSON_PARSE_INVALID);
630 PARSE_FAIL("{\"a\":true,\"}", SPDK_JSON_PARSE_INCOMPLETE);
631 PARSE_FAIL("{\"a\":true,\"b}", SPDK_JSON_PARSE_INCOMPLETE);
632 PARSE_FAIL("{\"a\":true,\"b\"}", SPDK_JSON_PARSE_INVALID);
633 PARSE_FAIL("{\"a\":true,\"b\":}", SPDK_JSON_PARSE_INVALID);
634 PARSE_FAIL("{\"a\":true,\"b\",}", SPDK_JSON_PARSE_INVALID);
635 PARSE_FAIL("{\"a\",}", SPDK_JSON_PARSE_INVALID);
636 PARSE_FAIL("{,\"a\": true}", SPDK_JSON_PARSE_INVALID);
637 PARSE_FAIL("{a:true}", SPDK_JSON_PARSE_INVALID);
638 PARSE_FAIL("{'a':true}", SPDK_JSON_PARSE_INVALID);
639 }
640
641 static void
642 test_parse_nesting(void)
643 {
644 PARSE_PASS("[[[[[[[[]]]]]]]]", 16, "");
645
646 PARSE_PASS("{\"a\": [0, 1, 2]}", 8, "");
647 VAL_OBJECT_BEGIN(6);
648 VAL_NAME("a");
649 VAL_ARRAY_BEGIN(3);
650 VAL_NUMBER("0");
651 VAL_NUMBER("1");
652 VAL_NUMBER("2");
653 VAL_ARRAY_END();
654 VAL_OBJECT_END();
655
656 PARSE_PASS("{\"a\": [0, 1, 2], \"b\": 3 }", 10, "");
657 VAL_OBJECT_BEGIN(8);
658 VAL_NAME("a");
659 VAL_ARRAY_BEGIN(3);
660 VAL_NUMBER("0");
661 VAL_NUMBER("1");
662 VAL_NUMBER("2");
663 VAL_ARRAY_END();
664 VAL_NAME("b");
665 VAL_NUMBER("3");
666 VAL_OBJECT_END();
667
668 PARSE_PASS("[0, 1, {\"a\": 3}, 4, 5]", 10, "");
669 VAL_ARRAY_BEGIN(8);
670 VAL_NUMBER("0");
671 VAL_NUMBER("1");
672 VAL_OBJECT_BEGIN(2);
673 VAL_NAME("a");
674 VAL_NUMBER("3");
675 VAL_OBJECT_END();
676 VAL_NUMBER("4");
677 VAL_NUMBER("5");
678 VAL_ARRAY_END();
679
680 PARSE_PASS("\t[ { \"a\": {\"b\": [ {\"c\": 1}, 2 ],\n\"d\": 3}, \"e\" : 4}, 5 ] ", 20, "");
681 VAL_ARRAY_BEGIN(18);
682 VAL_OBJECT_BEGIN(15);
683 VAL_NAME("a");
684 VAL_OBJECT_BEGIN(10);
685 VAL_NAME("b");
686 VAL_ARRAY_BEGIN(5);
687 VAL_OBJECT_BEGIN(2);
688 VAL_NAME("c");
689 VAL_NUMBER("1");
690 VAL_OBJECT_END();
691 VAL_NUMBER("2");
692 VAL_ARRAY_END();
693 VAL_NAME("d");
694 VAL_NUMBER("3");
695 VAL_OBJECT_END();
696 VAL_NAME("e");
697 VAL_NUMBER("4");
698 VAL_OBJECT_END();
699 VAL_NUMBER("5");
700 VAL_ARRAY_END();
701
702 /* Examples from RFC 7159 */
703 PARSE_PASS(
704 "{\n"
705 " \"Image\": {\n"
706 " \"Width\": 800,\n"
707 " \"Height\": 600,\n"
708 " \"Title\": \"View from 15th Floor\",\n"
709 " \"Thumbnail\": {\n"
710 " \"Url\": \"http://www.example.com/image/481989943\",\n"
711 " \"Height\": 125,\n"
712 " \"Width\": 100\n"
713 " },\n"
714 " \"Animated\" : false,\n"
715 " \"IDs\": [116, 943, 234, 38793]\n"
716 " }\n"
717 "}\n",
718 29, "");
719
720 VAL_OBJECT_BEGIN(27);
721 VAL_NAME("Image");
722 VAL_OBJECT_BEGIN(24);
723 VAL_NAME("Width");
724 VAL_NUMBER("800");
725 VAL_NAME("Height");
726 VAL_NUMBER("600");
727 VAL_NAME("Title");
728 VAL_STRING("View from 15th Floor");
729 VAL_NAME("Thumbnail");
730 VAL_OBJECT_BEGIN(6);
731 VAL_NAME("Url");
732 VAL_STRING("http://www.example.com/image/481989943");
733 VAL_NAME("Height");
734 VAL_NUMBER("125");
735 VAL_NAME("Width");
736 VAL_NUMBER("100");
737 VAL_OBJECT_END();
738 VAL_NAME("Animated");
739 VAL_FALSE();
740 VAL_NAME("IDs");
741 VAL_ARRAY_BEGIN(4);
742 VAL_NUMBER("116");
743 VAL_NUMBER("943");
744 VAL_NUMBER("234");
745 VAL_NUMBER("38793");
746 VAL_ARRAY_END();
747 VAL_OBJECT_END();
748 VAL_OBJECT_END();
749
750 PARSE_PASS(
751 "[\n"
752 " {\n"
753 " \"precision\": \"zip\",\n"
754 " \"Latitude\": 37.7668,\n"
755 " \"Longitude\": -122.3959,\n"
756 " \"Address\": \"\",\n"
757 " \"City\": \"SAN FRANCISCO\",\n"
758 " \"State\": \"CA\",\n"
759 " \"Zip\": \"94107\",\n"
760 " \"Country\": \"US\"\n"
761 " },\n"
762 " {\n"
763 " \"precision\": \"zip\",\n"
764 " \"Latitude\": 37.371991,\n"
765 " \"Longitude\": -122.026020,\n"
766 " \"Address\": \"\",\n"
767 " \"City\": \"SUNNYVALE\",\n"
768 " \"State\": \"CA\",\n"
769 " \"Zip\": \"94085\",\n"
770 " \"Country\": \"US\"\n"
771 " }\n"
772 "]",
773 38, "");
774
775 VAL_ARRAY_BEGIN(36);
776 VAL_OBJECT_BEGIN(16);
777 VAL_NAME("precision");
778 VAL_STRING("zip");
779 VAL_NAME("Latitude");
780 VAL_NUMBER("37.7668");
781 VAL_NAME("Longitude");
782 VAL_NUMBER("-122.3959");
783 VAL_NAME("Address");
784 VAL_STRING("");
785 VAL_NAME("City");
786 VAL_STRING("SAN FRANCISCO");
787 VAL_NAME("State");
788 VAL_STRING("CA");
789 VAL_NAME("Zip");
790 VAL_STRING("94107");
791 VAL_NAME("Country");
792 VAL_STRING("US");
793 VAL_OBJECT_END();
794 VAL_OBJECT_BEGIN(16);
795 VAL_NAME("precision");
796 VAL_STRING("zip");
797 VAL_NAME("Latitude");
798 VAL_NUMBER("37.371991");
799 VAL_NAME("Longitude");
800 VAL_NUMBER("-122.026020");
801 VAL_NAME("Address");
802 VAL_STRING("");
803 VAL_NAME("City");
804 VAL_STRING("SUNNYVALE");
805 VAL_NAME("State");
806 VAL_STRING("CA");
807 VAL_NAME("Zip");
808 VAL_STRING("94085");
809 VAL_NAME("Country");
810 VAL_STRING("US");
811 VAL_OBJECT_END();
812 VAL_ARRAY_END();
813
814 /* Trailing garbage */
815 PARSE_PASS("{\"a\": [0, 1, 2]}]", 8, "]");
816 VAL_OBJECT_BEGIN(6);
817 VAL_NAME("a");
818 VAL_ARRAY_BEGIN(3);
819 VAL_NUMBER("0");
820 VAL_NUMBER("1");
821 VAL_NUMBER("2");
822 VAL_ARRAY_END();
823 VAL_OBJECT_END();
824
825 PARSE_PASS("{\"a\": [0, 1, 2]}}", 8, "}");
826 PARSE_PASS("{\"a\": [0, 1, 2]}]", 8, "]");
827 VAL_OBJECT_BEGIN(6);
828 VAL_NAME("a");
829 VAL_ARRAY_BEGIN(3);
830 VAL_NUMBER("0");
831 VAL_NUMBER("1");
832 VAL_NUMBER("2");
833 VAL_ARRAY_END();
834 VAL_OBJECT_END();
835
836 PARSE_FAIL("{\"a\": [0, 1, 2}]", SPDK_JSON_PARSE_INVALID);
837 PARSE_FAIL("{\"a\": [0, 1, 2]", SPDK_JSON_PARSE_INCOMPLETE);
838 }
839
840
841 static void
842 test_parse_comment(void)
843 {
844 /* Comments are not allowed by the JSON RFC */
845 PARSE_PASS("[0]", 3, "");
846 PARSE_FAIL("/* test */[0]", SPDK_JSON_PARSE_INVALID);
847 PARSE_FAIL("[/* test */0]", SPDK_JSON_PARSE_INVALID);
848 PARSE_FAIL("[0/* test */]", SPDK_JSON_PARSE_INVALID);
849
850 /*
851 * This is allowed since the parser stops once it reads a complete JSON object.
852 * The next parse call would fail (see tests above) when parsing the comment.
853 */
854 PARSE_PASS("[0]/* test */", 3, "/* test */");
855
856 /*
857 * Test with non-standard comments enabled.
858 */
859 PARSE_PASS_FLAGS("/* test */[0]", 3, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
860 VAL_ARRAY_BEGIN(1);
861 VAL_NUMBER("0");
862 VAL_ARRAY_END();
863
864 PARSE_PASS_FLAGS("[/* test */0]", 3, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
865 VAL_ARRAY_BEGIN(1);
866 VAL_NUMBER("0");
867 VAL_ARRAY_END();
868
869 PARSE_PASS_FLAGS("[0/* test */]", 3, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
870 VAL_ARRAY_BEGIN(1);
871 VAL_NUMBER("0");
872 VAL_ARRAY_END();
873
874 PARSE_FAIL_FLAGS("/* test */", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
875 PARSE_FAIL_FLAGS("[/* test */", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
876 PARSE_FAIL_FLAGS("[0/* test */", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
877
878 /*
879 * Single-line comments
880 */
881 PARSE_PASS_FLAGS("// test\n0", 1, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
882 VAL_NUMBER("0");
883
884 PARSE_PASS_FLAGS("// test\r\n0", 1, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
885 VAL_NUMBER("0");
886
887 PARSE_PASS_FLAGS("// [0] test\n0", 1, "", SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
888 VAL_NUMBER("0");
889
890 PARSE_FAIL_FLAGS("//", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
891 PARSE_FAIL_FLAGS("// test", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
892 PARSE_FAIL_FLAGS("//\n", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
893
894 /* Invalid character following slash */
895 PARSE_FAIL_FLAGS("[0/x", SPDK_JSON_PARSE_INVALID, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
896
897 /* Single slash at end of buffer */
898 PARSE_FAIL_FLAGS("[0/", SPDK_JSON_PARSE_INCOMPLETE, SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS);
899 }
900
901 int main(int argc, char **argv)
902 {
903 CU_pSuite suite = NULL;
904 unsigned int num_failures;
905
906 CU_set_error_action(CUEA_ABORT);
907 CU_initialize_registry();
908
909 suite = CU_add_suite("json", NULL, NULL);
910
911 CU_ADD_TEST(suite, test_parse_literal);
912 CU_ADD_TEST(suite, test_parse_string_simple);
913 CU_ADD_TEST(suite, test_parse_string_control_chars);
914 CU_ADD_TEST(suite, test_parse_string_utf8);
915 CU_ADD_TEST(suite, test_parse_string_escapes_twochar);
916 CU_ADD_TEST(suite, test_parse_string_escapes_unicode);
917 CU_ADD_TEST(suite, test_parse_number);
918 CU_ADD_TEST(suite, test_parse_array);
919 CU_ADD_TEST(suite, test_parse_object);
920 CU_ADD_TEST(suite, test_parse_nesting);
921 CU_ADD_TEST(suite, test_parse_comment);
922
923 CU_basic_set_mode(CU_BRM_VERBOSE);
924
925 CU_basic_run_tests();
926
927 num_failures = CU_get_number_of_failures();
928 CU_cleanup_registry();
929
930 return num_failures;
931 }