12 changed files with 553 additions and 24 deletions
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2022 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.rule.engine.api; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.ApiUsageState; |
||||
|
import org.thingsboard.server.common.data.id.ApiUsageStateId; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
|
||||
|
public interface RuleEngineApiUsageStateService { |
||||
|
|
||||
|
ApiUsageState findApiUsageStateById(TenantId tenantId, ApiUsageStateId id); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,347 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2022 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.rule.engine.util; |
||||
|
|
||||
|
import com.google.common.util.concurrent.Futures; |
||||
|
import org.junit.After; |
||||
|
import org.junit.Assert; |
||||
|
import org.junit.Before; |
||||
|
import org.junit.Test; |
||||
|
import org.junit.runner.RunWith; |
||||
|
import org.mockito.Mock; |
||||
|
import org.mockito.junit.MockitoJUnitRunner; |
||||
|
import org.thingsboard.common.util.AbstractListeningExecutor; |
||||
|
import org.thingsboard.rule.engine.api.RuleEngineAlarmService; |
||||
|
import org.thingsboard.rule.engine.api.RuleEngineApiUsageStateService; |
||||
|
import org.thingsboard.rule.engine.api.RuleEngineAssetProfileCache; |
||||
|
import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; |
||||
|
import org.thingsboard.rule.engine.api.RuleEngineRpcService; |
||||
|
import org.thingsboard.rule.engine.api.TbContext; |
||||
|
import org.thingsboard.server.common.data.ApiUsageState; |
||||
|
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.DeviceProfile; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.EntityView; |
||||
|
import org.thingsboard.server.common.data.OtaPackage; |
||||
|
import org.thingsboard.server.common.data.TbResource; |
||||
|
import org.thingsboard.server.common.data.TenantProfile; |
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.alarm.Alarm; |
||||
|
import org.thingsboard.server.common.data.asset.Asset; |
||||
|
import org.thingsboard.server.common.data.asset.AssetProfile; |
||||
|
import org.thingsboard.server.common.data.edge.Edge; |
||||
|
import org.thingsboard.server.common.data.id.AssetProfileId; |
||||
|
import org.thingsboard.server.common.data.id.DeviceProfileId; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.id.EntityIdFactory; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.common.data.queue.Queue; |
||||
|
import org.thingsboard.server.common.data.rpc.Rpc; |
||||
|
import org.thingsboard.server.common.data.rule.RuleChain; |
||||
|
import org.thingsboard.server.common.data.rule.RuleNode; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetType; |
||||
|
import org.thingsboard.server.common.data.widget.WidgetsBundle; |
||||
|
import org.thingsboard.server.dao.asset.AssetService; |
||||
|
import org.thingsboard.server.dao.customer.CustomerService; |
||||
|
import org.thingsboard.server.dao.dashboard.DashboardService; |
||||
|
import org.thingsboard.server.dao.device.DeviceService; |
||||
|
import org.thingsboard.server.dao.edge.EdgeService; |
||||
|
import org.thingsboard.server.dao.entityview.EntityViewService; |
||||
|
import org.thingsboard.server.dao.ota.OtaPackageService; |
||||
|
import org.thingsboard.server.dao.queue.QueueService; |
||||
|
import org.thingsboard.server.dao.resource.ResourceService; |
||||
|
import org.thingsboard.server.dao.rule.RuleChainService; |
||||
|
import org.thingsboard.server.dao.user.UserService; |
||||
|
import org.thingsboard.server.dao.widget.WidgetTypeService; |
||||
|
import org.thingsboard.server.dao.widget.WidgetsBundleService; |
||||
|
|
||||
|
import java.util.UUID; |
||||
|
import java.util.concurrent.ExecutionException; |
||||
|
|
||||
|
import static org.mockito.ArgumentMatchers.any; |
||||
|
import static org.mockito.ArgumentMatchers.eq; |
||||
|
import static org.mockito.Mockito.doReturn; |
||||
|
import static org.mockito.Mockito.when; |
||||
|
|
||||
|
@RunWith(MockitoJUnitRunner.class) |
||||
|
public class EntitiesTenantIdAsyncLoaderTest { |
||||
|
|
||||
|
@Mock |
||||
|
private TbContext ctx; |
||||
|
@Mock |
||||
|
private CustomerService customerService; |
||||
|
@Mock |
||||
|
private UserService userService; |
||||
|
@Mock |
||||
|
private AssetService assetService; |
||||
|
@Mock |
||||
|
private DeviceService deviceService; |
||||
|
@Mock |
||||
|
private RuleEngineAlarmService alarmService; |
||||
|
@Mock |
||||
|
private RuleChainService ruleChainService; |
||||
|
@Mock |
||||
|
private EntityViewService entityViewService; |
||||
|
@Mock |
||||
|
private DashboardService dashboardService; |
||||
|
@Mock |
||||
|
private EdgeService edgeService; |
||||
|
@Mock |
||||
|
private OtaPackageService otaPackageService; |
||||
|
@Mock |
||||
|
private RuleEngineAssetProfileCache assetProfileCache; |
||||
|
@Mock |
||||
|
private RuleEngineDeviceProfileCache deviceProfileCache; |
||||
|
@Mock |
||||
|
private WidgetTypeService widgetTypeService; |
||||
|
@Mock |
||||
|
private WidgetsBundleService widgetsBundleService; |
||||
|
@Mock |
||||
|
private QueueService queueService; |
||||
|
@Mock |
||||
|
private ResourceService resourceService; |
||||
|
@Mock |
||||
|
private RuleEngineRpcService rpcService; |
||||
|
@Mock |
||||
|
private RuleEngineApiUsageStateService ruleEngineApiUsageStateService; |
||||
|
|
||||
|
private TenantId tenantId; |
||||
|
private AbstractListeningExecutor dbExecutor; |
||||
|
|
||||
|
@Before |
||||
|
public void before() { |
||||
|
dbExecutor = new AbstractListeningExecutor() { |
||||
|
@Override |
||||
|
protected int getThreadPollSize() { |
||||
|
return 3; |
||||
|
} |
||||
|
}; |
||||
|
dbExecutor.init(); |
||||
|
this.tenantId = new TenantId(UUID.randomUUID()); |
||||
|
|
||||
|
when(ctx.getTenantId()).thenReturn(tenantId); |
||||
|
when(ctx.getDbCallbackExecutor()).thenReturn(dbExecutor); |
||||
|
|
||||
|
for (EntityType entityType : EntityType.values()) { |
||||
|
initMocks(entityType, tenantId); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@After |
||||
|
public void after() { |
||||
|
dbExecutor.destroy(); |
||||
|
} |
||||
|
|
||||
|
private void initMocks(EntityType entityType, TenantId tenantId) { |
||||
|
switch (entityType) { |
||||
|
case TENANT: |
||||
|
break; |
||||
|
case CUSTOMER: |
||||
|
Customer customer = new Customer(); |
||||
|
customer.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getCustomerService()).thenReturn(customerService); |
||||
|
doReturn(Futures.immediateFuture(customer)).when(customerService).findCustomerByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case USER: |
||||
|
User user = new User(); |
||||
|
user.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getUserService()).thenReturn(userService); |
||||
|
doReturn(Futures.immediateFuture(user)).when(userService).findUserByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case ASSET: |
||||
|
Asset asset = new Asset(); |
||||
|
asset.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getAssetService()).thenReturn(assetService); |
||||
|
doReturn(Futures.immediateFuture(asset)).when(assetService).findAssetByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case DEVICE: |
||||
|
Device device = new Device(); |
||||
|
device.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getDeviceService()).thenReturn(deviceService); |
||||
|
doReturn(Futures.immediateFuture(device)).when(deviceService).findDeviceByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case ALARM: |
||||
|
Alarm alarm = new Alarm(); |
||||
|
alarm.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getAlarmService()).thenReturn(alarmService); |
||||
|
doReturn(Futures.immediateFuture(alarm)).when(alarmService).findAlarmByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case RULE_CHAIN: |
||||
|
RuleChain ruleChain = new RuleChain(); |
||||
|
ruleChain.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getRuleChainService()).thenReturn(ruleChainService); |
||||
|
doReturn(Futures.immediateFuture(ruleChain)).when(ruleChainService).findRuleChainByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case ENTITY_VIEW: |
||||
|
EntityView entityView = new EntityView(); |
||||
|
entityView.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getEntityViewService()).thenReturn(entityViewService); |
||||
|
doReturn(Futures.immediateFuture(entityView)).when(entityViewService).findEntityViewByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case DASHBOARD: |
||||
|
Dashboard dashboard = new Dashboard(); |
||||
|
dashboard.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getDashboardService()).thenReturn(dashboardService); |
||||
|
doReturn(Futures.immediateFuture(dashboard)).when(dashboardService).findDashboardByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case EDGE: |
||||
|
Edge edge = new Edge(); |
||||
|
edge.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getEdgeService()).thenReturn(edgeService); |
||||
|
doReturn(Futures.immediateFuture(edge)).when(edgeService).findEdgeByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case OTA_PACKAGE: |
||||
|
OtaPackage otaPackage = new OtaPackage(); |
||||
|
otaPackage.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getOtaPackageService()).thenReturn(otaPackageService); |
||||
|
doReturn(Futures.immediateFuture(otaPackage)).when(otaPackageService).findOtaPackageInfoByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case ASSET_PROFILE: |
||||
|
AssetProfile assetProfile = new AssetProfile(); |
||||
|
assetProfile.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getAssetProfileCache()).thenReturn(assetProfileCache); |
||||
|
doReturn(assetProfile).when(assetProfileCache).get(eq(tenantId), any(AssetProfileId.class)); |
||||
|
|
||||
|
break; |
||||
|
case DEVICE_PROFILE: |
||||
|
DeviceProfile deviceProfile = new DeviceProfile(); |
||||
|
deviceProfile.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getDeviceProfileCache()).thenReturn(deviceProfileCache); |
||||
|
doReturn(deviceProfile).when(deviceProfileCache).get(eq(tenantId), any(DeviceProfileId.class)); |
||||
|
|
||||
|
break; |
||||
|
case WIDGET_TYPE: |
||||
|
WidgetType widgetType = new WidgetType(); |
||||
|
widgetType.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getWidgetTypeService()).thenReturn(widgetTypeService); |
||||
|
doReturn(widgetType).when(widgetTypeService).findWidgetTypeById(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case WIDGETS_BUNDLE: |
||||
|
WidgetsBundle widgetsBundle = new WidgetsBundle(); |
||||
|
widgetsBundle.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getWidgetBundleService()).thenReturn(widgetsBundleService); |
||||
|
doReturn(widgetsBundle).when(widgetsBundleService).findWidgetsBundleById(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case RPC: |
||||
|
Rpc rps = new Rpc(); |
||||
|
rps.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getRpcService()).thenReturn(rpcService); |
||||
|
doReturn(Futures.immediateFuture(rps)).when(rpcService).findRpcByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case QUEUE: |
||||
|
Queue queue = new Queue(); |
||||
|
queue.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getQueueService()).thenReturn(queueService); |
||||
|
doReturn(queue).when(queueService).findQueueById(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case API_USAGE_STATE: |
||||
|
ApiUsageState apiUsageState = new ApiUsageState(); |
||||
|
apiUsageState.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getRuleEngineApiUsageStateService()).thenReturn(ruleEngineApiUsageStateService); |
||||
|
doReturn(apiUsageState).when(ruleEngineApiUsageStateService).findApiUsageStateById(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case TB_RESOURCE: |
||||
|
TbResource tbResource = new TbResource(); |
||||
|
tbResource.setTenantId(tenantId); |
||||
|
|
||||
|
when(ctx.getResourceService()).thenReturn(resourceService); |
||||
|
doReturn(Futures.immediateFuture(tbResource)).when(resourceService).findResourceInfoByIdAsync(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case RULE_NODE: |
||||
|
RuleNode ruleNode = new RuleNode(); |
||||
|
|
||||
|
when(ctx.getRuleChainService()).thenReturn(ruleChainService); |
||||
|
doReturn(ruleNode).when(ruleChainService).findRuleNodeById(eq(tenantId), any()); |
||||
|
|
||||
|
break; |
||||
|
case TENANT_PROFILE: |
||||
|
TenantProfile tenantProfile = new TenantProfile(); |
||||
|
|
||||
|
when(ctx.getTenantProfile()).thenReturn(tenantProfile); |
||||
|
when(ctx.getTenantProfile(any(TenantId.class))).thenReturn(tenantProfile); |
||||
|
|
||||
|
break; |
||||
|
default: |
||||
|
throw new RuntimeException("Unexpected original EntityType " + entityType); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private EntityId getEntityId(EntityType entityType) { |
||||
|
return EntityIdFactory.getByTypeAndUuid(entityType, UUID.randomUUID()); |
||||
|
} |
||||
|
|
||||
|
private void checkTenant(TenantId checkTenantId, boolean equals) throws ExecutionException, InterruptedException { |
||||
|
for (EntityType entityType : EntityType.values()) { |
||||
|
EntityId entityId = EntityType.TENANT.equals(entityType) ? tenantId : getEntityId(entityType); |
||||
|
TenantId targetTenantId = EntitiesTenantIdAsyncLoader.findEntityIdAsync(ctx, entityId).get(); |
||||
|
|
||||
|
Assert.assertNotNull(targetTenantId); |
||||
|
String msg = "Check entity type <" + entityType.name() + ">:"; |
||||
|
if (equals) { |
||||
|
Assert.assertEquals(msg, targetTenantId, checkTenantId); |
||||
|
} else { |
||||
|
Assert.assertNotEquals(msg, targetTenantId, checkTenantId); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void test_findEntityIdAsync_current_tenant() throws ExecutionException, InterruptedException { |
||||
|
checkTenant(tenantId, true); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void test_findEntityIdAsync_other_tenant() throws ExecutionException, InterruptedException { |
||||
|
checkTenant(new TenantId(UUID.randomUUID()), false); |
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue