From fa4bf2975acf50f80024c3c883e90e1f6a620b8c Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 11 Aug 2023 19:23:51 +0300 Subject: [PATCH 1/3] PROD-2339: fix getFeatureType method to handle RPC server-side response over DTLS --- .../transport/coap/CoapTransportResource.java | 11 +- .../coap/CoapTransportResourceTest.java | 352 ++++++++++++++++++ 2 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java index d6958137c7..bd02d9fcc4 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java @@ -30,6 +30,7 @@ import org.thingsboard.server.coapserver.TbCoapDtlsSessionInfo; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.common.data.security.DeviceTokenCredentials; import org.thingsboard.server.common.msg.session.FeatureType; @@ -379,12 +380,16 @@ public class CoapTransportResource extends AbstractCoapTransportResource { } } - private Optional getFeatureType(Request request) { + protected Optional getFeatureType(Request request) { List uriPath = request.getOptions().getUriPath(); try { - if (uriPath.size() >= FEATURE_TYPE_POSITION) { + int size = uriPath.size(); + if (size >= FEATURE_TYPE_POSITION) { + if (size == FEATURE_TYPE_POSITION && StringUtils.isNumeric(uriPath.get(size - 1))) { + return Optional.of(FeatureType.valueOf(uriPath.get(FEATURE_TYPE_POSITION - 2).toUpperCase())); + } return Optional.of(FeatureType.valueOf(uriPath.get(FEATURE_TYPE_POSITION - 1).toUpperCase())); - } else if (uriPath.size() >= FEATURE_TYPE_POSITION_CERTIFICATE_REQUEST) { + } else if (size == FEATURE_TYPE_POSITION_CERTIFICATE_REQUEST) { if (uriPath.contains(DataConstants.PROVISION)) { return Optional.of(FeatureType.valueOf(DataConstants.PROVISION.toUpperCase())); } diff --git a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java new file mode 100644 index 0000000000..666f6c95df --- /dev/null +++ b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java @@ -0,0 +1,352 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.coap; + +import org.eclipse.californium.core.coap.CoAP; +import org.eclipse.californium.core.coap.OptionSet; +import org.eclipse.californium.core.coap.Request; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.thingsboard.server.coapserver.CoapServerService; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.msg.session.FeatureType; +import org.thingsboard.server.common.transport.TransportService; +import org.thingsboard.server.queue.scheduler.SchedulerComponent; +import org.thingsboard.server.transport.coap.client.CoapClientContext; + +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class CoapTransportResourceTest { + + private static final String V1 = "v1"; + private static final String API = "api"; + private static final String TELEMETRY = "telemetry"; + private static final String ATTRIBUTES = "attributes"; + private static final String RPC = "rpc"; + private static final String CLAIM = "claim"; + private static final String PROVISION = "provision"; + private static final String GET_ATTRIBUTES_URI_QUERY = "clientKeys=attribute1,attribute2&sharedKeys=shared1,shared2"; + + private static final Random RANDOM = new Random(); + + private CoapTransportResource coapTransportResource; + + @BeforeEach + void setUp() { + + var ctxMock = mock(CoapTransportContext.class); + var coapServerServiceMock = mock(CoapServerService.class); + var transportServiceMock = mock(TransportService.class); + var clientContextMock = mock(CoapClientContext.class); + var schedulerComponentMock = mock(SchedulerComponent.class); + + when(ctxMock.getTransportService()).thenReturn(transportServiceMock); + when(ctxMock.getClientContext()).thenReturn(clientContextMock); + when(ctxMock.getSessionReportTimeout()).thenReturn(1L); + when(ctxMock.getScheduler()).thenReturn(schedulerComponentMock); + + coapTransportResource = new CoapTransportResource(ctxMock, coapServerServiceMock, V1); + } + + @AfterEach + void tearDown() { + } + + // accessToken based tests + + @Test + void givenPostTelemetryAccessTokenRequest_whenGetFeatureType_thenFeatureTypeTelemetry() { + // GIVEN + var request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), TELEMETRY); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.TELEMETRY, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenPostAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), ATTRIBUTES); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenGetAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + Request request = toGetAttributesAccessTokenRequest(StringUtils.randomAlphanumeric(20)); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenSubscribeForAttributesUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + Request request = toAccessTokenRequest(CoAP.Code.GET, StringUtils.randomAlphanumeric(20), ATTRIBUTES); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenSubscribeForRpcUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + Request request = toAccessTokenRequest(CoAP.Code.GET, StringUtils.randomAlphanumeric(20), RPC); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenRpcResponseAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + Request request = toRpcResponseAccessTokenRequest(StringUtils.randomAlphanumeric(20), RANDOM.nextInt(100)); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenClientSideRpcAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), RPC); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenClaimingAccessTokenRequest_whenGetFeatureType_thenFeatureTypeClaim() { + // GIVEN + Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), CLAIM); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.CLAIM, featureTypeOptional.get(), "Feature type is invalid"); + } + + // certificate based tests + + @Test + void givenPostTelemetryCertificateRequest_whenGetFeatureType_thenFeatureTypeTelemetry() { + // GIVEN + var request = toCertificateRequest(CoAP.Code.POST, TELEMETRY); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.TELEMETRY, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenPostAttributesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + var request = toCertificateRequest(CoAP.Code.POST, ATTRIBUTES); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenGetAttributesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + var request = toGetAttributesCertificateRequest(); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenSubscribeForAttributesUpdatesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { + // GIVEN + var request = toCertificateRequest(CoAP.Code.GET, ATTRIBUTES); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenSubscribeForRpcUpdatesCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + var request = toCertificateRequest(CoAP.Code.GET, RPC); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenRpcResponseCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + Request request = toRpcResponseCertificateRequest(RANDOM.nextInt(100)); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenClientSideRpcCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { + // GIVEN + Request request = toCertificateRequest(CoAP.Code.POST, RPC); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); + } + + @Test + void givenClaimingCertificateRequest_whenGetFeatureType_thenFeatureTypeClaim() { + // GIVEN + Request request = toCertificateRequest(CoAP.Code.POST, CLAIM); + + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.CLAIM, featureTypeOptional.get(), "Feature type is invalid"); + } + + // provision request + + @Test + void givenProvisionRequest_whenGetFeatureType_thenFeatureTypeProvision() { + // GIVEN + Request request = toCertificateRequest(CoAP.Code.POST, PROVISION); + // WHEN + var featureTypeOptional = coapTransportResource.getFeatureType(request); + + // THEN + assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); + assertEquals(FeatureType.PROVISION, featureTypeOptional.get(), "Feature type is invalid"); + } + + private Request toAccessTokenRequest(CoAP.Code method, String accessToken, String featureType) { + return getAccessTokenRequest(method, accessToken, featureType, null, null); + } + + private Request toGetAttributesAccessTokenRequest(String accessToken) { + return getAccessTokenRequest(CoAP.Code.GET, accessToken, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); + } + + private Request toRpcResponseAccessTokenRequest(String accessToken, Integer requestId) { + return getAccessTokenRequest(CoAP.Code.POST, accessToken, CoapTransportResourceTest.RPC, requestId, null); + } + + private Request toCertificateRequest(CoAP.Code method, String featureType) { + return getCertificateRequest(method, featureType, null, null); + } + + private Request toGetAttributesCertificateRequest() { + return getCertificateRequest(CoAP.Code.GET, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); + } + + private Request toRpcResponseCertificateRequest(Integer requestId) { + return getCertificateRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, requestId, null); + } + + private Request getAccessTokenRequest(CoAP.Code method, String accessToken, String featureType, Integer requestId, String uriQuery) { + var request = new Request(method); + var options = new OptionSet(); + options.addUriPath(API); + options.addUriPath(V1); + options.addUriPath(accessToken); + options.addUriPath(featureType); + if (requestId != null) { + options.addUriPath(String.valueOf(requestId)); + } + if (uriQuery != null) { + options.setUriQuery(uriQuery); + } + request.setOptions(options); + return request; + } + + private Request getCertificateRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { + var request = new Request(method); + var options = new OptionSet(); + options.addUriPath(API); + options.addUriPath(V1); + options.addUriPath(featureType); + if (requestId != null) { + options.addUriPath(String.valueOf(requestId)); + } + if (uriQuery != null) { + options.setUriQuery(uriQuery); + } + request.setOptions(options); + return request; + } + + +} From f647fca59c61130aa5f16d2691d404c10aa5be19 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Sat, 12 Aug 2023 09:38:49 +0300 Subject: [PATCH 2/3] refactoring of test base --- .../coap/CoapTransportResourceTest.java | 71 ++++++++----------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java index 666f6c95df..2e5b367e4c 100644 --- a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java +++ b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java @@ -18,7 +18,9 @@ package org.thingsboard.server.transport.coap; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.coap.Request; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.thingsboard.server.coapserver.CoapServerService; @@ -48,10 +50,10 @@ class CoapTransportResourceTest { private static final Random RANDOM = new Random(); - private CoapTransportResource coapTransportResource; + private static CoapTransportResource coapTransportResource; - @BeforeEach - void setUp() { + @BeforeAll + static void setUp() { var ctxMock = mock(CoapTransportContext.class); var coapServerServiceMock = mock(CoapServerService.class); @@ -67,16 +69,12 @@ class CoapTransportResourceTest { coapTransportResource = new CoapTransportResource(ctxMock, coapServerServiceMock, V1); } - @AfterEach - void tearDown() { - } - // accessToken based tests @Test void givenPostTelemetryAccessTokenRequest_whenGetFeatureType_thenFeatureTypeTelemetry() { // GIVEN - var request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), TELEMETRY); + var request = toAccessTokenRequest(CoAP.Code.POST, TELEMETRY); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -89,7 +87,7 @@ class CoapTransportResourceTest { @Test void givenPostAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), ATTRIBUTES); + Request request = toAccessTokenRequest(CoAP.Code.POST, ATTRIBUTES); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -102,7 +100,7 @@ class CoapTransportResourceTest { @Test void givenGetAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { // GIVEN - Request request = toGetAttributesAccessTokenRequest(StringUtils.randomAlphanumeric(20)); + Request request = toGetAttributesAccessTokenRequest(); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -114,7 +112,7 @@ class CoapTransportResourceTest { @Test void givenSubscribeForAttributesUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.GET, StringUtils.randomAlphanumeric(20), ATTRIBUTES); + Request request = toAccessTokenRequest(CoAP.Code.GET, ATTRIBUTES); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -126,7 +124,7 @@ class CoapTransportResourceTest { @Test void givenSubscribeForRpcUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.GET, StringUtils.randomAlphanumeric(20), RPC); + Request request = toAccessTokenRequest(CoAP.Code.GET, RPC); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -138,7 +136,7 @@ class CoapTransportResourceTest { @Test void givenRpcResponseAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { // GIVEN - Request request = toRpcResponseAccessTokenRequest(StringUtils.randomAlphanumeric(20), RANDOM.nextInt(100)); + Request request = toRpcResponseAccessTokenRequest(); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -150,7 +148,7 @@ class CoapTransportResourceTest { @Test void givenClientSideRpcAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), RPC); + Request request = toAccessTokenRequest(CoAP.Code.POST, RPC); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -162,7 +160,7 @@ class CoapTransportResourceTest { @Test void givenClaimingAccessTokenRequest_whenGetFeatureType_thenFeatureTypeClaim() { // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, StringUtils.randomAlphanumeric(20), CLAIM); + Request request = toAccessTokenRequest(CoAP.Code.POST, CLAIM); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -241,7 +239,7 @@ class CoapTransportResourceTest { @Test void givenRpcResponseCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { // GIVEN - Request request = toRpcResponseCertificateRequest(RANDOM.nextInt(100)); + Request request = toRpcResponseCertificateRequest(); // WHEN var featureTypeOptional = coapTransportResource.getFeatureType(request); @@ -291,16 +289,16 @@ class CoapTransportResourceTest { assertEquals(FeatureType.PROVISION, featureTypeOptional.get(), "Feature type is invalid"); } - private Request toAccessTokenRequest(CoAP.Code method, String accessToken, String featureType) { - return getAccessTokenRequest(method, accessToken, featureType, null, null); + private Request toAccessTokenRequest(CoAP.Code method, String featureType) { + return getAccessTokenRequest(method, featureType, null, null); } - private Request toGetAttributesAccessTokenRequest(String accessToken) { - return getAccessTokenRequest(CoAP.Code.GET, accessToken, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); + private Request toGetAttributesAccessTokenRequest() { + return getAccessTokenRequest(CoAP.Code.GET, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); } - private Request toRpcResponseAccessTokenRequest(String accessToken, Integer requestId) { - return getAccessTokenRequest(CoAP.Code.POST, accessToken, CoapTransportResourceTest.RPC, requestId, null); + private Request toRpcResponseAccessTokenRequest() { + return getAccessTokenRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, RANDOM.nextInt(100), null); } private Request toCertificateRequest(CoAP.Code method, String featureType) { @@ -311,32 +309,26 @@ class CoapTransportResourceTest { return getCertificateRequest(CoAP.Code.GET, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); } - private Request toRpcResponseCertificateRequest(Integer requestId) { - return getCertificateRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, requestId, null); + private Request toRpcResponseCertificateRequest() { + return getCertificateRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, RANDOM.nextInt(100), null); } - private Request getAccessTokenRequest(CoAP.Code method, String accessToken, String featureType, Integer requestId, String uriQuery) { - var request = new Request(method); - var options = new OptionSet(); - options.addUriPath(API); - options.addUriPath(V1); - options.addUriPath(accessToken); - options.addUriPath(featureType); - if (requestId != null) { - options.addUriPath(String.valueOf(requestId)); - } - if (uriQuery != null) { - options.setUriQuery(uriQuery); - } - request.setOptions(options); - return request; + private Request getAccessTokenRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { + return getRequest(method, featureType, false, requestId, uriQuery); } private Request getCertificateRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { + return getRequest(method, featureType, true, requestId, uriQuery); + } + + private Request getRequest(CoAP.Code method, String featureType, boolean dtls, Integer requestId, String uriQuery) { var request = new Request(method); var options = new OptionSet(); options.addUriPath(API); options.addUriPath(V1); + if (!dtls) { + options.addUriPath(StringUtils.randomAlphanumeric(20)); + } options.addUriPath(featureType); if (requestId != null) { options.addUriPath(String.valueOf(requestId)); @@ -348,5 +340,4 @@ class CoapTransportResourceTest { return request; } - } From c5ff8b4229af3adfde1e5c8436540afca1d71512 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Sat, 12 Aug 2023 09:52:36 +0300 Subject: [PATCH 3/3] refactored to parameterized test --- .../coap/CoapTransportResourceTest.java | 270 +++--------------- 1 file changed, 44 insertions(+), 226 deletions(-) diff --git a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java index 2e5b367e4c..c7f33e3694 100644 --- a/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java +++ b/common/transport/coap/src/test/java/org/thingsboard/server/transport/coap/CoapTransportResourceTest.java @@ -18,11 +18,10 @@ package org.thingsboard.server.transport.coap; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.OptionSet; import org.eclipse.californium.core.coap.Request; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.thingsboard.server.coapserver.CoapServerService; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.session.FeatureType; @@ -31,6 +30,7 @@ import org.thingsboard.server.queue.scheduler.SchedulerComponent; import org.thingsboard.server.transport.coap.client.CoapClientContext; import java.util.Random; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -69,259 +69,77 @@ class CoapTransportResourceTest { coapTransportResource = new CoapTransportResource(ctxMock, coapServerServiceMock, V1); } - // accessToken based tests - - @Test - void givenPostTelemetryAccessTokenRequest_whenGetFeatureType_thenFeatureTypeTelemetry() { - // GIVEN - var request = toAccessTokenRequest(CoAP.Code.POST, TELEMETRY); - - // WHEN + @ParameterizedTest + @MethodSource("provideRequestAndFeatureType") + void givenRequest_whenGetFeatureType_thenReturnedExpectedFeatureType(Request request, FeatureType expectedFeatureType) { var featureTypeOptional = coapTransportResource.getFeatureType(request); - // THEN assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.TELEMETRY, featureTypeOptional.get(), "Feature type is invalid"); + assertEquals(expectedFeatureType, featureTypeOptional.get(), "Feature type is invalid"); } - @Test - void givenPostAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, ATTRIBUTES); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); + static Stream provideRequestAndFeatureType() { + return Stream.of( + // accessToken based tests + Arguments.of(toAccessTokenRequest(CoAP.Code.POST, TELEMETRY), FeatureType.TELEMETRY), + Arguments.of(toAccessTokenRequest(CoAP.Code.POST, ATTRIBUTES), FeatureType.ATTRIBUTES), + Arguments.of(toGetAttributesAccessTokenRequest(), FeatureType.ATTRIBUTES), + Arguments.of(toAccessTokenRequest(CoAP.Code.GET, ATTRIBUTES), FeatureType.ATTRIBUTES), + Arguments.of(toAccessTokenRequest(CoAP.Code.GET, RPC), FeatureType.RPC), + Arguments.of(toRpcResponseAccessTokenRequest(), FeatureType.RPC), + Arguments.of(toAccessTokenRequest(CoAP.Code.POST, RPC), FeatureType.RPC), + Arguments.of(toAccessTokenRequest(CoAP.Code.POST, CLAIM), FeatureType.CLAIM), + // certificate based tests + Arguments.of(toCertificateRequest(CoAP.Code.POST, TELEMETRY), FeatureType.TELEMETRY), + Arguments.of(toCertificateRequest(CoAP.Code.POST, ATTRIBUTES), FeatureType.ATTRIBUTES), + Arguments.of(toGetAttributesCertificateRequest(), FeatureType.ATTRIBUTES), + Arguments.of(toCertificateRequest(CoAP.Code.GET, ATTRIBUTES), FeatureType.ATTRIBUTES), + Arguments.of(toCertificateRequest(CoAP.Code.GET, RPC), FeatureType.RPC), + Arguments.of(toRpcResponseCertificateRequest(), FeatureType.RPC), + Arguments.of(toCertificateRequest(CoAP.Code.POST, RPC), FeatureType.RPC), + Arguments.of(toCertificateRequest(CoAP.Code.POST, CLAIM), FeatureType.CLAIM), + // provision request + Arguments.of(toProvisionRequest(), FeatureType.PROVISION) + ); } - @Test - void givenGetAttributesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - Request request = toGetAttributesAccessTokenRequest(); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenSubscribeForAttributesUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.GET, ATTRIBUTES); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenSubscribeForRpcUpdatesAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.GET, RPC); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenRpcResponseAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - Request request = toRpcResponseAccessTokenRequest(); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenClientSideRpcAccessTokenRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, RPC); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenClaimingAccessTokenRequest_whenGetFeatureType_thenFeatureTypeClaim() { - // GIVEN - Request request = toAccessTokenRequest(CoAP.Code.POST, CLAIM); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.CLAIM, featureTypeOptional.get(), "Feature type is invalid"); - } - - // certificate based tests - - @Test - void givenPostTelemetryCertificateRequest_whenGetFeatureType_thenFeatureTypeTelemetry() { - // GIVEN - var request = toCertificateRequest(CoAP.Code.POST, TELEMETRY); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.TELEMETRY, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenPostAttributesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - var request = toCertificateRequest(CoAP.Code.POST, ATTRIBUTES); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenGetAttributesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - var request = toGetAttributesCertificateRequest(); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenSubscribeForAttributesUpdatesCertificateRequest_whenGetFeatureType_thenFeatureTypeAttributes() { - // GIVEN - var request = toCertificateRequest(CoAP.Code.GET, ATTRIBUTES); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.ATTRIBUTES, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenSubscribeForRpcUpdatesCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - var request = toCertificateRequest(CoAP.Code.GET, RPC); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenRpcResponseCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - Request request = toRpcResponseCertificateRequest(); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenClientSideRpcCertificateRequest_whenGetFeatureType_thenFeatureTypeRpc() { - // GIVEN - Request request = toCertificateRequest(CoAP.Code.POST, RPC); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.RPC, featureTypeOptional.get(), "Feature type is invalid"); - } - - @Test - void givenClaimingCertificateRequest_whenGetFeatureType_thenFeatureTypeClaim() { - // GIVEN - Request request = toCertificateRequest(CoAP.Code.POST, CLAIM); - - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.CLAIM, featureTypeOptional.get(), "Feature type is invalid"); - } - - // provision request - - @Test - void givenProvisionRequest_whenGetFeatureType_thenFeatureTypeProvision() { - // GIVEN - Request request = toCertificateRequest(CoAP.Code.POST, PROVISION); - // WHEN - var featureTypeOptional = coapTransportResource.getFeatureType(request); - - // THEN - assertTrue(featureTypeOptional.isPresent(), "Optional is empty"); - assertEquals(FeatureType.PROVISION, featureTypeOptional.get(), "Feature type is invalid"); - } - - private Request toAccessTokenRequest(CoAP.Code method, String featureType) { + private static Request toAccessTokenRequest(CoAP.Code method, String featureType) { return getAccessTokenRequest(method, featureType, null, null); } - private Request toGetAttributesAccessTokenRequest() { + private static Request toGetAttributesAccessTokenRequest() { return getAccessTokenRequest(CoAP.Code.GET, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); } - private Request toRpcResponseAccessTokenRequest() { + private static Request toRpcResponseAccessTokenRequest() { return getAccessTokenRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, RANDOM.nextInt(100), null); } - private Request toCertificateRequest(CoAP.Code method, String featureType) { + private static Request toCertificateRequest(CoAP.Code method, String featureType) { return getCertificateRequest(method, featureType, null, null); } - private Request toGetAttributesCertificateRequest() { + private static Request toGetAttributesCertificateRequest() { return getCertificateRequest(CoAP.Code.GET, CoapTransportResourceTest.ATTRIBUTES, null, CoapTransportResourceTest.GET_ATTRIBUTES_URI_QUERY); } - private Request toRpcResponseCertificateRequest() { + private static Request toRpcResponseCertificateRequest() { return getCertificateRequest(CoAP.Code.POST, CoapTransportResourceTest.RPC, RANDOM.nextInt(100), null); } - private Request getAccessTokenRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { + private static Request getAccessTokenRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { return getRequest(method, featureType, false, requestId, uriQuery); } - private Request getCertificateRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { + private static Request getCertificateRequest(CoAP.Code method, String featureType, Integer requestId, String uriQuery) { return getRequest(method, featureType, true, requestId, uriQuery); } - private Request getRequest(CoAP.Code method, String featureType, boolean dtls, Integer requestId, String uriQuery) { + private static Request toProvisionRequest() { + return getRequest(CoAP.Code.POST, PROVISION, true, null, null); + } + + private static Request getRequest(CoAP.Code method, String featureType, boolean dtls, Integer requestId, String uriQuery) { var request = new Request(method); var options = new OptionSet(); options.addUriPath(API);