From 5ffafbdf93cec0a34c34b1e65568bf9d2d7e0465 Mon Sep 17 00:00:00 2001 From: Jasper Kamerling Date: Tue, 28 May 2024 16:14:19 +0200 Subject: [PATCH 01/14] FDP-2306: Update downlink handeling Signed-off-by: Jasper Kamerling --- .../gxf/crestdeviceservice/coap/UrcService.kt | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt index 4b049908..79cc4285 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt @@ -14,7 +14,9 @@ class UrcService( private val pskService: PskService ) { companion object { - private const val URC_PSK_SUCCESS = "PSK:SET" + private const val URC_PSK_PREFIX = "PSK:" + private const val URC_PSK_SUCCESS = "${URC_PSK_PREFIX}SET" + private val URC_ERROR_CODES = listOf("DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER", "SK:EQER", "SK:TMP") private const val URC_PSK_ERROR = "ER" private const val URC_FIELD = "URC" } @@ -31,12 +33,11 @@ class UrcService( logger.debug { "Received message with urcs ${urcs.joinToString(", ")}" } when { - urcsContainsError(urcs) -> { - handleErrorUrc(identity) + urcsContainsPSKError(urcs) -> { + handleErrorPSKUrc(identity) } - - urcsContainsSuccess(urcs) -> { - handleSuccessUrc(identity) + urcsContainsPSKSuccess(urcs) -> { + handlePSKSuccessUrc(identity) } } } @@ -45,10 +46,10 @@ class UrcService( .filter { it.isTextual } .map { it.asText() } - private fun urcsContainsError(urcs: List) = - urcs.any { urc -> urc.contains(URC_PSK_ERROR) } + private fun urcsContainsPSKError(urcs: List) = + urcs.any { urc -> urc.startsWith(URC_PSK_PREFIX) && urc.endsWith(URC_PSK_ERROR) } - private fun handleErrorUrc(identity: String) { + private fun handleErrorPSKUrc(identity: String) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException("Failure URC received, but no pending key present to set as invalid") } @@ -56,10 +57,10 @@ class UrcService( pskService.setPendingKeyAsInvalid(identity) } - private fun urcsContainsSuccess(urcs: List) = - urcs.any { urc -> urc.contains(URC_PSK_SUCCESS) } + private fun urcsContainsPSKSuccess(urcs: List) = + urcs.any { urc -> urc.contains(URC_PSK_PREFIX + URC_PSK_SUCCESS) } - private fun handleSuccessUrc(identity: String) { + private fun handlePSKSuccessUrc(identity: String) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException("Success URC received, but no pending key present to set as active") } From d7513eb87fdca3b01d572d13974629ddc1e902fb Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Wed, 29 May 2024 15:34:00 +0200 Subject: [PATCH 02/14] FDP-2306: handle known psk and downlink urcs and ignore others Signed-off-by: Loes Immens --- .../coap/PskOrDownlinkErrorUrc.kt | 21 +++++++++ .../gxf/crestdeviceservice/coap/UrcService.kt | 46 +++++++++++++------ 2 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt new file mode 100644 index 00000000..e882dde0 --- /dev/null +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: Contributors to the GXF project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.gxf.crestdeviceservice.coap + +enum class PskOrDownlinkErrorUrc(val code: String) { + PSK_EQER("PSK:EQER"), + DL_UNK("DL:UNK"), + DL_DLNA("[DL]:DLNA"), + DL_DLER("[DL]:DLER"), + DL_ERR("[DL]:#ERR"), + DL_HSER("[DL]:HSER"), + DL_CSER("[DL]:CSER"); + + companion object { + fun from(code: String): PskOrDownlinkErrorUrc? = entries.firstOrNull { it.code == code } + } +} diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt index 7111f3eb..1267d2ea 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt @@ -12,11 +12,8 @@ import org.springframework.stereotype.Service @Service class UrcService(private val pskService: PskService) { companion object { - private const val URC_PSK_PREFIX = "PSK:" - private const val URC_PSK_SUCCESS = "${URC_PSK_PREFIX}SET" - private val URC_ERROR_CODES = listOf("DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER", "SK:EQER", "SK:TMP") - private const val URC_PSK_ERROR = "ER" private const val URC_FIELD = "URC" + private const val URC_PSK_SUCCESS = "PSK:SET" } private val logger = KotlinLogging.logger {} @@ -31,11 +28,11 @@ class UrcService(private val pskService: PskService) { logger.debug { "Received message with urcs ${urcs.joinToString(", ")}" } when { - urcsContainsPSKError(urcs) -> { - handleErrorPSKUrc(identity) + urcsContainPskOrDownlinkError(urcs) -> { + handlePskOrDownlinkErrors(identity, urcs) } - urcsContainsPSKSuccess(urcs) -> { - handlePSKSuccessUrc(identity) + urcsContainPskSuccess(urcs) -> { + handlePskSuccess(identity) } } } @@ -43,22 +40,41 @@ class UrcService(private val pskService: PskService) { private fun getUrcsFromMessage(body: JsonNode) = body[URC_FIELD].filter { it.isTextual }.map { it.asText() } - private fun urcsContainsPSKError(urcs: List) = - urcs.any { urc -> urc.startsWith(URC_PSK_PREFIX) && urc.endsWith(URC_PSK_ERROR) } + private fun urcsContainPskOrDownlinkError(urcs: List) = + urcs.any { urc -> isPskOrDownlinkErrorURC(urc) } - private fun handleErrorPSKUrc(identity: String) { + private fun isPskOrDownlinkErrorURC(urc: String) = + PskOrDownlinkErrorUrc.entries.toTypedArray().contains(PskOrDownlinkErrorUrc.from(urc)) + + private fun handlePskOrDownlinkErrors(identity: String, urcs: List) { + urcs.stream() + .filter{ urc -> isPskOrDownlinkErrorURC(urc) } + .forEach { urc -> handlePskOrDownlinkError(identity, urc) } + } + + private fun handlePskOrDownlinkError(identity: String, urc: String) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException( "Failure URC received, but no pending key present to set as invalid") } - logger.warn { "Error received for set PSK command, setting pending key to invalid" } + val errorMessage = when (PskOrDownlinkErrorUrc.from(urc)) { + PskOrDownlinkErrorUrc.PSK_EQER -> "Set PSK does not equal earlier PSK" + PskOrDownlinkErrorUrc.DL_UNK -> "Downlink unknown" + PskOrDownlinkErrorUrc.DL_DLNA -> "Downlink not allowed" + PskOrDownlinkErrorUrc.DL_DLER -> "Downlink (syntax) error" + PskOrDownlinkErrorUrc.DL_ERR -> "Error processing (downlink) value" + PskOrDownlinkErrorUrc.DL_HSER -> "SHA256 hash error" + PskOrDownlinkErrorUrc.DL_CSER -> "Checksum error" + null -> "Unknown URC" + } + logger.warn { "PSK set failed for device with id ${identity}: $errorMessage" } pskService.setPendingKeyAsInvalid(identity) } - private fun urcsContainsPSKSuccess(urcs: List) = - urcs.any { urc -> urc.contains(URC_PSK_PREFIX + URC_PSK_SUCCESS) } + private fun urcsContainPskSuccess(urcs: List) = + urcs.any { urc -> urc.contains(URC_PSK_SUCCESS) } - private fun handlePSKSuccessUrc(identity: String) { + private fun handlePskSuccess(identity: String) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException( "Success URC received, but no pending key present to set as active") From 35023f3132c32b6ae3cae8f2d96099cefe1f4bb4 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Wed, 29 May 2024 17:06:20 +0200 Subject: [PATCH 03/14] FDP-2306: update test to handle every failure urc Signed-off-by: Loes Immens --- .../crestdeviceservice/coap/UrcServiceTest.kt | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index aa5a6a8a..917e5b2c 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -3,9 +3,16 @@ // SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice.coap +import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ArrayNode +import com.fasterxml.jackson.databind.node.JsonNodeFactory +import com.fasterxml.jackson.databind.node.ObjectNode +import com.fasterxml.jackson.databind.node.TextNode import org.gxf.crestdeviceservice.psk.PskService import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.verify @@ -17,6 +24,11 @@ class UrcServiceTest { private val urcService = UrcService(pskService) private val mapper = spy() + companion object { + private const val URC_FIELD = "URC" + private const val DL_FIELD = "DL" + } + @Test fun shouldChangeActiveKeyWhenSuccessURCReceived() { val identity = "identity" @@ -32,17 +44,36 @@ class UrcServiceTest { verify(pskService).changeActiveKey(identity) } - @Test - fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived() { + @ParameterizedTest(name = "should set pending key as invalid for {0}") + @ValueSource(strings = ["PSK:EQER", "DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER"]) + fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urc: String) { val identity = "identity" whenever(pskService.needsKeyChange(identity)).thenReturn(false) whenever(pskService.isPendingKeyPresent(identity)).thenReturn(true) val fileToUse = ResourceUtils.getFile("classpath:messages/message_psk_set_failure.json") - val message = mapper.readTree(fileToUse) + val messageTemplate = mapper.readTree(fileToUse) + val receivedCommand = "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" + val message = updatePskCommandInMessage(messageTemplate, urc, receivedCommand) + urcService.interpretURCInMessage(identity, message) verify(pskService).setPendingKeyAsInvalid(identity) } + + private fun updatePskCommandInMessage( + message: JsonNode, + urc: String, + receivedCommand: String + ): JsonNode { + val newMessage = message as ObjectNode + val urcList = listOf( + TextNode(urc), + ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(receivedCommand))) + ) + val urcArray = mapper.valueToTree(urcList) + newMessage.replace(URC_FIELD, urcArray) + return newMessage + } } From 638007204f7f35f901ce1b07da0bd4ce093228b6 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Wed, 29 May 2024 17:10:13 +0200 Subject: [PATCH 04/14] FDP-2306: formatted Signed-off-by: Loes Immens --- .../coap/PskOrDownlinkErrorUrc.kt | 9 ++---- .../gxf/crestdeviceservice/coap/UrcService.kt | 28 ++++++++++--------- .../crestdeviceservice/coap/UrcServiceTest.kt | 15 ++++++---- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt index e882dde0..51ec1ab7 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt @@ -1,9 +1,6 @@ -/* - * SPDX-FileCopyrightText: Contributors to the GXF project - * - * SPDX-License-Identifier: Apache-2.0 - */ - +// SPDX-FileCopyrightText: Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice.coap enum class PskOrDownlinkErrorUrc(val code: String) { diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt index 1267d2ea..a11ffd0d 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt @@ -13,7 +13,7 @@ import org.springframework.stereotype.Service class UrcService(private val pskService: PskService) { companion object { private const val URC_FIELD = "URC" - private const val URC_PSK_SUCCESS = "PSK:SET" + private const val URC_PSK_SUCCESS = "PSK:SET" } private val logger = KotlinLogging.logger {} @@ -47,8 +47,9 @@ class UrcService(private val pskService: PskService) { PskOrDownlinkErrorUrc.entries.toTypedArray().contains(PskOrDownlinkErrorUrc.from(urc)) private fun handlePskOrDownlinkErrors(identity: String, urcs: List) { - urcs.stream() - .filter{ urc -> isPskOrDownlinkErrorURC(urc) } + urcs + .stream() + .filter { urc -> isPskOrDownlinkErrorURC(urc) } .forEach { urc -> handlePskOrDownlinkError(identity, urc) } } @@ -57,16 +58,17 @@ class UrcService(private val pskService: PskService) { throw NoExistingPskException( "Failure URC received, but no pending key present to set as invalid") } - val errorMessage = when (PskOrDownlinkErrorUrc.from(urc)) { - PskOrDownlinkErrorUrc.PSK_EQER -> "Set PSK does not equal earlier PSK" - PskOrDownlinkErrorUrc.DL_UNK -> "Downlink unknown" - PskOrDownlinkErrorUrc.DL_DLNA -> "Downlink not allowed" - PskOrDownlinkErrorUrc.DL_DLER -> "Downlink (syntax) error" - PskOrDownlinkErrorUrc.DL_ERR -> "Error processing (downlink) value" - PskOrDownlinkErrorUrc.DL_HSER -> "SHA256 hash error" - PskOrDownlinkErrorUrc.DL_CSER -> "Checksum error" - null -> "Unknown URC" - } + val errorMessage = + when (PskOrDownlinkErrorUrc.from(urc)) { + PskOrDownlinkErrorUrc.PSK_EQER -> "Set PSK does not equal earlier PSK" + PskOrDownlinkErrorUrc.DL_UNK -> "Downlink unknown" + PskOrDownlinkErrorUrc.DL_DLNA -> "Downlink not allowed" + PskOrDownlinkErrorUrc.DL_DLER -> "Downlink (syntax) error" + PskOrDownlinkErrorUrc.DL_ERR -> "Error processing (downlink) value" + PskOrDownlinkErrorUrc.DL_HSER -> "SHA256 hash error" + PskOrDownlinkErrorUrc.DL_CSER -> "Checksum error" + null -> "Unknown URC" + } logger.warn { "PSK set failed for device with id ${identity}: $errorMessage" } pskService.setPendingKeyAsInvalid(identity) } diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 917e5b2c..4880f082 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -45,7 +45,9 @@ class UrcServiceTest { } @ParameterizedTest(name = "should set pending key as invalid for {0}") - @ValueSource(strings = ["PSK:EQER", "DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER"]) + @ValueSource( + strings = + ["PSK:EQER", "DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER"]) fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urc: String) { val identity = "identity" @@ -54,7 +56,8 @@ class UrcServiceTest { val fileToUse = ResourceUtils.getFile("classpath:messages/message_psk_set_failure.json") val messageTemplate = mapper.readTree(fileToUse) - val receivedCommand = "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" + val receivedCommand = + "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" val message = updatePskCommandInMessage(messageTemplate, urc, receivedCommand) urcService.interpretURCInMessage(identity, message) @@ -68,10 +71,10 @@ class UrcServiceTest { receivedCommand: String ): JsonNode { val newMessage = message as ObjectNode - val urcList = listOf( - TextNode(urc), - ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(receivedCommand))) - ) + val urcList = + listOf( + TextNode(urc), + ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(receivedCommand)))) val urcArray = mapper.valueToTree(urcList) newMessage.replace(URC_FIELD, urcArray) return newMessage From 4c457080157fee85f50c0d15ba9bb6648e331d04 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Thu, 30 May 2024 11:15:51 +0200 Subject: [PATCH 05/14] FDP-2306: review comments and refactoring Signed-off-by: Loes Immens --- .../coap/PskOrDownlinkErrorUrc.kt | 23 ++- .../gxf/crestdeviceservice/coap/UrcService.kt | 31 +-- .../coap/DownlinkServiceTest.kt | 4 +- .../crestdeviceservice/coap/UrcServiceTest.kt | 63 +++--- .../message.json => message-template.json} | 0 .../messages/message_psk_set_failure.json | 188 ------------------ .../messages/message_psk_set_success.json | 188 ------------------ 7 files changed, 58 insertions(+), 439 deletions(-) rename application/src/test/resources/{messages/message.json => message-template.json} (100%) delete mode 100644 application/src/test/resources/messages/message_psk_set_failure.json delete mode 100644 application/src/test/resources/messages/message_psk_set_success.json diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt index 51ec1ab7..0deaaece 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt @@ -3,16 +3,21 @@ // SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice.coap -enum class PskOrDownlinkErrorUrc(val code: String) { - PSK_EQER("PSK:EQER"), - DL_UNK("DL:UNK"), - DL_DLNA("[DL]:DLNA"), - DL_DLER("[DL]:DLER"), - DL_ERR("[DL]:#ERR"), - DL_HSER("[DL]:HSER"), - DL_CSER("[DL]:CSER"); +enum class PskOrDownlinkErrorUrc(val code: String, val message: String) { + PSK_EQER("PSK:EQER", "Set PSK does not equal earlier PSK"), + DL_UNK("DL:UNK", "Downlink unknown"), + DL_DLNA("[DL]:DLNA", "Downlink not allowed"), + DL_DLER("[DL]:DLER", "Downlink (syntax) error"), + DL_ERR("[DL]:#ERR", "Error processing (downlink) value"), + DL_HSER("[DL]:HSER", "SHA256 hash error"), + DL_CSER("[DL]:CSER", "Checksum error"); companion object { - fun from(code: String): PskOrDownlinkErrorUrc? = entries.firstOrNull { it.code == code } + fun messageFromCode(code: String): String { + val error = entries.firstOrNull { it.code == code } + return error?.message ?: "Unknown URC" + } + + fun isPskOrDownlinkErrorURC(code: String) = entries.any { it.code == code } } } diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt index a11ffd0d..1ea0d2ca 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt @@ -41,35 +41,22 @@ class UrcService(private val pskService: PskService) { body[URC_FIELD].filter { it.isTextual }.map { it.asText() } private fun urcsContainPskOrDownlinkError(urcs: List) = - urcs.any { urc -> isPskOrDownlinkErrorURC(urc) } - - private fun isPskOrDownlinkErrorURC(urc: String) = - PskOrDownlinkErrorUrc.entries.toTypedArray().contains(PskOrDownlinkErrorUrc.from(urc)) + urcs.any { urc -> PskOrDownlinkErrorUrc.isPskOrDownlinkErrorURC(urc) } private fun handlePskOrDownlinkErrors(identity: String, urcs: List) { - urcs - .stream() - .filter { urc -> isPskOrDownlinkErrorURC(urc) } - .forEach { urc -> handlePskOrDownlinkError(identity, urc) } - } - - private fun handlePskOrDownlinkError(identity: String, urc: String) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException( "Failure URC received, but no pending key present to set as invalid") } - val errorMessage = - when (PskOrDownlinkErrorUrc.from(urc)) { - PskOrDownlinkErrorUrc.PSK_EQER -> "Set PSK does not equal earlier PSK" - PskOrDownlinkErrorUrc.DL_UNK -> "Downlink unknown" - PskOrDownlinkErrorUrc.DL_DLNA -> "Downlink not allowed" - PskOrDownlinkErrorUrc.DL_DLER -> "Downlink (syntax) error" - PskOrDownlinkErrorUrc.DL_ERR -> "Error processing (downlink) value" - PskOrDownlinkErrorUrc.DL_HSER -> "SHA256 hash error" - PskOrDownlinkErrorUrc.DL_CSER -> "Checksum error" - null -> "Unknown URC" + + urcs + .filter { urc -> PskOrDownlinkErrorUrc.isPskOrDownlinkErrorURC(urc) } + .forEach { urc -> + logger.warn { + "PSK set failed for device with id ${identity}: ${PskOrDownlinkErrorUrc.messageFromCode(urc)}" + } } - logger.warn { "PSK set failed for device with id ${identity}: $errorMessage" } + pskService.setPendingKeyAsInvalid(identity) } diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt index 21908522..d01212a2 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt @@ -33,7 +33,7 @@ class DownlinkServiceTest { whenever(pskService.needsKeyChange(identity)).thenReturn(true) whenever(pskService.setReadyKeyForIdentityAsPending(identity)).thenReturn(psk) - val fileToUse = ResourceUtils.getFile("classpath:messages/message.json") + val fileToUse = ResourceUtils.getFile("classpath:messages/message-template.json") val message = mapper.readTree(fileToUse) val result = downLinkService.getDownlinkForIdentity(identity, message) @@ -48,7 +48,7 @@ class DownlinkServiceTest { val identity = "identity" whenever(pskService.needsKeyChange(identity)).thenReturn(false) - val fileToUse = ResourceUtils.getFile("classpath:messages/message.json") + val fileToUse = ResourceUtils.getFile("classpath:messages/message-template.json") val message = mapper.readTree(fileToUse) val result = downLinkService.getDownlinkForIdentity(identity, message) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 4880f082..406b04c6 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -15,6 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource import org.mockito.kotlin.mock import org.mockito.kotlin.spy +import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.springframework.util.ResourceUtils @@ -27,21 +28,16 @@ class UrcServiceTest { companion object { private const val URC_FIELD = "URC" private const val DL_FIELD = "DL" + private const val PSK_COMMAND = + "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" + private const val IDENTITY = "identity" } @Test fun shouldChangeActiveKeyWhenSuccessURCReceived() { - val identity = "identity" - - whenever(pskService.needsKeyChange(identity)).thenReturn(false) - whenever(pskService.isPendingKeyPresent(identity)).thenReturn(true) - - val fileToUse = ResourceUtils.getFile("classpath:messages/message_psk_set_success.json") - val message = mapper.readTree(fileToUse) - - urcService.interpretURCInMessage(identity, message) - - verify(pskService).changeActiveKey(identity) + val urc = "PSK:SET" + interpretURCWhileNewKeyIsPending(urc) + verify(pskService).changeActiveKey(IDENTITY) } @ParameterizedTest(name = "should set pending key as invalid for {0}") @@ -49,34 +45,41 @@ class UrcServiceTest { strings = ["PSK:EQER", "DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER"]) fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urc: String) { - val identity = "identity" + interpretURCWhileNewKeyIsPending(urc) + verify(pskService).setPendingKeyAsInvalid(IDENTITY) + } - whenever(pskService.needsKeyChange(identity)).thenReturn(false) - whenever(pskService.isPendingKeyPresent(identity)).thenReturn(true) + @ParameterizedTest(name = "should not set pending key as invalid for {0}") + @ValueSource( + strings = + ["INIT", "ENPD", "TEL:RBT", "PSK:TMP", "JTR", "WDR", "BOR", "EXR", "POR", "TS:ERR"]) + fun shouldNotSetPendingKeyAsInvalidWhenOtherURCReceived(urc: String) { + interpretURCWhileNewKeyIsPending(urc) + verify(pskService, times(0)).setPendingKeyAsInvalid(IDENTITY) + } - val fileToUse = ResourceUtils.getFile("classpath:messages/message_psk_set_failure.json") - val messageTemplate = mapper.readTree(fileToUse) - val receivedCommand = - "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" - val message = updatePskCommandInMessage(messageTemplate, urc, receivedCommand) + private fun interpretURCWhileNewKeyIsPending(urc: String) { + whenever(pskService.needsKeyChange(IDENTITY)).thenReturn(false) + whenever(pskService.isPendingKeyPresent(IDENTITY)).thenReturn(true) - urcService.interpretURCInMessage(identity, message) + val message = updatePskCommandInMessage(urc) - verify(pskService).setPendingKeyAsInvalid(identity) + urcService.interpretURCInMessage(IDENTITY, message) } - private fun updatePskCommandInMessage( - message: JsonNode, - urc: String, - receivedCommand: String - ): JsonNode { - val newMessage = message as ObjectNode + private fun updatePskCommandInMessage(urc: String): JsonNode { + val message = messageTemplate() val urcList = listOf( TextNode(urc), - ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(receivedCommand)))) + ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(PSK_COMMAND)))) val urcArray = mapper.valueToTree(urcList) - newMessage.replace(URC_FIELD, urcArray) - return newMessage + message.replace(URC_FIELD, urcArray) + return message + } + + private fun messageTemplate(): ObjectNode { + val fileToUse = ResourceUtils.getFile("classpath:message-template.json") + return mapper.readTree(fileToUse) as ObjectNode } } diff --git a/application/src/test/resources/messages/message.json b/application/src/test/resources/message-template.json similarity index 100% rename from application/src/test/resources/messages/message.json rename to application/src/test/resources/message-template.json diff --git a/application/src/test/resources/messages/message_psk_set_failure.json b/application/src/test/resources/messages/message_psk_set_failure.json deleted file mode 100644 index e67e560a..00000000 --- a/application/src/test/resources/messages/message_psk_set_failure.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "ID": 867787050253370, - "TS": 1693318384, - "CON": "M", - "FW": 2100, - "TEL": "T-Mobile", - "cID": 49093243, - "PWR": 1, - "BAT": 3758, - "CSQ": 12, - "TRY": 1, - "MSI": 0, - "URC": [ - "PSK:EQER", - { - "DL": "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" - } - ], - "A": [ - 3, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "MEM": 0, - "UPT": 100, - "RLY": 0, - "T1": [ - 222 - ], - "H1": [ - 463 - ], - "D": 8, - "P1": [ - 2020, - 2034, - 2022, - 2050, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048 - ], - "P2": [ - 1800, - 1848, - 1948, - 2148, - 2248, - 1948, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048 - ], - "FMC": 0 -} diff --git a/application/src/test/resources/messages/message_psk_set_success.json b/application/src/test/resources/messages/message_psk_set_success.json deleted file mode 100644 index 292c33ad..00000000 --- a/application/src/test/resources/messages/message_psk_set_success.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "ID": 867787050253370, - "TS": 1693318384, - "CON": "M", - "FW": 2100, - "TEL": "T-Mobile", - "cID": 49093243, - "PWR": 1, - "BAT": 3758, - "CSQ": 12, - "TRY": 1, - "MSI": 0, - "URC": [ - "PSK:SET", - { - "DL": "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" - } - ], - "A": [ - 3, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "MEM": 0, - "UPT": 100, - "RLY": 0, - "T1": [ - 222 - ], - "H1": [ - 463 - ], - "D": 8, - "P1": [ - 2020, - 2034, - 2022, - 2050, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048 - ], - "P2": [ - 1800, - 1848, - 1948, - 2148, - 2248, - 1948, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048, - 2048 - ], - "FMC": 0 -} From b3052a1ee914fbac115c5e2763737471bb21f4e4 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Thu, 30 May 2024 12:41:37 +0200 Subject: [PATCH 06/14] FDP-2306: also test lists of urcs Signed-off-by: Loes Immens --- .../crestdeviceservice/coap/UrcServiceTest.kt | 81 +++++++++++++------ 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 406b04c6..4e4f53c9 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -6,19 +6,21 @@ package org.gxf.crestdeviceservice.coap import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.node.ArrayNode +import com.fasterxml.jackson.databind.node.BaseJsonNode import com.fasterxml.jackson.databind.node.JsonNodeFactory import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.databind.node.TextNode import org.gxf.crestdeviceservice.psk.PskService import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource +import org.junit.jupiter.params.provider.MethodSource import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.springframework.util.ResourceUtils +import java.util.stream.Stream class UrcServiceTest { private val pskService = mock() @@ -30,51 +32,73 @@ class UrcServiceTest { private const val DL_FIELD = "DL" private const val PSK_COMMAND = "!PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3;PSK:umU6KJ4g7Ye5ZU6o:4a3cfdd487298e2f048ebfd703a1da4800c18f2167b62192cf7dc9fd6cc4bcd3:SET" - private const val IDENTITY = "identity" + private const val IDENTITY = "867787050253370" + + @JvmStatic + private fun containingPskOrDownlinkErrorUrcs() = + Stream.of( + listOf("PSK:EQER"), + listOf("DL:UNK"), + listOf("[DL]:DLNA"), + listOf("[DL]:DLER"), + listOf("[DL]:#ERR"), + listOf("[DL]:HSER"), + listOf("[DL]:CSER"), + listOf("TS:ERR", "[DL]:#ERR", "[DL]:DLER"), + listOf("[DL]:#ERR", "[DL]:DLER") + ) + + @JvmStatic + private fun notContainingPskOrDownlinkErrorUrcs() = + Stream.of( + listOf("INIT"), + listOf("ENPD"), + listOf("TEL:RBT"), + listOf("JTR"), + listOf("WDR"), + listOf("BOR"), + listOf("EXR"), + listOf("POR"), + listOf("TS:ERR"), + listOf("INIT", "BOR", "POR") + ) } @Test fun shouldChangeActiveKeyWhenSuccessURCReceived() { - val urc = "PSK:SET" - interpretURCWhileNewKeyIsPending(urc) + val urcs = listOf("PSK:SET") + interpretURCWhileNewKeyIsPending(urcs) verify(pskService).changeActiveKey(IDENTITY) } @ParameterizedTest(name = "should set pending key as invalid for {0}") - @ValueSource( - strings = - ["PSK:EQER", "DL:UNK", "[DL]:DLNA", "[DL]:DLER", "[DL]:#ERR", "[DL]:HSER", "[DL]:CSER"]) - fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urc: String) { - interpretURCWhileNewKeyIsPending(urc) + @MethodSource("containingPskOrDownlinkErrorUrcs") + fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urcs: List) { + interpretURCWhileNewKeyIsPending(urcs) verify(pskService).setPendingKeyAsInvalid(IDENTITY) } @ParameterizedTest(name = "should not set pending key as invalid for {0}") - @ValueSource( - strings = - ["INIT", "ENPD", "TEL:RBT", "PSK:TMP", "JTR", "WDR", "BOR", "EXR", "POR", "TS:ERR"]) - fun shouldNotSetPendingKeyAsInvalidWhenOtherURCReceived(urc: String) { - interpretURCWhileNewKeyIsPending(urc) + @MethodSource("notContainingPskOrDownlinkErrorUrcs") + fun shouldNotSetPendingKeyAsInvalidWhenOtherURCReceived(urcs: List) { + interpretURCWhileNewKeyIsPending(urcs) verify(pskService, times(0)).setPendingKeyAsInvalid(IDENTITY) } - private fun interpretURCWhileNewKeyIsPending(urc: String) { + private fun interpretURCWhileNewKeyIsPending(urcs: List) { whenever(pskService.needsKeyChange(IDENTITY)).thenReturn(false) whenever(pskService.isPendingKeyPresent(IDENTITY)).thenReturn(true) - val message = updatePskCommandInMessage(urc) + val message = updatePskCommandInMessage(urcs) urcService.interpretURCInMessage(IDENTITY, message) } - private fun updatePskCommandInMessage(urc: String): JsonNode { + private fun updatePskCommandInMessage(urcs: List): JsonNode { val message = messageTemplate() - val urcList = - listOf( - TextNode(urc), - ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(PSK_COMMAND)))) - val urcArray = mapper.valueToTree(urcList) - message.replace(URC_FIELD, urcArray) + val urcFieldValue = urcFieldValue(urcs) + + message.replace(URC_FIELD, urcFieldValue) return message } @@ -82,4 +106,15 @@ class UrcServiceTest { val fileToUse = ResourceUtils.getFile("classpath:message-template.json") return mapper.readTree(fileToUse) as ObjectNode } + + private fun urcFieldValue(urcs: List): ArrayNode? { + val urcNodes = urcs.map { urc -> TextNode(urc) } + val downlinkNode = + ObjectNode(JsonNodeFactory.instance, mapOf(DL_FIELD to TextNode(PSK_COMMAND))) + val urcsPlusReceivedDownlink: MutableList = mutableListOf() + urcsPlusReceivedDownlink.addAll(urcNodes) + urcsPlusReceivedDownlink.add(downlinkNode) + val urcFieldValue = mapper.valueToTree(urcsPlusReceivedDownlink) + return urcFieldValue + } } From a194eb9ef67a218ce9e0433b91ee17212109735e Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Thu, 30 May 2024 12:43:14 +0200 Subject: [PATCH 07/14] FDP-2306: formatted Signed-off-by: Loes Immens --- .../org/gxf/crestdeviceservice/coap/UrcServiceTest.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 4e4f53c9..3db71a4c 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.node.BaseJsonNode import com.fasterxml.jackson.databind.node.JsonNodeFactory import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.databind.node.TextNode +import java.util.stream.Stream import org.gxf.crestdeviceservice.psk.PskService import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest @@ -20,7 +21,6 @@ import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.springframework.util.ResourceUtils -import java.util.stream.Stream class UrcServiceTest { private val pskService = mock() @@ -45,8 +45,7 @@ class UrcServiceTest { listOf("[DL]:HSER"), listOf("[DL]:CSER"), listOf("TS:ERR", "[DL]:#ERR", "[DL]:DLER"), - listOf("[DL]:#ERR", "[DL]:DLER") - ) + listOf("[DL]:#ERR", "[DL]:DLER")) @JvmStatic private fun notContainingPskOrDownlinkErrorUrcs() = @@ -60,8 +59,7 @@ class UrcServiceTest { listOf("EXR"), listOf("POR"), listOf("TS:ERR"), - listOf("INIT", "BOR", "POR") - ) + listOf("INIT", "BOR", "POR")) } @Test From 0859756b144de8c12fedaab052d81568567666bb Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Thu, 30 May 2024 12:57:07 +0200 Subject: [PATCH 08/14] FDP-2306: fix and refactor tests Signed-off-by: Loes Immens --- .../org/gxf/crestdeviceservice/TestHelper.kt | 11 +++++++ .../coap/DownlinkServiceTest.kt | 32 ++++++++----------- .../crestdeviceservice/coap/UrcServiceTest.kt | 9 ++---- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/TestHelper.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/TestHelper.kt index 54429602..8afa619b 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/TestHelper.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/TestHelper.kt @@ -3,11 +3,17 @@ // SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode import java.time.Instant import org.gxf.crestdeviceservice.psk.entity.PreSharedKey import org.gxf.crestdeviceservice.psk.entity.PreSharedKeyStatus +import org.mockito.kotlin.spy +import org.springframework.util.ResourceUtils object TestHelper { + private val mapper = spy() + fun preSharedKeyReady() = preSharedKeyWithStatus(PreSharedKeyStatus.READY) fun preSharedKeyActive() = preSharedKeyWithStatus(PreSharedKeyStatus.ACTIVE) @@ -16,4 +22,9 @@ object TestHelper { private fun preSharedKeyWithStatus(status: PreSharedKeyStatus) = PreSharedKey("identity", 1, Instant.now(), "key", "secret", status) + + fun messageTemplate(): ObjectNode { + val messageFile = ResourceUtils.getFile("classpath:message-template.json") + return mapper.readTree(messageFile) as ObjectNode + } } diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt index d01212a2..6b93e420 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/DownlinkServiceTest.kt @@ -3,40 +3,38 @@ // SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice.coap -import com.fasterxml.jackson.databind.ObjectMapper import java.time.Instant import org.assertj.core.api.Assertions.assertThat +import org.gxf.crestdeviceservice.TestHelper import org.gxf.crestdeviceservice.psk.PskService import org.gxf.crestdeviceservice.psk.entity.PreSharedKey import org.gxf.crestdeviceservice.psk.entity.PreSharedKeyStatus import org.junit.jupiter.api.Test import org.mockito.kotlin.mock -import org.mockito.kotlin.spy import org.mockito.kotlin.whenever -import org.springframework.util.ResourceUtils class DownlinkServiceTest { private val pskService = mock() private val downLinkService = DownlinkService(pskService) - private val mapper = spy() + private val message = TestHelper.messageTemplate() + + companion object { + private const val IDENTITY = "867787050253370" + } @Test fun shouldReturnPskDownlinkWhenThereIsANewPsk() { - val identity = "identity" val expectedKey = "key" val expectedHash = "238104b039438f9dcbbef1dd6e295aa3cf2f248406c01ba7f6034becfe1a53d9" val psk = PreSharedKey( - identity, 1, Instant.now(), expectedKey, "secret", PreSharedKeyStatus.PENDING) + IDENTITY, 1, Instant.now(), expectedKey, "secret", PreSharedKeyStatus.PENDING) - whenever(pskService.getCurrentActiveKey(identity)).thenReturn("oldKey") - whenever(pskService.needsKeyChange(identity)).thenReturn(true) - whenever(pskService.setReadyKeyForIdentityAsPending(identity)).thenReturn(psk) + whenever(pskService.getCurrentActiveKey(IDENTITY)).thenReturn("oldKey") + whenever(pskService.needsKeyChange(IDENTITY)).thenReturn(true) + whenever(pskService.setReadyKeyForIdentityAsPending(IDENTITY)).thenReturn(psk) - val fileToUse = ResourceUtils.getFile("classpath:messages/message-template.json") - val message = mapper.readTree(fileToUse) - - val result = downLinkService.getDownlinkForIdentity(identity, message) + val result = downLinkService.getDownlinkForIdentity(IDENTITY, message) // Psk command is formatted as: PSK:[Key]:[Hash];PSK:[Key]:[Hash]:SET assertThat(result) @@ -45,13 +43,9 @@ class DownlinkServiceTest { @Test fun shouldReturnNoActionDownlinkWhenThereIsNoNewPsk() { - val identity = "identity" - whenever(pskService.needsKeyChange(identity)).thenReturn(false) - - val fileToUse = ResourceUtils.getFile("classpath:messages/message-template.json") - val message = mapper.readTree(fileToUse) + whenever(pskService.needsKeyChange(IDENTITY)).thenReturn(false) - val result = downLinkService.getDownlinkForIdentity(identity, message) + val result = downLinkService.getDownlinkForIdentity(IDENTITY, message) assertThat(result).isEqualTo("0") } diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 3db71a4c..0b78194f 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.databind.node.TextNode import java.util.stream.Stream +import org.gxf.crestdeviceservice.TestHelper import org.gxf.crestdeviceservice.psk.PskService import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest @@ -20,7 +21,6 @@ import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever -import org.springframework.util.ResourceUtils class UrcServiceTest { private val pskService = mock() @@ -93,18 +93,13 @@ class UrcServiceTest { } private fun updatePskCommandInMessage(urcs: List): JsonNode { - val message = messageTemplate() + val message = TestHelper.messageTemplate() val urcFieldValue = urcFieldValue(urcs) message.replace(URC_FIELD, urcFieldValue) return message } - private fun messageTemplate(): ObjectNode { - val fileToUse = ResourceUtils.getFile("classpath:message-template.json") - return mapper.readTree(fileToUse) as ObjectNode - } - private fun urcFieldValue(urcs: List): ArrayNode? { val urcNodes = urcs.map { urc -> TextNode(urc) } val downlinkNode = From e8ef694a3d34a9c3d05ffdc404592626a85c41e9 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Thu, 30 May 2024 14:00:19 +0200 Subject: [PATCH 09/14] FDP-2306: testing formatting Signed-off-by: Loes Immens --- .../kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 0b78194f..52033e9f 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -44,6 +44,7 @@ class UrcServiceTest { listOf("[DL]:#ERR"), listOf("[DL]:HSER"), listOf("[DL]:CSER"), + listOf("TS:ERR", "[DL]:#ERR", "[DL]:DLER"), listOf("[DL]:#ERR", "[DL]:DLER")) From 35e6740b9218e74c896b0df6c2ff16ee8b4e3a87 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Fri, 31 May 2024 10:10:18 +0200 Subject: [PATCH 10/14] FDP-2239: revert formatting Signed-off-by: Loes Immens --- .../kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 52033e9f..0b78194f 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -44,7 +44,6 @@ class UrcServiceTest { listOf("[DL]:#ERR"), listOf("[DL]:HSER"), listOf("[DL]:CSER"), - listOf("TS:ERR", "[DL]:#ERR", "[DL]:DLER"), listOf("[DL]:#ERR", "[DL]:DLER")) From 239b542736386e124177ed21f13ed15cfd0df32a Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Fri, 31 May 2024 10:32:18 +0200 Subject: [PATCH 11/14] FDP-2239: replace placeholders in urcs Signed-off-by: Loes Immens --- ...skOrDownlinkErrorUrc.kt => PskErrorUrc.kt} | 14 +++++------ .../gxf/crestdeviceservice/coap/UrcService.kt | 14 +++++------ .../crestdeviceservice/coap/UrcServiceTest.kt | 25 ++++++++++--------- 3 files changed, 27 insertions(+), 26 deletions(-) rename application/src/main/kotlin/org/gxf/crestdeviceservice/coap/{PskOrDownlinkErrorUrc.kt => PskErrorUrc.kt} (52%) diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt similarity index 52% rename from application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt rename to application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt index 0deaaece..1066fbf5 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskOrDownlinkErrorUrc.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt @@ -3,14 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 package org.gxf.crestdeviceservice.coap -enum class PskOrDownlinkErrorUrc(val code: String, val message: String) { +enum class PskErrorUrc(val code: String, val message: String) { PSK_EQER("PSK:EQER", "Set PSK does not equal earlier PSK"), DL_UNK("DL:UNK", "Downlink unknown"), - DL_DLNA("[DL]:DLNA", "Downlink not allowed"), - DL_DLER("[DL]:DLER", "Downlink (syntax) error"), - DL_ERR("[DL]:#ERR", "Error processing (downlink) value"), - DL_HSER("[DL]:HSER", "SHA256 hash error"), - DL_CSER("[DL]:CSER", "Checksum error"); + PSK_DLNA("PSK:DLNA", "Downlink not allowed"), + PSK_DLER("PSK:DLER", "Downlink (syntax) error"), + PSK_ERR("PSK:#ERR", "Error processing (downlink) value"), + PSK_HSER("PSK:HSER", "SHA256 hash error"), + PSK_CSER("PSK:CSER", "Checksum error"); companion object { fun messageFromCode(code: String): String { @@ -18,6 +18,6 @@ enum class PskOrDownlinkErrorUrc(val code: String, val message: String) { return error?.message ?: "Unknown URC" } - fun isPskOrDownlinkErrorURC(code: String) = entries.any { it.code == code } + fun isPskErrorURC(code: String) = entries.any { it.code == code } } } diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt index 1ea0d2ca..648e67ba 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/UrcService.kt @@ -28,8 +28,8 @@ class UrcService(private val pskService: PskService) { logger.debug { "Received message with urcs ${urcs.joinToString(", ")}" } when { - urcsContainPskOrDownlinkError(urcs) -> { - handlePskOrDownlinkErrors(identity, urcs) + urcsContainPskError(urcs) -> { + handlePskErrors(identity, urcs) } urcsContainPskSuccess(urcs) -> { handlePskSuccess(identity) @@ -40,20 +40,20 @@ class UrcService(private val pskService: PskService) { private fun getUrcsFromMessage(body: JsonNode) = body[URC_FIELD].filter { it.isTextual }.map { it.asText() } - private fun urcsContainPskOrDownlinkError(urcs: List) = - urcs.any { urc -> PskOrDownlinkErrorUrc.isPskOrDownlinkErrorURC(urc) } + private fun urcsContainPskError(urcs: List) = + urcs.any { urc -> PskErrorUrc.isPskErrorURC(urc) } - private fun handlePskOrDownlinkErrors(identity: String, urcs: List) { + private fun handlePskErrors(identity: String, urcs: List) { if (!pskService.isPendingKeyPresent(identity)) { throw NoExistingPskException( "Failure URC received, but no pending key present to set as invalid") } urcs - .filter { urc -> PskOrDownlinkErrorUrc.isPskOrDownlinkErrorURC(urc) } + .filter { urc -> PskErrorUrc.isPskErrorURC(urc) } .forEach { urc -> logger.warn { - "PSK set failed for device with id ${identity}: ${PskOrDownlinkErrorUrc.messageFromCode(urc)}" + "PSK set failed for device with id ${identity}: ${PskErrorUrc.messageFromCode(urc)}" } } diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 0b78194f..b6ce18a1 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -35,20 +35,20 @@ class UrcServiceTest { private const val IDENTITY = "867787050253370" @JvmStatic - private fun containingPskOrDownlinkErrorUrcs() = + private fun containingPskErrorUrcs() = Stream.of( listOf("PSK:EQER"), listOf("DL:UNK"), - listOf("[DL]:DLNA"), - listOf("[DL]:DLER"), - listOf("[DL]:#ERR"), - listOf("[DL]:HSER"), - listOf("[DL]:CSER"), - listOf("TS:ERR", "[DL]:#ERR", "[DL]:DLER"), - listOf("[DL]:#ERR", "[DL]:DLER")) + listOf("PSK:DLNA"), + listOf("PSK:DLER"), + listOf("PSK:#ERR"), + listOf("PSK:HSER"), + listOf("PSK:CSER"), + listOf("TS:ERR", "PSK:#ERR", "PSK:DLER"), + listOf("PSK:#ERR", "PSK:DLER")) @JvmStatic - private fun notContainingPskOrDownlinkErrorUrcs() = + private fun notContainingPskErrorUrcs() = Stream.of( listOf("INIT"), listOf("ENPD"), @@ -59,7 +59,8 @@ class UrcServiceTest { listOf("EXR"), listOf("POR"), listOf("TS:ERR"), - listOf("INIT", "BOR", "POR")) + listOf("INIT", "BOR", "POR"), + listOf("OTA:HSER", "MSI:DLNA")) } @Test @@ -70,14 +71,14 @@ class UrcServiceTest { } @ParameterizedTest(name = "should set pending key as invalid for {0}") - @MethodSource("containingPskOrDownlinkErrorUrcs") + @MethodSource("containingPskErrorUrcs") fun shouldSetPendingKeyAsInvalidWhenFailureURCReceived(urcs: List) { interpretURCWhileNewKeyIsPending(urcs) verify(pskService).setPendingKeyAsInvalid(IDENTITY) } @ParameterizedTest(name = "should not set pending key as invalid for {0}") - @MethodSource("notContainingPskOrDownlinkErrorUrcs") + @MethodSource("notContainingPskErrorUrcs") fun shouldNotSetPendingKeyAsInvalidWhenOtherURCReceived(urcs: List) { interpretURCWhileNewKeyIsPending(urcs) verify(pskService, times(0)).setPendingKeyAsInvalid(IDENTITY) From 5d1ed160b8ee5bf1166bc1a18c64517f76609dd7 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Fri, 31 May 2024 10:34:44 +0200 Subject: [PATCH 12/14] FDP-2239: switch order for readability Signed-off-by: Loes Immens --- .../main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt index 1066fbf5..5ab32543 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt @@ -4,8 +4,8 @@ package org.gxf.crestdeviceservice.coap enum class PskErrorUrc(val code: String, val message: String) { - PSK_EQER("PSK:EQER", "Set PSK does not equal earlier PSK"), DL_UNK("DL:UNK", "Downlink unknown"), + PSK_EQER("PSK:EQER", "Set PSK does not equal earlier PSK"), PSK_DLNA("PSK:DLNA", "Downlink not allowed"), PSK_DLER("PSK:DLER", "Downlink (syntax) error"), PSK_ERR("PSK:#ERR", "Error processing (downlink) value"), From e75f8fed8d57bf4f409ec5a657b75432c49f8492 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Fri, 31 May 2024 10:50:00 +0200 Subject: [PATCH 13/14] FDP-2306: remove irrelevant urcs Signed-off-by: Loes Immens --- .../kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt | 2 -- .../kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt index 5ab32543..2d7c2495 100644 --- a/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt +++ b/application/src/main/kotlin/org/gxf/crestdeviceservice/coap/PskErrorUrc.kt @@ -4,11 +4,9 @@ package org.gxf.crestdeviceservice.coap enum class PskErrorUrc(val code: String, val message: String) { - DL_UNK("DL:UNK", "Downlink unknown"), PSK_EQER("PSK:EQER", "Set PSK does not equal earlier PSK"), PSK_DLNA("PSK:DLNA", "Downlink not allowed"), PSK_DLER("PSK:DLER", "Downlink (syntax) error"), - PSK_ERR("PSK:#ERR", "Error processing (downlink) value"), PSK_HSER("PSK:HSER", "SHA256 hash error"), PSK_CSER("PSK:CSER", "Checksum error"); diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index b6ce18a1..9a947435 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -38,13 +38,11 @@ class UrcServiceTest { private fun containingPskErrorUrcs() = Stream.of( listOf("PSK:EQER"), - listOf("DL:UNK"), listOf("PSK:DLNA"), listOf("PSK:DLER"), - listOf("PSK:#ERR"), listOf("PSK:HSER"), listOf("PSK:CSER"), - listOf("TS:ERR", "PSK:#ERR", "PSK:DLER"), + listOf("TS:ERR", "PSK:DLER"), listOf("PSK:#ERR", "PSK:DLER")) @JvmStatic From 971b2c1725fbcd88c91d48c834923ed69ba8b49d Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Fri, 31 May 2024 10:58:10 +0200 Subject: [PATCH 14/14] FDP-2306: small urc change in test Signed-off-by: Loes Immens --- .../kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt index 9a947435..12ee9ba3 100644 --- a/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/crestdeviceservice/coap/UrcServiceTest.kt @@ -43,7 +43,7 @@ class UrcServiceTest { listOf("PSK:HSER"), listOf("PSK:CSER"), listOf("TS:ERR", "PSK:DLER"), - listOf("PSK:#ERR", "PSK:DLER")) + listOf("PSK:HSER", "PSK:DLER")) @JvmStatic private fun notContainingPskErrorUrcs() =