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