From 6b1777bf08c682fab15f158e9946e36f3cb9698a Mon Sep 17 00:00:00 2001 From: Filip Krzywka Date: Thu, 6 Sep 2018 13:37:27 +0200 Subject: Fix common event header parsing During JSON parsing we were using 3 times 'version' field. Replaced parsing with protobuf parser to avoid mistakes like this in future Change-Id: I6224dc6533ab553e7e2315a95567a1fa48c1c5ad Issue-ID: DCAEGEN2-710 Signed-off-by: Filip Krzywka --- .../dcae/collectors/veshv/impl/MessageValidator.kt | 16 +---- .../dcae/collectors/veshv/domain/validation.kt | 35 ++++++++++ hv-collector-ves-message-generator/pom.xml | 4 ++ .../generator/impl/CommonEventHeaderParser.kt | 42 ++++++----- .../generator/impl/MessageParametersParserImpl.kt | 2 + .../generator/impl/CommonEventHeaderParserTest.kt | 81 ++++++++++++++++++++++ 6 files changed, 144 insertions(+), 36 deletions(-) create mode 100644 hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/validation.kt create mode 100644 hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParserTest.kt diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/MessageValidator.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/MessageValidator.kt index 543d7dc6..8affa0b1 100644 --- a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/MessageValidator.kt +++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/MessageValidator.kt @@ -19,29 +19,17 @@ */ package org.onap.dcae.collectors.veshv.impl +import org.onap.dcae.collectors.veshv.domain.headerRequiredFieldDescriptors import org.onap.dcae.collectors.veshv.model.VesMessage import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader internal object MessageValidator { - private val requiredFieldDescriptors = listOf( - "version", - "eventName", - "domain", - "eventId", - "sourceName", - "reportingEntityName", - "priority", - "startEpochMicrosec", - "lastEpochMicrosec", - "sequence") - .map { fieldName -> CommonEventHeader.getDescriptor().findFieldByName(fieldName) } - fun isValid(message: VesMessage): Boolean { return allMandatoryFieldsArePresent(message.header) } private fun allMandatoryFieldsArePresent(header: CommonEventHeader) = - requiredFieldDescriptors + headerRequiredFieldDescriptors .all { fieldDescriptor -> header.hasField(fieldDescriptor) } } diff --git a/hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/validation.kt b/hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/validation.kt new file mode 100644 index 00000000..91c75459 --- /dev/null +++ b/hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/validation.kt @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START======================================================= + * dcaegen2-collectors-veshv + * ================================================================================ + * Copyright (C) 2018 NOKIA + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.collectors.veshv.domain + +import org.onap.ves.VesEventV5 + +val headerRequiredFieldDescriptors = listOf( + "version", + "eventName", + "domain", + "eventId", + "sourceName", + "reportingEntityName", + "priority", + "startEpochMicrosec", + "lastEpochMicrosec", + "sequence") + .map { fieldName -> VesEventV5.VesEvent.CommonEventHeader.getDescriptor().findFieldByName(fieldName) } \ No newline at end of file diff --git a/hv-collector-ves-message-generator/pom.xml b/hv-collector-ves-message-generator/pom.xml index f06a9112..4afe7963 100644 --- a/hv-collector-ves-message-generator/pom.xml +++ b/hv-collector-ves-message-generator/pom.xml @@ -68,6 +68,10 @@ ${project.parent.version} test + + com.google.protobuf + protobuf-java-util + org.slf4j slf4j-api diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParser.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParser.kt index e5977fb7..768685c1 100644 --- a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParser.kt +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParser.kt @@ -19,11 +19,10 @@ */ package org.onap.dcae.collectors.veshv.ves.message.generator.impl -import com.google.protobuf.ByteString -import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader -import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader.Domain -import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader.Priority -import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader.newBuilder +import arrow.core.Option +import com.google.protobuf.util.JsonFormat +import org.onap.dcae.collectors.veshv.domain.headerRequiredFieldDescriptors +import org.onap.ves.VesEventV5.VesEvent.* import javax.json.JsonObject /** @@ -31,22 +30,21 @@ import javax.json.JsonObject * @since July 2018 */ class CommonEventHeaderParser { - fun parse(json: JsonObject): CommonEventHeader = newBuilder() - .setVersion(json.getString("version")) - .setDomain(Domain.valueOf(json.getString("domain"))) - .setSequence(json.getInt("sequence")) - .setPriority(Priority.forNumber(json.getInt("priority"))) - .setEventId(json.getString("version")) - .setEventName(json.getString("version")) - .setEventType(json.getString("version")) - .setStartEpochMicrosec(json.getJsonNumber("startEpochMicrosec").longValue()) - .setLastEpochMicrosec(json.getJsonNumber("lastEpochMicrosec").longValue()) - .setNfNamingCode(json.getString("nfNamingCode")) - .setNfcNamingCode(json.getString("nfcNamingCode")) - .setReportingEntityId(json.getString("reportingEntityId")) - .setReportingEntityName(ByteString.copyFromUtf8(json.getString("reportingEntityName"))) - .setSourceId(ByteString.copyFromUtf8(json.getString("sourceId"))) - .setSourceName(json.getString("sourceName")) - .build() + fun parse(json: JsonObject): Option = + Option.fromNullable( + CommonEventHeader.newBuilder() + .apply { JsonFormat.parser().merge(json.toString(), this) } + .build() + .takeUnless { !isValid(it) } + ) + + + private fun isValid(header: CommonEventHeader): Boolean { + return allMandatoryFieldsArePresent(header) + } + + private fun allMandatoryFieldsArePresent(header: CommonEventHeader) = + headerRequiredFieldDescriptors + .all { fieldDescriptor -> header.hasField(fieldDescriptor) } } diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageParametersParserImpl.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageParametersParserImpl.kt index f3095618..ea0ee282 100644 --- a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageParametersParserImpl.kt +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageParametersParserImpl.kt @@ -21,6 +21,7 @@ package org.onap.dcae.collectors.veshv.ves.message.generator.impl import arrow.core.Option import arrow.core.Try +import arrow.core.identity import org.onap.dcae.collectors.veshv.ves.message.generator.api.MessageParameters import org.onap.dcae.collectors.veshv.ves.message.generator.api.MessageParametersParser import org.onap.dcae.collectors.veshv.ves.message.generator.api.MessageType @@ -42,6 +43,7 @@ internal class MessageParametersParserImpl( .map { val commonEventHeader = commonEventHeaderParser .parse(it.getJsonObject("commonEventHeader")) + .fold({ throw IllegalStateException("Invalid common header") }, ::identity) val messageType = MessageType.valueOf(it.getString("messageType")) val messagesAmount = it.getJsonNumber("messagesAmount")?.longValue() ?: throw NullPointerException("\"messagesAmount\" could not be parsed from message.") diff --git a/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParserTest.kt b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParserTest.kt new file mode 100644 index 00000000..c16459ce --- /dev/null +++ b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/CommonEventHeaderParserTest.kt @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * dcaegen2-collectors-veshv + * ================================================================================ + * Copyright (C) 2018 NOKIA + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.collectors.veshv.ves.message.generator.impl + +import arrow.core.Option +import arrow.core.identity +import com.google.protobuf.util.JsonFormat +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.spek.api.Spek +import org.jetbrains.spek.api.dsl.describe +import org.jetbrains.spek.api.dsl.given +import org.jetbrains.spek.api.dsl.it +import org.onap.dcae.collectors.veshv.tests.utils.commonHeader +import org.onap.ves.VesEventV5 +import java.io.ByteArrayInputStream +import javax.json.Json +import kotlin.test.fail + +class CommonEventHeaderParserTest : Spek({ + + describe("Common event header parser") { + val parser = CommonEventHeaderParser() + + given("valid header in JSON format") { + val commonEventHeader = commonHeader( + domain = VesEventV5.VesEvent.CommonEventHeader.Domain.STATE_CHANGE, + id = "sample-event-id") + val json = JsonFormat.printer().print(commonEventHeader).byteInputStream() + + it("should parse common event header") { + val result = + parser.parse(jsonObject(json)) + .fold({ fail() }, ::identity) + + assertThat(result).describedAs("common event header").isEqualTo(commonEventHeader) + } + } + + given("invalid header in JSON format") { + val json = "{}".byteInputStream() + + it("should throw exception") { + val result = parser.parse(jsonObject(json)) + + assertFailed(result) + } + } + + given("invalid JSON") { + val json = "{}}}}".byteInputStream() + + it("should throw exception") { + val result = parser.parse(jsonObject(json)) + + assertFailed(result) + } + } + } +}) + +fun assertFailed(result: Option) = + result.fold({}, { fail() }) + +fun jsonObject(json: ByteArrayInputStream) = Json.createReader(json).readObject() \ No newline at end of file -- cgit 1.2.3-korg