Browse Source

Add parameterized test to cover `updateInactivityStateIfExpired()`

pull/9155/head
Dmytro Skarzhynets 3 years ago
parent
commit
4180866ccc
  1. 183
      application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java

183
application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java

@ -18,6 +18,10 @@ package org.thingsboard.server.service.state;
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.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
@ -25,10 +29,13 @@ import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.DeviceIdInfo;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.notification.rule.trigger.DeviceActivityTrigger;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.common.data.query.TsValue;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.queue.ServiceType;
@ -46,10 +53,13 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.willReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@ -57,7 +67,9 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
import static org.thingsboard.server.service.state.DefaultDeviceStateService.ACTIVITY_STATE;
import static org.thingsboard.server.service.state.DefaultDeviceStateService.INACTIVITY_ALARM_TIME;
import static org.thingsboard.server.service.state.DefaultDeviceStateService.INACTIVITY_TIMEOUT;
@ExtendWith(MockitoExtension.class)
@ -341,4 +353,173 @@ public class DefaultDeviceStateServiceTest {
verify(telemetrySubscriptionService, times(1)).saveAttrAndNotify(any(), eq(deviceId), any(), eq(ACTIVITY_STATE), eq(isActive), any());
}
}
@Test
public void givenStateDataIsNull_whenUpdateInactivityTimeoutIfExpired_thenShouldCleanupDevice() {
// GIVEN
service.deviceStates.put(deviceId, deviceStateDataMock);
// WHEN
service.updateInactivityStateIfExpired(System.currentTimeMillis(), deviceId, null);
// THEN
assertThat(service.deviceStates.get(deviceId)).isNull();
assertThat(service.deviceStates.size()).isEqualTo(0);
assertThat(service.deviceStates.isEmpty()).isTrue();
}
@Test
public void givenNotMyPartition_whenUpdateInactivityTimeoutIfExpired_thenShouldCleanupDevice() {
// GIVEN
long currentTime = System.currentTimeMillis();
DeviceState deviceState = DeviceState.builder()
.active(true)
.lastConnectTime(currentTime - 8000)
.lastActivityTime(currentTime - 4000)
.lastDisconnectTime(0)
.lastInactivityAlarmTime(0)
.inactivityTimeout(3000)
.build();
DeviceStateData stateData = DeviceStateData.builder()
.tenantId(tenantId)
.deviceId(deviceId)
.deviceCreationTime(currentTime - 10000)
.state(deviceState)
.build();
service.deviceStates.put(deviceId, stateData);
var notMyTpi = TopicPartitionInfo.builder().myPartition(false).build();
given(partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId)).willReturn(notMyTpi);
// WHEN
service.updateInactivityStateIfExpired(System.currentTimeMillis(), deviceId, stateData);
// THEN
assertThat(service.deviceStates.get(deviceId)).isNull();
assertThat(service.deviceStates.size()).isEqualTo(0);
assertThat(service.deviceStates.isEmpty()).isTrue();
}
@ParameterizedTest
@MethodSource("provideParametersForUpdateInactivityStateIfExpired")
public void givenTestParameters_whenUpdateInactivityStateIfExpired_thenShouldBeInTheExpectedStateAndPerformExpectedActions(
boolean activityState, long ts, long lastActivityTime, long lastInactivityAlarmTime, long inactivityTimeout, long deviceCreationTime,
boolean expectedActivityState, long expectedLastInactivityAlarmTime, boolean shouldUpdateActivityStateToInactive
) {
// GIVEN
var state = DeviceState.builder()
.active(activityState)
.lastActivityTime(lastActivityTime)
.lastInactivityAlarmTime(lastInactivityAlarmTime)
.inactivityTimeout(inactivityTimeout)
.build();
var deviceStateData = DeviceStateData.builder()
.tenantId(tenantId)
.deviceId(deviceId)
.deviceCreationTime(deviceCreationTime)
.metaData(new TbMsgMetaData())
.state(state)
.build();
if (shouldUpdateActivityStateToInactive) {
given(partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId)).willReturn(tpi);
}
// WHEN
service.updateInactivityStateIfExpired(ts, deviceId, deviceStateData);
// THEN
assertThat(state.isActive()).isEqualTo(expectedActivityState);
assertThat(state.getLastInactivityAlarmTime()).isEqualTo(expectedLastInactivityAlarmTime);
if (shouldUpdateActivityStateToInactive) {
then(telemetrySubscriptionService).should().saveAttrAndNotify(
eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(SERVER_SCOPE), eq(ACTIVITY_STATE), eq(false), any()
);
var msgCaptor = ArgumentCaptor.forClass(TbMsg.class);
then(clusterService).should().pushMsgToRuleEngine(eq(tenantId), eq(deviceId), msgCaptor.capture(), any());
var actualMsg = msgCaptor.getValue();
assertThat(actualMsg.getType()).isEqualTo(TbMsgType.INACTIVITY_EVENT.name());
assertThat(actualMsg.getOriginator()).isEqualTo(deviceId);
var notificationCaptor = ArgumentCaptor.forClass(DeviceActivityTrigger.class);
then(notificationRuleProcessor).should().process(notificationCaptor.capture());
var actualNotification = notificationCaptor.getValue();
assertThat(actualNotification.getTenantId()).isEqualTo(tenantId);
assertThat(actualNotification.getDeviceId()).isEqualTo(deviceId);
assertThat(actualNotification.isActive()).isFalse();
then(telemetrySubscriptionService).should().saveAttrAndNotify(
eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(SERVER_SCOPE),
eq(INACTIVITY_ALARM_TIME), eq(expectedLastInactivityAlarmTime), any()
);
}
}
private static Stream<Arguments> provideParametersForUpdateInactivityStateIfExpired() {
return Stream.of(
Arguments.of(false, 100, 70, 90, 70, 60, false, 90, false),
Arguments.of(false, 100, 40, 50, 70, 10, false, 50, false),
Arguments.of(false, 100, 25, 60, 75, 25, false, 60, false),
Arguments.of(false, 100, 60, 70, 10, 50, false, 70, false),
Arguments.of(false, 100, 10, 15, 90, 10, false, 15, false),
Arguments.of(false, 100, 0, 40, 75, 0, false, 40, false),
Arguments.of(true, 100, 90, 80, 80, 50, true, 80, false),
Arguments.of(true, 100, 95, 90, 10, 50, true, 90, false),
Arguments.of(true, 100, 10, 10, 90, 10, false, 100, true),
Arguments.of(true, 100, 10, 10, 90, 11, true, 10, false),
Arguments.of(true, 100, 15, 10, 85, 5, false, 100, true),
Arguments.of(true, 100, 15, 10, 75, 5, false, 100, true),
Arguments.of(true, 100, 95, 90, 5, 50, false, 100, true),
Arguments.of(true, 100, 0, 0, 101, 0, true, 0, false),
Arguments.of(true, 100, 0, 0, 100, 0, false, 100, true),
Arguments.of(true, 100, 0, 0, 99, 0, false, 100, true),
Arguments.of(true, 100, 0, 0, 120, 10, true, 0, false),
Arguments.of(true, 100, 50, 0, 100, 0, true, 0, false),
Arguments.of(true, 100, 10, 0, 91, 0, true, 0, false),
Arguments.of(true, 100, 90, 0, 10, 0, false, 100, true),
Arguments.of(true, 100, 100, 100, 1, 0, true, 100, false),
Arguments.of(true, 100, 100, 100, 100, 100, true, 100, false),
Arguments.of(false, 100, 59, 60, 30, 10, false, 60, false),
Arguments.of(true, 100, 60, 60, 30, 10, false, 100, true),
Arguments.of(true, 100, 61, 60, 30, 10, false, 100, true),
Arguments.of(true, 0, 0, 0, 1, 0, true, 0, false),
Arguments.of(true, 0, 0, 0, 0, 0, false, 0, true),
Arguments.of(true, 100, 90, 80, 20, 70, true, 80, false),
Arguments.of(true, 100, 80, 90, 30, 70, true, 90, false)
);
}
}

Loading…
Cancel
Save