From 8fe02f3f116026cb00c8e0932e4d2c700dc0e099 Mon Sep 17 00:00:00 2001 From: Hudson Cooper Date: Wed, 30 Jul 2025 09:49:43 -0700 Subject: [PATCH 1/2] allow negative test values for multipleOf --- parser/src/json/compiler.rs | 20 ++++++++++++-- sample_parser/tests/test_json_primitives.rs | 30 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/parser/src/json/compiler.rs b/parser/src/json/compiler.rs index f505e15f..21016d79 100644 --- a/parser/src/json/compiler.rs +++ b/parser/src/json/compiler.rs @@ -293,7 +293,15 @@ impl Compiler { })?; let mut ast = RegexAst::Regex(rx); if let Some(d) = num.multiple_of.as_ref() { - ast = RegexAst::And(vec![ast, RegexAst::MultipleOf(d.coef, d.exp)]); + let multiple_rx = if d.coef == 0 { + RegexAst::Literal("0".to_string()) + } else { + RegexAst::Concat(vec![ + RegexAst::Regex("-?".to_string()), + RegexAst::MultipleOf(d.coef, d.exp), + ]) + }; + ast = RegexAst::And(vec![ast, multiple_rx]); } Ok(ast) } @@ -314,7 +322,15 @@ impl Compiler { })?; let mut ast = RegexAst::Regex(rx); if let Some(d) = num.multiple_of.as_ref() { - ast = RegexAst::And(vec![ast, RegexAst::MultipleOf(d.coef, d.exp)]); + let multiple_rx = if d.coef == 0 { + RegexAst::Literal("0".to_string()) + } else { + RegexAst::Concat(vec![ + RegexAst::Regex("-?".to_string()), + RegexAst::MultipleOf(d.coef, d.exp), + ]) + }; + ast = RegexAst::And(vec![ast, multiple_rx]); } Ok(ast) } diff --git a/sample_parser/tests/test_json_primitives.rs b/sample_parser/tests/test_json_primitives.rs index 0dc7c914..a16aa740 100644 --- a/sample_parser/tests/test_json_primitives.rs +++ b/sample_parser/tests/test_json_primitives.rs @@ -471,3 +471,33 @@ fn string_length_unsatisfiable() { "Unsatisfiable schema: minLength (2) is greater than maxLength (1)", ); } + +#[test] +fn test_multiple_of_zero() { + let schema = &json!({"type":"integer", "multipleOf": 0}); + json_schema_check(schema, &json!(0), true); + json_schema_check(schema, &json!(1), false); + json_schema_check(schema, &json!(-1), false); +} + +#[test] +fn test_multiple_of_zero_float() { + let schema = &json!({"type":"number", "multipleOf": 0}); + json_schema_check(schema, &json!(0.0), true); + json_schema_check(schema, &json!(1.0), false); + json_schema_check(schema, &json!(-1.0), false); +} + +#[rstest] +#[case::positive_multipleof(3)] +#[case::negative_multipleof(-3)] +fn test_multiple_of_negative_multipleof(#[case] mult: i32) { + let schema = &json!({"type":"integer", "multipleOf": mult}); + json_schema_check(schema, &json!(0), true); + json_schema_check(schema, &json!(3), true); + json_schema_check(schema, &json!(6), true); + json_schema_check(schema, &json!(1), false); + json_schema_check(schema, &json!(-1), false); + json_schema_check(schema, &json!(-2), false); + json_schema_check(schema, &json!(-3), true); +} From dc99a3191a4eb0bb74737db6297604a7bcdaf317 Mon Sep 17 00:00:00 2001 From: Hudson Cooper Date: Wed, 30 Jul 2025 10:53:01 -0700 Subject: [PATCH 2/2] apparently multipleOf must be a positive number --- parser/src/json/compiler.rs | 24 +++------ parser/src/json/schema.rs | 6 ++- sample_parser/tests/test_json_primitives.rs | 59 ++++++++++++--------- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/parser/src/json/compiler.rs b/parser/src/json/compiler.rs index 21016d79..2a589cac 100644 --- a/parser/src/json/compiler.rs +++ b/parser/src/json/compiler.rs @@ -293,14 +293,10 @@ impl Compiler { })?; let mut ast = RegexAst::Regex(rx); if let Some(d) = num.multiple_of.as_ref() { - let multiple_rx = if d.coef == 0 { - RegexAst::Literal("0".to_string()) - } else { - RegexAst::Concat(vec![ - RegexAst::Regex("-?".to_string()), - RegexAst::MultipleOf(d.coef, d.exp), - ]) - }; + let multiple_rx = RegexAst::Concat(vec![ + RegexAst::Regex("-?".to_string()), + RegexAst::MultipleOf(d.coef, d.exp), + ]); ast = RegexAst::And(vec![ast, multiple_rx]); } Ok(ast) @@ -322,14 +318,10 @@ impl Compiler { })?; let mut ast = RegexAst::Regex(rx); if let Some(d) = num.multiple_of.as_ref() { - let multiple_rx = if d.coef == 0 { - RegexAst::Literal("0".to_string()) - } else { - RegexAst::Concat(vec![ - RegexAst::Regex("-?".to_string()), - RegexAst::MultipleOf(d.coef, d.exp), - ]) - }; + let multiple_rx = RegexAst::Concat(vec![ + RegexAst::Regex("-?".to_string()), + RegexAst::MultipleOf(d.coef, d.exp), + ]); ast = RegexAst::And(vec![ast, multiple_rx]); } Ok(ast) diff --git a/parser/src/json/schema.rs b/parser/src/json/schema.rs index 160db60c..c26b9cae 100644 --- a/parser/src/json/schema.rs +++ b/parser/src/json/schema.rs @@ -920,8 +920,10 @@ fn compile_numeric(schema: &HashMap<&str, &Value>, integer: bool) -> Result