diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntitiesIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java similarity index 57% rename from rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntitiesIdAsyncLoaderTest.java rename to rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java index fc93206c18..b29e451eaf 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntitiesIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java @@ -18,16 +18,13 @@ package org.thingsboard.rule.engine.util; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.ArgumentMatchers; import org.thingsboard.common.util.ListeningExecutor; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.data.RelationsQuery; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; @@ -36,25 +33,29 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationEntityTypeFilter; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import org.thingsboard.server.dao.relation.RelationService; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.Callable; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.thingsboard.common.util.DonAsynchron.withCallback; -@ExtendWith(MockitoExtension.class) -public class EntitiesRelatedEntitiesIdAsyncLoaderTest { +public class EntitiesRelatedEntityIdAsyncLoaderTest { - private static final EntityId DUMMY_ORIGINATOR = new DeviceId(UUID.randomUUID()); + private static final EntityId ASSET_ORIGINATOR_ID = new AssetId(UUID.randomUUID()); private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = new ListeningExecutor() { @Override @@ -71,23 +72,34 @@ public class EntitiesRelatedEntitiesIdAsyncLoaderTest { command.run(); } }; - @Mock + private TbContext ctxMock; - @Mock private RelationService relationServiceMock; - @Test - public void givenRelationsQuery_whenFindEntityAsync_ShouldBuildCorrectEntityRelationsQuery() { - // GIVEN - var relationsQuery = new RelationsQuery(); - var relationEntityTypeFilter = new RelationEntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.emptyList()); + private RelationsQuery relationsQuery; + + @BeforeEach + void setUp() { + ctxMock = mock(TbContext.class); + relationServiceMock = mock(RelationService.class); + when(ctxMock.getRelationService()).thenReturn(relationServiceMock); + when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR); + + relationsQuery = new RelationsQuery(); relationsQuery.setDirection(EntitySearchDirection.FROM); relationsQuery.setMaxLevel(1); - relationsQuery.setFilters(Collections.singletonList(relationEntityTypeFilter)); + RelationEntityTypeFilter entityTypeFilter = new RelationEntityTypeFilter( + EntityRelation.CONTAINS_TYPE, Collections.emptyList() + ); + relationsQuery.setFilters(Collections.singletonList(entityTypeFilter)); + } + @Test + public void givenRelationsQuery_whenFindEntityAsync_ShouldBuildCorrectEntityRelationsQuery() { + // GIVEN var expectedEntityRelationsQuery = new EntityRelationsQuery(); var parameters = new RelationsSearchParameters( - DUMMY_ORIGINATOR, + ASSET_ORIGINATOR_ID, relationsQuery.getDirection(), relationsQuery.getMaxLevel(), relationsQuery.isFetchLastLevelOnly() @@ -102,27 +114,19 @@ public class EntitiesRelatedEntitiesIdAsyncLoaderTest { when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR); // WHEN - EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, DUMMY_ORIGINATOR, relationsQuery); + EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, ASSET_ORIGINATOR_ID, relationsQuery); // THEN verify(relationServiceMock, times(1)).findByQuery(eq(TENANT_ID), eq(expectedEntityRelationsQuery)); } + @Test public void givenSeveralEntitiesFound_whenFindEntityAsync_ShouldKeepOneAndDiscardOthers() throws Exception { // GIVEN - var relationsQuery = new RelationsQuery(); - var relationEntityTypeFilter = new RelationEntityTypeFilter( - EntityRelation.CONTAINS_TYPE, - List.of(EntityType.DEVICE, EntityType.ASSET) - ); - relationsQuery.setDirection(EntitySearchDirection.FROM); - relationsQuery.setMaxLevel(2); - relationsQuery.setFilters(Collections.singletonList(relationEntityTypeFilter)); - var expectedEntityRelationsQuery = new EntityRelationsQuery(); var parameters = new RelationsSearchParameters( - DUMMY_ORIGINATOR, + ASSET_ORIGINATOR_ID, relationsQuery.getDirection(), relationsQuery.getMaxLevel(), relationsQuery.isFetchLastLevelOnly() @@ -134,25 +138,25 @@ public class EntitiesRelatedEntitiesIdAsyncLoaderTest { device1.setName("Device 1"); var device2 = new Device(new DeviceId(UUID.randomUUID())); device1.setName("Device 2"); - var asset = new Asset(new AssetId(UUID.randomUUID())); - asset.setName("Asset"); + var device3 = new Device(new DeviceId(UUID.randomUUID())); + device3.setName("Device 3"); var entityRelationDevice1 = new EntityRelation(); - entityRelationDevice1.setFrom(DUMMY_ORIGINATOR); + entityRelationDevice1.setFrom(ASSET_ORIGINATOR_ID); entityRelationDevice1.setTo(device1.getId()); entityRelationDevice1.setType(EntityRelation.CONTAINS_TYPE); var entityRelationDevice2 = new EntityRelation(); - entityRelationDevice2.setFrom(DUMMY_ORIGINATOR); + entityRelationDevice2.setFrom(ASSET_ORIGINATOR_ID); entityRelationDevice2.setTo(device2.getId()); entityRelationDevice2.setType(EntityRelation.CONTAINS_TYPE); - var entityRelationAsset = new EntityRelation(); - entityRelationAsset.setFrom(DUMMY_ORIGINATOR); - entityRelationAsset.setTo(asset.getId()); - entityRelationAsset.setType(EntityRelation.CONTAINS_TYPE); + var entityRelationDevice3 = new EntityRelation(); + entityRelationDevice3.setFrom(ASSET_ORIGINATOR_ID); + entityRelationDevice3.setTo(device3.getId()); + entityRelationDevice3.setType(EntityRelation.CONTAINS_TYPE); - var expectedEntityRelationsList = List.of(entityRelationDevice1, entityRelationDevice2, entityRelationAsset); + var expectedEntityRelationsList = List.of(entityRelationDevice1, entityRelationDevice2, entityRelationDevice3); when(ctxMock.getTenantId()).thenReturn(TENANT_ID); when(ctxMock.getRelationService()).thenReturn(relationServiceMock); @@ -161,7 +165,7 @@ public class EntitiesRelatedEntitiesIdAsyncLoaderTest { when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR); // WHEN - var deviceIdFuture = EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, DUMMY_ORIGINATOR, relationsQuery); + var deviceIdFuture = EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, ASSET_ORIGINATOR_ID, relationsQuery); // THEN assertNotNull(deviceIdFuture); @@ -171,4 +175,62 @@ public class EntitiesRelatedEntitiesIdAsyncLoaderTest { assertEquals(device1.getId(), actualDeviceId); } + + @Test + public void givenRelationQuery_whenFindEntityAsync_thenOK() { + // GIVEN + List entityRelations = new ArrayList<>(); + entityRelations.add(createEntityRelation(TENANT_ID, ASSET_ORIGINATOR_ID)); + when(relationServiceMock.findByQuery(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Futures.immediateFuture(entityRelations)); + + // WHEN + ListenableFuture entityIdFuture = EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, TENANT_ID, relationsQuery); + + // THEN + verifyEntityIdFuture(entityIdFuture, ASSET_ORIGINATOR_ID); + } + + @Test + public void givenRelationQuery_whenFindEntityAsync_thenReturnNull() { + // GIVEN + List entityRelations = new ArrayList<>(); + when(relationServiceMock.findByQuery(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Futures.immediateFuture(entityRelations)); + + // WHEN + ListenableFuture entityIdFuture = EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, TENANT_ID, relationsQuery); + + // THEN + verifyEntityIdFuture(entityIdFuture, null); + } + + @Test + public void givenRelationQuery_whenFindEntityAsync_thenFailure() { + // GIVEN + relationsQuery.setDirection(null); + List entityRelations = new ArrayList<>(); + entityRelations.add(createEntityRelation(TENANT_ID, ASSET_ORIGINATOR_ID)); + + when(relationServiceMock.findByQuery(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Futures.immediateFuture(entityRelations)); + + // WHEN + ListenableFuture entityIdFuture = EntitiesRelatedEntityIdAsyncLoader.findEntityAsync(ctxMock, TENANT_ID, relationsQuery); + + // THEN + verifyEntityIdFuture(entityIdFuture, ASSET_ORIGINATOR_ID); + } + + private void verifyEntityIdFuture(ListenableFuture entityIdFuture, EntityId assetId) { + withCallback(entityIdFuture, + entityId -> assertThat(entityId).isEqualTo(assetId), + throwable -> assertThat(throwable).isInstanceOf(IllegalStateException.class), ctxMock.getDbCallbackExecutor()); + } + + private static EntityRelation createEntityRelation(EntityId from, EntityId to) { + EntityRelation relation = new EntityRelation(); + relation.setFrom(from); + relation.setTo(to); + relation.setType(EntityRelation.CONTAINS_TYPE); + relation.setTypeGroup(RelationTypeGroup.COMMON); + return relation; + } }