Browse Source

added tests for alarm comment services

pull/7762/head
dashevchenko 4 years ago
parent
commit
81ed6a6702
  1. 4
      application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java
  2. 10
      application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java
  3. 4
      application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java
  4. 16
      application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java
  5. 5
      application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java
  6. 1
      application/src/main/resources/thingsboard.yml
  7. 8
      application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java
  8. 384
      application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java
  9. 23
      application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java
  10. 96
      application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java
  11. 3
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java
  12. 2
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java
  13. 11
      dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java
  14. 2
      dao/src/main/resources/sql/schema-entities.sql
  15. 3
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  16. 160
      dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java
  17. 23
      dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java
  18. 90
      dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java

4
application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java

@ -77,7 +77,7 @@ public class AlarmCommentController extends BaseController {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
alarmComment.setAlarmId(alarmId);
return tbAlarmCommentService.saveAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser());
return tbAlarmCommentService.saveAlarmComment(alarm, alarmComment, getCurrentUser());
}
@ApiOperation(value = "Delete Alarm comment(deleteAlarmComment)",
@ -92,7 +92,7 @@ public class AlarmCommentController extends BaseController {
AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strCommentId));
AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId);
return tbAlarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser());
return tbAlarmCommentService.deleteAlarmComment(alarm, alarmComment, getCurrentUser());
}
@ApiOperation(value = "Get Alarm comments (getAlarmComments)",

10
application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java

@ -231,15 +231,13 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
}
@Override
public void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo) {
logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, actionType, user, additionalInfo);
// TODO: should we send notification to edge?
public void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) {
logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), actionType, user);
}
@Override
public void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo) {
logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, ActionType.DELETED, user, additionalInfo);
// TODO: should we send notification to edge?
public void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) {
logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), ActionType.DELETED, user);
}
@Override

4
application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java

@ -103,9 +103,9 @@ public interface TbNotificationEntityService {
void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, User user, Object... additionalInfo);
void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo);
void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user);
void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo);
void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user);
<E extends HasName, I extends EntityId> void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId,
I entityId, E entity, User user,
ActionType actionType, boolean sendNotifyMsgToEdge,

16
application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java

@ -19,10 +19,10 @@ import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
@ -30,22 +30,22 @@ import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
@AllArgsConstructor
public class DefaultTbAlarmCommentService extends AbstractTbEntityService implements TbAlarmCommentService{
@Override
public AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException {
public AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException {
ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
UserId userId = user.getId();
alarmComment.setUserId(userId);
try {
AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment());
notificationEntityService.notifyCreateOrUpdateAlarmComment(tenantId, savedAlarmComment, actionType, user);
AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment).getAlarmComment());
notificationEntityService.notifyCreateOrUpdateAlarmComment(alarm, savedAlarmComment, actionType, user);
return savedAlarmComment;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e);
notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e);
throw e;
}
}
@Override
public Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) {
notificationEntityService.notifyDeleteAlarmComment(tenantId, alarmComment, user);
return alarmCommentService.deleteAlarmComment(tenantId, alarmComment.getId()).isSuccessful();
public Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) {
notificationEntityService.notifyDeleteAlarmComment(alarm, alarmComment, user);
return alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()).isSuccessful();
}
}

5
application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java

@ -16,12 +16,13 @@
package org.thingsboard.server.service.entitiy.alarm;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
public interface TbAlarmCommentService {
AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException;
AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException;
Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user);
Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user);
}

1
application/src/main/resources/thingsboard.yml

@ -584,6 +584,7 @@ audit-log:
"user": "${AUDIT_LOG_MASK_USER:W}"
"rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}"
"alarm": "${AUDIT_LOG_MASK_ALARM:W}"
"alarm_comment": "${AUDIT_LOG_MASK_ALARM_COMMENT:W}"
"entity_view": "${AUDIT_LOG_MASK_ENTITY_VIEW:W}"
"device_profile": "${AUDIT_LOG_MASK_DEVICE_PROFILE:W}"
"asset_profile": "${AUDIT_LOG_MASK_ASSET_PROFILE:W}"

