2020import org .junit .Test ;
2121import org .springframework .beans .factory .annotation .Autowired ;
2222import org .thingsboard .server .common .data .ApiUsageRecordKey ;
23+ import org .thingsboard .server .common .data .ApiUsageState ;
2324import org .thingsboard .server .common .data .ApiUsageStateValue ;
2425import org .thingsboard .server .common .data .Tenant ;
2526import org .thingsboard .server .common .data .TenantProfile ;
27+ import org .thingsboard .server .common .data .id .ApiUsageStateId ;
28+ import org .thingsboard .server .common .data .id .EntityId ;
2629import org .thingsboard .server .common .data .id .TenantId ;
2730import org .thingsboard .server .common .data .tenant .profile .DefaultTenantProfileConfiguration ;
2831import org .thingsboard .server .common .data .tenant .profile .TenantProfileData ;
3336import org .thingsboard .server .gen .transport .TransportProtos ;
3437import org .thingsboard .server .queue .common .TbProtoQueueMsg ;
3538
39+ import java .lang .reflect .Field ;
40+ import java .time .LocalDate ;
41+ import java .util .HashMap ;
42+ import java .util .Map ;
3643import java .util .UUID ;
44+ import java .util .concurrent .TimeUnit ;
3745
46+ import static java .time .ZoneOffset .UTC ;
47+ import static java .time .temporal .ChronoField .DAY_OF_MONTH ;
48+ import static java .time .temporal .ChronoUnit .MONTHS ;
49+ import static org .assertj .core .api .Assertions .assertThat ;
3850import static org .junit .Assert .assertEquals ;
3951
4052@ DaoSqlTest
@@ -48,6 +60,7 @@ public class DefaultTbApiUsageStateServiceTest extends AbstractControllerTest {
4860
4961 private TenantId tenantId ;
5062 private Tenant savedTenant ;
63+ private TenantProfile savedTenantProfile ;
5164
5265 private static final int MAX_ENABLE_VALUE = 5000 ;
5366 private static final long VALUE_WARNING = 4500L ;
@@ -59,7 +72,7 @@ public void init() throws Exception {
5972 loginSysAdmin ();
6073
6174 TenantProfile tenantProfile = createTenantProfile ();
62- TenantProfile savedTenantProfile = doPost ("/api/tenantProfile" , tenantProfile , TenantProfile .class );
75+ savedTenantProfile = doPost ("/api/tenantProfile" , tenantProfile , TenantProfile .class );
6376 Assert .assertNotNull (savedTenantProfile );
6477
6578 Tenant tenant = new Tenant ();
@@ -109,6 +122,41 @@ public void testProcess_transitionFromWarningToDisabled() {
109122 assertEquals (ApiUsageStateValue .DISABLED , apiUsageStateService .findTenantApiUsageState (tenantId ).getDbStorageState ());
110123 }
111124
125+ @ Test
126+ public void checkStartOfNextCycle_setsNextCycleToNextMonth () throws Exception {
127+ ApiUsageState apiUsageState = new ApiUsageState (new ApiUsageStateId (UUID .randomUUID ()));
128+ apiUsageState .setDbStorageState (ApiUsageStateValue .ENABLED );
129+ apiUsageState .setAlarmExecState (ApiUsageStateValue .ENABLED );
130+ apiUsageState .setSmsExecState (ApiUsageStateValue .ENABLED );
131+ apiUsageState .setTbelExecState (ApiUsageStateValue .ENABLED );
132+ apiUsageState .setReExecState (ApiUsageStateValue .ENABLED );
133+ apiUsageState .setTransportState (ApiUsageStateValue .ENABLED );
134+ apiUsageState .setEmailExecState (ApiUsageStateValue .ENABLED );
135+ apiUsageState .setJsExecState (ApiUsageStateValue .ENABLED );
136+ apiUsageState .setTenantId (tenantId );
137+ apiUsageState .setEntityId (tenantId );
138+
139+ long now = System .currentTimeMillis ();
140+ long currentCycleTs = now - TimeUnit .DAYS .toMillis (30 );
141+ long nextCycleTs = now - TimeUnit .MINUTES .toMillis (5 ); // < 1h ago
142+ TenantApiUsageState tenantApiUsageState = new TenantApiUsageState (savedTenantProfile , apiUsageState );
143+ tenantApiUsageState .setCycles (currentCycleTs , nextCycleTs );
144+ Map <EntityId , BaseApiUsageState > map = new HashMap <>();
145+ map .put (tenantId , tenantApiUsageState );
146+
147+ Field fieldToSet = DefaultTbApiUsageStateService .class .getDeclaredField ("myUsageStates" );
148+ fieldToSet .setAccessible (true );
149+ fieldToSet .set (service , map );
150+
151+ service .checkStartOfNextCycle ();
152+
153+ long firstOfNextMonth = LocalDate .now ()
154+ .with ((temporal ) -> temporal .with (DAY_OF_MONTH , 1 )
155+ .plus (1 , MONTHS ))
156+ .atStartOfDay (UTC ).toInstant ().toEpochMilli ();
157+ assertThat (tenantApiUsageState .getNextCycleTs ()).isEqualTo (firstOfNextMonth );
158+ }
159+
112160 private TenantProfile createTenantProfile () {
113161 TenantProfile tenantProfile = new TenantProfile ();
114162 tenantProfile .setName ("Tenant Profile" );
0 commit comments