24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
|
29 #include "util_allocator.h" |
29 #include "cx/test.h" |
30 #include "cx/test.h" |
30 |
31 |
31 #include "cx/json.h" |
32 #include "cx/json.h" |
32 #include "cx/mempool.h" |
33 #include "cx/mempool.h" |
33 |
34 |
34 CX_TEST(test_json_init_default) { |
35 CX_TEST(test_json_init_default) { |
35 CxJson json; |
36 CxJson json; |
36 CX_TEST_DO { |
37 CX_TEST_DO { |
37 cxJsonInit(NULL, &json); |
38 cxJsonInit(&json, NULL); |
38 CX_TEST_ASSERT(json.states == json.states_internal); |
39 CX_TEST_ASSERT(json.states == json.states_internal); |
39 CX_TEST_ASSERT(json.nstates == 0); |
40 CX_TEST_ASSERT(json.states_size == 1); |
40 CX_TEST_ASSERT(json.states_alloc == 8); |
41 CX_TEST_ASSERT(json.states_capacity >= 8); |
41 CX_TEST_ASSERT(json.reader_array_alloc == 8); |
42 CX_TEST_ASSERT(json.vbuf == json.vbuf_internal); |
|
43 CX_TEST_ASSERT(json.vbuf_size == 0); |
|
44 CX_TEST_ASSERT(json.vbuf_capacity >= 8); |
42 } |
45 } |
43 } |
46 } |
44 |
47 |
45 CX_TEST(test_json_simple_object) { |
48 CX_TEST(test_json_simple_object) { |
46 cxstring text = cx_str( |
49 cxstring text = cx_str( |
189 int result; |
192 int result; |
190 CxJson json; |
193 CxJson json; |
191 CxJsonValue *obj = NULL; |
194 CxJsonValue *obj = NULL; |
192 |
195 |
193 for(int i=0;i<5;i++) { |
196 for(int i=0;i<5;i++) { |
194 cxJsonInit(NULL, &json); |
197 cxJsonInit(&json, NULL); |
195 cxJsonFill(&json, tests[i]); |
198 cxJsonFill(&json, tests[i]); |
196 result = cxJsonNext(&json, &obj); |
199 result = cxJsonNext(&json, &obj); |
197 |
200 |
198 CX_TEST_ASSERT(result == -1); |
201 CX_TEST_ASSERT(result == -1); |
199 CX_TEST_ASSERT(obj == NULL); |
202 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
200 cxJsonDestroy(&json); |
203 cxJsonDestroy(&json); |
201 } |
204 } |
202 } |
205 } |
203 } |
206 } |
204 |
207 |
205 CX_TEST(test_json_large_nesting_depth) { |
208 CX_TEST(test_json_large_nesting_depth) { |
206 CxJson json; |
209 CxJson json; |
207 CxJsonValue *d1; |
210 CxJsonValue *d1; |
208 cxstring text = cx_str("{\"test\": [{},{\"foo\": [[{\"bar\":[4, 2, [null, {\"key\": 47}]]}]]}]}"); |
211 cxstring text = cx_str("{\"test\": [{},{\"foo\": [[{\"bar\":[4, 2, [null, {\"key\": 47}]]}]]}]}"); |
209 CX_TEST_DO { |
212 CX_TEST_DO { |
210 cxJsonInit(NULL, &json); |
213 cxJsonInit(&json, NULL); |
211 cxJsonFill(&json, text); |
214 cxJsonFill(&json, text); |
212 cxJsonNext(&json, &d1); |
215 cxJsonNext(&json, &d1); |
213 |
216 |
214 CX_TEST_ASSERT(d1 != NULL); |
217 CX_TEST_ASSERT(d1 != NULL); |
215 CX_TEST_ASSERT(cxJsonIsObject(d1)); |
218 CX_TEST_ASSERT(cxJsonIsObject(d1)); |
239 CxJsonValue *d10 = cxJsonObjGet(d9b, "key"); |
242 CxJsonValue *d10 = cxJsonObjGet(d9b, "key"); |
240 CX_TEST_ASSERT(cxJsonIsInteger(d10)); |
243 CX_TEST_ASSERT(cxJsonIsInteger(d10)); |
241 CX_TEST_ASSERT(cxJsonAsInteger(d10) == 47); |
244 CX_TEST_ASSERT(cxJsonAsInteger(d10) == 47); |
242 |
245 |
243 CX_TEST_ASSERT(json.states != json.states_internal); |
246 CX_TEST_ASSERT(json.states != json.states_internal); |
244 CX_TEST_ASSERT(json.states_alloc > cx_nmemb(json.states_internal)); |
247 CX_TEST_ASSERT(json.states_capacity > cx_nmemb(json.states_internal)); |
245 |
248 |
246 cxJsonValueFree(d1); |
249 cxJsonValueFree(d1); |
247 cxJsonDestroy(&json); |
250 cxJsonDestroy(&json); |
248 } |
251 } |
249 } |
252 } |
250 |
253 |
251 CX_TEST(test_json_number) { |
254 CX_TEST(test_json_number) { |
252 CxJson json; |
255 CxJson json; |
253 cxJsonInit(NULL, &json); |
256 cxJsonInit(&json, NULL); |
254 CX_TEST_DO { |
257 CX_TEST_DO { |
255 // TODO: find a better way to terminate values that are not arrays/objects |
258 // TODO: find a better way to terminate values that are not arrays/objects |
256 CxJsonValue *v; |
259 CxJsonValue *v; |
257 int result; |
260 int result; |
258 cxJsonFill(&json, "3.1415 "); |
261 cxJsonFill(&json, "3.1415 "); |
332 } |
335 } |
333 cxJsonDestroy(&json); |
336 cxJsonDestroy(&json); |
334 } |
337 } |
335 |
338 |
336 CX_TEST(test_json_allocator) { |
339 CX_TEST(test_json_allocator) { |
337 CxMempool *mp = cxMempoolCreate(64, NULL); |
340 CxTestingAllocator talloc; |
338 CxJson json; |
341 cx_testing_allocator_init(&talloc); |
339 cxJsonInit(mp->allocator, &json); |
342 CxAllocator *allocator = &talloc.base; |
340 |
343 |
341 cxstring text = cx_str( |
344 cxstring text = cx_str( |
342 "{\n" |
345 "{\n" |
343 "\t\"message\":\"success\",\n" |
346 "\t\"message\":\"success\",\n" |
344 "\t\"data\":[\"value1\",{\"x\":123, \"y\":523 }]\n" |
347 "\t\"data\":[\"value1\",{\"x\":123, \"y\":523 }]\n" |
345 "}" |
348 "}" |
346 ); |
349 ); |
347 |
350 |
348 CX_TEST_DO { |
351 CX_TEST_DO { |
349 int result; |
|
350 |
|
351 CxJson json; |
352 CxJson json; |
352 cxJsonInit(mp->allocator, &json); |
353 cxJsonInit(&json, allocator); |
353 cxJsonFill(&json, text); |
354 cxJsonFill(&json, text); |
354 |
355 |
355 CxJsonValue *obj; |
356 CxJsonValue *obj; |
356 result = cxJsonNext(&json, &obj); |
357 int result = cxJsonNext(&json, &obj); |
357 CX_TEST_ASSERT(result == 1); |
358 CX_TEST_ASSERT(result == 1); |
358 CX_TEST_ASSERT(obj->allocator == mp->allocator); |
359 CX_TEST_ASSERT(obj->allocator == allocator); |
359 |
360 |
360 // this recursively frees everything |
361 // this recursively frees everything |
361 cxJsonValueFree(obj); |
362 cxJsonValueFree(obj); |
362 cxJsonDestroy(&json); |
363 cxJsonDestroy(&json); |
363 cxMempoolFree(mp); |
364 |
364 } |
365 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
366 } |
|
367 cx_testing_allocator_destroy(&talloc); |
|
368 } |
|
369 |
|
370 CX_TEST(test_json_allocator_parse_error) { |
|
371 CxTestingAllocator talloc; |
|
372 cx_testing_allocator_init(&talloc); |
|
373 CxAllocator *allocator = &talloc.base; |
|
374 |
|
375 cxstring text = cx_str( |
|
376 "{\n" |
|
377 "\t\"message\":\"success\"\n" // <-- missing comma |
|
378 "\t\"data\":[\"value1\",{\"x\":123, \"y\":523 }]\n" |
|
379 "}" |
|
380 ); |
|
381 |
|
382 CX_TEST_DO { |
|
383 CxJson json; |
|
384 cxJsonInit(&json, allocator); |
|
385 cxJsonFill(&json, text); |
|
386 |
|
387 CxJsonValue *obj = NULL; |
|
388 int result = cxJsonNext(&json, &obj); |
|
389 CX_TEST_ASSERT(result == -1); |
|
390 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
|
391 |
|
392 // clean-up any left-over memory |
|
393 cxJsonDestroy(&json); |
|
394 |
|
395 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
396 } |
|
397 cx_testing_allocator_destroy(&talloc); |
365 } |
398 } |
366 |
399 |
367 CxTestSuite *cx_test_suite_json(void) { |
400 CxTestSuite *cx_test_suite_json(void) { |
368 CxTestSuite *suite = cx_test_suite_new("json"); |
401 CxTestSuite *suite = cx_test_suite_new("json"); |
369 |
402 |
373 cx_test_register(suite, test_json_object_error); |
406 cx_test_register(suite, test_json_object_error); |
374 cx_test_register(suite, test_json_large_nesting_depth); |
407 cx_test_register(suite, test_json_large_nesting_depth); |
375 cx_test_register(suite, test_json_number); |
408 cx_test_register(suite, test_json_number); |
376 cx_test_register(suite, test_json_multiple_values); |
409 cx_test_register(suite, test_json_multiple_values); |
377 cx_test_register(suite, test_json_allocator); |
410 cx_test_register(suite, test_json_allocator); |
|
411 cx_test_register(suite, test_json_allocator_parse_error); |
378 |
412 |
379 return suite; |
413 return suite; |
380 } |
414 } |
381 |
415 |