8
application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java

@ -340,6 +340,12 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
Mockito.argThat(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull());
}
protected void testPushMsgToRuleEngineTime(EntityId matcherOriginatorId, TenantId tenantId, HasName entity, int cntTime) {
tenantId = tenantId.isNullUid() && ((HasTenantId) entity).getTenantId() != null ? ((HasTenantId) entity).getTenantId() : tenantId;
Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId),
Mockito.eq(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull());
}
private void testNotificationMsgToEdgeServiceTime(EntityId entityId, TenantId tenantId, ActionType actionType, int cntTime) {
EdgeEventActionType edgeEventActionType = ActionType.CREDENTIALS_UPDATED.equals(actionType) ?
EdgeEventActionType.CREDENTIALS_UPDATED : edgeTypeByActionType(actionType);
@ -367,7 +373,7 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
Mockito.verify(tbClusterService, times(cntTime)).pushMsgToCore(Mockito.any(ToDeviceActorNotificationMsg.class), Mockito.isNull());
}
private void testLogEntityAction(HasName entity, EntityId originatorId, TenantId tenantId,
protected void testLogEntityAction(HasName entity, EntityId originatorId, TenantId tenantId,
CustomerId customerId, UserId userId, String userName,
ActionType actionType, int cntTime, Object... additionalInfo) {
ArgumentMatcher<HasName> matcherEntityEquals = entity == null ? Objects::isNull : argument -> argument.toString().equals(entity.toString());

384
application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java

@ -0,0 +1,384 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.TextNode;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.AdditionalAnswers;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.test.context.ContextConfiguration;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.dao.alarm.AlarmDao;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@ContextConfiguration(classes = {BaseAlarmCommentControllerTest.Config.class})
public abstract class BaseAlarmCommentControllerTest extends AbstractControllerTest {
protected Device customerDevice;
protected Alarm alarm;
static class Config {
@Bean
@Primary
public AlarmDao alarmDao(AlarmDao alarmDao) {
return Mockito.mock(AlarmDao.class, AdditionalAnswers.delegatesTo(alarmDao));
}
}
@Before
public void setup() throws Exception {
loginTenantAdmin();
Device device = new Device();
device.setTenantId(tenantId);
device.setName("Test device");
device.setLabel("Label");
device.setType("Type");
device.setCustomerId(customerId);
customerDevice = doPost("/api/device", device, Device.class);
alarm = Alarm.builder()
.tenantId(tenantId)
.customerId(customerId)
.originator(customerDevice.getId())
.status(AlarmStatus.ACTIVE_UNACK)
.severity(AlarmSeverity.CRITICAL)
.type("test alarm type")
.build();
alarm = doPost("/api/alarm", alarm, Alarm.class);
resetTokens();
}
@After
public void teardown() throws Exception {
Mockito.reset(tbClusterService, auditLogService);
loginSysAdmin();
deleteDifferentTenant();
}
@Test
public void testCreateAlarmCommentViaCustomer() throws Exception {
loginCustomerUser();
Mockito.reset(tbClusterService, auditLogService);
AlarmComment createdComment = createAlarmComment(alarm.getId());
testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ADDED, 1);
testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1);
}
@Test
public void testCreateAlarmCommentViaTenant() throws Exception {
loginTenantAdmin();
Mockito.reset(tbClusterService, auditLogService);
AlarmComment createdComment = createAlarmComment(alarm.getId());
Assert.assertEquals("OTHER", createdComment.getType());
testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED, 1);
testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1);
}
@Test
public void testUpdateAlarmCommentViaCustomer() throws Exception {
loginCustomerUser();
AlarmComment savedComment = createAlarmComment(alarm.getId());
Mockito.reset(tbClusterService, auditLogService);
JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment"));
savedComment.setComment(newComment);
AlarmComment updatedAlarmComment = saveAlarmComment(alarm.getId(), savedComment);
Assert.assertNotNull(updatedAlarmComment);
Assert.assertEquals(newComment.get("text"), updatedAlarmComment.getComment().get("text"));
Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText());
Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn"));
testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(),
tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED);
}
@Test
public void testUpdateAlarmViaTenant() throws Exception {
loginTenantAdmin();
AlarmComment savedComment = createAlarmComment(alarm.getId());
Mockito.reset(tbClusterService, auditLogService);
JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment"));
savedComment.setComment(newComment);
AlarmComment updatedAlarmComment = saveAlarmComment(alarm.getId(), savedComment);
Assert.assertNotNull(updatedAlarmComment);
Assert.assertEquals(newComment.get("text"), updatedAlarmComment.getComment().get("text"));
Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText());
Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn"));
testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(),
tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED);
}
@Test
public void testUpdateAlarmViaDifferentTenant() throws Exception {
loginTenantAdmin();
AlarmComment savedComment = createAlarmComment(alarm.getId());
loginDifferentTenant();
Mockito.reset(tbClusterService, auditLogService);
JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment"));
savedComment.setComment(newComment);
doPost("/api/alarm/" + alarm.getId() + "/comment", savedComment)
.andExpect(status().isForbidden())
.andExpect(statusReason(containsString(msgErrorPermission)));
testNotifyEntityNever(savedComment.getId(), savedComment);
}
@Test
public void testUpdateAlarmViaDifferentCustomer() throws Exception {
loginCustomerUser();
AlarmComment savedComment = createAlarmComment(alarm.getId());
loginDifferentCustomer();
Mockito.reset(tbClusterService, auditLogService);
JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment"));
savedComment.setComment(newComment);
doPost("/api/alarm/" + alarm.getId() + "/comment", savedComment)
.andExpect(status().isForbidden())
.andExpect(statusReason(containsString(msgErrorPermission)));
testNotifyEntityNever(savedComment.getId(), savedComment);
}
@Test
public void testDeleteAlarmViaCustomer() throws Exception {
loginCustomerUser();
AlarmComment alarmComment = createAlarmComment(alarm.getId());
Mockito.reset(tbClusterService, auditLogService);
doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId())
.andExpect(status().isOk());
testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(),
tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED);
}
@Test
public void testDeleteAlarmViaTenant() throws Exception {
loginTenantAdmin();
AlarmComment alarmComment = createAlarmComment(alarm.getId());
Mockito.reset(tbClusterService, auditLogService);
doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId())
.andExpect(status().isOk());
testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(),
tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED);
}
@Test
public void testDeleteAlarmViaDifferentTenant() throws Exception {
loginTenantAdmin();
AlarmComment alarmComment = createAlarmComment(alarm.getId());
loginDifferentTenant();
Mockito.reset(tbClusterService, auditLogService);
doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId())
.andExpect(status().isForbidden())
.andExpect(statusReason(containsString(msgErrorPermission)));
testNotifyEntityNever(alarm.getId(), alarm);
}
@Test
public void testDeleteAlarmViaDifferentCustomer() throws Exception {
loginCustomerUser();
AlarmComment alarmComment = createAlarmComment(alarm.getId());
loginDifferentCustomer();
Mockito.reset(tbClusterService, auditLogService);
doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId())
.andExpect(status().isForbidden())
.andExpect(statusReason(containsString(msgErrorPermission)));
testNotifyEntityNever(alarm.getId(), alarm);
}
@Test
public void testClearAlarmViaCustomer() throws Exception {
loginCustomerUser();
AlarmComment alarmComment = createAlarmComment(alarm.getId());
Mockito.reset(tbClusterService, auditLogService);
doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isOk());
Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class);
Assert.assertNotNull(foundAlarm);
Assert.assertEquals(AlarmStatus.CLEARED_UNACK, foundAlarm.getStatus());
}
@Test
public void testFindAlarmCommentsViaCustomerUser() throws Exception {
loginCustomerUser();
List<AlarmComment> createdAlarmComments = new LinkedList<>();
final int size = 10;
for (int i = 0; i < size; i++) {
createdAlarmComments.add(
createAlarmComment(alarm.getId(), RandomStringUtils.randomAlphanumeric(10))
);
}
var response = doGetTyped(
"/api/alarm/" + alarm.getId() + "/comment?page=0&pageSize=" + size,
new TypeReference<PageData<AlarmCommentInfo>>() {}
);
var foundAlarmCommentInfos = response.getData();
Assert.assertNotNull("Found pageData is null", foundAlarmCommentInfos);
Assert.assertNotEquals(
"Expected alarms are not found!",
0, foundAlarmCommentInfos.size()
);
boolean allMatch = createdAlarmComments.stream()
.allMatch(alarmComment -> foundAlarmCommentInfos.stream()
.map(AlarmCommentInfo::getComment)
.anyMatch(comment -> alarmComment.getComment().equals(comment))
);
Assert.assertTrue("Created alarm comment doesn't match any found!", allMatch);
}
@Test
public void testFindAlarmsViaDifferentCustomerUser() throws Exception {
loginCustomerUser();
final int size = 10;
List<AlarmComment> createdAlarmComments = new LinkedList<>();
for (int i = 0; i < size; i++) {
createdAlarmComments.add(
createAlarmComment(alarm.getId(), RandomStringUtils.randomAlphanumeric(10))
);
}
loginDifferentCustomer();
doGet("/api/alarm/" + alarm.getId() + "/comment?page=0&pageSize=" + size)
.andExpect(status().isForbidden())
.andExpect(statusReason(containsString(msgErrorPermission)));
}
@Test
public void testFindAlarmCommentsViaPublicCustomer() throws Exception {
loginTenantAdmin();
Device device = new Device();
device.setName("Test Public Device");
device.setLabel("Label");
device.setCustomerId(customerId);
device = doPost("/api/device", device, Device.class);
device = doPost("/api/customer/public/device/" + device.getUuidId(), Device.class);
String publicId = device.getCustomerId().toString();
Alarm alarm = Alarm.builder()
.originator(device.getId())
.status(AlarmStatus.ACTIVE_UNACK)
.severity(AlarmSeverity.CRITICAL)
.type("Test")
.build();
alarm = doPost("/api/alarm", alarm, Alarm.class);
Mockito.reset(tbClusterService, auditLogService);
AlarmComment alarmComment = createAlarmComment(alarm.getId());
resetTokens();
JsonNode publicLoginRequest = JacksonUtil.toJsonNode("{\"publicId\": \"" + publicId + "\"}");
JsonNode tokens = doPost("/api/auth/login/public", publicLoginRequest, JsonNode.class);
this.token = tokens.get("token").asText();
PageData<AlarmCommentInfo> pageData = doGetTyped(
"/api/alarm/" + alarm.getId() + "/comment" + "?page=0&pageSize=1", new TypeReference<PageData<AlarmCommentInfo>>() {}
);
Assert.assertNotNull("Found pageData is null", pageData);
Assert.assertNotEquals("Expected alarms are not found!", 0, pageData.getTotalElements());
AlarmCommentInfo alarmCommentInfo = pageData.getData().get(0);
boolean equals = alarmComment.getId().equals(alarmCommentInfo.getId()) && alarmComment.getComment().equals(alarmCommentInfo.getComment());
Assert.assertTrue("Created alarm doesn't match the found one!", equals);
}
private AlarmComment createAlarmComment(AlarmId alarmId, String text) {
AlarmComment alarmComment = AlarmComment.builder()
.comment(JacksonUtil.newObjectNode().set("text", new TextNode(text)))
.build();
return saveAlarmComment(alarmId, alarmComment);
}
private AlarmComment createAlarmComment(AlarmId alarmId) {
return createAlarmComment(alarmId, "Please take a look");
}
private AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) {
alarmComment = doPost("/api/alarm/" + alarmId + "/comment", alarmComment, AlarmComment.class);
Assert.assertNotNull(alarmComment);
return alarmComment;
}
}

