• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include "test.h"
7 #include "testutil.h"
8 
test_empty(void)9 int test_empty(void) {
10   check(parse("{}", 1, 1, JSMN_OBJECT, 0, 2, 0));
11   check(parse("[]", 1, 1, JSMN_ARRAY, 0, 2, 0));
12   check(parse("[{},{}]", 3, 3, JSMN_ARRAY, 0, 7, 2, JSMN_OBJECT, 1, 3, 0,
13               JSMN_OBJECT, 4, 6, 0));
14   return 0;
15 }
16 
test_object(void)17 int test_object(void) {
18   check(parse("{\"a\":0}", 3, 3, JSMN_OBJECT, 0, 7, 1, JSMN_STRING, "a", 1,
19               JSMN_PRIMITIVE, "0"));
20   check(parse("{\"a\":[]}", 3, 3, JSMN_OBJECT, 0, 8, 1, JSMN_STRING, "a", 1,
21               JSMN_ARRAY, 5, 7, 0));
22   check(parse("{\"a\":{},\"b\":{}}", 5, 5, JSMN_OBJECT, -1, -1, 2, JSMN_STRING,
23               "a", 1, JSMN_OBJECT, -1, -1, 0, JSMN_STRING, "b", 1, JSMN_OBJECT,
24               -1, -1, 0));
25   check(parse("{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }", 7, 7,
26               JSMN_OBJECT, -1, -1, 3, JSMN_STRING, "Day", 1, JSMN_PRIMITIVE,
27               "26", JSMN_STRING, "Month", 1, JSMN_PRIMITIVE, "9", JSMN_STRING,
28               "Year", 1, JSMN_PRIMITIVE, "12"));
29   check(parse("{\"a\": 0, \"b\": \"c\"}", 5, 5, JSMN_OBJECT, -1, -1, 2,
30               JSMN_STRING, "a", 1, JSMN_PRIMITIVE, "0", JSMN_STRING, "b", 1,
31               JSMN_STRING, "c", 0));
32 
33 #ifdef JSMN_STRICT
34   check(parse("{\"a\"\n0}", JSMN_ERROR_INVAL, 3));
35   check(parse("{\"a\", 0}", JSMN_ERROR_INVAL, 3));
36   check(parse("{\"a\": {2}}", JSMN_ERROR_INVAL, 3));
37   check(parse("{\"a\": {2: 3}}", JSMN_ERROR_INVAL, 3));
38   check(parse("{\"a\": {\"a\": 2 3}}", JSMN_ERROR_INVAL, 5));
39 /* FIXME */
40 /*check(parse("{\"a\"}", JSMN_ERROR_INVAL, 2));*/
41 /*check(parse("{\"a\": 1, \"b\"}", JSMN_ERROR_INVAL, 4));*/
42 /*check(parse("{\"a\",\"b\":1}", JSMN_ERROR_INVAL, 4));*/
43 /*check(parse("{\"a\":1,}", JSMN_ERROR_INVAL, 4));*/
44 /*check(parse("{\"a\":\"b\":\"c\"}", JSMN_ERROR_INVAL, 4));*/
45 /*check(parse("{,}", JSMN_ERROR_INVAL, 4));*/
46 #endif
47   return 0;
48 }
49 
test_array(void)50 int test_array(void) {
51   /* FIXME */
52   /*check(parse("[10}", JSMN_ERROR_INVAL, 3));*/
53   /*check(parse("[1,,3]", JSMN_ERROR_INVAL, 3)*/
54   check(parse("[10]", 2, 2, JSMN_ARRAY, -1, -1, 1, JSMN_PRIMITIVE, "10"));
55   check(parse("{\"a\": 1]", JSMN_ERROR_INVAL, 3));
56   /* FIXME */
57   /*check(parse("[\"a\": 1]", JSMN_ERROR_INVAL, 3));*/
58   return 0;
59 }
60 
test_primitive(void)61 int test_primitive(void) {
62   check(parse("{\"boolVar\" : true }", 3, 3, JSMN_OBJECT, -1, -1, 1,
63               JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "true"));
64   check(parse("{\"boolVar\" : false }", 3, 3, JSMN_OBJECT, -1, -1, 1,
65               JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "false"));
66   check(parse("{\"nullVar\" : null }", 3, 3, JSMN_OBJECT, -1, -1, 1,
67               JSMN_STRING, "nullVar", 1, JSMN_PRIMITIVE, "null"));
68   check(parse("{\"intVar\" : 12}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING,
69               "intVar", 1, JSMN_PRIMITIVE, "12"));
70   check(parse("{\"floatVar\" : 12.345}", 3, 3, JSMN_OBJECT, -1, -1, 1,
71               JSMN_STRING, "floatVar", 1, JSMN_PRIMITIVE, "12.345"));
72   return 0;
73 }
74 
test_string(void)75 int test_string(void) {
76   check(parse("{\"strVar\" : \"hello world\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
77               JSMN_STRING, "strVar", 1, JSMN_STRING, "hello world", 0));
78   check(parse("{\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"}", 3, 3,
79               JSMN_OBJECT, -1, -1, 1, JSMN_STRING, "strVar", 1, JSMN_STRING,
80               "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\", 0));
81   check(parse("{\"strVar\": \"\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING,
82               "strVar", 1, JSMN_STRING, "", 0));
83   check(parse("{\"a\":\"\\uAbcD\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING,
84               "a", 1, JSMN_STRING, "\\uAbcD", 0));
85   check(parse("{\"a\":\"str\\u0000\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
86               JSMN_STRING, "a", 1, JSMN_STRING, "str\\u0000", 0));
87   check(parse("{\"a\":\"\\uFFFFstr\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
88               JSMN_STRING, "a", 1, JSMN_STRING, "\\uFFFFstr", 0));
89   check(parse("{\"a\":[\"\\u0280\"]}", 4, 4, JSMN_OBJECT, -1, -1, 1,
90               JSMN_STRING, "a", 1, JSMN_ARRAY, -1, -1, 1, JSMN_STRING,
91               "\\u0280", 0));
92 
93   check(parse("{\"a\":\"str\\uFFGFstr\"}", JSMN_ERROR_INVAL, 3));
94   check(parse("{\"a\":\"str\\u@FfF\"}", JSMN_ERROR_INVAL, 3));
95   check(parse("{{\"a\":[\"\\u028\"]}", JSMN_ERROR_INVAL, 4));
96   return 0;
97 }
98 
test_partial_string(void)99 int test_partial_string(void) {
100   int r;
101   unsigned long i;
102   jsmn_parser p;
103   jsmntok_t tok[5];
104   const char *js = "{\"x\": \"va\\\\ue\", \"y\": \"value y\"}";
105 
106   jsmn_init(&p);
107   for (i = 1; i <= strlen(js); i++) {
108     r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0]));
109     if (i == strlen(js)) {
110       check(r == 5);
111       check(tokeq(js, tok, 5, JSMN_OBJECT, -1, -1, 2, JSMN_STRING, "x", 1,
112                   JSMN_STRING, "va\\\\ue", 0, JSMN_STRING, "y", 1, JSMN_STRING,
113                   "value y", 0));
114     } else {
115       check(r == JSMN_ERROR_PART);
116     }
117   }
118   return 0;
119 }
120 
test_partial_array(void)121 int test_partial_array(void) {
122 #ifdef JSMN_STRICT
123   int r;
124   unsigned long i;
125   jsmn_parser p;
126   jsmntok_t tok[10];
127   const char *js = "[ 1, true, [123, \"hello\"]]";
128 
129   jsmn_init(&p);
130   for (i = 1; i <= strlen(js); i++) {
131     r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0]));
132     if (i == strlen(js)) {
133       check(r == 6);
134       check(tokeq(js, tok, 6, JSMN_ARRAY, -1, -1, 3, JSMN_PRIMITIVE, "1",
135                   JSMN_PRIMITIVE, "true", JSMN_ARRAY, -1, -1, 2, JSMN_PRIMITIVE,
136                   "123", JSMN_STRING, "hello", 0));
137     } else {
138       check(r == JSMN_ERROR_PART);
139     }
140   }
141 #endif
142   return 0;
143 }
144 
test_array_nomem(void)145 int test_array_nomem(void) {
146   int i;
147   int r;
148   jsmn_parser p;
149   jsmntok_t toksmall[10], toklarge[10];
150   const char *js;
151 
152   js = "  [ 1, true, [123, \"hello\"]]";
153 
154   for (i = 0; i < 6; i++) {
155     jsmn_init(&p);
156     memset(toksmall, 0, sizeof(toksmall));
157     memset(toklarge, 0, sizeof(toklarge));
158     r = jsmn_parse(&p, js, strlen(js), toksmall, i);
159     check(r == JSMN_ERROR_NOMEM);
160 
161     memcpy(toklarge, toksmall, sizeof(toksmall));
162 
163     r = jsmn_parse(&p, js, strlen(js), toklarge, 10);
164     check(r >= 0);
165     check(tokeq(js, toklarge, 4, JSMN_ARRAY, -1, -1, 3, JSMN_PRIMITIVE, "1",
166                 JSMN_PRIMITIVE, "true", JSMN_ARRAY, -1, -1, 2, JSMN_PRIMITIVE,
167                 "123", JSMN_STRING, "hello", 0));
168   }
169   return 0;
170 }
171 
test_unquoted_keys(void)172 int test_unquoted_keys(void) {
173 #ifndef JSMN_STRICT
174   int r;
175   jsmn_parser p;
176   jsmntok_t tok[10];
177   const char *js;
178 
179   jsmn_init(&p);
180   js = "key1: \"value\"\nkey2 : 123";
181 
182   r = jsmn_parse(&p, js, strlen(js), tok, 10);
183   check(r >= 0);
184   check(tokeq(js, tok, 4, JSMN_PRIMITIVE, "key1", JSMN_STRING, "value", 0,
185               JSMN_PRIMITIVE, "key2", JSMN_PRIMITIVE, "123"));
186 #endif
187   return 0;
188 }
189 
test_issue_22(void)190 int test_issue_22(void) {
191   int r;
192   jsmn_parser p;
193   jsmntok_t tokens[128];
194   const char *js;
195 
196   js =
197       "{ \"height\":10, \"layers\":[ { \"data\":[6,6], \"height\":10, "
198       "\"name\":\"Calque de Tile 1\", \"opacity\":1, \"type\":\"tilelayer\", "
199       "\"visible\":true, \"width\":10, \"x\":0, \"y\":0 }], "
200       "\"orientation\":\"orthogonal\", \"properties\": { }, \"tileheight\":32, "
201       "\"tilesets\":[ { \"firstgid\":1, \"image\":\"..\\/images\\/tiles.png\", "
202       "\"imageheight\":64, \"imagewidth\":160, \"margin\":0, "
203       "\"name\":\"Tiles\", "
204       "\"properties\":{}, \"spacing\":0, \"tileheight\":32, \"tilewidth\":32 "
205       "}], "
206       "\"tilewidth\":32, \"version\":1, \"width\":10 }";
207   jsmn_init(&p);
208   r = jsmn_parse(&p, js, strlen(js), tokens, 128);
209   check(r >= 0);
210   return 0;
211 }
212 
test_issue_27(void)213 int test_issue_27(void) {
214   const char *js =
215       "{ \"name\" : \"Jack\", \"age\" : 27 } { \"name\" : \"Anna\", ";
216   check(parse(js, JSMN_ERROR_PART, 8));
217   return 0;
218 }
219 
test_input_length(void)220 int test_input_length(void) {
221   const char *js;
222   int r;
223   jsmn_parser p;
224   jsmntok_t tokens[10];
225 
226   js = "{\"a\": 0}garbage";
227 
228   jsmn_init(&p);
229   r = jsmn_parse(&p, js, 8, tokens, 10);
230   check(r == 3);
231   check(tokeq(js, tokens, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING, "a", 1,
232               JSMN_PRIMITIVE, "0"));
233   return 0;
234 }
235 
test_count(void)236 int test_count(void) {
237   jsmn_parser p;
238   const char *js;
239 
240   js = "{}";
241   jsmn_init(&p);
242   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1);
243 
244   js = "[]";
245   jsmn_init(&p);
246   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 1);
247 
248   js = "[[]]";
249   jsmn_init(&p);
250   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 2);
251 
252   js = "[[], []]";
253   jsmn_init(&p);
254   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3);
255 
256   js = "[[], []]";
257   jsmn_init(&p);
258   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 3);
259 
260   js = "[[], [[]], [[], []]]";
261   jsmn_init(&p);
262   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7);
263 
264   js = "[\"a\", [[], []]]";
265   jsmn_init(&p);
266   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5);
267 
268   js = "[[], \"[], [[]]\", [[]]]";
269   jsmn_init(&p);
270   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 5);
271 
272   js = "[1, 2, 3]";
273   jsmn_init(&p);
274   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 4);
275 
276   js = "[1, 2, [3, \"a\"], null]";
277   jsmn_init(&p);
278   check(jsmn_parse(&p, js, strlen(js), NULL, 0) == 7);
279 
280   return 0;
281 }
282 
test_nonstrict(void)283 int test_nonstrict(void) {
284 #ifndef JSMN_STRICT
285   const char *js;
286   js = "a: 0garbage";
287   check(parse(js, 2, 2, JSMN_PRIMITIVE, "a", JSMN_PRIMITIVE, "0garbage"));
288 
289   js = "Day : 26\nMonth : Sep\n\nYear: 12";
290   check(parse(js, 6, 6, JSMN_PRIMITIVE, "Day", JSMN_PRIMITIVE, "26",
291               JSMN_PRIMITIVE, "Month", JSMN_PRIMITIVE, "Sep", JSMN_PRIMITIVE,
292               "Year", JSMN_PRIMITIVE, "12"));
293 
294   /* nested {s don't cause a parse error. */
295   js = "\"key {1\": 1234";
296   check(parse(js, 2, 2, JSMN_STRING, "key {1", 1, JSMN_PRIMITIVE, "1234"));
297 
298 #endif
299   return 0;
300 }
301 
test_unmatched_brackets(void)302 int test_unmatched_brackets(void) {
303   const char *js;
304   js = "\"key 1\": 1234}";
305   check(parse(js, JSMN_ERROR_INVAL, 2));
306   js = "{\"key 1\": 1234";
307   check(parse(js, JSMN_ERROR_PART, 3));
308   js = "{\"key 1\": 1234}}";
309   check(parse(js, JSMN_ERROR_INVAL, 3));
310   js = "\"key 1\"}: 1234";
311   check(parse(js, JSMN_ERROR_INVAL, 3));
312   js = "{\"key {1\": 1234}";
313   check(parse(js, 3, 3, JSMN_OBJECT, 0, 16, 1, JSMN_STRING, "key {1", 1,
314               JSMN_PRIMITIVE, "1234"));
315   js = "{\"key 1\":{\"key 2\": 1234}";
316   check(parse(js, JSMN_ERROR_PART, 5));
317   return 0;
318 }
319 
test_object_key(void)320 int test_object_key(void) {
321   const char *js;
322 
323   js = "{\"key\": 1}";
324   check(parse(js, 3, 3, JSMN_OBJECT, 0, 10, 1, JSMN_STRING, "key", 1,
325               JSMN_PRIMITIVE, "1"));
326 #ifdef JSMN_STRICT
327   js = "{true: 1}";
328   check(parse(js, JSMN_ERROR_INVAL, 3));
329   js = "{1: 1}";
330   check(parse(js, JSMN_ERROR_INVAL, 3));
331   js = "{{\"key\": 1}: 2}";
332   check(parse(js, JSMN_ERROR_INVAL, 5));
333   js = "{[1,2]: 2}";
334   check(parse(js, JSMN_ERROR_INVAL, 5));
335 #endif
336   return 0;
337 }
338 
main(void)339 int main(void) {
340   test(test_empty, "test for a empty JSON objects/arrays");
341   test(test_object, "test for a JSON objects");
342   test(test_array, "test for a JSON arrays");
343   test(test_primitive, "test primitive JSON data types");
344   test(test_string, "test string JSON data types");
345 
346   test(test_partial_string, "test partial JSON string parsing");
347   test(test_partial_array, "test partial array reading");
348   test(test_array_nomem, "test array reading with a smaller number of tokens");
349   test(test_unquoted_keys, "test unquoted keys (like in JavaScript)");
350   test(test_input_length, "test strings that are not null-terminated");
351   test(test_issue_22, "test issue #22");
352   test(test_issue_27, "test issue #27");
353   test(test_count, "test tokens count estimation");
354   test(test_nonstrict, "test for non-strict mode");
355   test(test_unmatched_brackets, "test for unmatched brackets");
356   test(test_object_key, "test for key type");
357   printf("\nPASSED: %d\nFAILED: %d\n", test_passed, test_failed);
358   return (test_failed > 0);
359 }
360