#include "rjp_internal.hpp" #include #include #define MIN(x, y) ((x < y) ? (x) : (y)) int read_callback(char* c, int size, const char* data, int datalen, int& datapos){ if(datapos >= datalen) return 0; int min = MIN(size, datalen - datapos); int i; for(i = 0;i < min;++i){ c[i] = data[datapos++]; } return i; } int handle_res(const rjp::value& res){ if(res.valid()){ fprintf(stderr, "Accepted\n"); } return !res.valid(); } int test_cbacks(const char* str, RJP_parse_flag flags){ int pos = 0; rjp::value res = rjp::parse_json(flags, read_callback, str, strlen(str), pos); return handle_res(res); } int test(const char* str, RJP_parse_flag flags){ rjp::value res = rjp::parse_json(str, flags); return handle_res(res); } struct parse_pair{ const char* str; RJP_parse_flag flags; }; struct parse_pair should_pass_strings[] = { {"{}", RJP_PARSE_NONE}, {"[]", RJP_PARSE_NONE}, {"\"s\"", RJP_PARSE_NONE}, {"\"\\n\"", RJP_PARSE_NONE}, {"\"\\\"\"", RJP_PARSE_NONE}, {"\"str\\nstr\"", RJP_PARSE_NONE}, {"\"\\uD83D\\uDE10\"", RJP_PARSE_NONE}, {"true", RJP_PARSE_NONE}, {"false", RJP_PARSE_NONE}, {"null", RJP_PARSE_NONE}, {"5", RJP_PARSE_NONE}, {"-5", RJP_PARSE_NONE}, {"+5", RJP_PARSE_NONE}, {"5.5", RJP_PARSE_NONE}, {"-5.5", RJP_PARSE_NONE}, {"+5.5", RJP_PARSE_NONE}, {"5.5e6", RJP_PARSE_NONE}, {"-5.5e6", RJP_PARSE_NONE}, {"+5.5e6", RJP_PARSE_NONE}, {"5.5e+6", RJP_PARSE_NONE}, {"-5.5e+6", RJP_PARSE_NONE}, {"+5.5e+6", RJP_PARSE_NONE}, {"5.5e-6", RJP_PARSE_NONE}, {"-5.5e-6", RJP_PARSE_NONE}, {"+5.5e-6", RJP_PARSE_NONE}, {" {}", RJP_PARSE_NONE}, {"\n{}\n", RJP_PARSE_NONE}, {" { \"key\" \t:\n\n\n5 \n\t\n } ", RJP_PARSE_NONE}, {" {\t }\n", RJP_PARSE_NONE}, {"5.5 ", RJP_PARSE_NONE}, {"{\"key\":5}", RJP_PARSE_NONE}, {"{\"key\":{}}", RJP_PARSE_NONE}, {"{\"\\uD83D\\uDE10\":5}", RJP_PARSE_NONE}, {"{\"😐\":5}", RJP_PARSE_NONE}, {"{\"key\":{\"key\":5}}", RJP_PARSE_NONE}, {"{\"key\":{\"key\":5,\"key2\":6}}", RJP_PARSE_NONE}, {"{\"key\":{\"key\":5},\"key2\":6}", RJP_PARSE_NONE}, {"[5, 6, 7, 8, 9, \"10\"]", RJP_PARSE_NONE}, {"[[5,6],[7,8],[9,\"10\"]]", RJP_PARSE_NONE}, {"{\"arr\":[5,6,6]}", RJP_PARSE_NONE}, {"[{\"arr\":[5,6,6]}]", RJP_PARSE_NONE}, {"[{\"arr\":[5,6,6]}, 6]", RJP_PARSE_NONE}, {"[5,6,6,6,6.6]", RJP_PARSE_NONE}, {"[6,7,]", RJP_PARSE_ALLOW_TRAILING_COMMA}, {"{\"1\":1,\"2\":2,}", RJP_PARSE_ALLOW_TRAILING_COMMA}, {"[6,]", RJP_PARSE_ALLOW_TRAILING_COMMA}, {"{\"1\":1,}", RJP_PARSE_ALLOW_TRAILING_COMMA}, {"//comment\n{}", RJP_PARSE_ALLOW_COMMENTS}, {"{\"key\"://comment\n5}", RJP_PARSE_ALLOW_COMMENTS}, {"{\"key\"//comment\n:5}", RJP_PARSE_ALLOW_COMMENTS}, {"{}//comment", RJP_PARSE_ALLOW_COMMENTS}, {"{//\"key\":5\n}", RJP_PARSE_ALLOW_COMMENTS}, {"5 //comment*/", RJP_PARSE_ALLOW_COMMENTS}, {"{/*\"key\":5*/\"key\":5}", RJP_PARSE_ALLOW_COMMENTS}, {"[5, /*comment*/6]", RJP_PARSE_ALLOW_COMMENTS}, }; const int should_pass_cnt = sizeof(should_pass_strings)/sizeof(should_pass_strings[0]); struct parse_pair should_fail_strings[] = { {"//comment\n{}", RJP_PARSE_NONE}, {"{", RJP_PARSE_NONE}, {"}", RJP_PARSE_NONE}, {"[", RJP_PARSE_NONE}, {"]", RJP_PARSE_NONE}, {"6.", RJP_PARSE_NONE}, {"6.6e", RJP_PARSE_NONE}, {"6.6e+", RJP_PARSE_NONE}, {"5e", RJP_PARSE_NONE}, {"{6}", RJP_PARSE_NONE}, {"[\"key\":5]", RJP_PARSE_NONE}, {"\"string\n\"", RJP_PARSE_NONE}, {"[3 4]", RJP_PARSE_NONE}, {"\"\\uD83D\\uDE1\"", RJP_PARSE_NONE}, {"\"\\uD83D\\uDE1Q\"", RJP_PARSE_NONE}, {"\"\\uD83\\uDE10\"", RJP_PARSE_NONE}, {"\"\\uF83D\\uDE10\"", RJP_PARSE_NONE}, {"\"\\uU83D\\uDE10\"", RJP_PARSE_NONE}, {"{\"key\":1 \"key2\":2}", RJP_PARSE_NONE}, {"{\"key\" 1}", RJP_PARSE_NONE}, {"6, 7", RJP_PARSE_NONE}, {"[,]", RJP_PARSE_NONE}, {"{, RJP_PARSE_NONE}", RJP_PARSE_NONE}, {"[1, 2],", RJP_PARSE_NONE}, {"{\"key\nkey\":5}", RJP_PARSE_NONE}, {"{\"key\":\"key\n\"}", RJP_PARSE_NONE}, {"[6,7,]", RJP_PARSE_NONE}, {"{\"1\":1,\"2\":2, RJP_PARSE_NONE}", RJP_PARSE_NONE}, {"[6,]", RJP_PARSE_NONE}, {"{\"1\":1, RJP_PARSE_NONE}", RJP_PARSE_NONE}, {"{//comment\"key\":\n5}", RJP_PARSE_NONE}, {"{/*\"key\":*/5}", RJP_PARSE_NONE}, {"[5, /*6*/, 7]", RJP_PARSE_NONE}, {"{/*comment}", RJP_PARSE_NONE}, {"{//comment}", RJP_PARSE_NONE}, {"{\"key\"://comment\n5}", RJP_PARSE_NONE}, {"{\"key\"//comment\n:5}", RJP_PARSE_NONE}, {"{}//comment", RJP_PARSE_NONE}, {"{//\"key\":5\n}", RJP_PARSE_NONE}, {"5 //comment*/", RJP_PARSE_NONE}, {"{/*\"key\":5*/\"key\":5}", RJP_PARSE_NONE}, {"[5, /*comment*/6]", RJP_PARSE_NONE}, {"{\"key\"//:5}", RJP_PARSE_ALLOW_COMMENTS}, {"{,}", RJP_PARSE_ALLOW_TRAILING_COMMA}, {"[,]", RJP_PARSE_ALLOW_TRAILING_COMMA}, }; const int should_fail_cnt = sizeof(should_fail_strings)/sizeof(should_fail_strings[0]); const int total_tests = should_pass_cnt + should_fail_cnt; int run_test(int (*fun)(const char*,RJP_parse_flag)){ int passed = 0; fprintf(stderr, "Running %d tests that should pass...\n", should_pass_cnt); for(unsigned i = 0;i < sizeof(should_pass_strings)/sizeof(should_pass_strings[0]);++i){ fprintf(stderr, "%8d) ", i+1); if(!fun(should_pass_strings[i].str, should_pass_strings[i].flags)){ ++passed; }else{ fprintf(stderr, "%13s%s\n", "", should_pass_strings[i].str); } } fprintf(stderr, "\n"); fprintf(stderr, "Running %d tests that should fail...\n", should_fail_cnt); for(unsigned i = 0;i < sizeof(should_fail_strings)/sizeof(should_fail_strings[0]);++i){ fprintf(stderr, "%8d) ", i+1); if(fun(should_fail_strings[i].str, should_fail_strings[i].flags)){ ++passed; }else{ fprintf(stderr, "%13s%s\n", "", should_fail_strings[i].str); } } return passed; } int main(){ int normal_passed = run_test(test); int cback_passed = run_test(test_cbacks); int total_passed = normal_passed + cback_passed; fprintf(stderr, "\nResults: %d/%d normal tests passed\n", normal_passed, total_tests); fprintf(stderr, "Results: %d/%d callback tests passed\n", cback_passed, total_tests); fprintf(stderr, "Results: %d/%d tests passed\n", total_passed, total_tests*2); if(total_passed != (total_tests*2)) return 1; return 0; }