From 8bb8fddf40f26a972e0e7344ec5a4807618638a1 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 25 Apr 2024 20:13:20 +0200 Subject: [PATCH 01/12] SecurityConfiguration: deprecated authorizeRequests replaced with authorizeHttpRequests --- .../server/config/TbRuleEngineSecurityConfiguration.java | 7 ++++--- .../server/config/ThingsboardSecurityConfiguration.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java index e1ab755036..15d33c7fcb 100644 --- a/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java @@ -40,9 +40,10 @@ public class TbRuleEngineSecurityConfiguration { .frameOptions(config -> {}).disable()) .cors(cors -> {}) .csrf(AbstractHttpConfigurer::disable) - .authorizeRequests() - .requestMatchers("/actuator/prometheus").permitAll() - .anyRequest().authenticated(); + .authorizeHttpRequests(config -> config + .requestMatchers("/actuator/prometheus").permitAll()) + .authorizeHttpRequests(config -> config + .anyRequest().authenticated()); return http.build(); } } diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index c27ca35313..67c14ce656 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -209,7 +209,7 @@ public class ThingsboardSecurityConfiguration { .csrf(AbstractHttpConfigurer::disable) .exceptionHandling(config -> {}) .sessionManagement(config -> config.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .authorizeRequests(config -> config + .authorizeHttpRequests(config -> config .requestMatchers(WEBJARS_ENTRY_POINT).permitAll() // Webjars .requestMatchers(DEVICE_API_ENTRY_POINT).permitAll() // Device HTTP Transport API .requestMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point @@ -218,7 +218,7 @@ public class ThingsboardSecurityConfiguration { .requestMatchers(MAIL_OAUTH2_PROCESSING_ENTRY_POINT).permitAll() // Mail oauth2 code processing url .requestMatchers(DEVICE_CONNECTIVITY_CERTIFICATE_DOWNLOAD_ENTRY_POINT).permitAll() // Device connectivity certificate (public) .requestMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll()) // static resources, user activation and password reset end-points - .authorizeRequests(config -> config + .authorizeHttpRequests(config -> config .requestMatchers(WS_ENTRY_POINT).permitAll() // Protected WebSocket API End-points .requestMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()) // Protected API End-points .exceptionHandling(config -> config.accessDeniedHandler(restAccessDeniedHandler)) From 228bec0a9c27a443fd89b5be8847dd82fc8522a1 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 26 Apr 2024 10:49:38 +0300 Subject: [PATCH 02/12] UI: Change locale code ar_AR to ar_AE --- .../{locale.constant-ar_AR.json => locale.constant-ar_AE.json} | 0 ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename ui-ngx/src/assets/locale/{locale.constant-ar_AR.json => locale.constant-ar_AE.json} (100%) diff --git a/ui-ngx/src/assets/locale/locale.constant-ar_AR.json b/ui-ngx/src/assets/locale/locale.constant-ar_AE.json similarity index 100% rename from ui-ngx/src/assets/locale/locale.constant-ar_AR.json rename to ui-ngx/src/assets/locale/locale.constant-ar_AE.json diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 7485ba64f1..7de9b02687 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -7291,7 +7291,7 @@ "language": { "language": "Language", "locales": { - "ar_AR": "اَلْعَرَبِيَّةُ", + "ar_AE": "اَلْعَرَبِيَّةُ", "ca_ES": "Catalan", "cs_CZ": "Česky", "da_DK": "Dansk", From 872309e6a2ea5f6760cb350609d0b487a9683789 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 26 Apr 2024 16:02:49 +0200 Subject: [PATCH 03/12] added clear cache for upgrade from 3.6.4 to 3.7.0 --- .../service/install/update/DefaultCacheCleanupService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java index 42e1cb2cbf..5a1d2fe38d 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java @@ -55,7 +55,11 @@ public class DefaultCacheCleanupService implements CacheCleanupService { clearCacheByName(RESOURCE_INFO_CACHE); break; case "3.6.3": - log.info("Clearing cache to upgrade from version 3.6.3 to 3.7.0"); + log.info("Clearing cache to upgrade from version 3.6.3 to 3.6.4"); + clearAll(); + break; + case "3.6.4": + log.info("Clearing cache to upgrade from version 3.6.4 to 3.7.0"); clearAll(); break; default: From 94b46958f9f7d92d5f9024fd5768b5723f261939 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 26 Apr 2024 17:29:43 +0300 Subject: [PATCH 04/12] Improvement for EntityStateSourcingListener --- .../server/service/entitiy/EntityStateSourcingListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java index c013650fa7..6027ad92d9 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java @@ -73,6 +73,9 @@ public class EntityStateSourcingListener { public void handleEvent(SaveEntityEvent event) { TenantId tenantId = event.getTenantId(); EntityId entityId = event.getEntityId(); + if (entityId == null) { + return; + } EntityType entityType = entityId.getEntityType(); log.debug("[{}][{}][{}] Handling entity save event: {}", tenantId, entityType, entityId, event); boolean isCreated = event.getCreated() != null && event.getCreated(); From 4e6ab036de4d79cb4037d8a485035971b188415c Mon Sep 17 00:00:00 2001 From: nick Date: Fri, 26 Apr 2024 18:09:10 +0300 Subject: [PATCH 05/12] fix bug: coap dtls.connection_id_length --- .../org/thingsboard/server/coapserver/TbCoapDtlsSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java index f27131b7ab..9c6e606af5 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java @@ -61,7 +61,7 @@ public class TbCoapDtlsSettings { @Value("${transport.coap.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; - @Value("${transport.coap.dtls.connection_id_length}") + @Value("${transport.coap.dtls.connection_id_length:}") private Integer cIdLength; @Bean From 115596da28f9f196b1f8cb19486d6bb274f3cd9f Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 26 Apr 2024 17:19:24 +0200 Subject: [PATCH 06/12] coap.dtls.connection_id_length added default null value to tolerate yaml inconsistency case --- .../org/thingsboard/server/coapserver/TbCoapDtlsSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java index f27131b7ab..9c6e606af5 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java @@ -61,7 +61,7 @@ public class TbCoapDtlsSettings { @Value("${transport.coap.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; - @Value("${transport.coap.dtls.connection_id_length}") + @Value("${transport.coap.dtls.connection_id_length:}") private Integer cIdLength; @Bean From 8686a92944dcea231812644201983820c6ca985e Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 26 Apr 2024 20:18:53 +0300 Subject: [PATCH 07/12] Replace static mocks with consumers in DefaultRuleEngineDeviceStateManagerTest --- ...faultRuleEngineDeviceStateManagerTest.java | 94 ++++++++++--------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManagerTest.java b/application/src/test/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManagerTest.java index c97305c170..1fae187a15 100644 --- a/application/src/test/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManagerTest.java +++ b/application/src/test/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManagerTest.java @@ -40,6 +40,8 @@ import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import java.util.Optional; import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.stream.Stream; import static org.mockito.ArgumentMatchers.any; @@ -53,13 +55,13 @@ import static org.mockito.Mockito.never; public class DefaultRuleEngineDeviceStateManagerTest { @Mock - private static DeviceStateService deviceStateServiceMock; + private DeviceStateService deviceStateServiceMock; @Mock - private static TbCallback tbCallbackMock; + private TbCallback tbCallbackMock; @Mock - private static TbClusterService clusterServiceMock; + private TbClusterService clusterServiceMock; @Mock - private static TbQueueMsgMetadata metadataMock; + private TbQueueMsgMetadata metadataMock; @Mock private TbServiceInfoProvider serviceInfoProviderMock; @@ -67,9 +69,9 @@ public class DefaultRuleEngineDeviceStateManagerTest { private PartitionService partitionServiceMock; @Captor - private static ArgumentCaptor queueCallbackCaptor; + private ArgumentCaptor queueCallbackCaptor; - private static DefaultRuleEngineDeviceStateManager deviceStateManager; + private DefaultRuleEngineDeviceStateManager deviceStateManager; private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("57ab2e6c-bc4c-11ee-a506-0242ac120002")); private static final DeviceId DEVICE_ID = DeviceId.fromString("74a9053e-bc4c-11ee-a506-0242ac120002"); @@ -87,15 +89,17 @@ public class DefaultRuleEngineDeviceStateManagerTest { @DisplayName("Given event should be routed to local service and event processed has succeeded, " + "when onDeviceX() is called, then should route event to local service and call onSuccess() callback.") @MethodSource - public void givenRoutedToLocalAndProcessingSuccess_whenOnDeviceAction_thenShouldCallLocalServiceAndSuccessCallback(Runnable onDeviceAction, Runnable actionVerification) { + public void givenRoutedToLocalAndProcessingSuccess_whenOnDeviceAction_thenShouldCallLocalServiceAndSuccessCallback( + BiConsumer onDeviceAction, Consumer actionVerification + ) { // GIVEN given(serviceInfoProviderMock.isService(ServiceType.TB_CORE)).willReturn(true); given(partitionServiceMock.resolve(ServiceType.TB_CORE, TENANT_ID, DEVICE_ID)).willReturn(MY_TPI); - onDeviceAction.run(); + onDeviceAction.accept(deviceStateManager, tbCallbackMock); // THEN - actionVerification.run(); + actionVerification.accept(deviceStateServiceMock); then(clusterServiceMock).shouldHaveNoInteractions(); then(tbCallbackMock).should().onSuccess(); @@ -105,20 +109,20 @@ public class DefaultRuleEngineDeviceStateManagerTest { private static Stream givenRoutedToLocalAndProcessingSuccess_whenOnDeviceAction_thenShouldCallLocalServiceAndSuccessCallback() { return Stream.of( Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) ) ); } @@ -128,19 +132,19 @@ public class DefaultRuleEngineDeviceStateManagerTest { "when onDeviceX() is called, then should route event to local service and call onFailure() callback.") @MethodSource public void givenRoutedToLocalAndProcessingFailure_whenOnDeviceAction_thenShouldCallLocalServiceAndFailureCallback( - Runnable exceptionThrowSetup, Runnable onDeviceAction, Runnable actionVerification + Consumer exceptionThrowSetup, BiConsumer onDeviceAction, Consumer actionVerification ) { // GIVEN given(serviceInfoProviderMock.isService(ServiceType.TB_CORE)).willReturn(true); given(partitionServiceMock.resolve(ServiceType.TB_CORE, TENANT_ID, DEVICE_ID)).willReturn(MY_TPI); - exceptionThrowSetup.run(); + exceptionThrowSetup.accept(deviceStateServiceMock); // WHEN - onDeviceAction.run(); + onDeviceAction.accept(deviceStateManager, tbCallbackMock); // THEN - actionVerification.run(); + actionVerification.accept(deviceStateServiceMock); then(clusterServiceMock).shouldHaveNoInteractions(); then(tbCallbackMock).should(never()).onSuccess(); @@ -150,24 +154,24 @@ public class DefaultRuleEngineDeviceStateManagerTest { private static Stream givenRoutedToLocalAndProcessingFailure_whenOnDeviceAction_thenShouldCallLocalServiceAndFailureCallback() { return Stream.of( Arguments.of( - (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS), - (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) + (Consumer) deviceStateServiceMock -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS), + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS), - (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) + (Consumer) deviceStateServiceMock -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS), + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS), - (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) + (Consumer) deviceStateServiceMock -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS), + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) ), Arguments.of( - (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS), - (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) + (Consumer) deviceStateServiceMock -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS), + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Consumer) deviceStateServiceMock -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) ) ); } @@ -176,16 +180,18 @@ public class DefaultRuleEngineDeviceStateManagerTest { @DisplayName("Given event should be routed to external service, " + "when onDeviceX() is called, then should send correct queue message to external service with correct callback object.") @MethodSource - public void givenRoutedToExternal_whenOnDeviceAction_thenShouldSendQueueMsgToExternalServiceWithCorrectCallback(Runnable onDeviceAction, Runnable actionVerification) { + public void givenRoutedToExternal_whenOnDeviceAction_thenShouldSendQueueMsgToExternalServiceWithCorrectCallback( + BiConsumer onDeviceAction, BiConsumer> actionVerification + ) { // WHEN ReflectionTestUtils.setField(deviceStateManager, "deviceStateService", Optional.empty()); given(serviceInfoProviderMock.isService(ServiceType.TB_CORE)).willReturn(false); given(partitionServiceMock.resolve(ServiceType.TB_CORE, TENANT_ID, DEVICE_ID)).willReturn(EXTERNAL_TPI); - onDeviceAction.run(); + onDeviceAction.accept(deviceStateManager, tbCallbackMock); // THEN - actionVerification.run(); + actionVerification.accept(clusterServiceMock, queueCallbackCaptor); TbQueueCallback callback = queueCallbackCaptor.getValue(); callback.onSuccess(metadataMock); @@ -197,8 +203,8 @@ public class DefaultRuleEngineDeviceStateManagerTest { private static Stream givenRoutedToExternal_whenOnDeviceAction_thenShouldSendQueueMsgToExternalServiceWithCorrectCallback() { return Stream.of( Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> { + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (BiConsumer>) (clusterServiceMock, queueCallbackCaptor) -> { var deviceConnectMsg = TransportProtos.DeviceConnectProto.newBuilder() .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) @@ -213,8 +219,8 @@ public class DefaultRuleEngineDeviceStateManagerTest { } ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> { + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (BiConsumer>) (clusterServiceMock, queueCallbackCaptor) -> { var deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder() .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) @@ -229,8 +235,8 @@ public class DefaultRuleEngineDeviceStateManagerTest { } ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> { + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (BiConsumer>) (clusterServiceMock, queueCallbackCaptor) -> { var deviceDisconnectMsg = TransportProtos.DeviceDisconnectProto.newBuilder() .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) @@ -245,8 +251,8 @@ public class DefaultRuleEngineDeviceStateManagerTest { } ), Arguments.of( - (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), - (Runnable) () -> { + (BiConsumer) (deviceStateManager, tbCallbackMock) -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (BiConsumer>) (clusterServiceMock, queueCallbackCaptor) -> { var deviceInactivityMsg = TransportProtos.DeviceInactivityProto.newBuilder() .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) From abf85cb9b859c649c2f51e23b4c49b194a51aedb Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 26 Apr 2024 22:03:26 +0200 Subject: [PATCH 08/12] SecurityConfiguration fixed and refactored based on manual testing results on QA env --- .../server/config/TbRuleEngineSecurityConfiguration.java | 3 +-- .../server/config/ThingsboardSecurityConfiguration.java | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java index 15d33c7fcb..15171ba0c7 100644 --- a/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/TbRuleEngineSecurityConfiguration.java @@ -41,8 +41,7 @@ public class TbRuleEngineSecurityConfiguration { .cors(cors -> {}) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(config -> config - .requestMatchers("/actuator/prometheus").permitAll()) - .authorizeHttpRequests(config -> config + .requestMatchers("/actuator/prometheus").permitAll() .anyRequest().authenticated()); return http.build(); } diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 67c14ce656..eda8d3e89d 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -217,10 +217,11 @@ public class ThingsboardSecurityConfiguration { .requestMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point .requestMatchers(MAIL_OAUTH2_PROCESSING_ENTRY_POINT).permitAll() // Mail oauth2 code processing url .requestMatchers(DEVICE_CONNECTIVITY_CERTIFICATE_DOWNLOAD_ENTRY_POINT).permitAll() // Device connectivity certificate (public) - .requestMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll()) // static resources, user activation and password reset end-points - .authorizeHttpRequests(config -> config + .requestMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll() // static resources, user activation and password reset end-points .requestMatchers(WS_ENTRY_POINT).permitAll() // Protected WebSocket API End-points .requestMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()) // Protected API End-points + .formLogin(form -> form + .loginPage("/login").permitAll()) .exceptionHandling(config -> config.accessDeniedHandler(restAccessDeniedHandler)) .addFilterBefore(buildRestLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(buildRestPublicLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class) @@ -243,7 +244,7 @@ public class ThingsboardSecurityConfiguration { @Bean @ConditionalOnMissingBean(CorsFilter.class) public CorsFilter corsFilter(@Autowired MvcCorsProperties mvcCorsProperties) { - if (mvcCorsProperties.getMappings().size() == 0) { + if (mvcCorsProperties.getMappings().isEmpty()) { return new CorsFilter(new UrlBasedCorsConfigurationSource()); } else { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); From 20de60256cdc62960a4dc484b14a1a44f724afdc Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 29 Apr 2024 10:38:21 +0300 Subject: [PATCH 09/12] Add fail-fast for DeleteEntityEvent on EntityStateSourcingListener --- .../server/service/entitiy/EntityStateSourcingListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java index 6027ad92d9..4a7c1e1e87 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java @@ -125,6 +125,9 @@ public class EntityStateSourcingListener { public void handleEvent(DeleteEntityEvent event) { TenantId tenantId = event.getTenantId(); EntityId entityId = event.getEntityId(); + if (entityId == null) { + return; + } EntityType entityType = entityId.getEntityType(); if (!tenantId.isSysTenantId() && entityType != EntityType.TENANT && !tenantService.tenantExists(tenantId)) { log.debug("[{}] Ignoring DeleteEntityEvent because tenant does not exist: {}", tenantId, event); From 9d159526d919eaeb9a674dee1caf5ef3c0f3c5f2 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 29 Apr 2024 11:26:18 +0300 Subject: [PATCH 10/12] added tests for EntityService --- .../server/dao/service/EntityServiceTest.java | 155 +++++++++++++++++- 1 file changed, 153 insertions(+), 2 deletions(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java index d9b94fb26b..1fc2ff2ce6 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java @@ -18,18 +18,28 @@ package org.thingsboard.server.dao.service; import com.google.common.collect.Lists; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomUtils; import org.hamcrest.Matchers; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.ResultSetExtractor; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.AttributeScope; +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.EntityType; +import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; +import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; @@ -46,6 +56,7 @@ import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.query.ApiUsageStateFilter; import org.thingsboard.server.common.data.query.AssetSearchQueryFilter; import org.thingsboard.server.common.data.query.AssetTypeFilter; import org.thingsboard.server.common.data.query.DeviceSearchQueryFilter; @@ -65,6 +76,7 @@ import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.KeyFilter; import org.thingsboard.server.common.data.query.NumericFilterPredicate; import org.thingsboard.server.common.data.query.RelationsQueryFilter; +import org.thingsboard.server.common.data.query.SingleEntityFilter; import org.thingsboard.server.common.data.query.StringFilterPredicate; import org.thingsboard.server.common.data.query.StringFilterPredicate.StringOperation; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -72,15 +84,20 @@ import org.thingsboard.server.common.data.relation.EntitySearchDirection; import org.thingsboard.server.common.data.relation.RelationEntityTypeFilter; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.dao.dashboard.DashboardDao; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entity.EntityService; +import org.thingsboard.server.dao.entityview.EntityViewDao; import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.dao.sql.relation.RelationRepository; import org.thingsboard.server.dao.timeseries.TimeseriesService; +import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; import org.thingsboard.server.dao.user.UserService; import java.util.ArrayList; @@ -91,12 +108,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.thingsboard.server.common.data.query.EntityKeyType.ATTRIBUTE; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; @@ -106,6 +124,7 @@ import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIEL public class EntityServiceTest extends AbstractServiceTest { static final int ENTITY_COUNT = 5; + public static final String TEST_CUSTOMER_NAME = "Test"; @Autowired AssetService assetService; @@ -125,6 +144,27 @@ public class EntityServiceTest extends AbstractServiceTest { RelationService relationService; @Autowired TimeseriesService timeseriesService; + @Autowired + ApiUsageStateService apiUsageStateService; + @Autowired + CustomerService customerService; + @Autowired + DashboardDao dashboardDao; + @Autowired + EntityViewDao entityViewDao; + @Autowired + AlarmService alarmService; + + private CustomerId customerId; + + @Before + public void before() { + Customer customer = new Customer(); + customer.setTenantId(tenantId); + customer.setTitle(TEST_CUSTOMER_NAME); + customer = customerService.saveCustomer(customer); + customerId = customer.getId(); + } @Test public void testCountEntitiesByQuery() throws InterruptedException { @@ -810,7 +850,7 @@ public class EntityServiceTest extends AbstractServiceTest { } void createLoopRelations(TenantId tenantId, String type, EntityId... ids) { - assertThat("ids lenght", ids.length, Matchers.greaterThanOrEqualTo(1)); + assertThat(ids.length).isGreaterThanOrEqualTo(1); //chain all from the head to the tail for (int i = 1; i < ids.length; i++) { relationService.saveRelation(tenantId, new EntityRelation(ids[i - 1], ids[i], type, RelationTypeGroup.COMMON)); @@ -1179,6 +1219,117 @@ public class EntityServiceTest extends AbstractServiceTest { assertEquals(0, result.getTotalElements()); } + @Test + public void testFindEntitiesBySingleEntityFilter() { + List devices = new ArrayList<>(); + + for (int i = 0; i < 3; i++) { + Device device = new Device(); + device.setTenantId(tenantId); + device.setName("Device test" + i); + device.setType("default"); + devices.add(deviceService.saveDevice(device)); + } + + SingleEntityFilter singleEntityFilter = new SingleEntityFilter(); + singleEntityFilter.setSingleEntity(devices.get(0).getId()); + + List entityFields = List.of( + new EntityKey(EntityKeyType.ENTITY_FIELD, "name") + ); + + EntityDataPageLink pageLink = new EntityDataPageLink(1000, 0, null, null); + + EntityDataQuery query = new EntityDataQuery(singleEntityFilter, pageLink, entityFields, null, null); + + PageData result = searchEntities(query); + assertEquals(1, result.getTotalElements()); + + String deviceName = result.getData().get(0).getLatest().get(EntityKeyType.ENTITY_FIELD).get("name").getValue(); + assertThat(deviceName).isEqualTo(devices.get(0).getName()); + } + + @Test + public void testFindEntitiesByApiUsageStateFilter() { + apiUsageStateService.createDefaultApiUsageState(tenantId, customerId); + ApiUsageStateFilter apiUsageStateFilter = new ApiUsageStateFilter(); + apiUsageStateFilter.setCustomerId(customerId); + + List entityFields = List.of( + new EntityKey(EntityKeyType.ENTITY_FIELD, "name") + ); + + EntityDataPageLink pageLink = new EntityDataPageLink(1000, 0, null, null); + EntityDataQuery query = new EntityDataQuery(apiUsageStateFilter, pageLink, entityFields, null, null); + PageData result = searchEntities(query); + assertEquals(1, result.getTotalElements()); + String name = result.getData().get(0).getLatest().get(EntityKeyType.ENTITY_FIELD).get("name").getValue(); + assertThat(name).isEqualTo(TEST_CUSTOMER_NAME); + } + + @Test + public void testFindEntitiesByRelationEntityTypeFilter() { + Customer customer = new Customer(); + customer.setTenantId(tenantId); + customer.setTitle("Customer Relation Query"); + customer = customerService.saveCustomer(customer); + + final int assetCount = 2; + final int relationsCnt = 4; + final int deviceEntitiesCnt = assetCount * relationsCnt; + + List assets = new ArrayList<>(); + for (int i = 0; i < assetCount; i++) { + Asset building = new Asset(); + building.setTenantId(tenantId); + building.setCustomerId(customer.getId()); + building.setName("Building _" + i); + building.setType("building"); + building = assetService.saveAsset(building); + assets.add(building); + } + + List devices = new ArrayList<>(); + for (int i = 0; i < deviceEntitiesCnt; i++) { + Device device = new Device(); + device.setTenantId(tenantId); + device.setCustomerId(customer.getId()); + device.setName("Test device " + i); + device.setType("default"); + Device savedDevice = deviceService.saveDevice(device); + devices.add(savedDevice); + } + + for (int i = 0; i < assetCount; i++) { + for (int j = 0; j < relationsCnt; j++) { + EntityRelation relationEntity = new EntityRelation(); + relationEntity.setFrom(assets.get(i).getId()); + relationEntity.setTo(devices.get(j + (i * relationsCnt)).getId()); + relationEntity.setTypeGroup(RelationTypeGroup.COMMON); + relationEntity.setType("contains"); + relationService.saveRelation(tenantId, relationEntity); + } + } + + RelationEntityTypeFilter relationEntityTypeFilter = new RelationEntityTypeFilter("contains", Collections.singletonList(EntityType.DEVICE)); + RelationsQueryFilter filter = new RelationsQueryFilter(); + filter.setFilters(Collections.singletonList(relationEntityTypeFilter)); + filter.setDirection(EntitySearchDirection.FROM); + EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, null); + List keyFiltersEqualString = createStringKeyFilters("name", EntityKeyType.ENTITY_FIELD, StringOperation.STARTS_WITH, "Test device "); + + for (Asset asset : assets) { + filter.setRootEntity(asset.getId()); + + EntityDataQuery query = new EntityDataQuery(filter, pageLink, Collections.emptyList(), Collections.emptyList(), keyFiltersEqualString); + PageData relationsResult = entityService.findEntityDataByQuery(tenantId, customer.getId(), query); + long relationsResultCnt = entityService.countEntitiesByQuery(tenantId, customer.getId(), query); + + Assert.assertEquals(relationsCnt, relationsResult.getData().size()); + Assert.assertEquals(relationsCnt, relationsResultCnt); + } + } + @Test public void testFindEntityDataByQuery_filter_device_type_name_ends_with() { List devices = new ArrayList<>(); From 386795337ffb1b0d96ec89dca6b8d042c09163ea Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 29 Apr 2024 11:27:27 +0300 Subject: [PATCH 11/12] Fix partitions removed when tenant is updated --- .../server/common/transport/service/DefaultTransportService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index 6280f09cfd..41886bd88a 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -1001,7 +1001,6 @@ public class DefaultTransportService extends TransportActivityManager implements break; case TENANT: Tenant tenant = ProtoUtils.fromProto(msg.getTenant()); - partitionService.removeTenant(tenant.getId()); boolean updated = tenantProfileCache.put(tenant.getId(), tenant.getTenantProfileId()); partitionService.evictTenantInfo(tenant.getId()); if (updated) { From dc9706d3db258933c108ef0b63eb4df5acdcf006 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Mon, 29 Apr 2024 15:27:29 +0200 Subject: [PATCH 12/12] deprecated ISO_DATETIME_TIME_ZONE_FORMAT replaced with ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT --- .../service/event/BaseEventServiceTest.java | 12 +-- ...esDaoPartitioningDaysAlwaysExistsTest.java | 70 +++++++-------- ...sDaoPartitioningHoursAlwaysExistsTest.java | 88 +++++++++---------- ...artitioningIndefiniteAlwaysExistsTest.java | 4 +- ...aoPartitioningMinutesAlwaysExistsTest.java | 58 ++++++------ ...DaoPartitioningMonthsAlwaysExistsTest.java | 70 +++++++-------- ...sDaoPartitioningYearsAlwaysExistsTest.java | 50 +++++------ 7 files changed, 176 insertions(+), 176 deletions(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/event/BaseEventServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/event/BaseEventServiceTest.java index 8aa943484d..9cd355ccd0 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/event/BaseEventServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/event/BaseEventServiceTest.java @@ -38,7 +38,7 @@ import org.thingsboard.server.dao.service.AbstractServiceTest; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; public abstract class BaseEventServiceTest extends AbstractServiceTest { @@ -53,11 +53,11 @@ public abstract class BaseEventServiceTest extends AbstractServiceTest { @Before public void before() throws ParseException { - timeBeforeStartTime = ISO_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T11:30:00Z").getTime(); - startTime = ISO_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T12:00:00Z").getTime(); - eventTime = ISO_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T12:30:00Z").getTime(); - endTime = ISO_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T13:00:00Z").getTime(); - timeAfterEndTime = ISO_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T13:30:30Z").getTime(); + timeBeforeStartTime = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T11:30:00Z").getTime(); + startTime = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T12:00:00Z").getTime(); + eventTime = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T12:30:00Z").getTime(); + endTime = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T13:00:00Z").getTime(); + timeAfterEndTime = ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2016-11-01T13:30:30Z").getTime(); } @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java index 3505c3af00..a10515cc48 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java @@ -32,7 +32,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -66,68 +66,68 @@ public class CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest { public void testToPartitionsDays() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("DAYS"); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:00:01Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:00:01Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T00:00:00Z").getTime()); } @Test public void testCalculatePartitionsDays() throws ParseException { long startTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); long nextTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T23:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T23:59:59Z").getTime()); long endTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-15T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-15T00:00:00Z").getTime()); log.info("startTs {}, nextTs {}, endTs {}", startTs, nextTs, endTs); assertThat(tsDao.calculatePartitions(0, 0)).isEqualTo(List.of(0L)); assertThat(tsDao.calculatePartitions(0, 1)).isEqualTo(List.of(0L, 1L)); assertThat(tsDao.calculatePartitions(startTs, startTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, nextTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, endTs)).hasSize(6).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-13T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-14T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-15T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-12T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-13T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-14T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-15T00:00:00Z").getTime())); long leapStartTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-27T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-27T00:00:00Z").getTime()); long leapEndTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime()); assertThat(tsDao.calculatePartitions(leapStartTs, leapEndTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-27T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-28T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-29T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-27T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-28T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-29T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime())); long newYearStartTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-30T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-30T00:00:00Z").getTime()); long newYearEndTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime()); assertThat(tsDao.calculatePartitions(newYearStartTs, newYearEndTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-30T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-31T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-30T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-31T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java index 9b8e427ffc..d8149844ca 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java @@ -32,7 +32,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -66,69 +66,69 @@ public class CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest { public void testToPartitionsHours() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("HOURS"); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T01:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T01:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T01:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T01:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T02:00:01Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T02:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T02:00:01Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T02:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:00:00Z").getTime()); } @Test public void testCalculatePartitionsHours() throws ParseException { long startTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); long nextTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:59:59Z").getTime()); long endTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:59:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:59:00Z").getTime()); log.info("startTs {}, nextTs {}, endTs {}", startTs, nextTs, endTs); assertThat(tsDao.calculatePartitions(0, 0)).isEqualTo(List.of(0L)); assertThat(tsDao.calculatePartitions(0, 1)).isEqualTo(List.of(0L, 1L)); assertThat(tsDao.calculatePartitions(startTs, startTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, nextTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T01:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T02:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T01:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T02:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, endTs)).hasSize(25).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T01:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T02:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T04:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T05:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T06:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T07:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T08:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T09:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T10:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T11:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T12:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T13:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T14:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T15:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T16:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T17:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T18:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T19:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T20:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T21:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T22:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T23:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T01:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T02:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T03:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T04:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T05:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T06:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T07:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T08:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T09:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T10:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T11:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T12:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T13:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T14:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T15:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T16:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T17:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T18:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T19:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T20:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T21:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T22:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T23:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-11T00:00:00Z").getTime())); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java index 8d91121cc5..33989ff64f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java @@ -31,7 +31,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -64,7 +64,7 @@ public class CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest { @Test public void testToPartitionsIndefinite() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("INDEFINITE"); - assertThat(tsDao.toPartitionTs(ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo(0L); + assertThat(tsDao.toPartitionTs(ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo(0L); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java index c497da3047..ac0ea6dd4f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java @@ -32,7 +32,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -66,55 +66,55 @@ public class CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest { public void testToPartitionsMinutes() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("MINUTES"); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:01:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:01:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:01:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-02T00:01:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:02:01Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:02:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:02:01Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-03T00:02:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:00Z").getTime()); } @Test public void testCalculatePartitionsMinutes() throws ParseException { long startTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime()); long nextTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:59Z").getTime()); long endTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:10:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:10:00Z").getTime()); log.info("startTs {}, nextTs {}, endTs {}", startTs, nextTs, endTs); assertThat(tsDao.calculatePartitions(0, 0)).isEqualTo(List.of(0L)); assertThat(tsDao.calculatePartitions(0, 1)).isEqualTo(List.of(0L, 1L)); assertThat(tsDao.calculatePartitions(startTs, startTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, nextTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:01:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:01:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, endTs)).hasSize(11).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:01:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:03:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:04:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:05:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:06:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:07:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:08:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:09:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:10:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:01:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:02:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:03:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:04:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:05:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:06:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:07:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:08:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:09:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-10-10T00:10:00Z").getTime())); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java index 108620a43e..a99f42b668 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java @@ -32,7 +32,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -66,47 +66,47 @@ public class CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest { public void testToPartitionsMonths() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("MONTHS"); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo(1640995200000L).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo(1640995200000L).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime())).isEqualTo(1651363200000L).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime())).isEqualTo(1651363200000L).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:01Z").getTime())).isEqualTo(1651363200000L).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:01Z").getTime())).isEqualTo(1651363200000L).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo(1651363200000L).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo(1651363200000L).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo(1701388800000L).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo(1701388800000L).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-01T00:00:00Z").getTime()); } @Test public void testCalculatePartitionsMonths() throws ParseException { long startTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-12T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-12T00:00:00Z").getTime()); long nextTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-31T23:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-31T23:59:59Z").getTime()); long leapTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-29T23:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-29T23:59:59Z").getTime()); long endTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-31T23:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-31T23:59:59Z").getTime()); log.info("startTs {}, nextTs {}, leapTs {}, endTs {}", startTs, nextTs, leapTs, endTs); assertThat(tsDao.calculatePartitions(0, 0)).isEqualTo(List.of(0L)); assertThat(tsDao.calculatePartitions(0, 1)).isEqualTo(List.of(0L, 1L)); assertThat(tsDao.calculatePartitions(startTs, startTs)).isEqualTo(List.of(1575158400000L)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, nextTs)).isEqualTo(List.of(1575158400000L, 1577836800000L)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, leapTs)).isEqualTo(List.of(1575158400000L, 1577836800000L, 1580515200000L)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-01T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, endTs)).hasSize(14).isEqualTo(List.of( 1575158400000L, @@ -115,20 +115,20 @@ public class CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest { 1593561600000L, 1596240000000L, 1598918400000L, 1601510400000L, 1604188800000L, 1606780800000L, 1609459200000L)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-04-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-05-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-06-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-07-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-08-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-09-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-10-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-11-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-12-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-02-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-03-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-04-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-05-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-06-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-07-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-08-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-09-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-10-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-11-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-12-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java index 6806eab7e1..7443cba945 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java @@ -32,7 +32,7 @@ import org.thingsboard.server.dao.nosql.CassandraBufferedRateWriteExecutor; import java.text.ParseException; import java.util.List; -import static org.apache.commons.lang3.time.DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT; +import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @@ -66,50 +66,50 @@ public class CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest { public void testToPartitionsYears() throws ParseException { assertThat(tsDao.getPartitioning()).isEqualTo("YEARS"); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:00Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:01Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-01T00:00:01Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-05-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime()); assertThat(tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-12-31T23:59:59Z").getTime())).isEqualTo( + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-01-01T00:00:00Z").getTime()); } @Test public void testCalculatePartitionsYears() throws ParseException { long startTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime()); long nextTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-10-12T23:59:59Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-10-12T23:59:59Z").getTime()); long endTs = tsDao.toPartitionTs( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2025-07-15T00:00:00Z").getTime()); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2025-07-15T00:00:00Z").getTime()); log.info("startTs {}, nextTs {}, endTs {}", startTs, nextTs, endTs); assertThat(tsDao.calculatePartitions(0, 0)).isEqualTo(List.of(0L)); assertThat(tsDao.calculatePartitions(0, 1)).isEqualTo(List.of(0L, 1L)); assertThat(tsDao.calculatePartitions(startTs, startTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, nextTs)).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime())); assertThat(tsDao.calculatePartitions(startTs, endTs)).hasSize(7).isEqualTo(List.of( - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2023-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2024-01-01T00:00:00Z").getTime(), - ISO_DATETIME_TIME_ZONE_FORMAT.parse("2025-01-01T00:00:00Z").getTime())); + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2019-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2020-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2021-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2022-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2023-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2024-01-01T00:00:00Z").getTime(), + ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.parse("2025-01-01T00:00:00Z").getTime())); } }