Browse Source

Add tests

pull/8661/head
Dmytro Skarzhynets 4 years ago
parent
commit
6906b1ba64
  1. 4
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetEntityAttrNode.java
  2. 7
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetEntityDetailsNode.java
  3. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
  4. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java
  5. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
  6. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
  7. 6
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java
  8. 5
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeConfiguration.java
  9. 135
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java
  10. 45
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java
  11. 165
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java
  12. 97
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java
  13. 482
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java

4
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetEntityAttrNode.java

@ -49,8 +49,8 @@ public abstract class TbAbstractGetEntityAttrNode<T extends EntityId> extends Tb
protected abstract ListenableFuture<T> findEntityAsync(TbContext ctx, EntityId originator);
protected void checkIfMappingIsNotEmptyOrThrow(TbGetEntityAttrNodeConfiguration config) throws TbNodeException {
if (config.getAttrMapping().isEmpty()) {
protected void checkIfMappingIsNotEmptyOrElseThrow(Map<String, String> attrMapping) throws TbNodeException {
if (attrMapping == null || attrMapping.isEmpty()) {
throw new TbNodeException("At least one attribute mapping should be specified!");
}
}

7
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetEntityDetailsNode.java

@ -22,11 +22,14 @@ import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.util.EntityDetails;
import org.thingsboard.server.common.data.ContactBased;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import java.util.List;
import static org.thingsboard.common.util.DonAsynchron.withCallback;
@Slf4j
@ -45,8 +48,8 @@ public abstract class TbAbstractGetEntityDetailsNode<C extends TbAbstractGetEnti
protected abstract ListenableFuture<? extends ContactBased<I>> getContactBasedFuture(TbContext ctx, TbMsg msg);
protected void checkIfDetailsListIsNotEmptyOrThrow(C configuration) throws TbNodeException {
if (configuration.getDetailsList().isEmpty()) {
protected void checkIfDetailsListIsNotEmptyOrElseThrow(List<EntityDetails> detailsList) throws TbNodeException {
if (detailsList == null || detailsList.isEmpty()) {
throw new TbNodeException("No entity details selected!");
}
}

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java

@ -45,7 +45,7 @@ public class TbGetCustomerAttributeNode extends TbAbstractGetEntityAttrNode<Cust
@Override
protected TbGetEntityAttrNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
var config = TbNodeUtils.convert(configuration, TbGetEntityAttrNodeConfiguration.class);
checkIfMappingIsNotEmptyOrThrow(config);
checkIfMappingIsNotEmptyOrElseThrow(config.getAttrMapping());
return config;
}

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java

@ -24,7 +24,6 @@ import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.ContactBased;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.HasCustomerId;
import org.thingsboard.server.common.data.HasName;
@ -57,7 +56,7 @@ public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbG
@Override
protected TbGetCustomerDetailsNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
var config = TbNodeUtils.convert(configuration, TbGetCustomerDetailsNodeConfiguration.class);
checkIfDetailsListIsNotEmptyOrThrow(config);
checkIfDetailsListIsNotEmptyOrElseThrow(config.getDetailsList());
return config;
}
@ -67,7 +66,7 @@ public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbG
}
@Override
protected ListenableFuture<? extends ContactBased<CustomerId>> getContactBasedFuture(TbContext ctx, TbMsg msg) {
protected ListenableFuture<Customer> getContactBasedFuture(TbContext ctx, TbMsg msg) {
switch (msg.getOriginator().getEntityType()) {
case DEVICE:
return Futures.transformAsync(ctx.getDeviceService().findDeviceByIdAsync(ctx.getTenantId(), new DeviceId(msg.getOriginator().getId())),

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java

@ -46,7 +46,7 @@ public class TbGetRelatedAttributeNode extends TbAbstractGetEntityAttrNode<Entit
@Override
public TbGetRelatedAttrNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
var config = TbNodeUtils.convert(configuration, TbGetRelatedAttrNodeConfiguration.class);
checkIfMappingIsNotEmptyOrThrow(config);
checkIfMappingIsNotEmptyOrElseThrow(config.getAttrMapping());
return config;
}

2
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java

@ -44,7 +44,7 @@ public class TbGetTenantAttributeNode extends TbAbstractGetEntityAttrNode<Tenant
@Override
public TbGetEntityAttrNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
var config = TbNodeUtils.convert(configuration, TbGetEntityAttrNodeConfiguration.class);
checkIfMappingIsNotEmptyOrThrow(config);
checkIfMappingIsNotEmptyOrElseThrow(config.getAttrMapping());
return config;
}

6
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java

@ -22,7 +22,7 @@ import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.ContactBased;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
@ -44,7 +44,7 @@ public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGet
@Override
protected TbGetTenantDetailsNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
var config = TbNodeUtils.convert(configuration, TbGetTenantDetailsNodeConfiguration.class);
checkIfDetailsListIsNotEmptyOrThrow(config);
checkIfDetailsListIsNotEmptyOrElseThrow(config.getDetailsList());
return config;
}
@ -54,7 +54,7 @@ public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGet
}
@Override
protected ListenableFuture<? extends ContactBased<TenantId>> getContactBasedFuture(TbContext ctx, TbMsg msg) {
protected ListenableFuture<Tenant> getContactBasedFuture(TbContext ctx, TbMsg msg) {
return ctx.getTenantService().findTenantByIdAsync(ctx.getTenantId(), ctx.getTenantId());
}

5
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeConfiguration.java

@ -18,8 +18,9 @@ package org.thingsboard.rule.engine.metadata;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import org.thingsboard.rule.engine.util.EntityDetails;
import java.util.Collections;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@ -28,7 +29,7 @@ public class TbGetTenantDetailsNodeConfiguration extends TbAbstractGetEntityDeta
@Override
public TbGetTenantDetailsNodeConfiguration defaultConfiguration() {
var configuration = new TbGetTenantDetailsNodeConfiguration();
configuration.setDetailsList(Collections.emptyList());
configuration.setDetailsList(List.of(EntityDetails.STATE, EntityDetails.TITLE));
configuration.setFetchTo(FetchTo.DATA);
return configuration;
}

135
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java

@ -17,11 +17,13 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
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.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
@ -64,7 +66,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@ -77,8 +79,9 @@ import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
@ExtendWith(MockitoExtension.class)
public class TbGetCustomerAttributeNodeTest {
private static final EntityId DUMMY_ENTITY_ID = new DeviceId(UUID.randomUUID());
private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID());
private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID());
private static final CustomerId CUSTOMER_ID = new CustomerId(UUID.randomUUID());
private static final ListeningExecutor DB_EXECUTOR = new ListeningExecutor() {
@Override
public <T> ListenableFuture<T> executeAsync(Callable<T> task) {
@ -172,10 +175,9 @@ public class TbGetCustomerAttributeNodeTest {
@Test
public void givenEmptyAttributesMapping_whenInit_thenException() {
// SETUP
// GIVEN
var expectedExceptionMessage = "At least one attribute mapping should be specified!";
// GIVEN
config.setAttrMapping(Collections.emptyMap());
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
@ -191,7 +193,7 @@ public class TbGetCustomerAttributeNodeTest {
public void givenMsgDataIsNotAnJsonObjectAndFetchToData_whenOnMsg_thenException() {
// GIVEN
node.fetchTo = FetchTo.DATA;
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "[]");
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "[]");
// WHEN
var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg));
@ -203,13 +205,12 @@ public class TbGetCustomerAttributeNodeTest {
@Test
public void givenEntityThatDoesNotBelongToTheCurrentTenant_whenOnMsg_thenException() {
// SETUP
var expectedExceptionMessage = "Entity with id: '" + DUMMY_ENTITY_ID +
// GIVEN
var expectedExceptionMessage = "Entity with id: '" + DUMMY_DEVICE_ORIGINATOR +
"' specified in the configuration doesn't belong to the current tenant.";
// GIVEN
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_ENTITY_ID);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "{}");
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_DEVICE_ORIGINATOR);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "{}");
// WHEN
var exception = assertThrows(RuntimeException.class, () -> node.onMsg(ctxMock, msg));
@ -226,9 +227,12 @@ public class TbGetCustomerAttributeNodeTest {
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", userId, new TbMsgMetaData(), "{}");
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getUserService()).thenReturn(userServiceMock);
doReturn(Futures.immediateFuture(null)).when(userServiceMock).findUserByIdAsync(any(), any());
doReturn(Futures.immediateFuture(null)).when(userServiceMock).findUserByIdAsync(eq(TENANT_ID), eq(userId));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
node.onMsg(ctxMock, msg);
@ -257,22 +261,26 @@ public class TbGetCustomerAttributeNodeTest {
public void givenFetchAttributesToData_whenOnMsg_thenShouldFetchAttributesToData() {
// GIVEN
var device = new Device(new DeviceId(UUID.randomUUID()));
device.setCustomerId(new CustomerId(UUID.randomUUID()));
device.setCustomerId(CUSTOMER_ID);
prepareMsgAndConfig(FetchTo.DATA, false, device.getId());
when(ctxMock.getDeviceService()).thenReturn(deviceServiceMock);
doReturn(Futures.immediateFuture(device)).when(deviceServiceMock).findDeviceByIdAsync(any(), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
List<AttributeKvEntry> attributesList = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(device.getCustomerId()), eq(SERVER_SCOPE), anyList()))
.thenReturn(Futures.immediateFuture(attributes));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getDeviceService()).thenReturn(deviceServiceMock);
doReturn(Futures.immediateFuture(device)).when(deviceServiceMock).findDeviceByIdAsync(eq(TENANT_ID), eq(device.getId()));
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(CUSTOMER_ID), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -280,6 +288,7 @@ public class TbGetCustomerAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -299,22 +308,26 @@ public class TbGetCustomerAttributeNodeTest {
public void givenFetchAttributesToMetaData_whenOnMsg_thenShouldFetchAttributesToMetaData() {
// GIVEN
var user = new User(new UserId(UUID.randomUUID()));
user.setCustomerId(new CustomerId(UUID.randomUUID()));
user.setCustomerId(CUSTOMER_ID);
prepareMsgAndConfig(FetchTo.METADATA, false, user.getId());
when(ctxMock.getUserService()).thenReturn(userServiceMock);
doReturn(Futures.immediateFuture(user)).when(userServiceMock).findUserByIdAsync(any(), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
List<AttributeKvEntry> attributesList = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(user.getCustomerId()), eq(SERVER_SCOPE), anyList()))
.thenReturn(Futures.immediateFuture(attributes));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getUserService()).thenReturn(userServiceMock);
doReturn(Futures.immediateFuture(user)).when(userServiceMock).findUserByIdAsync(eq(TENANT_ID), eq(user.getId()));
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(CUSTOMER_ID), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -322,6 +335,7 @@ public class TbGetCustomerAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -344,15 +358,19 @@ public class TbGetCustomerAttributeNodeTest {
prepareMsgAndConfig(FetchTo.DATA, true, customer.getId());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
List<TsKvEntry> timeseriesList = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(customer.getId()), anyList()))
.thenReturn(Futures.immediateFuture(timeseries));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(customer.getId()), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseriesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -360,6 +378,7 @@ public class TbGetCustomerAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -383,18 +402,22 @@ public class TbGetCustomerAttributeNodeTest {
prepareMsgAndConfig(FetchTo.METADATA, true, asset.getId());
when(ctxMock.getAssetService()).thenReturn(assetServiceMock);
doReturn(Futures.immediateFuture(asset)).when(assetServiceMock).findAssetByIdAsync(any(), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
List<TsKvEntry> timeseriesList = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(asset.getCustomerId()), anyList()))
.thenReturn(Futures.immediateFuture(timeseries));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAssetService()).thenReturn(assetServiceMock);
doReturn(Futures.immediateFuture(asset)).when(assetServiceMock).findAssetByIdAsync(eq(TENANT_ID), eq(asset.getId()));
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(asset.getCustomerId()), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseriesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -402,6 +425,7 @@ public class TbGetCustomerAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -417,7 +441,7 @@ public class TbGetCustomerAttributeNodeTest {
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(expectedMsgMetaData);
}
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId entityId) {
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId originator) {
config.setAttrMapping(Map.of(
"sourceKey1", "targetKey1",
"${metaDataPattern1}", "$[messageBodyPattern1]",
@ -427,11 +451,32 @@ public class TbGetCustomerAttributeNodeTest {
node.config = config;
node.fetchTo = fetchTo;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaDataPattern1", "sourceKey2");
msgMetaData.putValue("metaDataPattern2", "targetKey3");
var msgData = "{\"temp\":42,\"humidity\":77,\"messageBodyPattern1\":\"targetKey2\",\"messageBodyPattern2\":\"sourceKey3\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", entityId, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", originator, msgMetaData, msgData);
}
@RequiredArgsConstructor
private static class ListMatcher<T> implements ArgumentMatcher<List<T>> {
private final List<T> expectedList;
@Override
public boolean matches(List<T> actualList) {
if (actualList == expectedList) {
return true;
}
if (actualList.size() != expectedList.size()) {
return false;
}
return actualList.containsAll(expectedList);
}
}
}

45
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java

@ -32,7 +32,7 @@ import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.device.DeviceService;
@ -55,7 +55,8 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class TbGetOriginatorFieldsNodeTest {
private static final EntityId DUMMY_ENTITY_ID = new DeviceId(UUID.randomUUID());
private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID());
private static final TenantId DUMMY_TENANT_ID = new TenantId(UUID.randomUUID());
private static final ListeningExecutor DB_EXECUTOR = new ListeningExecutor() {
@Override
public <T> ListenableFuture<T> executeAsync(Callable<T> task) {
@ -74,7 +75,7 @@ public class TbGetOriginatorFieldsNodeTest {
@Mock
private TbContext ctxMock;
@Mock
private DeviceService deviceService;
private DeviceService deviceServiceMock;
private TbGetOriginatorFieldsNode node;
private TbGetOriginatorFieldsConfiguration config;
private TbNodeConfiguration nodeConfiguration;
@ -114,6 +115,7 @@ public class TbGetOriginatorFieldsNodeTest {
"name", "originatorName",
"type", "originatorType"));
assertThat(config.isIgnoreNullStrings()).isEqualTo(false);
assertThat(config.getFetchTo()).isEqualTo(FetchTo.METADATA);
assertThat(node.fetchTo).isEqualTo(FetchTo.METADATA);
}
@ -138,6 +140,7 @@ public class TbGetOriginatorFieldsNodeTest {
"sourceField2", "targetKey2",
"sourceField3", "targetKey3"));
assertThat(config.isIgnoreNullStrings()).isEqualTo(true);
assertThat(config.getFetchTo()).isEqualTo(FetchTo.DATA);
assertThat(node.fetchTo).isEqualTo(FetchTo.DATA);
}
@ -145,7 +148,7 @@ public class TbGetOriginatorFieldsNodeTest {
public void givenMsgDataIsNotAnJsonObjectAndFetchToData_whenOnMsg_thenException() {
// GIVEN
node.fetchTo = FetchTo.DATA;
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_ENTITY_ID, new TbMsgMetaData(), "[]");
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "[]");
// WHEN
var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg));
@ -158,12 +161,12 @@ public class TbGetOriginatorFieldsNodeTest {
@Test
public void givenEntityThatDoesNotBelongToTheCurrentTenant_whenOnMsg_thenException() {
// SETUP
var expectedExceptionMessage = "Entity with id: '" + DUMMY_ENTITY_ID +
var expectedExceptionMessage = "Entity with id: '" + DUMMY_DEVICE_ORIGINATOR +
"' specified in the configuration doesn't belong to the current tenant.";
// GIVEN
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_ENTITY_ID);
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_ENTITY_ID, new TbMsgMetaData(), "{}");
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_DEVICE_ORIGINATOR);
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "{}");
// WHEN
var exception = assertThrows(RuntimeException.class, () -> node.onMsg(ctxMock, msg));
@ -177,7 +180,7 @@ public class TbGetOriginatorFieldsNodeTest {
public void givenValidMsgAndFetchToData_whenOnMsg_thenShouldTellSuccessAndFetchToData() {
// GIVEN
var device = new Device();
device.setId((DeviceId) DUMMY_ENTITY_ID);
device.setId(DUMMY_DEVICE_ORIGINATOR);
device.setName("Test device");
device.setType("Test device type");
@ -192,10 +195,11 @@ public class TbGetOriginatorFieldsNodeTest {
node.fetchTo = FetchTo.DATA;
var msgMetaData = new TbMsgMetaData();
var msgData = "{\"temp\":42,\"humidity\":77}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, msgMetaData, msgData);
when(ctxMock.getDeviceService()).thenReturn(deviceService);
when(deviceService.findDeviceByIdAsync(any(), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDeviceService()).thenReturn(deviceServiceMock);
when(ctxMock.getTenantId()).thenReturn(DUMMY_TENANT_ID);
when(deviceServiceMock.findDeviceByIdAsync(eq(DUMMY_TENANT_ID), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
@ -217,7 +221,7 @@ public class TbGetOriginatorFieldsNodeTest {
public void givenValidMsgAndFetchToMetaData_whenOnMsg_thenShouldTellSuccessAndFetchToMetaData() {
// GIVEN
var device = new Device();
device.setId((DeviceId) DUMMY_ENTITY_ID);
device.setId(DUMMY_DEVICE_ORIGINATOR);
device.setName("Test device");
device.setType("Test device type");
@ -234,10 +238,11 @@ public class TbGetOriginatorFieldsNodeTest {
"testKey1", "testValue1",
"testKey2", "123"));
var msgData = "[\"value1\",\"value2\"]";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, msgMetaData, msgData);
when(ctxMock.getDeviceService()).thenReturn(deviceService);
when(deviceService.findDeviceByIdAsync(any(), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDeviceService()).thenReturn(deviceServiceMock);
when(ctxMock.getTenantId()).thenReturn(DUMMY_TENANT_ID);
when(deviceServiceMock.findDeviceByIdAsync(eq(DUMMY_TENANT_ID), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
@ -264,7 +269,7 @@ public class TbGetOriginatorFieldsNodeTest {
public void givenNullEntityFieldsAndIgnoreNullStringsFalse_whenOnMsg_thenShouldTellSuccessAndFetchNullField() {
// GIVEN
var device = new Device();
device.setId((DeviceId) DUMMY_ENTITY_ID);
device.setId(DUMMY_DEVICE_ORIGINATOR);
device.setName("Test device");
device.setType("Test device type");
@ -281,10 +286,11 @@ public class TbGetOriginatorFieldsNodeTest {
"testKey1", "testValue1",
"testKey2", "123"));
var msgData = "[\"value1\",\"value2\"]";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, msgMetaData, msgData);
when(ctxMock.getDeviceService()).thenReturn(deviceService);
when(deviceService.findDeviceByIdAsync(any(), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDeviceService()).thenReturn(deviceServiceMock);
when(ctxMock.getTenantId()).thenReturn(DUMMY_TENANT_ID);
when(deviceServiceMock.findDeviceByIdAsync(eq(DUMMY_TENANT_ID), eq(device.getId()))).thenReturn(Futures.immediateFuture(device));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
@ -311,7 +317,6 @@ public class TbGetOriginatorFieldsNodeTest {
@Test
public void givenEmptyFieldsMapping_whenInit_thenException() {
// GIVEN
config = config.defaultConfiguration();
config.setFieldsMapping(Collections.emptyMap());
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));

165
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java

@ -17,11 +17,13 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
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.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
@ -31,13 +33,16 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.data.RelationsQuery;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.Device;
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.asset.Asset;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@ -66,7 +71,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@ -79,7 +84,7 @@ import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
@ExtendWith(MockitoExtension.class)
public class TbGetRelatedAttributeNodeTest {
private static final EntityId DUMMY_ENTITY_ID = new DeviceId(UUID.randomUUID());
private static final EntityId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID());
private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID());
private static final ListeningExecutor DB_EXECUTOR = new ListeningExecutor() {
@Override
@ -192,10 +197,9 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenEmptyAttributesMapping_whenInit_thenException() {
// SETUP
// GIVEN
var expectedExceptionMessage = "At least one attribute mapping should be specified!";
// GIVEN
config.setAttrMapping(Collections.emptyMap());
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
@ -211,7 +215,7 @@ public class TbGetRelatedAttributeNodeTest {
public void givenMsgDataIsNotAnJsonObjectAndFetchToData_whenOnMsg_thenException() {
// GIVEN
node.fetchTo = FetchTo.DATA;
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "[]");
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "[]");
// WHEN
var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg));
@ -223,13 +227,12 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenEntityThatDoesNotBelongToTheCurrentTenant_whenOnMsg_thenException() {
// SETUP
var expectedExceptionMessage = "Entity with id: '" + DUMMY_ENTITY_ID +
// GIVEN
var expectedExceptionMessage = "Entity with id: '" + DUMMY_DEVICE_ORIGINATOR +
"' specified in the configuration doesn't belong to the current tenant.";
// GIVEN
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_ENTITY_ID);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "{}");
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_DEVICE_ORIGINATOR);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "{}");
// WHEN
var exception = assertThrows(RuntimeException.class, () -> node.onMsg(ctxMock, msg));
@ -242,11 +245,14 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenDidNotFindEntity_whenOnMsg_thenShouldTellFailure() {
// GIVEN
prepareMsgAndConfig(FetchTo.METADATA, false, DUMMY_ENTITY_ID);
prepareMsgAndConfig(FetchTo.METADATA, false, DUMMY_DEVICE_ORIGINATOR);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(null)).when(relationServiceMock).findByQuery(any(), any());
doReturn(Futures.immediateFuture(null)).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
node.onMsg(ctxMock, msg);
@ -275,25 +281,28 @@ public class TbGetRelatedAttributeNodeTest {
var customer = new Customer(new CustomerId(UUID.randomUUID()));
var user = new User(new UserId(UUID.randomUUID()));
prepareMsgAndConfig(FetchTo.DATA, false, user.getId());
prepareMsgAndConfig(FetchTo.DATA, false, customer.getId());
entityRelation.setFrom(user.getId());
entityRelation.setTo(customer.getId());
entityRelation.setFrom(customer.getId());
entityRelation.setTo(user.getId());
entityRelation.setType(EntityRelation.CONTAINS_TYPE);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(customer.getId()), eq(SERVER_SCOPE), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(user.getId()), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributes));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -301,6 +310,7 @@ public class TbGetRelatedAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -319,26 +329,31 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenFetchAttributesToMetaData_whenOnMsg_thenShouldFetchAttributesToMetaData() {
// GIVEN
var customer = new Customer(new CustomerId(UUID.randomUUID()));
var firstCustomer = new Customer(new CustomerId(UUID.randomUUID()));
var secondCustomer = new Customer(new CustomerId(UUID.randomUUID()));
prepareMsgAndConfig(FetchTo.METADATA, false, customer.getId());
prepareMsgAndConfig(FetchTo.METADATA, false, firstCustomer.getId());
entityRelation.setFrom(customer.getId());
entityRelation.setTo(customer.getId());
entityRelation.setType(EntityRelation.CONTAINS_TYPE);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
entityRelation.setFrom(firstCustomer.getId());
entityRelation.setTo(secondCustomer.getId());
entityRelation.setType(EntityRelation.MANAGES_TYPE);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(customer.getId()), eq(SERVER_SCOPE), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(secondCustomer.getId()), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributes));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -346,6 +361,7 @@ public class TbGetRelatedAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -364,27 +380,31 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenFetchTelemetryToData_whenOnMsg_thenShouldFetchTelemetryToData() {
// GIVEN
var customer = new Customer(new CustomerId(UUID.randomUUID()));
var asset = new Asset(new AssetId(UUID.randomUUID()));
var dashboard = new Dashboard(new DashboardId(UUID.randomUUID()));
var entityView = new EntityView(new EntityViewId(UUID.randomUUID()));
prepareMsgAndConfig(FetchTo.DATA, true, asset.getId());
prepareMsgAndConfig(FetchTo.DATA, true, dashboard.getId());
entityRelation.setFrom(asset.getId());
entityRelation.setTo(customer.getId());
entityRelation.setFrom(dashboard.getId());
entityRelation.setTo(entityView.getId());
entityRelation.setType(EntityRelation.CONTAINS_TYPE);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(customer.getId()), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(entityView.getId()), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseries));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -392,6 +412,7 @@ public class TbGetRelatedAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -410,27 +431,31 @@ public class TbGetRelatedAttributeNodeTest {
@Test
public void givenFetchTelemetryToMetaData_whenOnMsg_thenShouldFetchTelemetryToMetaData() {
// GIVEN
var customer = new Customer(new CustomerId(UUID.randomUUID()));
var tenant = new Tenant(new TenantId(UUID.randomUUID()));
var device = new Device(new DeviceId(UUID.randomUUID()));
prepareMsgAndConfig(FetchTo.METADATA, true, device.getId());
prepareMsgAndConfig(FetchTo.METADATA, true, tenant.getId());
entityRelation.setFrom(device.getId());
entityRelation.setTo(customer.getId());
entityRelation.setFrom(tenant.getId());
entityRelation.setTo(device.getId());
entityRelation.setType(EntityRelation.CONTAINS_TYPE);
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(TENANT_ID), any());
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(customer.getId()), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getRelationService()).thenReturn(relationServiceMock);
doReturn(Futures.immediateFuture(List.of(entityRelation))).when(relationServiceMock).findByQuery(eq(tenant.getId()), any());
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(tenant.getId()), eq(device.getId()), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseries));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -438,6 +463,7 @@ public class TbGetRelatedAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -453,7 +479,7 @@ public class TbGetRelatedAttributeNodeTest {
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(expectedMsgMetaData);
}
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId entityId) {
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId originator) {
config.setAttrMapping(Map.of(
"sourceKey1", "targetKey1",
"${metaDataPattern1}", "$[messageBodyPattern1]",
@ -463,11 +489,32 @@ public class TbGetRelatedAttributeNodeTest {
node.config = config;
node.fetchTo = fetchTo;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaDataPattern1", "sourceKey2");
msgMetaData.putValue("metaDataPattern2", "targetKey3");
var msgData = "{\"temp\":42,\"humidity\":77,\"messageBodyPattern1\":\"targetKey2\",\"messageBodyPattern2\":\"sourceKey3\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", entityId, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", originator, msgMetaData, msgData);
}
@RequiredArgsConstructor
private static class ListMatcher<T> implements ArgumentMatcher<List<T>> {
private final List<T> expectedList;
@Override
public boolean matches(List<T> actualList) {
if (actualList == expectedList) {
return true;
}
if (actualList.size() != expectedList.size()) {
return false;
}
return actualList.containsAll(expectedList);
}
}
}

97
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java

@ -17,11 +17,13 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.RequiredArgsConstructor;
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.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
@ -53,7 +55,7 @@ import java.util.concurrent.Callable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
@ -65,7 +67,7 @@ import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
@ExtendWith(MockitoExtension.class)
public class TbGetTenantAttributeNodeTest {
private static final EntityId DUMMY_ENTITY_ID = new DeviceId(UUID.randomUUID());
private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID());
private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID());
private static final ListeningExecutor DB_EXECUTOR = new ListeningExecutor() {
@Override
@ -154,10 +156,9 @@ public class TbGetTenantAttributeNodeTest {
@Test
public void givenEmptyAttributesMapping_whenInit_thenException() {
// SETUP
// GIVEN
var expectedExceptionMessage = "At least one attribute mapping should be specified!";
// GIVEN
config.setAttrMapping(Collections.emptyMap());
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
@ -173,7 +174,7 @@ public class TbGetTenantAttributeNodeTest {
public void givenMsgDataIsNotAnJsonObjectAndFetchToData_whenOnMsg_thenException() {
// GIVEN
node.fetchTo = FetchTo.DATA;
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "[]");
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "[]");
// WHEN
var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg));
@ -185,13 +186,12 @@ public class TbGetTenantAttributeNodeTest {
@Test
public void givenEntityThatDoesNotBelongToTheCurrentTenant_whenOnMsg_thenException() {
// SETUP
var expectedExceptionMessage = "Entity with id: '" + DUMMY_ENTITY_ID +
// GIVEN
var expectedExceptionMessage = "Entity with id: '" + DUMMY_DEVICE_ORIGINATOR +
"' specified in the configuration doesn't belong to the current tenant.";
// GIVEN
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_ENTITY_ID);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_ENTITY_ID, new TbMsgMetaData(), "{}");
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_DEVICE_ORIGINATOR);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "{}");
// WHEN
var exception = assertThrows(RuntimeException.class, () -> node.onMsg(ctxMock, msg));
@ -208,15 +208,19 @@ public class TbGetTenantAttributeNodeTest {
prepareMsgAndConfig(FetchTo.DATA, false, deviceId);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
List<AttributeKvEntry> attributesList = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(TENANT_ID), eq(SERVER_SCOPE), anyList()))
.thenReturn(Futures.immediateFuture(attributes));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(TENANT_ID), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -224,6 +228,7 @@ public class TbGetTenantAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -244,15 +249,19 @@ public class TbGetTenantAttributeNodeTest {
// GIVEN
prepareMsgAndConfig(FetchTo.METADATA, false, TENANT_ID);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
List<AttributeKvEntry> attributes = List.of(
List<AttributeKvEntry> attributesList = List.of(
new BaseAttributeKvEntry(new StringDataEntry("sourceKey1", "sourceValue1"), 1L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey2", "sourceValue2"), 2L),
new BaseAttributeKvEntry(new StringDataEntry("sourceKey3", "sourceValue3"), 3L)
);
when(attributesServiceMock.find(eq(TENANT_ID), eq(TENANT_ID), eq(SERVER_SCOPE), anyList()))
.thenReturn(Futures.immediateFuture(attributes));
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getAttributesService()).thenReturn(attributesServiceMock);
when(attributesServiceMock.find(eq(TENANT_ID), eq(TENANT_ID), eq(SERVER_SCOPE), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(attributesList));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -260,6 +269,7 @@ public class TbGetTenantAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -282,15 +292,19 @@ public class TbGetTenantAttributeNodeTest {
prepareMsgAndConfig(FetchTo.DATA, true, customerId);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(TENANT_ID), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(TENANT_ID), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseries));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -298,6 +312,7 @@ public class TbGetTenantAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -320,15 +335,19 @@ public class TbGetTenantAttributeNodeTest {
prepareMsgAndConfig(FetchTo.METADATA, true, ruleChainId);
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
List<TsKvEntry> timeseries = List.of(
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey1", "sourceValue1")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey2", "sourceValue2")),
new BasicTsKvEntry(1L, new StringDataEntry("sourceKey3", "sourceValue3"))
);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(TENANT_ID), anyList()))
var expectedPatternProcessedKeysList = List.of("sourceKey1", "sourceKey2", "sourceKey3");
when(ctxMock.getTenantId()).thenReturn(TENANT_ID);
when(ctxMock.getTimeseriesService()).thenReturn(timeseriesServiceMock);
when(timeseriesServiceMock.findLatest(eq(TENANT_ID), eq(TENANT_ID), argThat(new ListMatcher<>(expectedPatternProcessedKeysList))))
.thenReturn(Futures.immediateFuture(timeseries));
when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR);
// WHEN
@ -336,6 +355,7 @@ public class TbGetTenantAttributeNodeTest {
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
@ -351,7 +371,7 @@ public class TbGetTenantAttributeNodeTest {
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(expectedMsgMetaData);
}
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId entityId) {
private void prepareMsgAndConfig(FetchTo fetchTo, boolean isTelemetry, EntityId originator) {
config.setAttrMapping(Map.of(
"sourceKey1", "targetKey1",
"${metaDataPattern1}", "$[messageBodyPattern1]",
@ -361,11 +381,32 @@ public class TbGetTenantAttributeNodeTest {
node.config = config;
node.fetchTo = fetchTo;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaDataPattern1", "sourceKey2");
msgMetaData.putValue("metaDataPattern2", "targetKey3");
var msgData = "{\"temp\":42,\"humidity\":77,\"messageBodyPattern1\":\"targetKey2\",\"messageBodyPattern2\":\"sourceKey3\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", entityId, msgMetaData, msgData);
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", originator, msgMetaData, msgData);
}
@RequiredArgsConstructor
private static class ListMatcher<T> implements ArgumentMatcher<List<T>> {
private final List<T> expectedList;
@Override
public boolean matches(List<T> actualList) {
if (actualList == expectedList) {
return true;
}
if (actualList.size() != expectedList.size()) {
return false;
}
return actualList.containsAll(expectedList);
}
}
}

482
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java

@ -0,0 +1,482 @@
/**
* Copyright © 2016-2023 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.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.util.EntityDetails;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.tenant.TenantService;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class TbGetTenantDetailsNodeTest {
private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID());
@Mock
private TbContext ctxMock;
@Mock
private TenantService tenantServiceMock;
private TbGetTenantDetailsNode node;
private TbGetTenantDetailsNodeConfiguration config;
private TbNodeConfiguration nodeConfiguration;
private TbMsg msg;
@BeforeEach
public void setUp() {
node = new TbGetTenantDetailsNode();
config = new TbGetTenantDetailsNodeConfiguration().defaultConfiguration();
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
}
@Test
public void givenConfigWithNullFetchTo_whenInit_thenException() {
// GIVEN
config.setFetchTo(null);
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
// WHEN
var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration));
// THEN
assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!");
verify(ctxMock, never()).tellSuccess(any());
}
@Test
public void givenDefaultConfig_whenInit_thenOK() throws TbNodeException {
// GIVEN
// WHEN
node.init(ctxMock, nodeConfiguration);
// THEN
assertThat(node.config).isEqualTo(config);
assertThat(config.getDetailsList()).isEqualTo(List.of(EntityDetails.STATE, EntityDetails.TITLE));
assertThat(config.getFetchTo()).isEqualTo(FetchTo.DATA);
assertThat(node.fetchTo).isEqualTo(FetchTo.DATA);
}
@Test
public void givenCustomConfig_whenInit_thenOK() throws TbNodeException {
// GIVEN
config.setDetailsList(List.of(EntityDetails.ID, EntityDetails.PHONE));
config.setFetchTo(FetchTo.METADATA);
nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config));
// WHEN
node.init(ctxMock, nodeConfiguration);
// THEN
assertThat(node.config).isEqualTo(config);
assertThat(config.getDetailsList()).isEqualTo(List.of(EntityDetails.ID, EntityDetails.PHONE));
assertThat(config.getFetchTo()).isEqualTo(FetchTo.METADATA);
assertThat(node.fetchTo).isEqualTo(FetchTo.METADATA);
}
@Test
public void givenMsgDataIsNotAnJsonObjectAndFetchToData_whenOnMsg_thenException() {
// GIVEN
node.fetchTo = FetchTo.DATA;
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "[]");
// WHEN
var exception = assertThrows(IllegalArgumentException.class, () -> node.onMsg(ctxMock, msg));
// THEN
assertThat(exception.getMessage()).isEqualTo("Message body is not an object!");
verify(ctxMock, never()).tellSuccess(any());
}
@Test
public void givenEntityThatDoesNotBelongToTheCurrentTenant_whenOnMsg_thenException() {
// SETUP
var expectedExceptionMessage = "Entity with id: '" + DUMMY_DEVICE_ORIGINATOR +
"' specified in the configuration doesn't belong to the current tenant.";
// GIVEN
doThrow(new RuntimeException(expectedExceptionMessage)).when(ctxMock).checkTenantEntity(DUMMY_DEVICE_ORIGINATOR);
msg = TbMsg.newMsg("SOME_MESSAGE_TYPE", DUMMY_DEVICE_ORIGINATOR, new TbMsgMetaData(), "{}");
// WHEN
var exception = assertThrows(RuntimeException.class, () -> node.onMsg(ctxMock, msg));
// THEN
assertThat(exception.getMessage()).isEqualTo(expectedExceptionMessage);
verify(ctxMock, never()).tellSuccess(any());
}
@Test
public void givenAllEntityDetailsAndFetchToData_whenOnMsg_thenShouldTellSuccessAndFetchAllToData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setZip("123456");
tenant.setAddress("Tenant address 1");
tenant.setAddress2("Tenant address 2");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":\"Tenant description\"}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(List.of(EntityDetails.values()));
config.setFetchTo(FetchTo.DATA);
node.config = config;
node.fetchTo = FetchTo.DATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(tenant));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
var expectedMsgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"," +
"\"tenant_id\":\"" + tenant.getId() + "\"," +
"\"tenant_title\":\"" + tenant.getTitle() + "\"," +
"\"tenant_country\":\"" + tenant.getCountry() + "\"," +
"\"tenant_city\":\"" + tenant.getCity() + "\"," +
"\"tenant_state\":\"" + tenant.getState() + "\"," +
"\"tenant_zip\":\"" + tenant.getZip() + "\"," +
"\"tenant_address\":\"" + tenant.getAddress() + "\"," +
"\"tenant_address2\":\"" + tenant.getAddress2() + "\"," +
"\"tenant_phone\":\"" + tenant.getPhone() + "\"," +
"\"tenant_email\":\"" + tenant.getEmail() + "\"," +
"\"tenant_additionalInfo\":\"" + tenant.getAdditionalInfo().get("description").asText() + "\"}";
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(expectedMsgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(msgMetaData);
}
@Test
public void givenSomeEntityDetailsAndFetchToMetadata_whenOnMsg_thenShouldTellSuccessAndFetchSomeToMetaData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setZip("123456");
tenant.setAddress("Tenant address 1");
tenant.setAddress2("Tenant address 2");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":\"Tenant description\"}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(List.of(EntityDetails.ID, EntityDetails.TITLE, EntityDetails.PHONE));
config.setFetchTo(FetchTo.METADATA);
node.config = config;
node.fetchTo = FetchTo.METADATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(tenant));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
var expectedMsgMetaData = new TbMsgMetaData(msgMetaData.getData());
expectedMsgMetaData.putValue("tenant_id", tenant.getId().getId().toString());
expectedMsgMetaData.putValue("tenant_title", tenant.getTitle());
expectedMsgMetaData.putValue("tenant_phone", tenant.getPhone());
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(msgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(expectedMsgMetaData);
}
@Test
public void givenNoEntityDetailsAndFetchToMetadata_whenOnMsg_thenShouldTellSuccessAndFetchNothingToMetaData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setZip("123456");
tenant.setAddress("Tenant address 1");
tenant.setAddress2("Tenant address 2");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":\"Tenant description\"}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(Collections.emptyList());
config.setFetchTo(FetchTo.METADATA);
node.config = config;
node.fetchTo = FetchTo.METADATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(tenant));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(msgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(msgMetaData);
}
@Test
public void givenNotPresentEntityDetailsAndFetchToData_whenOnMsg_thenShouldTellSuccessAndFetchNothingToData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":\"Tenant description\"}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(List.of(EntityDetails.ZIP, EntityDetails.ADDRESS, EntityDetails.ADDRESS2));
config.setFetchTo(FetchTo.DATA);
node.config = config;
node.fetchTo = FetchTo.DATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(tenant));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(msgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(msgMetaData);
}
@Test
public void givenDidNotFindTenant_whenOnMsg_thenShouldTellSuccessAndFetchNothingToData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":\"Tenant description\"}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(List.of(EntityDetails.ZIP, EntityDetails.ADDRESS, EntityDetails.ADDRESS2));
config.setFetchTo(FetchTo.DATA);
node.config = config;
node.fetchTo = FetchTo.DATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(null));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(msgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(msgMetaData);
}
@Test
public void givenNullDescription_whenOnMsg_thenShouldTellSuccessAndFetchNothingToData() {
// GIVEN
var tenant = new Tenant();
tenant.setId(new TenantId(UUID.randomUUID()));
tenant.setTitle("Tenant title");
tenant.setCountry("Tenant country");
tenant.setCity("Tenant city");
tenant.setState("Tenant state");
tenant.setPhone("+123456789");
tenant.setEmail("email@tenant.com");
tenant.setAdditionalInfo(JacksonUtil.toJsonNode("{\"someProperty\":\"someValue\",\"description\":null}"));
var device = new Device();
device.setId(new DeviceId(UUID.randomUUID()));
device.setTenantId(tenant.getId());
device.setName("Test device");
device.setType("Test device type");
config.setDetailsList(List.of(EntityDetails.ADDITIONAL_INFO));
config.setFetchTo(FetchTo.DATA);
node.config = config;
node.fetchTo = FetchTo.DATA;
var msgMetaData = new TbMsgMetaData();
msgMetaData.putValue("metaKey1", "metaValue1");
msgMetaData.putValue("metaKey2", "metaValue2");
var msgData = "{\"dataKey1\":123,\"dataKey2\":\"dataValue2\"}";
msg = TbMsg.newMsg("POST_TELEMETRY_REQUEST", device.getId(), msgMetaData, msgData);
when(ctxMock.getTenantId()).thenReturn(tenant.getId());
when(ctxMock.getTenantService()).thenReturn(tenantServiceMock);
when(tenantServiceMock.findTenantByIdAsync(eq(tenant.getId()), eq(tenant.getId()))).thenReturn(Futures.immediateFuture(tenant));
// WHEN
node.onMsg(ctxMock, msg);
// THEN
var actualMessageCaptor = ArgumentCaptor.forClass(TbMsg.class);
verify(ctxMock, times(1)).tellSuccess(actualMessageCaptor.capture());
verify(ctxMock, never()).tellFailure(any(), any());
assertThat(actualMessageCaptor.getValue().getData()).isEqualTo(msgData);
assertThat(actualMessageCaptor.getValue().getMetaData()).isEqualTo(msgMetaData);
}
}
Loading…
Cancel
Save