|
|
|
@ -21,6 +21,8 @@ import org.junit.jupiter.api.BeforeEach; |
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
import org.junit.jupiter.api.extension.ExtendWith; |
|
|
|
import org.junit.jupiter.params.ParameterizedTest; |
|
|
|
import org.junit.jupiter.params.provider.Arguments; |
|
|
|
import org.junit.jupiter.params.provider.MethodSource; |
|
|
|
import org.junit.jupiter.params.provider.NullAndEmptySource; |
|
|
|
import org.mockito.ArgumentCaptor; |
|
|
|
import org.mockito.Mock; |
|
|
|
@ -32,8 +34,10 @@ import org.thingsboard.rule.engine.api.RuleEngineAlarmService; |
|
|
|
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.rule.engine.data.RelationsQuery; |
|
|
|
import org.thingsboard.server.common.data.Device; |
|
|
|
import org.thingsboard.server.common.data.EntityType; |
|
|
|
import org.thingsboard.server.common.data.alarm.Alarm; |
|
|
|
import org.thingsboard.server.common.data.asset.Asset; |
|
|
|
import org.thingsboard.server.common.data.id.AlarmId; |
|
|
|
@ -58,8 +62,11 @@ import org.thingsboard.server.dao.device.DeviceService; |
|
|
|
import org.thingsboard.server.dao.relation.RelationService; |
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.NoSuchElementException; |
|
|
|
import java.util.UUID; |
|
|
|
import java.util.stream.Stream; |
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
|
|
|
@ -72,11 +79,22 @@ import static org.mockito.BDDMockito.then; |
|
|
|
public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("79830b6d-4f93-49bd-9b5b-d31ce51da77b")); |
|
|
|
private final CustomerId CUSTOMER_ID = new CustomerId(UUID.fromString("c6b2c94b-5517-4f20-bf8e-ae9407eb8a7a")); |
|
|
|
private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("990605a4-db46-4ed4-942f-e18200453571")); |
|
|
|
private final AssetId ASSET_ID = new AssetId(UUID.fromString("55de3f10-1b55-4950-b711-ed132896b260")); |
|
|
|
|
|
|
|
private final ListeningExecutor dbExecutor = new TestDbCallbackExecutor(); |
|
|
|
|
|
|
|
private final String CUSTOMER_SOURCE = "CUSTOMER"; |
|
|
|
private final String TENANT_SOURCE = "TENANT"; |
|
|
|
private final String RELATED_SOURCE = "RELATED"; |
|
|
|
private final String ALARM_ORIGINATOR_SOURCE = "ALARM_ORIGINATOR"; |
|
|
|
private final String ENTITY_SOURCE = "ENTITY"; |
|
|
|
|
|
|
|
private final String supportedOriginatorSourcesStr = String.join(", ", List.of( |
|
|
|
CUSTOMER_SOURCE, TENANT_SOURCE, RELATED_SOURCE, ALARM_ORIGINATOR_SOURCE, ENTITY_SOURCE) |
|
|
|
); |
|
|
|
|
|
|
|
private TbChangeOriginatorNode node; |
|
|
|
private TbChangeOriginatorNodeConfiguration config; |
|
|
|
|
|
|
|
@ -99,52 +117,37 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
@Test |
|
|
|
public void newChainCanBeStarted() throws TbNodeException { |
|
|
|
init(); |
|
|
|
AssetId assetId = new AssetId(Uuids.timeBased()); |
|
|
|
CustomerId customerId = new CustomerId(Uuids.timeBased()); |
|
|
|
Asset asset = new Asset(); |
|
|
|
asset.setCustomerId(customerId); |
|
|
|
asset.setCustomerId(CUSTOMER_ID); |
|
|
|
|
|
|
|
RuleChainId ruleChainId = new RuleChainId(Uuids.timeBased()); |
|
|
|
RuleNodeId ruleNodeId = new RuleNodeId(Uuids.timeBased()); |
|
|
|
|
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, assetId, TbMsgMetaData.EMPTY, TbMsgDataType.JSON,TbMsg.EMPTY_JSON_OBJECT, ruleChainId, ruleNodeId); |
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ASSET_ID, TbMsgMetaData.EMPTY, TbMsgDataType.JSON, TbMsg.EMPTY_JSON_OBJECT, ruleChainId, ruleNodeId); |
|
|
|
|
|
|
|
given(ctxMock.getDbCallbackExecutor()).willReturn(dbExecutor); |
|
|
|
given(ctxMock.getAssetService()).willReturn(assetServiceMock); |
|
|
|
given(assetServiceMock.findAssetByIdAsync(any(), eq(assetId))).willReturn(Futures.immediateFuture(asset)); |
|
|
|
given(assetServiceMock.findAssetByIdAsync(any(), eq(ASSET_ID))).willReturn(Futures.immediateFuture(asset)); |
|
|
|
|
|
|
|
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); |
|
|
|
node.onMsg(ctxMock, msg); |
|
|
|
ArgumentCaptor<TbMsg> msgCaptor = ArgumentCaptor.forClass(TbMsg.class); |
|
|
|
ArgumentCaptor<EntityId> originatorCaptor = ArgumentCaptor.forClass(EntityId.class); |
|
|
|
then(ctxMock).should().transformMsgOriginator(msgCaptor.capture(), originatorCaptor.capture()); |
|
|
|
|
|
|
|
assertThat(originatorCaptor.getValue()).isEqualTo(customerId); |
|
|
|
} |
|
|
|
|
|
|
|
public void init() throws TbNodeException { |
|
|
|
TbChangeOriginatorNodeConfiguration config = new TbChangeOriginatorNodeConfiguration(); |
|
|
|
config.setOriginatorSource("CUSTOMER"); |
|
|
|
TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); |
|
|
|
|
|
|
|
given(ctxMock.getDbCallbackExecutor()).willReturn(dbExecutor); |
|
|
|
|
|
|
|
node = new TbChangeOriginatorNode(); |
|
|
|
node.init(null, nodeConfiguration); |
|
|
|
assertThat(originatorCaptor.getValue()).isEqualTo(CUSTOMER_ID); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void verifyDefaultConfig() { |
|
|
|
var config = new TbChangeOriginatorNodeConfiguration().defaultConfiguration(); |
|
|
|
assertThat(config.getOriginatorSource()).isEqualTo("CUSTOMER"); |
|
|
|
|
|
|
|
assertThat(config.getOriginatorSource()).isEqualTo(CUSTOMER_SOURCE); |
|
|
|
RelationsQuery relationsQuery = new RelationsQuery(); |
|
|
|
relationsQuery.setDirection(EntitySearchDirection.FROM); |
|
|
|
relationsQuery.setMaxLevel(1); |
|
|
|
RelationEntityTypeFilter relationEntityTypeFilter = new RelationEntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.emptyList()); |
|
|
|
relationsQuery.setFilters(Collections.singletonList(relationEntityTypeFilter)); |
|
|
|
assertThat(config.getRelationsQuery()).isEqualTo(relationsQuery); |
|
|
|
|
|
|
|
assertThat(config.getEntityType()).isNull(); |
|
|
|
assertThat(config.getEntityNamePattern()).isNull(); |
|
|
|
} |
|
|
|
@ -155,45 +158,45 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) |
|
|
|
.isInstanceOf(IllegalArgumentException.class) |
|
|
|
.hasMessage("Source 'UNSUPPORTED_SOURCE' is unsupported."); |
|
|
|
.hasMessage("Unsupported source type 'UNSUPPORTED_SOURCE'! Only " + supportedOriginatorSourcesStr + " types are allowed."); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenRelatedSourceAndRelatedQueryIsNull_whenInit_thenThrowsException() { |
|
|
|
config.setOriginatorSource("RELATED"); |
|
|
|
config.setOriginatorSource(RELATED_SOURCE); |
|
|
|
config.setRelationsQuery(null); |
|
|
|
|
|
|
|
assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) |
|
|
|
.isInstanceOf(IllegalArgumentException.class) |
|
|
|
.hasMessage("Relations query should be specified for the related entity."); |
|
|
|
.hasMessage("Relations query should be specified if 'Related entity' source is selected."); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenEntitySourceAndEntityTypeIsNull_whenInit_thenThrowsException() { |
|
|
|
config.setOriginatorSource("ENTITY"); |
|
|
|
config.setOriginatorSource(ENTITY_SOURCE); |
|
|
|
config.setEntityType(null); |
|
|
|
|
|
|
|
assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) |
|
|
|
.isInstanceOf(IllegalArgumentException.class) |
|
|
|
.hasMessage("Entity type should be specified for the entity."); |
|
|
|
.hasMessage("Entity type should be specified if 'Entity by name pattern' source is selected."); |
|
|
|
} |
|
|
|
|
|
|
|
@ParameterizedTest |
|
|
|
@NullAndEmptySource |
|
|
|
public void givenEntitySourceAndEntityNamePatternIsEmpty_whenInit_thenThrowsException(String entityName) { |
|
|
|
config.setOriginatorSource("ENTITY"); |
|
|
|
config.setEntityType("DEVICE"); |
|
|
|
config.setOriginatorSource(ENTITY_SOURCE); |
|
|
|
config.setEntityType(EntityType.DEVICE.name()); |
|
|
|
config.setEntityNamePattern(entityName); |
|
|
|
|
|
|
|
assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) |
|
|
|
.isInstanceOf(IllegalArgumentException.class) |
|
|
|
.hasMessage("Entity name pattern should be specified for the entity."); |
|
|
|
.hasMessage("Name pattern should be specified if 'Entity by name pattern' source is selected."); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenEntitySourceAndUnexpectedEntityType_whenInit_thenThrowsException() { |
|
|
|
config.setOriginatorSource("ENTITY"); |
|
|
|
config.setEntityType("TENANT"); |
|
|
|
config.setOriginatorSource(ENTITY_SOURCE); |
|
|
|
config.setEntityType(EntityType.TENANT.name()); |
|
|
|
config.setEntityNamePattern("tenant-A"); |
|
|
|
|
|
|
|
assertThatThrownBy(() -> node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config)))) |
|
|
|
@ -203,14 +206,11 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsCustomer_whenOnMsg_thenTellSuccess() throws TbNodeException { |
|
|
|
config.setOriginatorSource("CUSTOMER"); |
|
|
|
|
|
|
|
CustomerId customerId = new CustomerId(UUID.fromString("d2746ed1-2c45-41d7-b34c-94f947f2aa03")); |
|
|
|
Device device = new Device(DEVICE_ID); |
|
|
|
device.setCustomerId(customerId); |
|
|
|
device.setCustomerId(CUSTOMER_ID); |
|
|
|
|
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); |
|
|
|
TbMsg expectedMsg = TbMsg.transformMsgOriginator(msg, customerId); |
|
|
|
TbMsg expectedMsg = TbMsg.transformMsgOriginator(msg, CUSTOMER_ID); |
|
|
|
|
|
|
|
given(ctxMock.getDbCallbackExecutor()).willReturn(dbExecutor); |
|
|
|
given(ctxMock.getDeviceService()).willReturn(deviceServiceMock); |
|
|
|
@ -229,7 +229,7 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsTenant_whenOnMsg_thenTellSuccess() throws TbNodeException { |
|
|
|
config.setOriginatorSource("TENANT"); |
|
|
|
config.setOriginatorSource(TENANT_SOURCE); |
|
|
|
|
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ASSET_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); |
|
|
|
TbMsg expectedMsg = TbMsg.transformMsgOriginator(msg, TENANT_ID); |
|
|
|
@ -248,7 +248,7 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsRelatedAndNewOriginatorIsNull_whenOnMsg_thenTellFailure() throws TbNodeException { |
|
|
|
config.setOriginatorSource("RELATED"); |
|
|
|
config.setOriginatorSource(RELATED_SOURCE); |
|
|
|
|
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, ASSET_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); |
|
|
|
|
|
|
|
@ -278,7 +278,7 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsAlarmOriginator_whenOnMsg_thenTellSuccess() throws TbNodeException { |
|
|
|
config.setOriginatorSource("ALARM_ORIGINATOR"); |
|
|
|
config.setOriginatorSource(ALARM_ORIGINATOR_SOURCE); |
|
|
|
|
|
|
|
AlarmId alarmId = new AlarmId(UUID.fromString("6b43f694-cb5f-4199-9023-e9e40eeb82dd")); |
|
|
|
Alarm alarm = new Alarm(alarmId); |
|
|
|
@ -302,15 +302,14 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(expectedMsg); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsEntity_whenOnMsg_thenTellSuccess() throws TbNodeException { |
|
|
|
config.setOriginatorSource("ENTITY"); |
|
|
|
config.setEntityType("ASSET"); |
|
|
|
config.setEntityNamePattern("${md-name-pattern}"); |
|
|
|
@ParameterizedTest |
|
|
|
@MethodSource |
|
|
|
public void givenOriginatorSourceIsEntity_whenOnMsg_thenTellSuccess(String entityNamePattern, TbMsgMetaData metaData, String data) throws TbNodeException { |
|
|
|
config.setOriginatorSource(ENTITY_SOURCE); |
|
|
|
config.setEntityType(EntityType.ASSET.name()); |
|
|
|
config.setEntityNamePattern(entityNamePattern); |
|
|
|
|
|
|
|
TbMsgMetaData metaData = new TbMsgMetaData(); |
|
|
|
metaData.putValue("md-name-pattern", "test-asset"); |
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, TbMsg.EMPTY_JSON_OBJECT); |
|
|
|
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, data); |
|
|
|
TbMsg expectedMsg = TbMsg.transformMsgOriginator(msg, ASSET_ID); |
|
|
|
|
|
|
|
given(ctxMock.getDbCallbackExecutor()).willReturn(dbExecutor); |
|
|
|
@ -322,16 +321,25 @@ public class TbChangeOriginatorNodeTest { |
|
|
|
node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); |
|
|
|
node.onMsg(ctxMock, msg); |
|
|
|
|
|
|
|
then(assetServiceMock).should().findAssetByTenantIdAndName(TENANT_ID, "test-asset"); |
|
|
|
String expectedEntityName = TbNodeUtils.processPattern(entityNamePattern, msg); |
|
|
|
then(assetServiceMock).should().findAssetByTenantIdAndName(TENANT_ID, expectedEntityName); |
|
|
|
ArgumentCaptor<TbMsg> actualMsg = ArgumentCaptor.forClass(TbMsg.class); |
|
|
|
then(ctxMock).should().tellSuccess(actualMsg.capture()); |
|
|
|
assertThat(actualMsg.getValue()).usingRecursiveComparison().ignoringFields("ctx").isEqualTo(expectedMsg); |
|
|
|
} |
|
|
|
|
|
|
|
private static Stream<Arguments> givenOriginatorSourceIsEntity_whenOnMsg_thenTellSuccess() { |
|
|
|
return Stream.of( |
|
|
|
Arguments.of("test-asset", TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT), |
|
|
|
Arguments.of("${md-name-pattern}", new TbMsgMetaData(Map.of("md-name-pattern", "md-test-asset")), TbMsg.EMPTY_JSON_OBJECT), |
|
|
|
Arguments.of("${msg-name-pattern}", TbMsgMetaData.EMPTY, "{\"msg-name-pattern\":\"msg-test-asset\"}") |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@Test |
|
|
|
public void givenOriginatorSourceIsEntityAndEntityCouldNotFound_whenOnMsg_thenTellFailure() throws TbNodeException { |
|
|
|
config.setOriginatorSource("ENTITY"); |
|
|
|
config.setEntityType("ASSET"); |
|
|
|
config.setOriginatorSource(ENTITY_SOURCE); |
|
|
|
config.setEntityType(EntityType.ASSET.name()); |
|
|
|
config.setEntityNamePattern("${md-name-pattern}"); |
|
|
|
|
|
|
|
TbMsgMetaData metaData = new TbMsgMetaData(); |
|
|
|
|