Imported Upstream version 0.10
[platform/upstream/json-c.git] / tests / test_parse.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stddef.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #include "json.h"
8 #include "json_tokener.h"
9
10 static void test_basic_parse(void);
11 static void test_verbose_parse(void);
12 static void test_incremental_parse(void);
13
14 int main(int argc, char **argv)
15 {
16         MC_SET_DEBUG(1);
17
18         test_basic_parse();
19         printf("==================================\n");
20         test_verbose_parse();
21         printf("==================================\n");
22         test_incremental_parse();
23         printf("==================================\n");
24 }
25
26 static void test_basic_parse()
27 {
28   json_object *new_obj;
29
30   new_obj = json_tokener_parse("\"\003\"");
31   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
32   json_object_put(new_obj);
33
34   new_obj = json_tokener_parse("/* hello */\"foo\"");
35   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
36   json_object_put(new_obj);
37
38   new_obj = json_tokener_parse("// hello\n\"foo\"");
39   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
40   json_object_put(new_obj);
41
42   new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\"");
43   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
44   json_object_put(new_obj);
45
46   new_obj = json_tokener_parse("null");
47   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
48   json_object_put(new_obj);
49
50   new_obj = json_tokener_parse("True");
51   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
52   json_object_put(new_obj);
53
54   new_obj = json_tokener_parse("12");
55   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
56   json_object_put(new_obj);
57
58   new_obj = json_tokener_parse("12.3");
59   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
60   json_object_put(new_obj);
61
62   new_obj = json_tokener_parse("[\"\\n\"]");
63   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
64   json_object_put(new_obj);
65
66   new_obj = json_tokener_parse("[\"\\nabc\\n\"]");
67   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
68   json_object_put(new_obj);
69
70   new_obj = json_tokener_parse("[null]");
71   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
72   json_object_put(new_obj);
73
74   new_obj = json_tokener_parse("[]");
75   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
76   json_object_put(new_obj);
77
78   new_obj = json_tokener_parse("[false]");
79   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
80   json_object_put(new_obj);
81
82   new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]");
83   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
84   json_object_put(new_obj);
85
86   new_obj = json_tokener_parse("{}");
87   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
88   json_object_put(new_obj);
89
90   new_obj = json_tokener_parse("{ \"foo\": \"bar\" }");
91   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
92   json_object_put(new_obj);
93
94   new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }");
95   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
96   json_object_put(new_obj);
97
98   new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }");
99   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
100   json_object_put(new_obj);
101
102   new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }");
103   printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
104   json_object_put(new_obj);
105 }
106
107 static void test_verbose_parse()
108 {
109         json_object *new_obj;
110         enum json_tokener_error error = json_tokener_success;
111
112         new_obj = json_tokener_parse_verbose("{ foo }", &error);
113         assert (error == json_tokener_error_parse_object_key_name);
114         assert (new_obj == NULL);
115
116         new_obj = json_tokener_parse("{ foo }");
117         assert (new_obj == NULL);
118
119         new_obj = json_tokener_parse("foo");
120         assert (new_obj == NULL);
121         new_obj = json_tokener_parse_verbose("foo", &error);
122         assert (new_obj == NULL);
123
124         /* b/c the string starts with 'f' parsing return a boolean error */
125         assert (error == json_tokener_error_parse_boolean);
126
127         printf("json_tokener_parse_versbose() OK\n");
128 }
129
130 struct incremental_step {
131         const char *string_to_parse;
132         int length;
133         int char_offset;
134         enum json_tokener_error expected_error;
135         int reset_tokener;
136 } incremental_steps[] = {
137
138         /* Check that full json messages can be parsed, both w/ and w/o a reset */
139         { "{ \"foo\": 123 }", -1, -1, json_tokener_success,  0 },
140         { "{ \"foo\": 456 }", -1, -1, json_tokener_success,  1 },
141         { "{ \"foo\": 789 }", -1, -1, json_tokener_success,  1 },
142
143         /*  Check a basic incremental parse */
144         { "{ \"foo",          -1, -1, json_tokener_continue, 0 },
145         { "\": {\"bar",       -1, -1, json_tokener_continue, 0 },
146         { "\":13}}",          -1, -1, json_tokener_success,  1 },
147
148         /* Check that json_tokener_reset actually resets */
149         { "{ \"foo",          -1, -1, json_tokener_continue, 1 },
150         { ": \"bar\"}",       -1, 0, json_tokener_error_parse_unexpected, 1 },
151
152         /* Check incremental parsing with trailing characters */
153         { "{ \"foo",          -1, -1, json_tokener_continue, 0 },
154         { "\": {\"bar",       -1, -1, json_tokener_continue, 0 },
155         { "\":13}}XXXX",      10, 6, json_tokener_success,  0 },
156         { "XXXX",              4, 0, json_tokener_error_parse_unexpected, 1 },
157
158         /* Check that trailing characters can change w/o a reset */
159         { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 },
160         { "\"Y\"",            -1, -1, json_tokener_success, 1 },
161
162         /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */
163         { "1",                 1, 1, json_tokener_continue, 0 },
164         { "2",                 2, 1, json_tokener_success, 0 },
165
166         /* Strings have a well defined end point, so we can stop at the quote */
167         { "\"blue\"",         -1, -1, json_tokener_success, 0 },
168
169         { "[1,2,3]",          -1, -1, json_tokener_success, 0 },
170
171         /* This behaviour doesn't entirely follow the json spec, but until we have
172            a way to specify how strict to be we follow Postel's Law and be liberal
173            in what we accept (up to a point). */
174         { "[1,2,3,]",         -1, -1, json_tokener_success, 0 },
175         { "[1,2,,3,]",        -1, 5, json_tokener_error_parse_unexpected, 0 },
176
177         { NULL, json_tokener_success },
178 };
179
180 static void test_incremental_parse()
181 {
182         json_object *new_obj;
183         enum json_tokener_error jerr;
184         json_tokener *tok;
185         const char *string_to_parse;
186         int ii;
187         int num_ok, num_error;
188
189         num_ok = 0;
190         num_error = 0;
191
192         printf("Starting incremental tests.\n");
193
194         string_to_parse = "{ \"foo"; /* } */
195         printf("json_tokener_parse(%s) ... ", string_to_parse);
196         new_obj = json_tokener_parse(string_to_parse);
197         if (new_obj == NULL) printf("got error as expected\n");
198
199         /* test incremental parsing in various forms */
200         tok = json_tokener_new();
201         for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++)
202         {
203                 int this_step_ok = 0;
204                 struct incremental_step *step = &incremental_steps[ii];
205                 int length = step->length;
206                 int expected_char_offset = step->char_offset;
207                 if (length == -1)
208                         length = strlen(step->string_to_parse);
209                 if (expected_char_offset == -1)
210                         expected_char_offset = length;
211
212                 printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ",
213                         step->string_to_parse, length);
214                 new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length);
215
216                 jerr = json_tokener_get_error(tok);
217                 if (step->expected_error != json_tokener_success)
218                 {
219                         if (new_obj != NULL)
220                                 printf("ERROR: invalid object returned: %s\n",
221                                         json_object_to_json_string(new_obj));
222                         else if (jerr != step->expected_error)
223                                 printf("ERROR: got wrong error: %s\n",
224                                         json_tokener_error_desc(jerr));
225                         else if (tok->char_offset != expected_char_offset)
226                                 printf("ERROR: wrong char_offset %d != expected %d\n",
227                                         tok->char_offset,
228                                         expected_char_offset);
229                         else
230                         {
231                                 printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr));
232                                 this_step_ok = 1;
233                         }
234                 }
235                 else
236                 {
237                         if (new_obj == NULL)
238                                 printf("ERROR: expected valid object, instead: %s\n",
239                                         json_tokener_error_desc(jerr));
240                         else if (tok->char_offset != expected_char_offset)
241                                 printf("ERROR: wrong char_offset %d != expected %d\n",
242                                         tok->char_offset,
243                                         expected_char_offset);
244                         else
245                         {
246                                 printf("OK: got object of type [%s]: %s\n",
247                                         json_type_to_name(json_object_get_type(new_obj)),
248                                         json_object_to_json_string(new_obj));
249                                 this_step_ok = 1;
250                         }
251                 }
252
253                 if (new_obj)
254                         json_object_put(new_obj);
255
256                 if (step->reset_tokener)
257                         json_tokener_reset(tok);
258
259                 if (this_step_ok)
260                         num_ok++;
261                 else
262                         num_error++;
263         }
264
265         json_tokener_free(tok);
266
267         printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error);
268
269         return;
270 }