Compare commits

...

2 Commits

Author SHA1 Message Date
dhmemi
a33fe4bcdd make clang-tidy happy. 2023-09-22 15:29:02 +02:00
dhmemi
a19d71ddcb fix: validate multipleOf fails on float-point value 2023-09-22 15:29:02 +02:00
4 changed files with 39 additions and 3 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ cmake-build-*
venv
env
compile_commands.json
.vs/*

View File

@ -863,9 +863,13 @@ class numeric : public schema
// multipleOf - if the remainder of the division is 0 -> OK
bool violates_multiple_of(T x) const
{
double res = std::remainder(x, multipleOf_.second);
double eps = std::nextafter(x, 0) - static_cast<double>(x);
return std::fabs(res) > std::fabs(eps);
if constexpr (std::is_floating_point<T>::value) {
auto multiple = x / multipleOf_.second;
auto error = std::abs((multiple - std::round(multiple)) * multipleOf_.second);
return error > std::numeric_limits<T>::epsilon();
} else {
return x % static_cast<T>(multipleOf_.second) != 0;
}
}
void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override

View File

@ -43,6 +43,10 @@ add_executable(issue-98 issue-98.cpp)
target_link_libraries(issue-98 nlohmann_json_schema_validator)
add_test(NAME issue-98-erase-exception-unknown-keywords COMMAND issue-98)
add_executable(issue-293 issue-293.cpp)
target_link_libraries(issue-293 nlohmann_json_schema_validator)
add_test(NAME issue-293-float-point-error COMMAND issue-293)
# Unit test for string format checks
add_executable(string-format-check-test string-format-check-test.cpp)
target_include_directories(string-format-check-test PRIVATE ${PROJECT_SOURCE_DIR}/src/)

27
test/issue-293.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "nlohmann/json-schema.hpp"
int main(void)
{
using nlohmann::json_schema::json_validator;
json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.3 - 0.2);
json_validator({{"type", "number"}, {"multipleOf", 3.3}}).validate(8.0 - 1.4);
json_validator({{"type", "number"}, {"multipleOf", 1000.01}}).validate((1000.03 - 0.02) * 15.0);
int expect_exception = 2;
try {
json_validator({{"type", "number"}, {"multipleOf", 0.001}}).validate(0.3 - 0.2005);
} catch (const std::exception &ex) {
expect_exception--;
}
try {
json_validator({{"type", "number"}, {"multipleOf", 1000.02}}).validate((1000.03 - 0.02) * 15.0);
} catch (const std::exception &ex) {
expect_exception--;
}
return expect_exception;
}