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 10static void test_basic_parse(void); 11static void test_verbose_parse(void); 12static void test_incremental_parse(void); 13 14int 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 26static 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("NaN"); 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("-NaN"); /* non-sensical, returns null */ 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("Inf"); /* must use full string, returns null */ 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("inf"); /* must use full string, returns null */ 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("Infinity"); 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("infinity"); 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("-Infinity"); 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("-infinity"); 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("True"); 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("12"); 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("12.3"); 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("[\"\\n\"]"); 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("[\"\\nabc\\n\"]"); 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("[null]"); 103 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 104 json_object_put(new_obj); 105 106 new_obj = json_tokener_parse("[]"); 107 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 108 json_object_put(new_obj); 109 110 new_obj = json_tokener_parse("[false]"); 111 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 112 json_object_put(new_obj); 113 114 new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]"); 115 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 116 json_object_put(new_obj); 117 118 new_obj = json_tokener_parse("{}"); 119 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 120 json_object_put(new_obj); 121 122 new_obj = json_tokener_parse("{ \"foo\": \"bar\" }"); 123 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 124 json_object_put(new_obj); 125 126 new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }"); 127 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 128 json_object_put(new_obj); 129 130 new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }"); 131 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 132 json_object_put(new_obj); 133 134 new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); 135 printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); 136 json_object_put(new_obj); 137} 138 139static void test_verbose_parse() 140{ 141 json_object *new_obj; 142 enum json_tokener_error error = json_tokener_success; 143 144 new_obj = json_tokener_parse_verbose("{ foo }", &error); 145 assert (error == json_tokener_error_parse_object_key_name); 146 assert (new_obj == NULL); 147 148 new_obj = json_tokener_parse("{ foo }"); 149 assert (new_obj == NULL); 150 151 new_obj = json_tokener_parse("foo"); 152 assert (new_obj == NULL); 153 new_obj = json_tokener_parse_verbose("foo", &error); 154 assert (new_obj == NULL); 155 156 /* b/c the string starts with 'f' parsing return a boolean error */ 157 assert (error == json_tokener_error_parse_boolean); 158 159 printf("json_tokener_parse_versbose() OK\n"); 160} 161 162struct incremental_step { 163 const char *string_to_parse; 164 int length; 165 int char_offset; 166 enum json_tokener_error expected_error; 167 int reset_tokener; 168} incremental_steps[] = { 169 170 /* Check that full json messages can be parsed, both w/ and w/o a reset */ 171 { "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 }, 172 { "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 }, 173 { "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 }, 174 175 /* Check a basic incremental parse */ 176 { "{ \"foo", -1, -1, json_tokener_continue, 0 }, 177 { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, 178 { "\":13}}", -1, -1, json_tokener_success, 1 }, 179 180 /* Check that json_tokener_reset actually resets */ 181 { "{ \"foo", -1, -1, json_tokener_continue, 1 }, 182 { ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 }, 183 184 /* Check incremental parsing with trailing characters */ 185 { "{ \"foo", -1, -1, json_tokener_continue, 0 }, 186 { "\": {\"bar", -1, -1, json_tokener_continue, 0 }, 187 { "\":13}}XXXX", 10, 6, json_tokener_success, 0 }, 188 { "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 }, 189 190 /* Check that trailing characters can change w/o a reset */ 191 { "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 }, 192 { "\"Y\"", -1, -1, json_tokener_success, 1 }, 193 194 /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */ 195 { "1", 1, 1, json_tokener_continue, 0 }, 196 { "2", 2, 1, json_tokener_success, 0 }, 197 198 /* Strings have a well defined end point, so we can stop at the quote */ 199 { "\"blue\"", -1, -1, json_tokener_success, 0 }, 200 201 /* Check each of the escape sequences defined by the spec */ 202 { "\"\\\"\"", -1, -1, json_tokener_success, 0 }, 203 { "\"\\\\\"", -1, -1, json_tokener_success, 0 }, 204 { "\"\\b\"", -1, -1, json_tokener_success, 0 }, 205 { "\"\\f\"", -1, -1, json_tokener_success, 0 }, 206 { "\"\\n\"", -1, -1, json_tokener_success, 0 }, 207 { "\"\\r\"", -1, -1, json_tokener_success, 0 }, 208 { "\"\\t\"", -1, -1, json_tokener_success, 0 }, 209 210 { "[1,2,3]", -1, -1, json_tokener_success, 0 }, 211 212 /* This behaviour doesn't entirely follow the json spec, but until we have 213 a way to specify how strict to be we follow Postel's Law and be liberal 214 in what we accept (up to a point). */ 215 { "[1,2,3,]", -1, -1, json_tokener_success, 0 }, 216 { "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 }, 217 218 { "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 }, 219 { "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 }, 220 221 { NULL, -1, -1, json_tokener_success, 0 }, 222}; 223 224static void test_incremental_parse() 225{ 226 json_object *new_obj; 227 enum json_tokener_error jerr; 228 json_tokener *tok; 229 const char *string_to_parse; 230 int ii; 231 int num_ok, num_error; 232 233 num_ok = 0; 234 num_error = 0; 235 236 printf("Starting incremental tests.\n"); 237 printf("Note: quotes and backslashes seen in the output here are literal values passed\n"); 238 printf(" to the parse functions. e.g. this is 4 characters: \"\\f\"\n"); 239 240 string_to_parse = "{ \"foo"; /* } */ 241 printf("json_tokener_parse(%s) ... ", string_to_parse); 242 new_obj = json_tokener_parse(string_to_parse); 243 if (new_obj == NULL) printf("got error as expected\n"); 244 245 /* test incremental parsing in various forms */ 246 tok = json_tokener_new(); 247 for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++) 248 { 249 int this_step_ok = 0; 250 struct incremental_step *step = &incremental_steps[ii]; 251 int length = step->length; 252 int expected_char_offset = step->char_offset; 253 254 if (step->reset_tokener & 2) 255 json_tokener_set_flags(tok, JSON_TOKENER_STRICT); 256 else 257 json_tokener_set_flags(tok, 0); 258 259 if (length == -1) 260 length = strlen(step->string_to_parse); 261 if (expected_char_offset == -1) 262 expected_char_offset = length; 263 264 printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", 265 step->string_to_parse, length); 266 new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); 267 268 jerr = json_tokener_get_error(tok); 269 if (step->expected_error != json_tokener_success) 270 { 271 if (new_obj != NULL) 272 printf("ERROR: invalid object returned: %s\n", 273 json_object_to_json_string(new_obj)); 274 else if (jerr != step->expected_error) 275 printf("ERROR: got wrong error: %s\n", 276 json_tokener_error_desc(jerr)); 277 else if (tok->char_offset != expected_char_offset) 278 printf("ERROR: wrong char_offset %d != expected %d\n", 279 tok->char_offset, 280 expected_char_offset); 281 else 282 { 283 printf("OK: got correct error: %s\n", json_tokener_error_desc(jerr)); 284 this_step_ok = 1; 285 } 286 } 287 else 288 { 289 if (new_obj == NULL) 290 printf("ERROR: expected valid object, instead: %s\n", 291 json_tokener_error_desc(jerr)); 292 else if (tok->char_offset != expected_char_offset) 293 printf("ERROR: wrong char_offset %d != expected %d\n", 294 tok->char_offset, 295 expected_char_offset); 296 else 297 { 298 printf("OK: got object of type [%s]: %s\n", 299 json_type_to_name(json_object_get_type(new_obj)), 300 json_object_to_json_string(new_obj)); 301 this_step_ok = 1; 302 } 303 } 304 305 if (new_obj) 306 json_object_put(new_obj); 307 308 if (step->reset_tokener & 1) 309 json_tokener_reset(tok); 310 311 if (this_step_ok) 312 num_ok++; 313 else 314 num_error++; 315 } 316 317 json_tokener_free(tok); 318 319 printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error); 320 321 return; 322} 323