1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 static int test_passed = 0;
6 static int test_failed = 0;
7
8 /* Terminate current test with error */
9 #define fail() return __LINE__
10
11 /* Successfull end of the test case */
12 #define done() return 0
13
14 /* Check single condition */
15 #define check(cond) \
16 do { \
17 if (!(cond)) fail(); \
18 } while (0)
19
20 /* Test runner */
test(int (* func)(void),const char * name)21 static void test(int (*func)(void), const char *name) {
22 int r = func();
23 if (r == 0) {
24 test_passed++;
25 } else {
26 test_failed++;
27 printf("FAILED: %s (at line %d)\n", name, r);
28 }
29 }
30
31 #include "json.cpp"
32
33 using namespace std;
34 using namespace JSON;
35
TOKEN_STRING(const Token & t,const char * s)36 static bool TOKEN_STRING(const Token &t, const char *s) {
37 return !t.value().compare(string(s));
38 }
39
isObject(const Token & t,int children)40 static bool isObject(const Token &t, int children) {
41 return t.isObject() && t.children() == children;
42 }
43
isArray(const Token & t,int children)44 static bool isArray(const Token &t, int children) {
45 return t.isArray() && t.children() == children;
46 }
47
isKey(const Token & t,const char * v)48 static bool isKey(const Token &t, const char *v) {
49 return t.isString() && t.children() == 1 && t.value() == v;
50 }
51
isPrimitive(const Token & t,const char * v)52 static bool isPrimitive(const Token &t, const char *v) {
53 return t.isPrimitive() && t.children() == 0 && t.value() == v;
54 }
55
test_empty()56 int test_empty() {
57 const char *js;
58 int r;
59 Parser p;
60
61 js = "{}";
62 r = p.parse(string(js));
63 check(r == 1);
64 check(isObject(p[0], 0));
65
66 js = "[]";
67 r = p.parse(string(js));
68 check(r == 1);
69 check(isArray(p[0], 0));
70
71 js = "{\"a\":[]}";
72 r = p.parse(string(js));
73 check(r == 3);
74 check(isObject(p[0], 1));
75 check(isKey(p[1], "a"));
76 check(isArray(p[2], 0));
77
78 js = "[{},{}]";
79 r = p.parse(string(js));
80 check(r >= 0);
81 check(isArray(p[0], 2));
82 check(isObject(p[1], 0));
83 check(isObject(p[2], 0));
84 return 0;
85 }
86
test_simple()87 int test_simple() {
88 const char *js;
89 int r;
90 Parser p;
91
92 js = "{\"a\": 0}";
93
94 r = p.parse(string(js));
95 check(r == 3);
96 check(isObject(p[0], 1));
97 check(isKey(p[1], "a"));
98 check(isPrimitive(p[2], "0"));
99
100 js = "[\"a\":{},\"b\":{}]";
101 r = p.parse(string(js));
102 check(r == 5);
103 check(isArray(p[0], 2));
104 check(isKey(p[1], "a"));
105 check(isObject(p[2], 0));
106 check(isKey(p[3], "b"));
107 check(isObject(p[4], 0));
108
109 js = "{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }";
110 r = p.parse(string(js));
111 check(r == 7);
112
113 return 0;
114 }
115
test_primitive()116 int test_primitive() {
117 int r;
118 Parser p;
119 const char *js;
120 js = "{\"boolVar\" : true}";
121 r = p.parse(string(js));
122 check(r == 3);
123 check(p[0].isObject() && p[1].isString() && p[2].isPrimitive());
124 check(TOKEN_STRING(p[1], "boolVar"));
125 check(TOKEN_STRING(p[2], "true"));
126
127 js = "{\"boolVar\" : false}";
128 r = p.parse(string(js));
129 check(r == 3);
130 check(p[0].isObject() && p[1].isString() && p[2].isPrimitive());
131 check(TOKEN_STRING(p[1], "boolVar"));
132 check(TOKEN_STRING(p[2], "false"));
133
134 js = "{\"intVar\" : 12345}";
135 r = p.parse(string(js));
136 check(r == 3);
137 check(p[0].isObject() && p[1].isString() && p[2].isPrimitive());
138 check(TOKEN_STRING(p[1], "intVar"));
139 check(TOKEN_STRING(p[2], "12345"));
140
141 js = "{\"floatVar\" : 12.345}";
142 r = p.parse(string(js));
143 check(r == 3);
144 check(p[0].isObject() && p[1].isString() && p[2].isPrimitive());
145 check(TOKEN_STRING(p[1], "floatVar"));
146 check(TOKEN_STRING(p[2], "12.345"));
147
148 js = "{\"nullVar\" : null}";
149 r = p.parse(string(js));
150 check(r == 3);
151 check(p[0].isObject() && p[1].isString() && p[2].isPrimitive());
152 check(TOKEN_STRING(p[1], "nullVar"));
153 check(TOKEN_STRING(p[2], "null"));
154
155 return 0;
156 }
157
test_string()158 int test_string() {
159 int r;
160 Parser p;
161 const char *js;
162
163 js = "\"strVar\" : \"hello world\"";
164 r = p.parse(string(js));
165 check(r >= 0 && p[0].isString() && p[1].isString());
166 check(TOKEN_STRING(p[0], "strVar"));
167 check(TOKEN_STRING(p[1], "hello world"));
168
169 js = "\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"";
170 r = p.parse(string(js));
171 check(r >= 0 && p[0].isString() && p[1].isString());
172 check(TOKEN_STRING(p[0], "strVar"));
173 check(TOKEN_STRING(p[1], "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\"));
174
175 js = "\"strVar\" : \"\"";
176 r = p.parse(string(js));
177 check(r >= 0 && p[0].isString() && p[1].isString());
178 check(TOKEN_STRING(p[0], "strVar"));
179 check(TOKEN_STRING(p[1], ""));
180
181 return 0;
182 }
183
test_partial_string()184 int test_partial_string() {
185 int r;
186 Parser p;
187 const char *js;
188
189 js = "\"x\": \"va";
190 r = p.parse(string(js));
191 check(r == ERROR_PART && p[0].isString());
192 check(TOKEN_STRING(p[0], "x"));
193 check(p.size() == 1);
194
195 char js_slash[] = "\"x\": \"va\\";
196 r = p.parse(string(js_slash)); // intentionally not sizeof(js_slash)
197 check(r == ERROR_PART);
198
199 char js_unicode[] = "\"x\": \"va\\u";
200 r = p.parse(string(js_unicode)); // intentionally not sizeof(js_unicode)
201 check(r == ERROR_PART);
202
203 js = "\"x\": \"valu";
204 r = p.parse(string(js));
205 check(r == ERROR_PART && p[0].isString());
206 check(TOKEN_STRING(p[0], "x"));
207 check(p.size() == 1);
208
209 js = "\"x\": \"value\"";
210 r = p.parse(string(js));
211 check(r >= 0 && p[0].isString() && p[1].isString());
212 check(TOKEN_STRING(p[0], "x"));
213 check(TOKEN_STRING(p[1], "value"));
214
215 js = "{\"x\": \"value\", \"y\": \"value y\"}";
216 r = p.parse(string(js));
217 check(r >= 0 && p[0].isObject() && p[1].isString() && p[2].isString() &&
218 p[3].isString() && p[4].isString());
219 check(TOKEN_STRING(p[1], "x"));
220 check(TOKEN_STRING(p[2], "value"));
221 check(TOKEN_STRING(p[3], "y"));
222 check(TOKEN_STRING(p[4], "value y"));
223
224 return 0;
225 }
226
test_partial_array()227 int test_partial_array() {
228 int r;
229 Parser p;
230 const char *js;
231
232 js = " [ 1, true, ";
233 r = p.parse(string(js));
234 check(r == ERROR_PART && p[0].isArray() && p[1].isPrimitive() &&
235 p[2].isPrimitive());
236
237 js = " [ 1, true, [123, \"hello";
238 r = p.parse(string(js));
239 check(r == ERROR_PART && p[0].isArray() && p[1].isPrimitive() &&
240 p[2].isPrimitive() && p[3].isArray() && p[4].isPrimitive());
241
242 js = " [ 1, true, [123, \"hello\"]";
243 r = p.parse(string(js));
244 check(r == ERROR_PART && p[0].isArray() && p[1].isPrimitive() &&
245 p[2].isPrimitive() && p[3].isArray() && p[4].isPrimitive() &&
246 p[5].isString());
247 /* check child nodes of the 2nd array */
248 check(p[3].children() == 2);
249
250 js = " [ 1, true, [123, \"hello\"]]";
251 r = p.parse(string(js));
252 check(r >= 0 && p[0].isArray() && p[1].isPrimitive() && p[2].isPrimitive() &&
253 p[3].isArray() && p[4].isPrimitive() && p[5].isString());
254 check(p[3].children() == 2);
255 check(p[0].children() == 3);
256 return 0;
257 }
258
test_objects_arrays()259 int test_objects_arrays() {
260 int r;
261 Parser p;
262 const char *js;
263
264 js = "[10}";
265 r = p.parse(string(js));
266 check(r == ERROR_INVAL);
267
268 js = "[10]";
269 r = p.parse(string(js));
270 check(r >= 0);
271
272 js = "{\"a\": 1]";
273 r = p.parse(string(js));
274 check(r == ERROR_INVAL);
275
276 js = "{\"a\": 1}";
277 r = p.parse(string(js));
278 check(r >= 0);
279
280 return 0;
281 }
282
test_issue_22()283 int test_issue_22() {
284 int r;
285 Parser p;
286 const char *js;
287
288 js =
289 "{ \"height\":10, \"layers\":[ { \"data\":[6,6], \"height\":10, "
290 "\"name\":\"Calque de Tile 1\", \"opacity\":1, \"type\":\"tilelayer\", "
291 "\"visible\":true, \"width\":10, \"x\":0, \"y\":0 }], "
292 "\"orientation\":\"orthogonal\", \"properties\": { }, \"tileheight\":32, "
293 "\"tilesets\":[ { \"firstgid\":1, \"image\":\"..\\/images\\/tiles.png\", "
294 "\"imageheight\":64, \"imagewidth\":160, \"margin\":0, "
295 "\"name\":\"Tiles\", "
296 "\"properties\":{}, \"spacing\":0, \"tileheight\":32, \"tilewidth\":32 "
297 "}], "
298 "\"tilewidth\":32, \"version\":1, \"width\":10 }";
299 r = p.parse(string(js));
300 check(r >= 0);
301 return 0;
302 }
303
test_unicode_characters()304 int test_unicode_characters() {
305 Parser p;
306 const char *js;
307
308 int r;
309 js = "{\"a\":\"\\uAbcD\"}";
310 r = p.parse(string(js));
311 check(r >= 0);
312
313 js = "{\"a\":\"str\\u0000\"}";
314 r = p.parse(string(js));
315 check(r >= 0);
316
317 js = "{\"a\":\"\\uFFFFstr\"}";
318 r = p.parse(string(js));
319 check(r >= 0);
320
321 js = "{\"a\":\"str\\uFFGFstr\"}";
322 r = p.parse(string(js));
323 check(r == ERROR_INVAL);
324
325 js = "{\"a\":\"str\\u@FfF\"}";
326 r = p.parse(string(js));
327 check(r == ERROR_INVAL);
328
329 js = "{\"a\":[\"\\u028\"]}";
330 r = p.parse(string(js));
331 check(r == ERROR_INVAL);
332
333 js = "{\"a\":[\"\\u0280\"]}";
334 r = p.parse(string(js));
335 check(r >= 0);
336
337 return 0;
338 }
339
test_count()340 int test_count() {
341 Parser p;
342 const char *js;
343
344 js = "{}";
345 check(p.parse(string(js)) == 1);
346
347 js = "[]";
348 check(p.parse(string(js)) == 1);
349
350 js = "[[]]";
351 check(p.parse(string(js)) == 2);
352
353 js = "[[], []]";
354 check(p.parse(string(js)) == 3);
355
356 js = "[[], []]";
357 check(p.parse(string(js)) == 3);
358
359 js = "[[], [[]], [[], []]]";
360 check(p.parse(string(js)) == 7);
361
362 js = "[\"a\", [[], []]]";
363 check(p.parse(string(js)) == 5);
364
365 js = "[[], \"[], [[]]\", [[]]]";
366 check(p.parse(string(js)) == 5);
367
368 js = "[1, 2, 3]";
369 check(p.parse(string(js)) == 4);
370
371 js = "[1, 2, [3, \"a\"], null]";
372 check(p.parse(string(js)) == 7);
373
374 return 0;
375 }
376
test_keyvalue()377 int test_keyvalue() {
378 const char *js;
379 int r;
380 Parser p;
381 vector<Token> tokens;
382
383 js = "{\"a\": 0, \"b\": \"c\"}";
384
385 r = p.parse(string(js));
386 check(r == 5);
387 check(p[0].children() == 2); /* two keys */
388 check(p[1].children() == 1 && p[3].children() == 1); /* one value per key */
389 check(p[2].children() == 0 &&
390 p[4].children() == 0); /* values have zero size */
391
392 js = "{\"a\"\n0}";
393 r = p.parse(string(js));
394 check(r == ERROR_INVAL);
395
396 js = "{\"a\", 0}";
397 r = p.parse(string(js));
398 check(r == ERROR_INVAL);
399
400 js = "{\"a\": {2}}";
401 r = p.parse(string(js));
402 check(r == ERROR_INVAL);
403
404 js = "{\"a\": {2: 3}}";
405 r = p.parse(string(js));
406 check(r == ERROR_INVAL);
407
408 js = "{\"a\": {\"a\": 2 3}}";
409 r = p.parse(string(js));
410 check(r == ERROR_INVAL);
411 return 0;
412 }
413
main()414 int main() {
415 test(test_empty, "general test for a empty JSON objects/arrays");
416 test(test_simple, "general test for a simple JSON string");
417 test(test_primitive, "test primitive JSON data types");
418 test(test_string, "test string JSON data types");
419 test(test_partial_string, "test partial JSON string parsing");
420 test(test_partial_array, "test partial array reading");
421 test(test_objects_arrays, "test objects and arrays");
422 test(test_unicode_characters, "test unicode characters");
423 test(test_issue_22, "test issue #22");
424 test(test_count, "test tokens count estimation");
425 test(test_keyvalue, "test for keys/values");
426 printf("PASSED: %d\nFAILED: %d\n", test_passed, test_failed);
427 return 0;
428 }
429