23
application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller.sql;
import org.thingsboard.server.controller.BaseAlarmCommentControllerTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest
public class AlarmCommentControllerSqlTest extends BaseAlarmCommentControllerTest {
}

96
application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java

@ -0,0 +1,96 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.entitiy.alarmComment;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AlarmCommentId;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.dao.alarm.AlarmCommentOperationResult;
import org.thingsboard.server.dao.alarm.AlarmCommentService;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.service.entitiy.TbNotificationEntityService;
import org.thingsboard.server.service.entitiy.alarm.DefaultTbAlarmCommentService;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.telemetry.AlarmSubscriptionService;
import java.util.UUID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@Slf4j
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = DefaultTbAlarmCommentService.class)
@TestPropertySource(properties = {
"server.log_controller_error_stack_trace=false"
})
public class DefaultTbAlarmCommentServiceTest {
@MockBean
protected DbCallbackExecutorService dbExecutor;
@MockBean
protected TbNotificationEntityService notificationEntityService;
@MockBean
protected AlarmService alarmService;
@MockBean
protected AlarmCommentService alarmCommentService;
@MockBean
protected AlarmSubscriptionService alarmSubscriptionService;
@MockBean
protected CustomerService customerService;
@MockBean
protected TbClusterService tbClusterService;
@SpyBean
DefaultTbAlarmCommentService service;
@Test
public void testSave() throws ThingsboardException {
var alarm = new Alarm();
var alarmComment = new AlarmComment();
when(alarmCommentService.createOrUpdateAlarmComment(Mockito.any(), eq(alarmComment))).thenReturn(new AlarmCommentOperationResult(alarmComment, true));
service.saveAlarmComment(alarm, alarmComment, new User());
verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarmComment(any(), any(), any(), any());
}
@Test
public void testDelete() {
var alarmId = new AlarmId(UUID.randomUUID());
var alarmCommentId = new AlarmCommentId(UUID.randomUUID());
when(alarmCommentService.deleteAlarmComment(Mockito.any(), eq(alarmCommentId))).thenReturn(new AlarmCommentOperationResult(new AlarmComment(), true));
service.deleteAlarmComment(new Alarm(alarmId), new AlarmComment(alarmCommentId), new User());
verify(notificationEntityService, times(1)).notifyDeleteAlarmComment(any(), any(), any());
}
}

