From fab3cfbc863e06a68d4cf3dd3d4570dd46ce2d2f Mon Sep 17 00:00:00 2001 From: VIacheslavKlimov Date: Mon, 20 Oct 2025 14:16:28 +0300 Subject: [PATCH] Alarm rules CF: add test for manual alarm clear --- .../alarm/AlarmCalculatedFieldState.java | 4 +- .../thingsboard/server/cf/AlarmRulesTest.java | 47 ++++++++++++++++--- .../src/test/resources/logback-test.xml | 2 + 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java index e36892378c..02f1725cf2 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java @@ -220,10 +220,8 @@ public class AlarmCalculatedFieldState extends BaseCalculatedFieldState { private void processAlarmClear(Alarm alarm) { currentAlarm = null; - createRuleStates.values().forEach(AlarmRuleState::clear); - createRuleStates.clear(); + createRuleStates.values().forEach(this::clearState); clearState(clearRuleState); - clearRuleState = null; } private void processAlarmAck(Alarm alarm) { diff --git a/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java b/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java index ae0010ea57..2b43373ee5 100644 --- a/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java +++ b/application/src/test/java/org/thingsboard/server/cf/AlarmRulesTest.java @@ -29,6 +29,7 @@ import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.rule.AlarmRule; @@ -689,16 +690,49 @@ public class AlarmRulesTest extends AbstractControllerTest { }); } + @Test + public void testManualClearAlarm() throws Exception { + Argument temperatureArgument = new Argument(); + temperatureArgument.setRefEntityKey(new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null)); + temperatureArgument.setDefaultValue("0"); + Map arguments = Map.of( + "temperature", temperatureArgument + ); + + Map createRules = Map.of( + AlarmSeverity.CRITICAL, new Condition("return temperature >= 50;", null, null) + ); + + CalculatedField calculatedField = createAlarmCf(deviceId, "High Temperature Alarm", + arguments, createRules, null); + + postTelemetry(deviceId, "{\"temperature\":50}"); + Alarm alarm = checkAlarmResult(calculatedField, alarmResult -> { + assertThat(alarmResult.isCreated()).isTrue(); + assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); + assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK); + }).getAlarm(); + + doPost("/api/alarm/" + alarm.getId() + "/clear", AlarmInfo.class); + Thread.sleep(1000); + postTelemetry(deviceId, "{\"temperature\":50}"); + checkAlarmResult(calculatedField, alarmResult -> { + assertThat(alarmResult.getAlarm().getId()).isNotEqualTo(alarm.getId()); + assertThat(alarmResult.isCreated()).isTrue(); + assertThat(alarmResult.getAlarm().getSeverity()).isEqualTo(AlarmSeverity.CRITICAL); + assertThat(alarmResult.getAlarm().getStatus()).isEqualTo(AlarmStatus.ACTIVE_UNACK); + }); + } + // TODO: MSA tests - // TODO: test when attribute or telemetry is deleted without default value - perform calculation not happens - private void checkAlarmResult(CalculatedField calculatedField, Consumer assertion) { - checkAlarmResult(calculatedField, null, assertion); + private TbAlarmResult checkAlarmResult(CalculatedField calculatedField, Consumer assertion) { + return checkAlarmResult(calculatedField, null, assertion); } - private void checkAlarmResult(CalculatedField calculatedField, - Predicate waitFor, - Consumer assertion) { + private TbAlarmResult checkAlarmResult(CalculatedField calculatedField, + Predicate waitFor, + Consumer assertion) { TbAlarmResult alarmResult = await().atMost(TIMEOUT, TimeUnit.SECONDS) .until(() -> getLatestAlarmResult(calculatedField.getId()), result -> result != null && (waitFor == null || waitFor.test(result))); @@ -707,6 +741,7 @@ public class AlarmRulesTest extends AbstractControllerTest { Alarm alarm = alarmResult.getAlarm(); assertThat(alarm.getOriginator()).isEqualTo(originatorId); assertThat(alarm.getType()).isEqualTo(calculatedField.getName()); + return alarmResult; } private TbAlarmResult getLatestAlarmResult(CalculatedFieldId calculatedFieldId) { diff --git a/application/src/test/resources/logback-test.xml b/application/src/test/resources/logback-test.xml index 13c93da411..56dbbfc125 100644 --- a/application/src/test/resources/logback-test.xml +++ b/application/src/test/resources/logback-test.xml @@ -17,6 +17,8 @@ + +