Browse Source

Fix NotificationRuleApiTest

pull/14193/head
VIacheslavKlimov 12 months ago
parent
commit
a0b38a7eb4
  1. 2
      application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java
  2. 91
      application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java

2
application/src/main/java/org/thingsboard/server/service/cf/ctx/state/alarm/AlarmCalculatedFieldState.java

@ -189,8 +189,6 @@ public class AlarmCalculatedFieldState extends BaseCalculatedFieldState {
@Override
public ListenableFuture<CalculatedFieldResult> performCalculation(Map<String, ArgumentEntry> updatedArgs, CalculatedFieldCtx ctx) {
initCurrentAlarm(ctx);
// FIXME: don't create alarm if attrs were deleted, or config is updated
// TODO: what if expression is changed? do we reevaluate? or only on new events?
TbAlarmResult result = createOrClearAlarms(state -> {
if (updatedArgs != null) {
boolean newEvent = !updatedArgs.isEmpty();

91
application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java

@ -27,7 +27,7 @@ import org.springframework.data.util.Pair;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.limits.RateLimitService;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityType;
@ -39,17 +39,19 @@ import org.thingsboard.server.common.data.alarm.AlarmCommentType;
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
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;
import org.thingsboard.server.common.data.alarm.rule.condition.SimpleAlarmCondition;
import org.thingsboard.server.common.data.alarm.rule.condition.expression.TbelAlarmConditionExpression;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.cf.CalculatedField;
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
import org.thingsboard.server.common.data.cf.configuration.AlarmCalculatedFieldConfiguration;
import org.thingsboard.server.common.data.cf.configuration.Argument;
import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey;
import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration;
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration;
import org.thingsboard.server.common.data.device.data.DeviceData;
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
import org.thingsboard.server.common.data.device.profile.AlarmRule;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.DeviceId;
@ -87,9 +89,6 @@ import org.thingsboard.server.common.data.notification.targets.platform.SystemAd
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
import org.thingsboard.server.common.data.query.EntityKeyValueType;
import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.security.Authority;
@ -106,12 +105,10 @@ import org.thingsboard.server.service.system.DefaultSystemInfoService;
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@ -193,7 +190,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
@Test
public void testNotificationRuleProcessing_alarmTrigger() throws Exception {
String notificationSubject = "Alarm type: ${alarmType}, status: ${alarmStatus}, " +
"severity: ${alarmSeverity}, deviceId: ${alarmOriginatorId}";
"severity: ${alarmSeverity}, deviceId: ${alarmOriginatorId}";
String notificationText = "Status: ${alarmStatus}, severity: ${alarmSeverity}";
NotificationTemplate notificationTemplate = createNotificationTemplate(NotificationType.ALARM, notificationSubject, notificationText, NotificationDeliveryMethod.WEB);
@ -234,8 +231,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
});
JsonNode attr = JacksonUtil.newObjectNode()
.set("bool", BooleanNode.TRUE);
doPost("/api/plugins/telemetry/" + device.getId() + "/" + DataConstants.SHARED_SCOPE, attr);
.set("createAlarm", BooleanNode.TRUE);
postAttributes(device.getId(), AttributeScope.SERVER_SCOPE, attr.toString());
await().atMost(10, TimeUnit.SECONDS)
.until(() -> alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType) != null);
@ -250,7 +247,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
assertThat(actualDelay).isCloseTo(expectedDelay, offset(2.0));
assertThat(notification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + AlarmStatus.ACTIVE_UNACK + ", " +
"severity: " + AlarmSeverity.CRITICAL.toString().toLowerCase() + ", deviceId: " + device.getId());
"severity: " + AlarmSeverity.CRITICAL.toString().toLowerCase() + ", deviceId: " + device.getId());
assertThat(notification.getText()).isEqualTo("Status: " + AlarmStatus.ACTIVE_UNACK + ", severity: " + AlarmSeverity.CRITICAL.toString().toLowerCase());
assertThat(notification.getType()).isEqualTo(NotificationType.ALARM);
@ -270,7 +267,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
wsClient.waitForUpdate(true);
Notification updatedNotification = wsClient.getLastDataUpdate().getUpdate();
assertThat(updatedNotification.getSubject()).isEqualTo("Alarm type: " + alarmType + ", status: " + expectedStatus + ", " +
"severity: " + expectedSeverity.toString().toLowerCase() + ", deviceId: " + device.getId());
"severity: " + expectedSeverity.toString().toLowerCase() + ", deviceId: " + device.getId());
assertThat(updatedNotification.getText()).isEqualTo("Status: " + expectedStatus + ", severity: " + expectedSeverity.toString().toLowerCase());
wsClient.close();
@ -296,7 +293,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
List<Notification> notifications = getMyNotifications(false, 10);
assertThat(notifications).singleElement().matches(notification -> {
return notification.getType() == NotificationType.ALARM &&
notification.getSubject().equals("New alarm 'testAlarm'");
notification.getSubject().equals("New alarm 'testAlarm'");
});
});
}
@ -341,8 +338,8 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
getWsClient().subscribeForUnreadNotifications(10).waitForReply(true);
getWsClient().registerWaitForUpdate();
JsonNode attr = JacksonUtil.newObjectNode()
.set("bool", BooleanNode.TRUE);
doPost("/api/plugins/telemetry/" + device.getId() + "/" + DataConstants.SHARED_SCOPE, attr);
.set("createAlarm", BooleanNode.TRUE);
postAttributes(device.getId(), AttributeScope.SERVER_SCOPE, attr.toString());
await().atMost(10, TimeUnit.SECONDS)
.until(() -> alarmSubscriptionService.findLatestByOriginatorAndType(tenantId, device.getId(), alarmType) != null);
@ -491,11 +488,11 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
});
assertThat(notifications).anySatisfy(notification -> {
assertThat(notification.getText()).isEqualTo("Rate limits for REST API requests per customer " +
"exceeded for 'Customer'");
"exceeded for 'Customer'");
});
assertThat(notifications).anySatisfy(notification -> {
assertThat(notification.getText()).isEqualTo("Rate limits for notification requests " +
"per rule exceeded for '" + rule.getName() + "'");
"per rule exceeded for '" + rule.getName() + "'");
});
loginSysAdmin();
@ -748,7 +745,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
.build();
assertThat(DefaultNotificationDeduplicationService.getDeduplicationKey(expectedTrigger, rule))
.isEqualTo("RATE_LIMITS:TENANT:" + tenantId + ":ENTITY_EXPORT_" +
target.getId() + ":ENTITY_EXPORT,TRANSPORT_MESSAGES_PER_DEVICE");
target.getId() + ":ENTITY_EXPORT,TRANSPORT_MESSAGES_PER_DEVICE");
loginTenantAdmin();
getWsClient().subscribeForUnreadNotifications(10).waitForReply();
@ -944,35 +941,27 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
private DeviceProfile createDeviceProfileWithAlarmRules(String alarmType) {
DeviceProfile deviceProfile = createDeviceProfile("For notification rule test");
deviceProfile.setTenantId(tenantId);
deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
List<DeviceProfileAlarm> alarms = new ArrayList<>();
DeviceProfileAlarm alarm = new DeviceProfileAlarm();
alarm.setAlarmType(alarmType);
alarm.setId(alarmType);
CalculatedField alarmCf = new CalculatedField();
alarmCf.setType(CalculatedFieldType.ALARM);
alarmCf.setEntityId(deviceProfile.getId());
alarmCf.setName(alarmType);
AlarmCalculatedFieldConfiguration configuration = new AlarmCalculatedFieldConfiguration();
Argument argument = new Argument();
argument.setRefEntityKey(new ReferencedEntityKey("createAlarm", ArgumentType.ATTRIBUTE, AttributeScope.SERVER_SCOPE));
configuration.setArguments(Map.of("createAlarm", argument));
AlarmRule alarmRule = new AlarmRule();
alarmRule.setAlarmDetails("Details");
AlarmCondition alarmCondition = new AlarmCondition();
alarmCondition.setSpec(new SimpleAlarmConditionSpec());
List<AlarmConditionFilter> condition = new ArrayList<>();
AlarmConditionFilter alarmConditionFilter = new AlarmConditionFilter();
alarmConditionFilter.setKey(new AlarmConditionFilterKey(AlarmConditionKeyType.ATTRIBUTE, "bool"));
BooleanFilterPredicate predicate = new BooleanFilterPredicate();
predicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL);
predicate.setValue(new FilterPredicateValue<>(true));
alarmConditionFilter.setPredicate(predicate);
alarmConditionFilter.setValueType(EntityKeyValueType.BOOLEAN);
condition.add(alarmConditionFilter);
alarmCondition.setCondition(condition);
alarmRule.setCondition(alarmCondition);
TreeMap<AlarmSeverity, AlarmRule> createRules = new TreeMap<>();
createRules.put(AlarmSeverity.CRITICAL, alarmRule);
alarm.setCreateRules(createRules);
alarms.add(alarm);
deviceProfile.getProfileData().setAlarms(alarms);
deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
SimpleAlarmCondition condition = new SimpleAlarmCondition();
TbelAlarmConditionExpression expression = new TbelAlarmConditionExpression();
expression.setExpression("return createAlarm == true;");
condition.setExpression(expression);
alarmRule.setCondition(condition);
configuration.setCreateRules(Map.of(
AlarmSeverity.CRITICAL, alarmRule
));
alarmCf.setConfiguration(configuration);
saveCalculatedField(alarmCf);
return deviceProfile;
}

Loading…
Cancel
Save