Skip to content

Commit 17e90d8

Browse files
authored
Merge pull request #164 from networknt/fix/#160-max-value-float
Fix/#160 max value float
2 parents d1c9468 + 7ce7f98 commit 17e90d8

File tree

7 files changed

+422
-102
lines changed

7 files changed

+422
-102
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
</distributionManagement>
6060
<properties>
6161
<java.version>1.8</java.version>
62-
<java.testversion>1.7</java.testversion>
62+
<java.testversion>1.8</java.testversion>
6363
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
6464
<version.jackson>2.9.9</version.jackson>
6565
<version.slf4j>1.7.25</version.slf4j>

src/main/java/com/networknt/schema/MaximumValidator.java

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
2222

23+
import java.math.BigDecimal;
2324
import java.math.BigInteger;
2425
import java.util.Collections;
2526
import java.util.Set;
@@ -33,7 +34,7 @@ public class MaximumValidator extends BaseJsonValidator implements JsonValidator
3334
private final ThresholdMixin typedMaximum;
3435

3536

36-
public MaximumValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
37+
public MaximumValidator(String schemaPath, final JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
3738
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.MAXIMUM, validationContext);
3839

3940
if (!schemaNode.isNumber()) {
@@ -47,33 +48,16 @@ public MaximumValidator(String schemaPath, JsonNode schemaNode, JsonSchema paren
4748

4849
parseErrorCode(getValidatorType().getErrorCodeKey());
4950

50-
if (!JsonType.INTEGER.toString().equals(getNodeFieldType())) {
51-
// "number" or no type
52-
// by default treat value as double: compatible with previous behavior
53-
final double dm = schemaNode.doubleValue();
54-
typedMaximum = new ThresholdMixin() {
55-
@Override
56-
public boolean crossesThreshold(JsonNode node) {
57-
double value = node.asDouble();
58-
return greaterThan(value, dm) || (excludeEqual && MaximumValidator.this.equals(value, dm));
59-
}
60-
61-
@Override
62-
public String thresholdValue() {
63-
return String.valueOf(dm);
64-
}
65-
};
66-
67-
} else if ( schemaNode.isLong() || schemaNode.isInt() ) {
51+
if (( schemaNode.isLong() || schemaNode.isInt() ) && (JsonType.INTEGER.toString().equals(getNodeFieldType()))) {
6852
// "integer", and within long range
6953
final long lm = schemaNode.asLong();
7054
typedMaximum = new ThresholdMixin() {
7155
@Override
7256
public boolean crossesThreshold(JsonNode node) {
7357
long val = node.asLong();
74-
if(node.isBigInteger()) {
58+
if (node.isBigInteger()) {
7559
//node.isBigInteger is not trustable, the type BigInteger doesn't mean it is a big number.
76-
if(node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0) {
60+
if (node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0) {
7761
return true;
7862
}
7963
}
@@ -85,20 +69,22 @@ public String thresholdValue() {
8569
return String.valueOf(lm);
8670
}
8771
};
88-
8972
} else {
90-
// "integer" outside long range
91-
final BigInteger bim = new BigInteger(schemaNode.asText());
9273
typedMaximum = new ThresholdMixin() {
9374
@Override
9475
public boolean crossesThreshold(JsonNode node) {
95-
int cmp = bim.compareTo(node.bigIntegerValue());
96-
return cmp < 0 || (excludeEqual && cmp <= 0);
76+
if(schemaNode.doubleValue() == Double.POSITIVE_INFINITY) {
77+
return false;
78+
}
79+
final BigDecimal max = new BigDecimal(schemaNode.asText());
80+
if(node.doubleValue() == Double.POSITIVE_INFINITY) {return true;}
81+
BigDecimal value = new BigDecimal(node.asText());
82+
return value.compareTo(max) > 0 || (excludeEqual && value.compareTo(max) == 0);
9783
}
9884

9985
@Override
10086
public String thresholdValue() {
101-
return String.valueOf(bim);
87+
return schemaNode.asText();
10288
}
10389
};
10490
}
@@ -117,5 +103,4 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
117103
}
118104
return Collections.emptySet();
119105
}
120-
121106
}

src/main/java/com/networknt/schema/MinimumValidator.java

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
2222

23+
import java.math.BigDecimal;
2324
import java.math.BigInteger;
2425
import java.util.Collections;
2526
import java.util.Set;
@@ -50,24 +51,7 @@ public MinimumValidator(String schemaPath, JsonNode schemaNode, JsonSchema paren
5051

5152
parseErrorCode(getValidatorType().getErrorCodeKey());
5253

53-
if (!JsonType.INTEGER.toString().equals(getNodeFieldType())) {
54-
// "number" or no type
55-
// by default treat value as double: compatible with previous behavior
56-
final double dmin = schemaNode.doubleValue();
57-
typedMinimum = new ThresholdMixin() {
58-
@Override
59-
public boolean crossesThreshold(JsonNode node) {
60-
double value = node.asDouble();
61-
return lessThan(value, dmin) || (excluded && MinimumValidator.this.equals(value, dmin));
62-
}
63-
64-
@Override
65-
public String thresholdValue() {
66-
return String.valueOf(dmin);
67-
}
68-
};
69-
70-
} else if ( schemaNode.isLong() || schemaNode.isInt() ) {
54+
if ( schemaNode.isLong() || schemaNode.isInt() && JsonType.INTEGER.toString().equals(getNodeFieldType())) {
7155
// "integer", and within long range
7256
final long lmin = schemaNode.asLong();
7357
typedMinimum = new ThresholdMixin() {
@@ -90,18 +74,21 @@ public String thresholdValue() {
9074
};
9175

9276
} else {
93-
// "integer" outside long range
94-
final BigInteger bimin = new BigInteger(schemaNode.asText());
9577
typedMinimum = new ThresholdMixin() {
9678
@Override
9779
public boolean crossesThreshold(JsonNode node) {
98-
int cmp = bimin.compareTo(node.bigIntegerValue());
99-
return cmp > 0 || (excluded && cmp >= 0);
80+
if(schemaNode.doubleValue() == Double.NEGATIVE_INFINITY) {
81+
return false;
82+
}
83+
final BigDecimal min = new BigDecimal(schemaNode.asText());
84+
if(node.doubleValue() == Double.NEGATIVE_INFINITY) {return true;}
85+
BigDecimal value = new BigDecimal(node.asText());
86+
return value.compareTo(min) < 0 || (excluded && value.compareTo(min) == 0);
10087
}
10188

10289
@Override
10390
public String thresholdValue() {
104-
return String.valueOf(bimin);
91+
return schemaNode.asText();
10592
}
10693
};
10794
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.networknt.schema;
2+
3+
import org.junit.Ignore;
4+
import org.junit.Test;
5+
6+
import java.lang.annotation.Annotation;
7+
import java.lang.reflect.InvocationTargetException;
8+
import java.lang.reflect.Method;
9+
import java.util.ArrayList;
10+
import java.util.Arrays;
11+
import java.util.List;
12+
import java.util.stream.Collectors;
13+
@Ignore
14+
public class MaximumValidatorPerfTest {
15+
MaximumValidatorTest test = new MaximumValidatorTest();
16+
17+
@Test
18+
public void testTime() throws InvocationTargetException, IllegalAccessException {
19+
test.setUp();
20+
String[] testMethodsToBeExecuted = {"testMaximumDoubleValue"};
21+
List<Method> testMethods = getTestMethods(testMethodsToBeExecuted);
22+
long start = System.currentTimeMillis();
23+
executeTests(testMethods, 200000);
24+
long end = System.currentTimeMillis();
25+
System.out.println("time to execute all tests using:" + (end - start) +"ms");
26+
}
27+
28+
public void executeTests(List<Method> methods, int executeTimes) throws InvocationTargetException, IllegalAccessException {
29+
30+
for(int i = 0; i < executeTimes; i++) {
31+
for(Method testMethod : methods) {
32+
testMethod.invoke(test);
33+
}
34+
}
35+
36+
}
37+
38+
public List<Method> getTestMethods(String[] methodNames) {
39+
Method[] methods = test.getClass().getMethods();
40+
List<Method> testMethods = new ArrayList<Method>();
41+
if(methodNames.length > 0) {
42+
for(String name : methodNames) {
43+
testMethods.addAll(Arrays.stream(methods).filter(m -> m.getName().equals(name)).collect(Collectors.toList()));
44+
}
45+
return testMethods;
46+
}
47+
for (Method m : methods) {
48+
Annotation[] annotations = m.getDeclaredAnnotations();
49+
boolean isTestMethod = false;
50+
for(Annotation annotation : annotations) {
51+
if(annotation.annotationType() == Test.class) {
52+
isTestMethod = true;
53+
}
54+
}
55+
if(isTestMethod) {
56+
//filter out incompatible test cases.
57+
if(!m.getName().equals("doubleValueCoarsing") && !m.getName().equals("negativeDoubleOverflowTest"))
58+
testMethods.add(m);
59+
}
60+
}
61+
return testMethods;
62+
}
63+
}

0 commit comments

Comments
 (0)