From ecbe1158ed744a29dd99380e557be26e49fdafb5 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 27 Sep 2018 20:26:27 -0400 Subject: [PATCH] Added testing for number parsing. --- Makefile | 2 +- include/jsonparser/numberparsing.h | 3 ++ tests/jsoncheck.cpp | 2 +- tests/numberparsingcheck.cpp | 55 +++++++++++++++++++++++------- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 01e9a6fad..320895ae5 100644 --- a/Makefile +++ b/Makefile @@ -23,8 +23,8 @@ LIBS=$(RAPIDJSON_INCLUDE) all: $(LIBS) $(EXECUTABLES) test: jsoncheck numberparsingcheck + -./numberparsingcheck ./jsoncheck - ./numberparsingcheck $(RAPIDJSON_INCLUDE): git submodule update --init --recursive diff --git a/include/jsonparser/numberparsing.h b/include/jsonparser/numberparsing.h index ab8b7bad6..58544e1f0 100644 --- a/include/jsonparser/numberparsing.h +++ b/include/jsonparser/numberparsing.h @@ -320,6 +320,9 @@ static really_inline bool parse_number(const u8 *const buf, UNUSED size_t len, result = result * power_of_ten[308 - exppart]; } } + if (found_minus) { + result = -result; + } #ifdef JSON_TEST_NUMBERS // for unit testing foundFloat(result, buf + offset); #endif diff --git a/tests/jsoncheck.cpp b/tests/jsoncheck.cpp index 67b11b3b7..e399d9a8f 100644 --- a/tests/jsoncheck.cpp +++ b/tests/jsoncheck.cpp @@ -40,7 +40,7 @@ bool validate(const char *dirname) { for (int i = 0; i < c; i++) { const char *name = entry_list[i]->d_name; if (hasExtension(name, extension)) { - printf("validating: file %s \n", name); + //printf("validating: file %s \n", name); size_t filelen = strlen(name); char *fullpath = (char *)malloc(dirlen + filelen + 1 + 1); strcpy(fullpath, dirname); diff --git a/tests/numberparsingcheck.cpp b/tests/numberparsingcheck.cpp index fabc03223..95c3aeaee 100644 --- a/tests/numberparsingcheck.cpp +++ b/tests/numberparsingcheck.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #ifndef JSON_TEST_NUMBERS #define JSON_TEST_NUMBERS @@ -13,17 +14,44 @@ #include "jsonparser/common_defs.h" +int parse_error; +char *fullpath; +enum{PARSE_WARNING, PARSE_ERROR}; inline void foundInvalidNumber(const u8 * buf) { - printf("foundInvalidNumber %.64s \n", buf); + char * endptr; + double expected = strtod((char *)buf, &endptr); + if(endptr != (char *)buf) { + printf("Warning: foundInvalidNumber %.32s whereas strtod parses it to %f, ", buf, expected); + printf(" while parsing %s \n", fullpath); + parse_error |= PARSE_WARNING; + } } inline void foundInteger(int64_t result, const u8 * buf) { - printf("parsed %" PRId64 " out of %.64s \n", result, buf); + char * endptr; + long long expected = strtoll((char *)buf, & endptr, 10); + if((endptr == (char *)buf) || (expected != result)) { + printf("Error: parsed %" PRId64 " out of %.32s, ", result, buf); + printf(" while parsing %s \n", fullpath); + parse_error |= PARSE_ERROR; + } } inline void foundFloat(double result, const u8 * buf) { - printf("parsed %f from %.64s \n", result, buf); + char * endptr; + double expected = strtod((char *)buf, &endptr); + if(endptr == (char *)buf) { + printf("parsed %f from %.32s whereas strtod refuses to parse a float, ", result, buf); + printf(" while parsing %s \n", fullpath); + parse_error |= PARSE_ERROR; + } + // we want to get some reasonable relative accuracy + if(fabs(expected - result)/fmax(fabs(expected),fabs(result)) > 0.000000000000001) { + printf("parsed %f from %.32s whereas strtod gives %f,", result, buf, expected); + printf(" while parsing %s \n", fullpath); + parse_error |= PARSE_ERROR; + } } @@ -45,7 +73,7 @@ bool startsWith(const char *pre, const char *str) { } bool validate(const char *dirname) { - bool everythingfine = true; + parse_error = 0; // init_state_machine(); // no longer necessary const char *extension = ".json"; size_t dirlen = strlen(dirname); @@ -63,9 +91,8 @@ bool validate(const char *dirname) { for (int i = 0; i < c; i++) { const char *name = entry_list[i]->d_name; if (hasExtension(name, extension)) { - printf("validating numbers in file %s \n", name); size_t filelen = strlen(name); - char *fullpath = (char *)malloc(dirlen + filelen + 1 + 1); + fullpath = (char *)malloc(dirlen + filelen + 1 + 1); strcpy(fullpath, dirname); if (needsep) { fullpath[dirlen] = '/'; @@ -81,18 +108,22 @@ bool validate(const char *dirname) { return false; } ParsedJson &pj(*pj_ptr); - bool isok = json_parse(p.first, p.second, pj); - printf("File %s %s.\n", name, - isok ? " is valid JSON " : " is not valid JSON"); + //bool isok = + json_parse(p.first, p.second, pj); + //printf("File %s %s.\n", name, + // isok ? " is valid JSON " : " is not valid JSON"); free(p.first); free(fullpath); deallocate_ParsedJson(pj_ptr); } } + if((parse_error & PARSE_ERROR) != 0) { + printf("NUMBER PARSING FAILS?\n"); + } for (int i = 0; i < c; ++i) free(entry_list[i]); free(entry_list); - return everythingfine; + return ((parse_error & PARSE_ERROR) == 0); } int main(int argc, char *argv[]) { @@ -100,9 +131,9 @@ int main(int argc, char *argv[]) { std::cerr << "Usage: " << argv[0] << " " << std::endl; std::cout - << "We are going to assume you mean to use the 'jsonchecker' directory." + << "We are going to assume you mean to use the 'jsonchecker' and 'jsonexamples' directories." << std::endl; - return validate("jsonchecker/") ? EXIT_SUCCESS : EXIT_FAILURE; + return validate("jsonchecker/") && validate("jsonexamples/") ? EXIT_SUCCESS : EXIT_FAILURE; } return validate(argv[1]) ? EXIT_SUCCESS : EXIT_FAILURE; }