3
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.common.data.alarm;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -65,6 +66,8 @@ public class AlarmComment extends BaseData<AlarmCommentId> implements HasName {
}
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
@ApiModelProperty(position = 5, required = true, value = "representing comment text", example = "Please take a look")
public String getName() {
return comment.toString();
}

2
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java

@ -19,7 +19,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel
public class AlarmCommentInfo extends AlarmComment{
public class AlarmCommentInfo extends AlarmComment {
private static final long serialVersionUID = 2807343093519543377L;
@ApiModelProperty(position = 19, value = "User name", example = "John")

11
dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java

@ -33,7 +33,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.user.UserService;
@ -52,8 +51,6 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al
@Autowired
private UserService userService;
@Autowired
private EntityService entityService;
@Autowired
private DataValidator<AlarmComment> alarmCommentDataValidator;
@Override
public AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) {
@ -77,7 +74,7 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al
@Override
public ListenableFuture<PageData<AlarmCommentInfo>> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) {
PageData<AlarmCommentInfo> alarmComments = alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink);
return fetchAlarmCommentUserNames(tenantId,alarmComments);
return fetchAlarmCommentUserNames(tenantId, alarmComments);
}
private ListenableFuture<PageData<AlarmCommentInfo>> fetchAlarmCommentUserNames(TenantId tenantId, PageData<AlarmCommentInfo> alarmComments) {
@ -85,8 +82,10 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al
for (AlarmCommentInfo alarmCommentInfo : alarmComments.getData()) {
alarmCommentFutures.add(Futures.transform(
userService.findUserByIdAsync(tenantId, alarmCommentInfo.getUserId()), user -> {
alarmCommentInfo.setFirstName(user.getFirstName());
alarmCommentInfo.setLastName(user.getLastName());
if (user != null) {
alarmCommentInfo.setFirstName(user.getFirstName());
alarmCommentInfo.setLastName(user.getLastName());
}
return alarmCommentInfo;
}, MoreExecutors.directExecutor()
));

2
dao/src/main/resources/sql/schema-entities.sql

@ -777,7 +777,7 @@ CREATE TABLE IF NOT EXISTS user_auth_settings (
two_fa_settings varchar
);
REATE TABLE IF NOT EXISTS alarm_comment (
CREATE TABLE IF NOT EXISTS alarm_comment (
id uuid NOT NULL,
created_time bigint NOT NULL,
alarm_id uuid NOT NULL,

3
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.dao.alarm.AlarmCommentService;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetProfileService;
import org.thingsboard.server.dao.asset.AssetService;
@ -149,6 +150,8 @@ public abstract class AbstractServiceTest {
@Autowired
protected AlarmService alarmService;
@Autowired
protected AlarmCommentService alarmCommentService;
@Autowired
protected RuleChainService ruleChainService;

160
dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java

@ -0,0 +1,160 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.service;
import com.datastax.oss.driver.api.core.uuid.Uuids;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest {
public static final String TEST_ALARM = "TEST_ALARM";
private TenantId tenantId;
private Alarm alarm;
private User user;
@Before
public void before() {
Tenant tenant = new Tenant();
tenant.setTitle("My tenant");
Tenant savedTenant = tenantService.saveTenant(tenant);
Assert.assertNotNull(savedTenant);
tenantId = savedTenant.getId();
alarm = Alarm.builder().tenantId(tenantId).originator(new AssetId(Uuids.timeBased()))
.type(TEST_ALARM)
.severity(AlarmSeverity.CRITICAL).status(AlarmStatus.ACTIVE_UNACK)
.startTs(System.currentTimeMillis()).build();
alarm = alarmService.createOrUpdateAlarm(alarm).getAlarm();
user = new User();
user.setAuthority(Authority.TENANT_ADMIN);
user.setTenantId(tenantId);
user.setEmail("tenant@thingsboard.org");
user = userService.saveUser(user);
}
@After
public void after() {
alarmService.deleteAlarm(tenantId, alarm.getId());
tenantService.deleteTenant(tenantId);
}
@Test
public void testSaveAndFetchAlarmComment() throws ExecutionException, InterruptedException {
AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId())
.userId(user.getId())
.type("OTHER")
.comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10)))
.build();
AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment();
Assert.assertNotNull(createdComment);
Assert.assertNotNull(createdComment.getId());
Assert.assertEquals(alarm.getId(), createdComment.getAlarmId());
Assert.assertEquals(user.getId(), createdComment.getUserId());
Assert.assertEquals("OTHER", createdComment.getType());
Assert.assertTrue(createdComment.getCreatedTime() > 0);
AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get();
Assert.assertEquals(createdComment, fetched);
PageData<AlarmCommentInfo> alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get();
Assert.assertNotNull(alarmComments.getData());
Assert.assertEquals(1, alarmComments.getData().size());
Assert.assertEquals(createdComment, alarmComments.getData().get(0));
}
@Test
public void testUpdateAlarmComment() throws ExecutionException, InterruptedException {
UserId userId = new UserId(UUID.randomUUID());
AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId())
.userId(userId)
.type("OTHER")
.comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10)))
.build();
AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment();
Assert.assertNotNull(createdComment);
Assert.assertNotNull(createdComment.getId());
//update comment
String newComment = "new comment";
createdComment.setComment(JacksonUtil.newObjectNode().put("text", newComment));
AlarmComment updatedComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, createdComment).getAlarmComment();
Assert.assertEquals(alarm.getId(), updatedComment.getAlarmId());
Assert.assertEquals(userId, updatedComment.getUserId());
Assert.assertEquals("OTHER", updatedComment.getType());
Assert.assertTrue(updatedComment.getCreatedTime() > 0);
Assert.assertEquals(newComment, updatedComment.getComment().get("text").asText());
Assert.assertEquals("true", updatedComment.getComment().get("edited").asText());
Assert.assertNotNull(updatedComment.getComment().get("editedOn").asText());
AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get();
Assert.assertEquals(updatedComment, fetched);
PageData<AlarmCommentInfo> alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get();
Assert.assertNotNull(alarmComments.getData());
Assert.assertEquals(1, alarmComments.getData().size());
Assert.assertEquals(new AlarmCommentInfo(updatedComment), alarmComments.getData().get(0));
}
@Test
public void testDeleteAlarmComment() throws ExecutionException, InterruptedException {
UserId userId = new UserId(UUID.randomUUID());
AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId())
.userId(userId)
.type("OTHER")
.comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10)))
.build();
AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment();
Assert.assertNotNull(createdComment);
Assert.assertNotNull(createdComment.getId());
Assert.assertTrue("Alarm comment was not deleted when expected", alarmCommentService.deleteAlarmComment(tenantId, createdComment.getId()).isSuccessful());
AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get();
Assert.assertNull("Alarm comment was returned when it was expected to be null", fetched);
}
}

