blob: 18839809fdcd229b103f2008b7bd666e158f2f50 [file] [log] [blame]
Radek Krejci50f0c6b2020-06-18 16:31:48 +02001/*
2 * @file json.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for a generic JSON parser
5 *
6 * Copyright (c) 2020 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _DEFAULT_SOURCE
16#define _GNU_SOURCE
17
18#include <stdarg.h>
19#include <stddef.h>
20#include <setjmp.h>
21#include <cmocka.h>
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "json.h"
28#include "context.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020029#include "in_internal.h"
Radek Krejci50f0c6b2020-06-18 16:31:48 +020030
31void *testfunc = NULL;
32
33static int
34setup(void **state)
35{
36 if (ly_ctx_new(NULL, 0, (struct ly_ctx **)state)) {
37 return 1;
38 }
39
40 return 0;
41}
42
43static int
44teardown(void **state)
45{
46 ly_ctx_destroy(*state, NULL);
47 return 0;
48}
49
50#define BUFSIZE 1024
51char logbuf[BUFSIZE] = {0};
52
53/* set to 0 to printing error messages to stderr instead of checking them in code */
54#define ENABLE_LOGGER_CHECKING 1
55
56static void
57logger(LY_LOG_LEVEL level, const char *msg, const char *path)
58{
59 (void) level; /* unused */
60
61 if (path) {
62 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
63 } else {
64 strncpy(logbuf, msg, BUFSIZE - 1);
65 }
66}
67
68static int
69logger_setup(void **state)
70{
71 (void) state; /* unused */
72#if ENABLE_LOGGER_CHECKING
73 ly_set_log_clb(logger, 1);
74#endif
75 return 0;
76}
77
78static int
79logger_teardown(void **state)
80{
81 (void) state; /* unused */
82#if ENABLE_LOGGER_CHECKING
83 if (testfunc) {
84 fprintf(stderr, "%s\n", logbuf);
85 }
86#endif
87 return 0;
88}
89
90void
91logbuf_clean(void)
92{
93 logbuf[0] = '\0';
94}
95
96#if ENABLE_LOGGER_CHECKING
97# define logbuf_assert(str) assert_string_equal(logbuf, str)
98#else
99# define logbuf_assert(str)
100#endif
101
102
103
104static void
105test_general(void **state)
106{
107 struct lyjson_ctx *jsonctx;
108 struct ly_in *in;
109 const char *str;
110
111 testfunc = test_general;
112
113 /* empty */
114 str = "";
115 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
116 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
117 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
118 lyjson_ctx_free(jsonctx);
119
120 str = " \n\t \n";
121 assert_non_null(ly_in_memory(in, str));
122 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
123 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
124 lyjson_ctx_free(jsonctx);
125
126 /* constant values */
127 str = "true";
128 assert_non_null(ly_in_memory(in, str));
129 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
130 assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx, 0));
131 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
132 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
133 lyjson_ctx_free(jsonctx);
134
135 str = "false";
136 assert_non_null(ly_in_memory(in, str));
137 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
138 assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx, 0));
139 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
140 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
141 lyjson_ctx_free(jsonctx);
142
143 str = "null";
144 assert_non_null(ly_in_memory(in, str));
145 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
146 assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
147 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
148 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
149 lyjson_ctx_free(jsonctx);
150
151 ly_in_free(in, 0);
152 testfunc = NULL;
153}
154
155static void
156test_number(void **state)
157{
158 struct lyjson_ctx *jsonctx;
159 struct ly_in *in;
160 const char *str;
161
162 testfunc = test_number;
163
164 /* simple value */
165 str = "11";
166 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
167 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
168 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
169 assert_string_equal("11", jsonctx->value);
170 assert_int_equal(2, jsonctx->value_len);
171 assert_int_equal(0, jsonctx->dynamic);
172 lyjson_ctx_free(jsonctx);
173
174 /* fraction number */
175 str = "37.7668";
176 assert_non_null(ly_in_memory(in, str));
177 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
178 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
179 assert_string_equal("37.7668", jsonctx->value);
180 assert_int_equal(7, jsonctx->value_len);
181 assert_int_equal(0, jsonctx->dynamic);
182 lyjson_ctx_free(jsonctx);
183
184 /* negative number */
185 str = "-122.3959";
186 assert_non_null(ly_in_memory(in, str));
187 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
188 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
189 assert_string_equal("-122.3959", jsonctx->value);
190 assert_int_equal(9, jsonctx->value_len);
191 assert_int_equal(0, jsonctx->dynamic);
192 lyjson_ctx_free(jsonctx);
193
194 /* exp number */
195 str = "1E10";
196 assert_non_null(ly_in_memory(in, str));
197 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
198 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
199 assert_string_equal("10000000000", jsonctx->value);
200 assert_int_equal(11, jsonctx->value_len);
201 assert_int_equal(1, jsonctx->dynamic);
202 lyjson_ctx_free(jsonctx);
203
204 str = "15E-1";
205 assert_non_null(ly_in_memory(in, str));
206 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
207 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
208 assert_string_equal("1.5", jsonctx->value);
209 assert_int_equal(3, jsonctx->value_len);
210 assert_int_equal(1, jsonctx->dynamic);
211 lyjson_ctx_free(jsonctx);
212
213 str = "15E-3";
214 assert_non_null(ly_in_memory(in, str));
215 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
216 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
217 assert_string_equal("0.015", jsonctx->value);
218 assert_int_equal(5, jsonctx->value_len);
219 assert_int_equal(1, jsonctx->dynamic);
220 lyjson_ctx_free(jsonctx);
221
222 /* exp fraction number */
223 str = "1.1e3";
224 assert_non_null(ly_in_memory(in, str));
225 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
226 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
227 assert_string_equal("1100", jsonctx->value);
228 assert_int_equal(4, jsonctx->value_len);
229 assert_int_equal(1, jsonctx->dynamic);
230 lyjson_ctx_free(jsonctx);
231
232 /* negative exp fraction number */
233 str = "1.1e-3";
234 assert_non_null(ly_in_memory(in, str));
235 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
236 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
237 assert_string_equal("0.0011", jsonctx->value);
238 assert_int_equal(6, jsonctx->value_len);
239 assert_int_equal(1, jsonctx->dynamic);
240 lyjson_ctx_free(jsonctx);
241
242 /* exp negative fraction number */
243 str = "-0.11e3";
244 assert_non_null(ly_in_memory(in, str));
245 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
246 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
247 assert_string_equal("-110", jsonctx->value);
248 assert_int_equal(4, jsonctx->value_len);
249 assert_int_equal(1, jsonctx->dynamic);
250 lyjson_ctx_free(jsonctx);
251
252 /* negative exp negative fraction number */
253 str = "-3.14e-3";
254 assert_non_null(ly_in_memory(in, str));
255 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
256 assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
257 assert_string_equal("-0.00314", jsonctx->value);
258 assert_int_equal(8, jsonctx->value_len);
259 assert_int_equal(1, jsonctx->dynamic);
260 lyjson_ctx_free(jsonctx);
261
262 /* various invalid inputs */
263 str = "-x";
264 assert_non_null(ly_in_memory(in, str));
265 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
266 logbuf_assert("Invalid character in JSON Number value (\"x\"). Line number 1.");
267
268 str = " -";
269 assert_non_null(ly_in_memory(in, str));
270 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
271 logbuf_assert("Unexpected end-of-input. Line number 1.");
272
273 str = "--1";
274 assert_non_null(ly_in_memory(in, str));
275 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
276 logbuf_assert("Invalid character in JSON Number value (\"-\"). Line number 1.");
277
278 str = "+1";
279 assert_non_null(ly_in_memory(in, str));
280 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
281 logbuf_assert("Invalid character sequence \"+1\", expected a JSON value. Line number 1.");
282
283 str = " 1.x ";
284 assert_non_null(ly_in_memory(in, str));
285 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
286 logbuf_assert("Invalid character in JSON Number value (\"x\"). Line number 1.");
287
288 str = "1.";
289 assert_non_null(ly_in_memory(in, str));
290 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
291 logbuf_assert("Unexpected end-of-input. Line number 1.");
292
293 str = " 1eo ";
294 assert_non_null(ly_in_memory(in, str));
295 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
296 logbuf_assert("Invalid character in JSON Number value (\"o\"). Line number 1.");
297
298 str = "1e";
299 assert_non_null(ly_in_memory(in, str));
300 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
301 logbuf_assert("Unexpected end-of-input. Line number 1.");
302
303 ly_in_free(in, 0);
304 testfunc = NULL;
305}
306
307static void
308test_string(void **state)
309{
310 struct lyjson_ctx *jsonctx;
311 struct ly_in *in;
312 const char *str;
313
314 testfunc = test_string;
315
316 /* simple string */
317 str = "\"hello\"";
318 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
319 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
320 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
321 assert_ptr_equal(&str[1], jsonctx->value);
322 assert_int_equal(5, jsonctx->value_len);
323 assert_int_equal(0, jsonctx->dynamic);
324 lyjson_ctx_free(jsonctx);
325
326 /* 4-byte utf8 character */
327 str = "\"\\t𠜎\"";
328 assert_non_null(ly_in_memory(in, str));
329 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
330 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
331 assert_string_equal("\t𠜎", jsonctx->value);
332 assert_int_equal(5, jsonctx->value_len);
333 assert_int_equal(1, jsonctx->dynamic);
334 lyjson_ctx_free(jsonctx);
335
336 /* valid escape sequences - note that here it mixes valid JSON string characters (RFC 7159, sec. 7) and
337 * valid characters in YANG string type (RFC 7950, sec. 9.4). Since the latter is a subset of JSON string,
338 * the YANG string type's restrictions apply to the JSON escape sequences */
339 str = "\"\\\" \\\\ \\r \\/ \\n \\t \\u20ac\"";
340 assert_non_null(ly_in_memory(in, str));
341 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
342 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
343 assert_string_equal("\" \\ \r / \n \t €", jsonctx->value);
344 assert_int_equal(15, jsonctx->value_len);
345 assert_int_equal(1, jsonctx->dynamic);
346 lyjson_ctx_free(jsonctx);
347
348 /* backspace and form feed are valid JSON escape sequences, but the control characters they represents are not allowed values for YANG string type */
349 str = "\"\\b\"";
350 assert_non_null(ly_in_memory(in, str));
351 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
352 logbuf_assert("Invalid character reference \"\\b\" (0x00000008). Line number 1.");
353
354 str = "\"\\f\"";
355 assert_non_null(ly_in_memory(in, str));
356 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
357 logbuf_assert("Invalid character reference \"\\f\" (0x0000000c). Line number 1.");
358
359 /* unterminated string */
360 str = "\"unterminated string";
361 assert_non_null(ly_in_memory(in, str));
362 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
363 logbuf_assert("Missing quotation-mark at the end of a JSON string. Line number 1.");
364
365 /* invalid escape sequence */
366 str = "\"char \\x \"";
367 assert_non_null(ly_in_memory(in, str));
368 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
369 logbuf_assert("Invalid character escape sequence \\x. Line number 1.");
370
371 /* new line is allowed only as escaped character in JSON */
372 str = "\"\n\"";
373 assert_non_null(ly_in_memory(in, str));
374 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
375 logbuf_assert("Invalid character in JSON string \"\n\" (0x0000000a). Line number 1.");
376
377 ly_in_free(in, 0);
378 testfunc = NULL;
379}
380
381static void
382test_object(void **state)
383{
384 struct lyjson_ctx *jsonctx;
385 struct ly_in *in;
386 const char *str;
387
388 testfunc = test_object;
389
390 /* empty */
391 str = " { } ";
392 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
393 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
394 assert_int_equal(LYJSON_OBJECT_EMPTY, lyjson_ctx_status(jsonctx, 0));
395 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
396 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
397 lyjson_ctx_free(jsonctx);
398
399 /* simple value */
400 str = "{\"name\" : \"Radek\"}";
401 assert_non_null(ly_in_memory(in, str));
402 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
403 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
404 assert_ptr_equal(&str[2], jsonctx->value);
405 assert_int_equal(4, jsonctx->value_len);
406 assert_int_equal(0, jsonctx->dynamic);
407 assert_string_equal("\"Radek\"}", jsonctx->in->current);
408 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
409 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
410 assert_string_equal("Radek\"}", jsonctx->value);
411 assert_int_equal(5, jsonctx->value_len);
412 assert_int_equal(0, jsonctx->dynamic);
413 assert_string_equal("}", jsonctx->in->current);
414 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
415 assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
416 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
417 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
418 lyjson_ctx_free(jsonctx);
419
420 /* two values */
421 str = "{\"smart\" : true,\"handsom\":false}";
422 assert_non_null(ly_in_memory(in, str));
423 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
424 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
425 assert_string_equal("smart\" : true,\"handsom\":false}", jsonctx->value);
426 assert_int_equal(5, jsonctx->value_len);
427 assert_int_equal(0, jsonctx->dynamic);
428 assert_string_equal("true,\"handsom\":false}", jsonctx->in->current);
429 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
430 assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx, 0));
431 assert_string_equal(",\"handsom\":false}", jsonctx->in->current);
432 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
433 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
434 assert_string_equal("handsom\":false}", jsonctx->value);
435 assert_int_equal(7, jsonctx->value_len);
436 assert_int_equal(0, jsonctx->dynamic);
437 assert_string_equal("false}", jsonctx->in->current);
438 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
439 assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx, 0));
440 assert_string_equal("}", jsonctx->in->current);
441 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
442 assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
443 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
444 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
445 lyjson_ctx_free(jsonctx);
446
447 /* inherited objects */
448 str = "{\"person\" : {\"name\":\"Radek\"}}";
449 assert_non_null(ly_in_memory(in, str));
450 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
451 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
452 assert_string_equal("person\" : {\"name\":\"Radek\"}}", jsonctx->value);
453 assert_int_equal(6, jsonctx->value_len);
454 assert_int_equal(0, jsonctx->dynamic);
455 assert_string_equal("{\"name\":\"Radek\"}}", jsonctx->in->current);
456 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
457 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
458 assert_string_equal("name\":\"Radek\"}}", jsonctx->value);
459 assert_int_equal(4, jsonctx->value_len);
460 assert_int_equal(0, jsonctx->dynamic);
461 assert_string_equal("\"Radek\"}}", jsonctx->in->current);
462 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
463 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
464 assert_string_equal("Radek\"}}", jsonctx->value);
465 assert_int_equal(5, jsonctx->value_len);
466 assert_int_equal(0, jsonctx->dynamic);
467 assert_string_equal("}}", jsonctx->in->current);
468 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
469 assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
470 assert_string_equal("}", jsonctx->in->current);
471 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
472 assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
473 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
474 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
475 lyjson_ctx_free(jsonctx);
476
477 /* new line is allowed only as escaped character in JSON */
478 str = "{ unquoted : \"data\"}";
479 assert_non_null(ly_in_memory(in, str));
480 assert_int_equal(LY_EVALID, lyjson_ctx_new(*state, in, &jsonctx));
481 logbuf_assert("Invalid character sequence \"unquoted : \"data\"}\", expected a JSON object's member. Line number 1.");
482
483 ly_in_free(in, 0);
484 testfunc = NULL;
485}
486
487static void
488test_array(void **state)
489{
490 struct lyjson_ctx *jsonctx;
491 struct ly_in *in;
492 const char *str;
493
494 testfunc = test_array;
495
496 /* empty */
497 str = " [ ] ";
498 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
499 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
500 assert_int_equal(LYJSON_ARRAY_EMPTY, lyjson_ctx_status(jsonctx, 0));
501 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
502 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
503 lyjson_ctx_free(jsonctx);
504
505 /* simple value */
506 str = "[ null]";
507 assert_non_null(ly_in_memory(in, str));
508 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
509 assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx, 0));
510 assert_null(jsonctx->value);
511 assert_int_equal(0, jsonctx->value_len);
512 assert_int_equal(0, jsonctx->dynamic);
513 assert_string_equal("null]", jsonctx->in->current);
514 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
515 assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
516 assert_string_equal("]", jsonctx->in->current);
517 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
518 assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx, 0));
519 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
520 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
521 lyjson_ctx_free(jsonctx);
522
523 /* two values */
524 str = "[{\"a\":null},\"x\"]";
525 assert_non_null(ly_in_memory(in, str));
526 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
527 assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx, 0));
528 assert_null(jsonctx->value);
529 assert_int_equal(0, jsonctx->value_len);
530 assert_int_equal(0, jsonctx->dynamic);
531 assert_string_equal("{\"a\":null},\"x\"]", jsonctx->in->current);
532 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
533 assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
534 assert_string_equal("a\":null},\"x\"]", jsonctx->value);
535 assert_int_equal(1, jsonctx->value_len);
536 assert_int_equal(0, jsonctx->dynamic);
537 assert_string_equal("null},\"x\"]", jsonctx->in->current);
538 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
539 assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
540 assert_string_equal("},\"x\"]", jsonctx->in->current);
541 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
542 assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
543 assert_string_equal(",\"x\"]", jsonctx->in->current);
544 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
545 assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
546 assert_string_equal("x\"]", jsonctx->value);
547 assert_int_equal(1, jsonctx->value_len);
548 assert_int_equal(0, jsonctx->dynamic);
549 assert_string_equal("]", jsonctx->in->current);
550 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
551 assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx, 0));
552 assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
553 assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
554 lyjson_ctx_free(jsonctx);
555
556 /* new line is allowed only as escaped character in JSON */
557 str = "[ , null]";
558 assert_non_null(ly_in_memory(in, str));
559 assert_int_equal(LY_SUCCESS, lyjson_ctx_new(*state, in, &jsonctx));
560 assert_int_equal(LY_EVALID, lyjson_ctx_next(jsonctx, NULL));
561 logbuf_assert("Invalid character sequence \", null]\", expected a JSON value. Line number 1.");
562 lyjson_ctx_free(jsonctx);
563
564 ly_in_free(in, 0);
565 testfunc = NULL;
566}
567
568int main(void)
569{
570 const struct CMUnitTest tests[] = {
571 cmocka_unit_test_setup_teardown(test_general, logger_setup, logger_teardown),
572 cmocka_unit_test_setup_teardown(test_number, logger_setup, logger_teardown),
573 cmocka_unit_test_setup_teardown(test_string, logger_setup, logger_teardown),
574 cmocka_unit_test_setup_teardown(test_object, logger_setup, logger_teardown),
575 cmocka_unit_test_setup_teardown(test_array, logger_setup, logger_teardown),
576 };
577
578 return cmocka_run_group_tests(tests, setup, teardown);
579}