diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index 406a288505..2929635949 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -61,3 +61,5 @@ DO $$ $$; -- UPDATE SAVE TIME SERIES NODES END + +ALTER TABLE api_usage_state ADD COLUMN IF NOT EXISTS version BIGINT DEFAULT 1; \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java b/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java index 78176bb4f7..aa1117572b 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java @@ -40,7 +40,8 @@ public abstract class BaseApiUsageState { private final Map gaugesReportCycles = new HashMap<>(); @Getter - private final ApiUsageState apiUsageState; + @Setter + private ApiUsageState apiUsageState; @Getter private volatile long currentCycleTs; @Getter diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index cfc5040329..aecb31ca0c 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -355,7 +355,8 @@ public class DefaultTbApiUsageStateService extends AbstractPartitionBasedService private void persistAndNotify(BaseApiUsageState state, Map result) { log.info("[{}] Detected update of the API state for {}: {}", state.getEntityId(), state.getEntityType(), result); - apiUsageStateService.update(state.getApiUsageState()); + ApiUsageState updatedState = apiUsageStateService.update(state.getApiUsageState()); + state.setApiUsageState(updatedState); long ts = System.currentTimeMillis(); List stateTelemetry = new ArrayList<>(); result.forEach((apiFeature, aState) -> stateTelemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(apiFeature.getApiStateKey(), aState.name())))); diff --git a/application/src/test/java/org/thingsboard/server/service/apiusage/ApiUsageTest.java b/application/src/test/java/org/thingsboard/server/service/apiusage/ApiUsageTest.java new file mode 100644 index 0000000000..961185d3cd --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/apiusage/ApiUsageTest.java @@ -0,0 +1,144 @@ +/** + * Copyright © 2016-2025 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.server.service.apiusage; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.common.data.ApiUsageStateValue; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.security.DeviceCredentialsType; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; +import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; +import org.thingsboard.server.controller.AbstractControllerTest; +import org.thingsboard.server.controller.TbUrlConstants; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; + +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@DaoSqlTest +@TestPropertySource(properties = { + "usage.stats.report.enabled=true", + "usage.stats.report.interval=2", + "usage.stats.gauge_report_interval=1", +}) +public class ApiUsageTest extends AbstractControllerTest { + + private Tenant savedTenant; + private User tenantAdmin; + + private static final int MAX_DP_ENABLE_VALUE = 12; + private static final double WARN_THRESHOLD_VALUE = 0.5; + @Autowired + private ApiUsageStateService apiUsageStateService; + + @Before + public void beforeTest() throws Exception { + loginSysAdmin(); + + TenantProfile tenantProfile = createTenantProfile(); + TenantProfile savedTenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class); + assertNotNull(savedTenantProfile); + + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + tenant.setTenantProfileId(savedTenantProfile.getId()); + savedTenant = saveTenant(tenant); + tenantId = savedTenant.getId(); + assertNotNull(savedTenant); + + tenantAdmin = new User(); + tenantAdmin.setAuthority(Authority.TENANT_ADMIN); + tenantAdmin.setTenantId(savedTenant.getId()); + tenantAdmin.setEmail("tenant2@thingsboard.org"); + + tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); + } + + @Test + public void testTelemetryApiCall() throws Exception { + Device device = createDevice(); + assertNotNull(device); + String telemetryPayload = "{\"temperature\":25, \"humidity\":60}"; + String url = TbUrlConstants.TELEMETRY_URL_PREFIX + "/DEVICE/" + device.getId() + "/timeseries/ANY"; + + long VALUE_WARNING = (long) (MAX_DP_ENABLE_VALUE * WARN_THRESHOLD_VALUE) / 2; + + for (int i = 0; i < VALUE_WARNING; i++) { + doPostAsync(url, telemetryPayload, String.class, status().isOk()); + } + + await().atMost(TIMEOUT, TimeUnit.SECONDS).untilAsserted(() -> assertEquals(ApiUsageStateValue.WARNING, apiUsageStateService.findTenantApiUsageState(tenantId).getDbStorageState())); + + long VALUE_DISABLE = (long) (MAX_DP_ENABLE_VALUE - (MAX_DP_ENABLE_VALUE * WARN_THRESHOLD_VALUE)) / 2; + + for (int i = 0; i < VALUE_DISABLE; i++) { + doPostAsync(url, telemetryPayload, String.class, status().isOk()); + } + + await().atMost(TIMEOUT, TimeUnit.SECONDS) + .untilAsserted(() -> { + assertEquals(ApiUsageStateValue.DISABLED, apiUsageStateService.findTenantApiUsageState(tenantId).getDbStorageState()); + }); + } + + private TenantProfile createTenantProfile() { + TenantProfile tenantProfile = new TenantProfile(); + tenantProfile.setName("Tenant Profile"); + tenantProfile.setDescription("Tenant Profile" + " Test"); + + TenantProfileData tenantProfileData = new TenantProfileData(); + DefaultTenantProfileConfiguration config = DefaultTenantProfileConfiguration.builder() + .maxDPStorageDays(MAX_DP_ENABLE_VALUE) + .warnThreshold(WARN_THRESHOLD_VALUE) + .build(); + + tenantProfileData.setConfiguration(config); + tenantProfile.setProfileData(tenantProfileData); + return tenantProfile; + } + + private Device createDevice() throws Exception { + String testToken = "TEST_TOKEN"; + + Device device = new Device(); + device.setName("My device"); + device.setType("default"); + device.setTenantId(tenantId); + + DeviceCredentials deviceCredentials = new DeviceCredentials(); + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); + deviceCredentials.setCredentialsId(testToken); + + SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(device, deviceCredentials); + + return readResponse(doPost("/api/device-with-credentials", saveRequest).andExpect(status().isOk()), Device.class); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java b/application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java index 9701e57eb9..20f8aaf881 100644 --- a/application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateServiceTest.java @@ -15,45 +15,114 @@ */ package org.thingsboard.server.service.apiusage; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.thingsboard.server.common.data.ApiUsageState; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.ApiUsageRecordKey; +import org.thingsboard.server.common.data.ApiUsageStateValue; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; +import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; +import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.controller.AbstractControllerTest; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.common.TbProtoQueueMsg; import java.util.UUID; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.never; +import static org.junit.Assert.assertEquals; -@ExtendWith(MockitoExtension.class) -public class DefaultTbApiUsageStateServiceTest { +@DaoSqlTest +public class DefaultTbApiUsageStateServiceTest extends AbstractControllerTest { - @Mock - TenantApiUsageState tenantUsageStateMock; + @Autowired + DefaultTbApiUsageStateService service; - TenantId tenantId = TenantId.fromUUID(UUID.fromString("00797a3b-7aeb-4b5b-b57a-c2a810d0f112")); + @Autowired + private ApiUsageStateService apiUsageStateService; - @Spy - @InjectMocks - DefaultTbApiUsageStateService service; + private TenantId tenantId; + private Tenant savedTenant; + + private static final int MAX_ENABLE_VALUE = 5000; + private static final long VALUE_WARNING = 4500L; + private static final long VALUE_DISABLE = 5500L; + private static final double WARN_THRESHOLD_VALUE = 0.8; + + @Before + public void init() throws Exception { + loginSysAdmin(); - @BeforeEach - public void setUp() { + TenantProfile tenantProfile = createTenantProfile(); + TenantProfile savedTenantProfile = doPost("/api/tenantProfile", tenantProfile, TenantProfile.class); + Assert.assertNotNull(savedTenantProfile); + + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + tenant.setTenantProfileId(savedTenantProfile.getId()); + savedTenant = saveTenant(tenant); + tenantId = savedTenant.getId(); + Assert.assertNotNull(savedTenant); } @Test - public void givenTenantIdFromEntityStatesMap_whenGetApiUsageState() { - service.myUsageStates.put(tenantId, tenantUsageStateMock); - ApiUsageState tenantUsageState = service.getApiUsageState(tenantId); - assertThat(tenantUsageState, is(tenantUsageStateMock.getApiUsageState())); - Mockito.verify(service, never()).getOrFetchState(tenantId, tenantId); + public void testProcess_transitionFromWarningToDisabled() { + TransportProtos.ToUsageStatsServiceMsg.Builder warningMsgBuilder = TransportProtos.ToUsageStatsServiceMsg.newBuilder() + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) + .setCustomerIdMSB(0) + .setCustomerIdLSB(0) + .setServiceId("testService"); + + warningMsgBuilder.addValues(TransportProtos.UsageStatsKVProto.newBuilder() + .setKey(ApiUsageRecordKey.STORAGE_DP_COUNT.name()) + .setValue(VALUE_WARNING) + .build()); + + TransportProtos.ToUsageStatsServiceMsg warningStatsMsg = warningMsgBuilder.build(); + TbProtoQueueMsg warningMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), warningStatsMsg); + + service.process(warningMsg, TbCallback.EMPTY); + assertEquals(ApiUsageStateValue.WARNING, apiUsageStateService.findTenantApiUsageState(tenantId).getDbStorageState()); + + TransportProtos.ToUsageStatsServiceMsg.Builder disableMsgBuilder = TransportProtos.ToUsageStatsServiceMsg.newBuilder() + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) + .setCustomerIdMSB(0) + .setCustomerIdLSB(0) + .setServiceId("testService"); + + disableMsgBuilder.addValues(TransportProtos.UsageStatsKVProto.newBuilder() + .setKey(ApiUsageRecordKey.STORAGE_DP_COUNT.name()) + .setValue(VALUE_DISABLE) + .build()); + + TransportProtos.ToUsageStatsServiceMsg disableStatsMsg = disableMsgBuilder.build(); + TbProtoQueueMsg disableMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), disableStatsMsg); + + service.process(disableMsg, TbCallback.EMPTY); + assertEquals(ApiUsageStateValue.DISABLED, apiUsageStateService.findTenantApiUsageState(tenantId).getDbStorageState()); + } + + private TenantProfile createTenantProfile() { + TenantProfile tenantProfile = new TenantProfile(); + tenantProfile.setName("Tenant Profile"); + tenantProfile.setDescription("Tenant Profile" + " Test"); + + TenantProfileData tenantProfileData = new TenantProfileData(); + DefaultTenantProfileConfiguration config = DefaultTenantProfileConfiguration.builder() + .maxDPStorageDays(MAX_ENABLE_VALUE) + .warnThreshold(WARN_THRESHOLD_VALUE) + .build(); + + tenantProfileData.setConfiguration(config); + tenantProfile.setProfileData(tenantProfileData); + return tenantProfile; } } \ No newline at end of file diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java index 98bf6363b8..ad02ade403 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateService.java @@ -34,4 +34,5 @@ public interface ApiUsageStateService extends EntityDaoService { void deleteApiUsageStateByEntityId(EntityId entityId); ApiUsageState findApiUsageStateById(TenantId tenantId, ApiUsageStateId id); + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java index d3f57e6efa..5a102f31e2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.id.TenantId; @EqualsAndHashCode(callSuper = true) @Getter @Setter -public class ApiUsageState extends BaseData implements HasTenantId { +public class ApiUsageState extends BaseData implements HasTenantId, HasVersion { private static final long serialVersionUID = 8250339805336035966L; @@ -41,6 +41,7 @@ public class ApiUsageState extends BaseData implements HasTenan private ApiUsageStateValue emailExecState; private ApiUsageStateValue smsExecState; private ApiUsageStateValue alarmExecState; + private Long version; public ApiUsageState() { super(); @@ -62,6 +63,7 @@ public class ApiUsageState extends BaseData implements HasTenan this.emailExecState = ur.getEmailExecState(); this.smsExecState = ur.getSmsExecState(); this.alarmExecState = ur.getAlarmExecState(); + this.version = ur.getVersion(); } public boolean isTransportEnabled() { @@ -84,15 +86,16 @@ public class ApiUsageState extends BaseData implements HasTenan return !ApiUsageStateValue.DISABLED.equals(tbelExecState); } - public boolean isEmailSendEnabled(){ + public boolean isEmailSendEnabled() { return !ApiUsageStateValue.DISABLED.equals(emailExecState); } - public boolean isSmsSendEnabled(){ + public boolean isSmsSendEnabled() { return !ApiUsageStateValue.DISABLED.equals(smsExecState); } public boolean isAlarmCreationEnabled() { return alarmExecState != ApiUsageStateValue.DISABLED; } + } diff --git a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java index f911ef3e6e..be210ed4ed 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java @@ -1019,7 +1019,9 @@ public class ProtoUtils { .setTbelExecState(apiUsageState.getTbelExecState().name()) .setEmailExecState(apiUsageState.getEmailExecState().name()) .setSmsExecState(apiUsageState.getSmsExecState().name()) - .setAlarmExecState(apiUsageState.getAlarmExecState().name()).build(); + .setAlarmExecState(apiUsageState.getAlarmExecState().name()) + .setVersion(apiUsageState.getVersion()) + .build(); } public static ApiUsageState fromProto(TransportProtos.ApiUsageStateProto proto) { @@ -1035,6 +1037,7 @@ public class ProtoUtils { apiUsageState.setEmailExecState(ApiUsageStateValue.valueOf(proto.getEmailExecState())); apiUsageState.setSmsExecState(ApiUsageStateValue.valueOf(proto.getSmsExecState())); apiUsageState.setAlarmExecState(ApiUsageStateValue.valueOf(proto.getAlarmExecState())); + apiUsageState.setVersion(proto.getVersion()); return apiUsageState; } diff --git a/common/proto/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto index d5d079c18a..1ecd4e6a3a 100644 --- a/common/proto/src/main/proto/queue.proto +++ b/common/proto/src/main/proto/queue.proto @@ -325,6 +325,7 @@ message ApiUsageStateProto { string emailExecState = 14; string smsExecState = 15; string alarmExecState = 16; + int64 version = 17; } message RepositorySettingsProto { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java index 6caacd0ffb..40f7442047 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.BaseVersionedEntity; import org.thingsboard.server.dao.model.ModelConstants; import java.util.UUID; @@ -40,7 +40,7 @@ import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Entity @Table(name = ModelConstants.API_USAGE_STATE_TABLE_NAME) -public class ApiUsageStateEntity extends BaseSqlEntity implements BaseEntity { +public class ApiUsageStateEntity extends BaseVersionedEntity implements BaseEntity { @Column(name = ModelConstants.API_USAGE_STATE_TENANT_ID_COLUMN) private UUID tenantId; @@ -77,10 +77,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements } public ApiUsageStateEntity(ApiUsageState ur) { - if (ur.getId() != null) { - this.setUuid(ur.getId().getId()); - } - this.setCreatedTime(ur.getCreatedTime()); + super(ur); if (ur.getTenantId() != null) { this.tenantId = ur.getTenantId().getId(); } @@ -116,6 +113,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity implements ur.setEmailExecState(emailExecState); ur.setSmsExecState(smsExecState); ur.setAlarmExecState(alarmExecState); + ur.setVersion(version); return ur; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index a33eddec13..3a867587e1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -154,6 +154,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A log.trace("Executing save [{}]", apiUsageState.getTenantId()); validateId(apiUsageState.getTenantId(), id -> INCORRECT_TENANT_ID + id); validateId(apiUsageState.getId(), "Can't save new usage state. Only update is allowed!"); + apiUsageState.setVersion(null); ApiUsageState savedState = apiUsageStateDao.save(apiUsageState.getTenantId(), apiUsageState); eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(savedState.getTenantId()).entityId(savedState.getId()) .entity(savedState).build()); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 50460b2b29..b88c6bba50 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -702,6 +702,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( email_exec varchar(32), sms_exec varchar(32), alarm_exec varchar(32), + version BIGINT DEFAULT 1, CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) ); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/ApiUsageStateServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/ApiUsageStateServiceTest.java index 1ffca98a14..d87018573c 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/ApiUsageStateServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/ApiUsageStateServiceTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.ApiUsageStateValue; +import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; @@ -30,22 +31,42 @@ public class ApiUsageStateServiceTest extends AbstractServiceTest { ApiUsageStateService apiUsageStateService; @Test - public void testFindApiUsageStateByTenantId() { - ApiUsageState apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); - Assert.assertNotNull(apiUsageState); + public void testFindTenantApiUsageState() { + ApiUsageState state = apiUsageStateService.findTenantApiUsageState(tenantId); + Assert.assertNotNull(state); } @Test - public void testUpdateApiUsageState(){ - ApiUsageState apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); - Assert.assertNotNull(apiUsageState); - Assert.assertTrue(apiUsageState.isTransportEnabled()); - apiUsageState.setTransportState(ApiUsageStateValue.DISABLED); - apiUsageState = apiUsageStateService.update(apiUsageState); - Assert.assertNotNull(apiUsageState); - apiUsageState = apiUsageStateService.findTenantApiUsageState(tenantId); - Assert.assertNotNull(apiUsageState); - Assert.assertFalse(apiUsageState.isTransportEnabled()); + public void testUpdate() { + ApiUsageState state = apiUsageStateService.findTenantApiUsageState(tenantId); + + state.setTransportState(ApiUsageStateValue.DISABLED); + ApiUsageState updated = apiUsageStateService.update(state); + Assert.assertEquals(ApiUsageStateValue.DISABLED, updated.getTransportState()); + } + + @Test + public void testUpdateWithNullId() { + ApiUsageState newState = new ApiUsageState(); + newState.setTenantId(tenantId); + newState.setTransportState(ApiUsageStateValue.ENABLED); + Assert.assertThrows(IncorrectParameterException.class, () -> apiUsageStateService.update(newState)); + } + + @Test + public void testFindApiUsageStateByEntityId() { + ApiUsageState state = apiUsageStateService.findApiUsageStateByEntityId(tenantId); + Assert.assertNotNull(state); + } + + @Test + public void testDeleteByTenantId() { + ApiUsageState state = apiUsageStateService.findTenantApiUsageState(tenantId); + Assert.assertNotNull(state); + + apiUsageStateService.deleteByTenantId(tenantId); + state = apiUsageStateService.findTenantApiUsageState(tenantId); + Assert.assertNull(state); } }