Merge pull request #6872 from thingsboard/refactoring_tests_11

[3.4] refactoring: tests EntityRelation
This commit is contained in:
Andrew Shvayka 2022-07-05 10:36:12 +03:00 committed by GitHub
commit 04d962c18c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 260 additions and 25 deletions

View File

@ -25,12 +25,14 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.ToDeviceActorNotificationMsg;
import org.thingsboard.server.dao.audit.AuditLogService;
@ -74,6 +76,39 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
Mockito.reset(tbClusterService, auditLogService);
}
protected void testNotifyEntityAllOneTimeRelation(EntityRelation relation,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, Object... additionalInfo) {
int cntTime = 1;
Mockito.verify(tbClusterService, times(cntTime)).sendNotificationMsgToEdge(Mockito.eq(tenantId),
Mockito.isNull(), Mockito.isNull(), Mockito.any(), Mockito.eq(EdgeEventType.RELATION),
Mockito.eq(edgeTypeByActionType(actionType)));
ArgumentMatcher<EntityId> matcherOriginatorId = argument -> argument.equals(relation.getTo());
ArgumentMatcher<HasName> matcherEntityClassEquals = Objects::isNull;
testLogEntityActionAdditionalInfo(matcherEntityClassEquals, matcherOriginatorId, tenantId, customerId, userId, userName, actionType, cntTime,
extractMatcherAdditionalInfo(additionalInfo));
testPushMsgToRuleEngineNever(relation.getTo());
matcherOriginatorId = argument -> argument.equals(relation.getFrom());
testLogEntityActionAdditionalInfo(matcherEntityClassEquals, matcherOriginatorId, tenantId, customerId, userId, userName, actionType, cntTime,
extractMatcherAdditionalInfo(additionalInfo));
testPushMsgToRuleEngineNever(relation.getFrom());
Mockito.reset(tbClusterService, auditLogService);
}
protected void testNotifyEntityAllManyRelation(EntityRelation relation,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, int cntTime) {
Mockito.verify(tbClusterService, times(cntTime)).sendNotificationMsgToEdge(Mockito.eq(tenantId),
Mockito.isNull(), Mockito.isNull(), Mockito.any(), Mockito.eq(EdgeEventType.RELATION),
Mockito.eq(edgeTypeByActionType(actionType)));
ArgumentMatcher<EntityId> matcherOriginatorId = argument -> argument.getClass().equals(relation.getFrom().getClass());
ArgumentMatcher<HasName> matcherEntityClassEquals = Objects::isNull;
testLogEntityActionAdditionalInfoAny(matcherEntityClassEquals, matcherOriginatorId, tenantId, customerId, userId,
userName, actionType, cntTime * 2, 1);
testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, cntTime);
Mockito.reset(tbClusterService, auditLogService);
}
protected void testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(HasName entity, EntityId entityId, EntityId originatorId,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, Object... additionalInfo) {
@ -100,7 +135,11 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
testNotificationMsgToEdgeServiceNever(entityId);
testLogEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo);
ArgumentMatcher<EntityId> matcherOriginatorId = argument -> argument.equals(originatorId);
testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, cntTime);
if (ActionType.RELATIONS_DELETED.equals(actionType)) {
testPushMsgToRuleEngineNever(originatorId);
} else {
testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, cntTime);
}
Mockito.reset(tbClusterService, auditLogService);
}
@ -160,8 +199,8 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
}
protected void testNotifyEntityBroadcastEntityStateChangeEventOneTime(HasName entity, EntityId entityId, EntityId originatorId,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, Object... additionalInfo) {
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, Object... additionalInfo) {
int cntTime = 1;
testSendNotificationMsgToEdgeServiceTime(entityId, tenantId, actionType, cntTime);
testLogEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo);
@ -184,8 +223,8 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
}
protected void testNotifyEntityBroadcastEntityStateChangeEventManyMsgToEdgeServiceNever(HasName entity, HasName originator,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, int cntTime, int cntAdditionalInfo) {
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, int cntTime, int cntAdditionalInfo) {
EntityId entityId = createEntityId_NULL_UUID(entity);
EntityId originatorId = createEntityId_NULL_UUID(originator);
testNotificationMsgToEdgeServiceNever(entityId);
@ -266,8 +305,10 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
}
private void testLogEntityActionNever(EntityId entityId, HasName entity) {
ArgumentMatcher<HasName> matcherEntity = entity == null ? Objects::isNull :
argument -> argument.getClass().equals(entity.getClass());
Mockito.verify(auditLogService, never()).logEntityAction(Mockito.any(), Mockito.any(),
Mockito.any(), Mockito.any(), Mockito.any(entityId.getClass()), Mockito.any(entity.getClass()),
Mockito.any(), Mockito.any(), Mockito.any(entityId.getClass()), Mockito.argThat(matcherEntity),
Mockito.any(), Mockito.any());
}
@ -307,7 +348,7 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
private void testLogEntityAction(HasName entity, EntityId originatorId, TenantId tenantId,
CustomerId customerId, UserId userId, String userName,
ActionType actionType, int cntTime, Object... additionalInfo) {
ArgumentMatcher<HasName> matcherEntityEquals = argument -> argument.equals(entity);
ArgumentMatcher<HasName> matcherEntityEquals = entity == null ? Objects::isNull : argument -> argument.equals(entity);
ArgumentMatcher<EntityId> matcherOriginatorId = argument -> argument.equals(originatorId);
testLogEntityActionAdditionalInfo(matcherEntityEquals, matcherOriginatorId, tenantId, customerId, userId, userName,
actionType, cntTime, extractMatcherAdditionalInfo(additionalInfo));
@ -521,11 +562,11 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
return EntityIdFactory.getByTypeAndUuid(entityClassToEntityTypeName(entity), ModelConstants.NULL_UUID);
}
protected String msgErrorFieldLength(String fieldName){
protected String msgErrorFieldLength(String fieldName) {
return "length of " + fieldName + " must be equal or less than 255";
}
protected String msgErrorNoFound(String entityClassName, String assetIdStr){
protected String msgErrorNoFound(String entityClassName, String assetIdStr) {
return entityClassName + " with id [" + assetIdStr + "] is not found";
}

View File

@ -22,6 +22,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
@ -29,6 +30,8 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.EntityRelationInfo;
import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
@ -41,7 +44,9 @@ import org.thingsboard.server.dao.relation.RelationService;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@ -93,8 +98,10 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
@Test
public void testSaveAndFindRelation() throws Exception {
Device device = buildSimpleDevice("Test device 1");
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
Mockito.reset(tbClusterService, auditLogService);
doPost("/api/relation", relation).andExpect(status().isOk());
String url = String.format("/api/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s",
@ -106,12 +113,73 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
Assert.assertNotNull("Relation is not found!", foundRelation);
Assert.assertEquals("Found relation is not equals origin!", relation, foundRelation);
testNotifyEntityAllOneTimeRelation(foundRelation,
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.RELATION_ADD_OR_UPDATE, foundRelation);
}
@Test
public void testSaveWithDeviceFromNotCreated() throws Exception {
Device device = new Device();
device.setName("Test device 2");
device.setType("default");
EntityRelation relation = createFromRelation(device, mainDevice, "CONTAINS");
Mockito.reset(tbClusterService, auditLogService);
doPost("/api/relation", relation)
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString("Parameter entityId can't be empty!")));
testNotifyEntityNever(mainDevice.getId(), null);
}
@Test
public void testSaveWithDeviceToNotCreated() throws Exception {
Device device = new Device();
device.setName("Test device 2");
device.setType("default");
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
Mockito.reset(tbClusterService, auditLogService);
doPost("/api/relation", relation)
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString("Parameter entityId can't be empty!")));
testNotifyEntityNever(mainDevice.getId(), null);
}
@Test
public void testSaveWithDeviceToMissing() throws Exception {
Device device = new Device();
device.setName("Test device 2");
device.setType("default");
device.setId(new DeviceId(UUID.randomUUID()));
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
Mockito.reset(tbClusterService, auditLogService);
doPost("/api/relation", relation)
.andExpect(status().isNotFound())
.andExpect(statusReason(containsString(msgErrorNoFound("Device", device.getId().getId().toString()))));
testNotifyEntityNever(mainDevice.getId(), null);
}
@Test
public void testSaveAndFindRelationsByFrom() throws Exception {
final int numOfDevices = 30;
Mockito.reset(tbClusterService, auditLogService);
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
EntityRelation relationTest = createFromRelation(mainDevice, mainDevice, "TEST_NOTIFY_ENTITY");
testNotifyEntityAllManyRelation(relationTest, savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.RELATION_ADD_OR_UPDATE, numOfDevices);
String url = String.format("/api/relations?fromId=%s&fromType=%s",
mainDevice.getUuidId(), EntityType.DEVICE
);
@ -136,32 +204,73 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
Device device = buildSimpleDevice("Unique dummy test device ");
EntityRelation relation = createFromRelation(mainDevice, device, "TEST");
String relationType = "TEST";
EntityRelation relation = createFromRelation(mainDevice, device, relationType);
doPost("/api/relation", relation).andExpect(status().isOk());
String url = String.format("/api/relations?fromId=%s&fromType=%s&relationType=%s",
mainDevice.getUuidId(), EntityType.DEVICE, "TEST"
mainDevice.getUuidId(), EntityType.DEVICE, relationType
);
assertFoundList(url, 1);
}
@Test
public void testSaveAndFindRelationsByFromWithRelationTypeOther() throws Exception {
final int numOfDevices = 30;
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
Device device = buildSimpleDevice("Unique dummy test device ");
String relationType = "TEST";
EntityRelation relation = createFromRelation(mainDevice, device, relationType);
doPost("/api/relation", relation).andExpect(status().isOk());
String relationTypeOther = "TEST_OTHER";
String url = String.format("/api/relations?fromId=%s&fromType=%s&relationType=%s",
mainDevice.getUuidId(), EntityType.DEVICE, relationTypeOther
);
assertFoundList(url, 0);
}
@Test
public void testSaveAndFindRelationsByToWithRelationType() throws Exception {
final int numOfDevices = 30;
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
Device device = buildSimpleDevice("Unique dummy test device ");
EntityRelation relation = createFromRelation(device, mainDevice, "TEST");
String relationType = "TEST";
EntityRelation relation = createFromRelation(device, mainDevice, relationType);
doPost("/api/relation", relation).andExpect(status().isOk());
String url = String.format("/api/relations?toId=%s&toType=%s&relationType=%s",
mainDevice.getUuidId(), EntityType.DEVICE, "TEST"
mainDevice.getUuidId(), EntityType.DEVICE, relationType
);
assertFoundList(url, 1);
}
@Test
public void testSaveAndFindRelationsByToWithRelationTypeOther() throws Exception {
final int numOfDevices = 30;
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
Device device = buildSimpleDevice("Unique dummy test device ");
String relationType = "TEST";
EntityRelation relation = createFromRelation(device, mainDevice, relationType);
doPost("/api/relation", relation).andExpect(status().isOk());
String relationTypeOther = "TEST_OTHER";
String url = String.format("/api/relations?toId=%s&toType=%s&relationType=%s",
mainDevice.getUuidId(), EntityType.DEVICE, relationTypeOther
);
assertFoundList(url, 0);
}
@Test
public void testFindRelationsInfoByFrom() throws Exception {
final int numOfDevices = 30;
@ -171,7 +280,7 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
);
List<EntityRelationInfo> relationsInfos =
JacksonUtil.convertValue(doGet(url, JsonNode.class), new TypeReference<List<EntityRelationInfo>>() {
JacksonUtil.convertValue(doGet(url, JsonNode.class), new TypeReference<>() {
});
Assert.assertNotNull("Relations is not found!", relationsInfos);
@ -190,7 +299,7 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
);
List<EntityRelationInfo> relationsInfos =
JacksonUtil.convertValue(doGet(url, JsonNode.class), new TypeReference<List<EntityRelationInfo>>() {
JacksonUtil.convertValue(doGet(url, JsonNode.class), new TypeReference<>() {
});
Assert.assertNotNull("Relations is not found!", relationsInfos);
@ -217,10 +326,62 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
Assert.assertNotNull("Relation is not found!", foundRelation);
Assert.assertEquals("Found relation is not equals origin!", relation, foundRelation);
Mockito.reset(tbClusterService, auditLogService);
doDelete(url).andExpect(status().isOk());
testNotifyEntityAllOneTimeRelation(foundRelation,
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.RELATION_DELETED, foundRelation);
doGet(url).andExpect(status().is4xxClientError());
}
@Test
public void testDeleteRelationWithOtherFromDeviceError() throws Exception {
Device device = buildSimpleDevice("Test device 1");
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
doPost("/api/relation", relation).andExpect(status().isOk());
Device device2 = buildSimpleDevice("Test device 2");
String url = String.format("/api/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s",
device2.getUuidId(), EntityType.DEVICE,
"CONTAINS", device.getUuidId(), EntityType.DEVICE
);
Mockito.reset(tbClusterService, auditLogService);
doDelete(url)
.andExpect(status().isNotFound())
.andExpect(statusReason(containsString("Requested item wasn't found!")));
testNotifyEntityNever(mainDevice.getId(), null);
}
@Test
public void testDeleteRelationWithOtherToDeviceError() throws Exception {
Device device = buildSimpleDevice("Test device 1");
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
doPost("/api/relation", relation).andExpect(status().isOk());
Device device2 = buildSimpleDevice("Test device 2");
String url = String.format("/api/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s",
mainDevice.getUuidId(), EntityType.DEVICE,
"CONTAINS", device2.getUuidId(), EntityType.DEVICE
);
Mockito.reset(tbClusterService, auditLogService);
doDelete(url)
.andExpect(status().isNotFound())
.andExpect(statusReason(containsString("Requested item wasn't found!")));
testNotifyEntityNever(mainDevice.getId(), null);
}
@Test
public void testDeleteRelations() throws Exception {
final int numOfDevices = 30;
@ -240,8 +401,15 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
String url = String.format("/api/relations?entityId=%s&entityType=%s",
mainDevice.getUuidId(), EntityType.DEVICE
);
Mockito.reset(tbClusterService, auditLogService);
doDelete(url).andExpect(status().isOk());
testNotifyEntityOneTimeMsgToEdgeServiceNever(null, mainDevice.getId(), mainDevice.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.RELATIONS_DELETED);
Assert.assertTrue(
"Performed deletion of all relations but some relations were found!",
doGet(urlTo, List.class).isEmpty()
@ -263,14 +431,15 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
EntitySearchDirection.FROM,
RelationTypeGroup.COMMON,
1, true
));
));
query.setFilters(Collections.singletonList(
new RelationEntityTypeFilter("CONTAINS", List.of(EntityType.DEVICE))
));
List<EntityRelation> relations = readResponse(
doPost("/api/relations", query).andExpect(status().isOk()),
new TypeReference<List<EntityRelation>>() {}
new TypeReference<List<EntityRelation>>() {
}
);
assertFoundRelations(relations, numOfDevices);
@ -294,14 +463,15 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
List<EntityRelation> relations = readResponse(
doPost("/api/relations", query).andExpect(status().isOk()),
new TypeReference<List<EntityRelation>>() {}
new TypeReference<>() {
}
);
assertFoundRelations(relations, numOfDevices);
}
@Test
public void testFindRelationsInfoByFromQuery() throws Exception{
public void testFindRelationsInfoByFromQuery() throws Exception {
final int numOfDevices = 30;
createDevicesByFrom(numOfDevices, BASE_DEVICE_NAME);
@ -318,14 +488,15 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
List<EntityRelationInfo> relationsInfo = readResponse(
doPost("/api/relations/info", query).andExpect(status().isOk()),
new TypeReference<List<EntityRelationInfo>>() {}
new TypeReference<>() {
}
);
assertRelationsInfosByFrom(relationsInfo);
}
@Test
public void testFindRelationsInfoByToQuery() throws Exception{
public void testFindRelationsInfoByToQuery() throws Exception {
final int numOfDevices = 30;
createDevicesByTo(numOfDevices, BASE_DEVICE_NAME);
@ -342,14 +513,15 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
List<EntityRelationInfo> relationsInfo = readResponse(
doPost("/api/relations/info", query).andExpect(status().isOk()),
new TypeReference<List<EntityRelationInfo>>() {}
new TypeReference<>() {
}
);
assertRelationsInfosByTo(relationsInfo);
}
@Test
public void testCreateRelationFromTenantToDevice() throws Exception{
public void testCreateRelationFromTenantToDevice() throws Exception {
EntityRelation relation = new EntityRelation(tenantAdmin.getTenantId(), mainDevice.getId(), "CONTAINS");
doPost("/api/relation", relation).andExpect(status().isOk());
@ -365,7 +537,7 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
}
@Test
public void testCreateRelationFromDeviceToTenant() throws Exception{
public void testCreateRelationFromDeviceToTenant() throws Exception {
EntityRelation relation = new EntityRelation(mainDevice.getId(), tenantAdmin.getTenantId(), "CONTAINS");
doPost("/api/relation", relation).andExpect(status().isOk());
@ -380,6 +552,28 @@ public abstract class BaseEntityRelationControllerTest extends AbstractControlle
Assert.assertEquals("Found relation is not equals origin!", relation, foundRelation);
}
@Test
public void testSaveAndFindRelationDifferentTenant() throws Exception {
Device device = buildSimpleDevice("Test device 1");
EntityRelation relation = createFromRelation(mainDevice, device, "CONTAINS");
doPost("/api/relation", relation).andExpect(status().isOk());
String url = String.format("/api/relation?fromId=%s&fromType=%s&relationType=%s&toId=%s&toType=%s",
mainDevice.getUuidId(), EntityType.DEVICE,
"CONTAINS", device.getUuidId(), EntityType.DEVICE
);
loginDifferentTenant();
doGet(url)
.andExpect(status().isNotFound())
.andExpect(statusReason(containsString(msgErrorNoFound("Device", relation.getFrom().getId().toString()))));
deleteDifferentTenant();
}
private Device buildSimpleDevice(String name) throws Exception {
Device device = new Device();
device.setName(name);