Repository: networknt/json-schema-validator
Pull request #150 (2019-05-22 18:08:08)

fixed for PR https://github.com/networknt/json-schema-validator/pull/148
related issue: https://github.com/networknt/json-schema-validator/issues/147
-fixed when the node is BigInteger, when it's smaller than Long.MAX_VALUE, it should do the comparison instead of return false directly.
-added test cases.



Patch:
diff --git a/src/main/java/com/networknt/schema/MaximumValidator.java b/src/main/java/com/networknt/schema/MaximumValidator.java
index cb38e30..14e7ee8 100644
--- a/src/main/java/com/networknt/schema/MaximumValidator.java
+++ b/src/main/java/com/networknt/schema/MaximumValidator.java
@@ -73,7 +73,9 @@ public class MaximumValidator extends BaseJsonValidator implements JsonValidator
                     long val = node.asLong();
                     if(node.isBigInteger()) {
                         //node.isBigInteger is not trustable, the type BigInteger doesn't mean it is a big number.
-                        return node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0;
+                        if(node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0) {
+                            return true;
+                        }
                     }
                     return lm < val || (excludeEqual && lm <= val);
                 }
diff --git a/src/main/java/com/networknt/schema/MinimumValidator.java b/src/main/java/com/networknt/schema/MinimumValidator.java
index 70d1493..672380f 100644
--- a/src/main/java/com/networknt/schema/MinimumValidator.java
+++ b/src/main/java/com/networknt/schema/MinimumValidator.java
@@ -76,7 +76,9 @@ public class MinimumValidator extends BaseJsonValidator implements JsonValidator
                     long val = node.asLong();
                     if(node.isBigInteger()) {
                         //node.isBigInteger is not trustable, the type BigInteger doesn't mean it is a big number.
-                        return node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0;
+                        if(node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0) {
+                            return true;
+                        }
                     }
                     return lmin > val || (excluded && lmin >= val);
                 }


Test patch:
diff --git a/src/test/java/com/networknt/schema/MaximumValidatorTest.java b/src/test/java/com/networknt/schema/MaximumValidatorTest.java
index 04da6cd..5cdcb12 100644
--- a/src/test/java/com/networknt/schema/MaximumValidatorTest.java
+++ b/src/test/java/com/networknt/schema/MaximumValidatorTest.java
@@ -35,11 +35,13 @@ public class MaximumValidatorTest {
 
     private static ObjectMapper mapper;
     private static ObjectMapper bigDecimalMapper;
+    private static ObjectMapper bigIntegerMapper;
 
     @Before
     public void setUp() {
         mapper = new ObjectMapper();
         bigDecimalMapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+        bigIntegerMapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
     }
 
     @Test
@@ -219,6 +221,166 @@ public class MaximumValidatorTest {
             assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
         }
     }
+
+    @Test
+    public void BigIntegerBothWithinLongRangePositive() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"20",         "10"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothWithinLongRangeNegative() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"10",         "20"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecting validation error with maximum %s and value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerOverflow() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775806",         "9223372036854775808"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecting validation error with maximum %s and value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerNotOverflow() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775809",         "9223372036854775806"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothAboveLongRangePositive() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775809",         "9223372036854775808"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothAboveLongRangeNegative() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775808",         "9223372036854775809"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": true}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecting validation error with maximum %s and value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerNotOverflowOnLongRangeEdge() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775807",         "9223372036854775807"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": false}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerOverflowOnLongRangeEdge() throws IOException {
+        String[][] values = {
+//            maximum,                       value
+                {"9223372036854775808",         "9223372036854775808"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": false}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
 }
 
 
diff --git a/src/test/java/com/networknt/schema/MinimumValidatorTest.java b/src/test/java/com/networknt/schema/MinimumValidatorTest.java
index 21d76c2..a197f84 100644
--- a/src/test/java/com/networknt/schema/MinimumValidatorTest.java
+++ b/src/test/java/com/networknt/schema/MinimumValidatorTest.java
@@ -35,11 +35,14 @@ public class MinimumValidatorTest {
 
     private static ObjectMapper mapper;
     private static ObjectMapper bigDecimalMapper;
+    private static ObjectMapper bigIntegerMapper;
 
     @Before
     public void setUp() {
         mapper = new ObjectMapper();
         bigDecimalMapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+        bigIntegerMapper = new ObjectMapper().enable(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS);
+
     }
 
     @Test
@@ -219,6 +222,165 @@ public class MinimumValidatorTest {
             assertTrue(format("Expecing no validation errors as minimum %s is lesser than value %s", minimum, value), messages.isEmpty());
         }
     }
+    @Test
+    public void BigIntegerBothWithinLongRangePositive() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"10",         "20"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecting no validation errors as minimum %s is lesser than value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothWithinLongRangeNegative() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"20",         "10"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecting validation error with minimum %s and value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerOverflow() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775807",         "-9223372036854775809"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecing validation error with minimum %s and value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerNotOverflow() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775809",         "-9223372036854775807"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecting no validation errors as minimum %s is lesser than value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothAboveLongRangePositive() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775810",         "-9223372036854775809"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecting no validation errors as minimum %s is lesser than value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerBothAboveLongRangeNegative() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775809",         "-9223372036854775810"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": true}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertFalse(format("Expecing validation error with minimum %s and value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerNotOverflowOnLongRangeEdge() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775808",         "-9223372036854775808"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String minimum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"minimum\": %s, \"exclusiveMinimum\": false}", minimum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as minimum %s is lesser than value %s", minimum, value), messages.isEmpty());
+        }
+    }
+
+    @Test
+    public void BigIntegerOverflowOnLongRangeEdge() throws IOException {
+        String[][] values = {
+//            minimum,                       value
+                {"-9223372036854775809",         "-9223372036854775809"}
+        };
+
+        for(String[] aTestCycle : values) {
+            String maximum = aTestCycle[0];
+            String value = aTestCycle[1];
+            String schema = format("{ \"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\", \"maximum\": %s, \"exclusiveMaximum\": false}", maximum);
+
+            JsonSchema v = factory.getSchema(mapper.readTree(schema));
+            JsonNode doc = bigIntegerMapper.readTree(value);
+
+            Set<ValidationMessage> messages = v.validate(doc);
+            assertTrue(format("Expecing no validation errors as maximum %s is greater than value %s", maximum, value), messages.isEmpty());
+        }
+    }
 }