Browse Source
Merge pull request #15621 from volodymyr-babak/fix-sum-overflow-43
fix(cf): prevent integer overflow in calculated field SUM output
pull/15731/head
Viacheslav Klimov
1 month ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with
19 additions and
4 deletions
-
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java
-
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldStateTest.java
-
common/util/src/main/java/org/thingsboard/common/util/NumberUtils.java
-
common/util/src/test/java/org/thingsboard/common/util/NumberUtilsTest.java
|
|
|
@ -67,6 +67,8 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState { |
|
|
|
ObjectNode valuesNode = JacksonUtil.newObjectNode(); |
|
|
|
if (result instanceof Double doubleValue) { |
|
|
|
valuesNode.put(outputName, doubleValue); |
|
|
|
} else if (result instanceof Long longValue) { |
|
|
|
valuesNode.put(outputName, longValue); |
|
|
|
} else if (result instanceof Integer integerValue) { |
|
|
|
valuesNode.put(outputName, integerValue); |
|
|
|
} else { |
|
|
|
|
|
|
|
@ -154,7 +154,7 @@ public class SimpleCalculatedFieldStateTest { |
|
|
|
Output output = getCalculatedFieldConfig().getOutput(); |
|
|
|
assertThat(result.getType()).isEqualTo(output.getType()); |
|
|
|
assertThat(result.getScope()).isEqualTo(output.getScope()); |
|
|
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49))); |
|
|
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49L))); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
@ -184,7 +184,7 @@ public class SimpleCalculatedFieldStateTest { |
|
|
|
Output output = getCalculatedFieldConfig().getOutput(); |
|
|
|
assertThat(result.getType()).isEqualTo(output.getType()); |
|
|
|
assertThat(result.getScope()).isEqualTo(output.getScope()); |
|
|
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 35))); |
|
|
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 35L))); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
@ -36,12 +36,16 @@ public class NumberUtils { |
|
|
|
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue(); |
|
|
|
} |
|
|
|
|
|
|
|
public static long toLong(double value) { |
|
|
|
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).longValue(); |
|
|
|
} |
|
|
|
|
|
|
|
public static Object roundResult(double value, Integer precision) { |
|
|
|
if (precision == null) { |
|
|
|
return value; |
|
|
|
} |
|
|
|
if (precision.equals(0)) { |
|
|
|
return toInt(value); |
|
|
|
return toLong(value); |
|
|
|
} |
|
|
|
return toFixed(value, precision); |
|
|
|
} |
|
|
|
|
|
|
|
@ -51,11 +51,20 @@ public class NumberUtilsTest { |
|
|
|
assertThat(NumberUtils.toInt(28.0)).isEqualTo(28); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void toLong() { |
|
|
|
assertThat(NumberUtils.toLong(doubleVal)).isEqualTo(1729L); |
|
|
|
assertThat(NumberUtils.toLong(12.8)).isEqualTo(13L); |
|
|
|
assertThat(NumberUtils.toLong(28.0)).isEqualTo(28L); |
|
|
|
assertThat(NumberUtils.toLong(3_980_173_734.0)).isEqualTo(3_980_173_734L); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void roundResult() { |
|
|
|
assertThat(NumberUtils.roundResult(doubleVal, null)).isEqualTo(1729.1729); |
|
|
|
assertThat(NumberUtils.roundResult(doubleVal, 0)).isEqualTo(1729); |
|
|
|
assertThat(NumberUtils.roundResult(doubleVal, 0)).isEqualTo(1729L); |
|
|
|
assertThat(NumberUtils.roundResult(doubleVal, 2)).isEqualTo(1729.17); |
|
|
|
assertThat(NumberUtils.roundResult(3_980_173_734.0, 0)).isEqualTo(3_980_173_734L); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|