23
dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.service.sql;
import org.thingsboard.server.dao.service.BaseAlarmCommentServiceTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest
public class AlarmCommentServiceSqlTest extends BaseAlarmCommentServiceTest {
}

90
dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java

@ -0,0 +1,90 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.sql.alarm;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.AlarmCommentId;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.AbstractJpaDaoTest;
import org.thingsboard.server.dao.alarm.AlarmCommentDao;
import org.thingsboard.server.dao.alarm.AlarmDao;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
@Slf4j
public class JpaAlarmCommentDaoTest extends AbstractJpaDaoTest {
@Autowired
private AlarmCommentDao alarmCommentDao;
@Autowired
private AlarmDao alarmDao;
@Test
public void testFindAlarmCommentsByAlarmId() {
log.info("Current system time in millis = {}", System.currentTimeMillis());
UUID tenantId = UUID.randomUUID();
UUID userId = UUID.randomUUID();
UUID alarmId1 = UUID.randomUUID();
UUID alarmId2 = UUID.randomUUID();
UUID commentId1 = UUID.randomUUID();
UUID commentId2 = UUID.randomUUID();
UUID commentId3 = UUID.randomUUID();
saveAlarm(alarmId1, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM");
saveAlarm(alarmId2, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM");
saveAlarmComment(commentId1, alarmId1, userId, "OTHER");
saveAlarmComment(commentId2, alarmId1, userId, "OTHER");
saveAlarmComment(commentId3, alarmId2, userId, "OTHER");
int count = alarmCommentDao.findAlarmComments(TenantId.fromUUID(tenantId), new AlarmId(alarmId1), new PageLink(10, 0)).getData().size();
assertEquals(2, count);
}
private void saveAlarm(UUID id, UUID tenantId, UUID deviceId, String type) {
Alarm alarm = new Alarm();
alarm.setId(new AlarmId(id));
alarm.setTenantId(TenantId.fromUUID(tenantId));
alarm.setOriginator(new DeviceId(deviceId));
alarm.setType(type);
alarm.setPropagate(true);
alarm.setStartTs(System.currentTimeMillis());
alarm.setEndTs(System.currentTimeMillis());
alarm.setStatus(AlarmStatus.ACTIVE_UNACK);
alarmDao.save(TenantId.fromUUID(tenantId), alarm);
}
private void saveAlarmComment(UUID id, UUID alarmId, UUID userId, String type) {
AlarmComment alarmComment = new AlarmComment();
alarmComment.setId(new AlarmCommentId(id));
alarmComment.setAlarmId(TenantId.fromUUID(alarmId));
alarmComment.setUserId(new UserId(userId));
alarmComment.setType(type);
alarmComment.setComment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10)));
alarmCommentDao.createAlarmComment(TenantId.fromUUID(UUID.randomUUID()), alarmComment);
}
}
Loading…
Cancel
Save