Browse Source

Address review comments on EntityAggregationCalculatedFieldStateTest

- Drop the dangling "spec §7" reference from the test comments; inline the
  actual rule (a lexical MIN/MAX result over string telemetry stays a string).
- Use a zero-padded code ("0009") for the string-result case - a clearer example
  of a genuine string that must not be coerced to a number (would lose padding).
- Define the maxCode metric in the test CF configuration alongside consumption
  and avgConsumption, so all parameterized metric names are configured.
pull/15917/head
dshvaika 3 months ago
parent
commit
da3f2e933a
  1. 17
      application/src/test/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldStateTest.java

17
application/src/test/java/org/thingsboard/server/service/cf/ctx/state/aggregation/single/EntityAggregationCalculatedFieldStateTest.java

@ -98,9 +98,10 @@ public class EntityAggregationCalculatedFieldStateTest {
} }
// A numeric aggregation result (SUM/AVG/COUNT/..., numeric MIN/MAX) must be serialized as a numeric // A numeric aggregation result (SUM/AVG/COUNT/..., numeric MIN/MAX) must be serialized as a numeric
// JSON node; a genuine string result (lexical MIN/MAX over string telemetry, spec §7) must stay a string // JSON node; a genuine string result (lexical MIN/MAX over string telemetry, e.g. a zero-padded code)
// node. The node type is asserted explicitly, so asText() is only used to verify the value once the type // must stay a string node. The node type is asserted explicitly, so asText() is only used to verify the
// is already pinned - it is not relied on to distinguish the types (that blindness is what hid the bug). // value once the type is already pinned - it is not relied on to distinguish the types (that blindness
// is what hid the bug).
@ParameterizedTest(name = "{0} (precision {2}) -> numeric={3}") @ParameterizedTest(name = "{0} (precision {2}) -> numeric={3}")
@MethodSource("toResultSerializationCases") @MethodSource("toResultSerializationCases")
void toResultSerializesResultWithTypePreservingNode(String metricName, BasicKvEntry kvEntry, Integer precision, void toResultSerializesResultWithTypePreservingNode(String metricName, BasicKvEntry kvEntry, Integer precision,
@ -118,8 +119,9 @@ public class EntityAggregationCalculatedFieldStateTest {
arguments("consumption", new DoubleDataEntry("consumption", 400.0), 0, true, "400"), arguments("consumption", new DoubleDataEntry("consumption", 400.0), 0, true, "400"),
// AVG: Number result, precision 2 -> half-up rounded double node // AVG: Number result, precision 2 -> half-up rounded double node
arguments("avgConsumption", new DoubleDataEntry("avgConsumption", 133.335), 2, true, "133.34"), arguments("avgConsumption", new DoubleDataEntry("avgConsumption", 133.335), 2, true, "133.34"),
// MIN/MAX over string telemetry: lexical String result -> preserved as string node (spec §7) // MAX over string telemetry: a zero-padded code is a genuine String result and must stay a
arguments("maxCode", new StringDataEntry("maxCode", "9"), 0, false, "9") // string node - as a number it would lose its padding ("0009" -> 9).
arguments("maxCode", new StringDataEntry("maxCode", "0009"), 0, false, "0009")
); );
} }
@ -165,6 +167,11 @@ public class EntityAggregationCalculatedFieldStateTest {
avgConsumption.setFunction(AggFunction.AVG); avgConsumption.setFunction(AggFunction.AVG);
avgConsumption.setInput(new AggKeyInput("en")); avgConsumption.setInput(new AggKeyInput("en"));
metrics.put("avgConsumption", avgConsumption); metrics.put("avgConsumption", avgConsumption);
AggMetric maxCode = new AggMetric();
maxCode.setFunction(AggFunction.MAX);
maxCode.setInput(new AggKeyInput("en"));
metrics.put("maxCode", maxCode);
configuration.setMetrics(metrics); configuration.setMetrics(metrics);
configuration.setInterval(new CustomInterval("UTC", 0L, 5L)); configuration.setInterval(new CustomInterval("UTC", 0L, 5L));

Loading…
Cancel
Save