public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH common 2/3] json schema: add tests for numeric behavior
Date: Thu,  8 Oct 2026 15:48:12 +0200	[thread overview]
Message-ID: <20261008135224.3323985-3-d.csapak@proxmox.com> (raw)
In-Reply-To: <20261008135224.3323985-1-d.csapak@proxmox.com>

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 test/json-schema-test.pl | 166 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/test/json-schema-test.pl b/test/json-schema-test.pl
index f1c968f..c5014e9 100755
--- a/test/json-schema-test.pl
+++ b/test/json-schema-test.pl
@@ -22,6 +22,10 @@ use Test::More;
 #   in - input of the sub-test
 #   out - expected output of the sub-test, falls back to outer `out`
 #   must_fail - if set the test must fail and the error must match the regex defined here.
+
+# exceeds the range of a double, so it numifies to infinity
+my $huge_int = '1' . ('0' x 400);
+
 my $property_string_tests = [
     {
         name => 'default-key-with-type-boolean',
@@ -99,6 +103,38 @@ my $property_string_tests = [
             },
         ],
     },
+    {
+        name => 'huge-numeric-values',
+        format => {
+            int => { type => 'integer', optional => 1 },
+            num => { type => 'number', optional => 1 },
+            'int-ranged' => { type => 'integer', optional => 1, minimum => -10, maximum => 10 },
+            'num-ranged' => { type => 'number', optional => 1, minimum => -1, maximum => 1 },
+        },
+        subtests => [
+            { in => "int=$huge_int", out => { int => $huge_int } },
+            { in => "int=-$huge_int", out => { int => "-$huge_int" } },
+            { in => "num=$huge_int", out => { num => $huge_int } },
+            { in => "num=1e400", out => { num => '1e400' } },
+            { in => "num=-1e400", out => { num => '-1e400' } },
+            {
+                in => "int-ranged=$huge_int",
+                must_fail => qr/int-ranged: value must have a maximum value of 10/,
+            },
+            {
+                in => "int-ranged=-$huge_int",
+                must_fail => qr/int-ranged: value must have a minimum value of -10/,
+            },
+            {
+                in => "num-ranged=1e400",
+                must_fail => qr/num-ranged: value must have a maximum value of 1/,
+            },
+            {
+                in => "num-ranged=-1e400",
+                must_fail => qr/num-ranged: value must have a minimum value of -1/,
+            },
+        ],
+    },
     # TODO: more tests, like complex formats and ranges and the like
 ];
 
@@ -863,4 +899,134 @@ for my $test ($check_one_of->@*) {
     };
 }
 
+# check numeric type and range checks with values exceeding the range of a double
+#
+# Properties of a test:
+#
+# name - describes the test
+# schema - the schema of the property 'value'
+# subtests - list of:
+#   name - describes the sub-test
+#   in - the value to check
+#   must_fail - regex that must match the error of the property
+my $numeric_tests = [
+    {
+        name => 'huge integer',
+        schema => { type => 'integer' },
+        subtests => [
+            { name => 'positive', in => "100" },
+            { name => 'negative', in => "-100" },
+            { name => 'explicit plus sign', in => "+100" },
+            {
+                name => 'exponent notation',
+                in => '1e2',
+                must_fail => qr/^type check \('integer'\) failed - got '1e2'/,
+            },
+            {
+                name => 'not a number',
+                in => 'foo',
+                must_fail => qr/^type check \('integer'\) failed/,
+            },
+        ],
+    },
+    {
+        name => 'huge integer',
+        schema => { type => 'integer' },
+        subtests => [
+            { name => 'positive', in => $huge_int },
+            { name => 'negative', in => "-$huge_int" },
+            { name => 'explicit plus sign', in => "+$huge_int" },
+            {
+                name => 'exponent notation',
+                in => '1e400',
+                must_fail => qr/^type check \('integer'\) failed/,
+            },
+            {
+                name => 'fractional part',
+                in => "$huge_int.0",
+                must_fail => qr/^type check \('integer'\) failed/,
+            },
+        ],
+    },
+    {
+        name => 'huge integer with range',
+        schema => { type => 'integer', minimum => -10, maximum => 10 },
+        subtests => [
+            {
+                name => 'above maximum',
+                in => $huge_int,
+                must_fail => qr/^value must have a maximum value of 10$/,
+            },
+            {
+                name => 'below minimum',
+                in => "-$huge_int",
+                must_fail => qr/^value must have a minimum value of -10$/,
+            },
+        ],
+    },
+    {
+        name => 'huge number',
+        schema => { type => 'number' },
+        subtests => [
+            { name => 'integer notation', in => $huge_int },
+            { name => 'negative integer notation', in => "-$huge_int" },
+            { name => 'fractional part', in => "$huge_int.5" },
+            { name => 'exponent notation', in => '1e400' },
+            { name => 'negative exponent notation', in => '-1e400' },
+            { name => 'tiny exponent notation', in => '1e-400' },
+            {
+                name => 'infinity literal',
+                in => 'inf',
+                must_fail => qr/^type check \('number'\) failed/,
+            },
+        ],
+    },
+    {
+        name => 'huge number with range',
+        schema => { type => 'number', minimum => 0, maximum => 1 },
+        subtests => [
+            {
+                name => 'above maximum',
+                in => '1e400',
+                must_fail => qr/^value must have a maximum value of 1$/,
+            },
+            {
+                name => 'above maximum in integer notation',
+                in => $huge_int,
+                must_fail => qr/^value must have a maximum value of 1$/,
+            },
+            {
+                name => 'below minimum',
+                in => '-1e400',
+                must_fail => qr/^value must have a minimum value of 0$/,
+            },
+            { name => 'tiny value within range', in => '1e-400' },
+        ],
+    },
+];
+
+for my $test ($numeric_tests->@*) {
+    subtest $test->{name}, sub {
+        for my $subtest ($test->{subtests}->@*) {
+            my $name = $subtest->{name};
+            my $schema = {
+                type => 'object',
+                properties => { value => $test->{schema} },
+            };
+            my $value = { value => $subtest->{in} };
+
+            my $errors = {};
+            PVE::JSONSchema::check_prop($value, $schema, undef, $errors);
+
+            if (my $must_fail = $subtest->{must_fail}) {
+                like(delete($errors->{value}) // '', $must_fail, "$name - failed as expected");
+            }
+            my $err_str = join("\n", map { "$_: $errors->{$_}" } sort keys %$errors);
+            is($err_str, '', "$name - no unexpected errors");
+            is($value->{value}, $subtest->{in}, "$name - value remains unchanged");
+        }
+        done_testing();
+    };
+}
+
 done_testing();
-- 
2.47.3





  parent reply	other threads:[~2026-10-08 13:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08 13:48 [PATCH common 0/3] fix #7612 Dominik Csapak
2026-10-08 13:48 ` [PATCH common 1/3] json schema: reorder imports to our style guide Dominik Csapak
2026-10-08 13:48 ` Dominik Csapak [this message]
2026-10-08 13:48 ` [PATCH common 3/3] fix #7612: json schema: don't allow integers that are too large Dominik Csapak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261008135224.3323985-3-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal