From 3bdd41724d031c5d787239ce1b4186ac7680d03c Mon Sep 17 00:00:00 2001 From: kjaniak Date: Thu, 12 Jul 2018 10:57:58 +0200 Subject: Extract message generator module Closes ONAP-501 Change-Id: Ia5dc5f67e18c302abbeac7e0373cef479f4befb8 Signed-off-by: kjaniak Issue-ID: DCAEGEN2-601 --- hv-collector-ves-message-generator/pom.xml | 110 +++++++++++++++++++++ .../ves/message/generator/api/MessageGenerator.kt | 44 +++++++++ .../message/generator/config/MessageParameters.kt | 28 ++++++ .../message/generator/impl/MessageGeneratorImpl.kt | 75 ++++++++++++++ .../ves/message/generator/impl/PayloadGenerator.kt | 62 ++++++++++++ .../impl/impl/MessageGeneratorImplTest.kt | 84 ++++++++++++++++ .../generator/impl/impl/PayloadGeneratorTest.kt | 75 ++++++++++++++ 7 files changed, 478 insertions(+) create mode 100644 hv-collector-ves-message-generator/pom.xml create mode 100644 hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/api/MessageGenerator.kt create mode 100644 hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/config/MessageParameters.kt create mode 100644 hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageGeneratorImpl.kt create mode 100644 hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/PayloadGenerator.kt create mode 100644 hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/MessageGeneratorImplTest.kt create mode 100644 hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/PayloadGeneratorTest.kt (limited to 'hv-collector-ves-message-generator') diff --git a/hv-collector-ves-message-generator/pom.xml b/hv-collector-ves-message-generator/pom.xml new file mode 100644 index 00000000..dfa30b10 --- /dev/null +++ b/hv-collector-ves-message-generator/pom.xml @@ -0,0 +1,110 @@ + + + + 4.0.0 + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + org.onap.dcaegen2.collectors.veshv + ves-hv-collector + 1.0.0-SNAPSHOT + .. + + + hv-collector-ves-message-generator + VES HighVolume Collector :: VES message generator + + + false + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + + + maven-surefire-plugin + org.apache.maven.plugins + + + + + + ${project.parent.groupId} + hv-collector-domain + ${project.parent.version} + + + ${project.parent.groupId} + hv-collector-utils + ${project.parent.version} + + + org.slf4j + slf4j-api + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.assertj + assertj-core + + + org.jetbrains.kotlin + kotlin-test + + + org.jetbrains.spek + spek-api + + + org.jetbrains.spek + spek-junit-platform-engine + + + io.projectreactor + reactor-test + + + ch.qos.logback + logback-classic + runtime + + + org.glassfish + javax.json + + + + + \ No newline at end of file diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/api/MessageGenerator.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/api/MessageGenerator.kt new file mode 100644 index 00000000..e52db848 --- /dev/null +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/api/MessageGenerator.kt @@ -0,0 +1,44 @@ +/* + * ============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.api + +import org.onap.dcae.collectors.veshv.domain.PayloadWireFrameMessage +import org.onap.dcae.collectors.veshv.ves.message.generator.config.MessageParameters +import org.onap.dcae.collectors.veshv.ves.message.generator.impl.MessageGeneratorImpl +import org.onap.dcae.collectors.veshv.ves.message.generator.impl.PayloadGenerator +import org.onap.ves.VesEventV5 +import reactor.core.publisher.Flux +import javax.json.JsonObject + +/** + * @author Piotr Jaszczyk + * @since June 2018 + */ +interface MessageGenerator { + fun createMessageFlux(messageParameters: MessageParameters): Flux + fun parseCommonHeader(json: JsonObject): VesEventV5.VesEvent.CommonEventHeader + + companion object { + val INSTANCE: MessageGenerator by lazy { + MessageGeneratorImpl(PayloadGenerator()) + } + } +} + diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/config/MessageParameters.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/config/MessageParameters.kt new file mode 100644 index 00000000..7e80cc66 --- /dev/null +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/config/MessageParameters.kt @@ -0,0 +1,28 @@ +/* + * ============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.config + +import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader + +/** + * @author Jakub Dudycz + * @since June 2018 + */ +data class MessageParameters(val commonEventHeader: CommonEventHeader, val amount: Long = -1) diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageGeneratorImpl.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageGeneratorImpl.kt new file mode 100644 index 00000000..b2f73894 --- /dev/null +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/MessageGeneratorImpl.kt @@ -0,0 +1,75 @@ +/* + * ============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 com.google.protobuf.ByteString +import org.onap.dcae.collectors.veshv.domain.PayloadWireFrameMessage +import org.onap.dcae.collectors.veshv.ves.message.generator.api.MessageGenerator +import org.onap.dcae.collectors.veshv.ves.message.generator.config.MessageParameters +import org.onap.ves.VesEventV5.VesEvent +import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono +import javax.json.JsonObject + +/** + * @author Jakub Dudycz + * @since June 2018 + */ +class MessageGeneratorImpl internal constructor(private val payloadGenerator: PayloadGenerator) : MessageGenerator { + + override fun createMessageFlux(messageParameters: MessageParameters): Flux = + Mono.fromCallable { createMessage(messageParameters.commonEventHeader) }.let { + if (messageParameters.amount < 0) + it.repeat() + else + it.repeat(messageParameters.amount) + } + + override fun parseCommonHeader(json: JsonObject): CommonEventHeader = CommonEventHeader.newBuilder() + .setVersion(json.getString("version")) + .setDomain(CommonEventHeader.Domain.forNumber(json.getInt("domain"))) + .setSequence(json.getInt("sequence")) + .setPriority(CommonEventHeader.Priority.forNumber(json.getInt("priority"))) + .setEventId(json.getString("eventId")) + .setEventName(json.getString("eventName")) + .setEventType(json.getString("eventType")) + .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() + + + private fun createMessage(commonHeader: CommonEventHeader): PayloadWireFrameMessage = + PayloadWireFrameMessage(vesMessageBytes(commonHeader)) + + + private fun vesMessageBytes(commonHeader: CommonEventHeader): ByteArray = + VesEvent.newBuilder() + .setCommonEventHeader(commonHeader) + .setHvRanMeasFields(payloadGenerator.generatePayload().toByteString()) + .build() + .toByteArray() +} diff --git a/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/PayloadGenerator.kt b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/PayloadGenerator.kt new file mode 100644 index 00000000..66f34e9e --- /dev/null +++ b/hv-collector-ves-message-generator/src/main/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/PayloadGenerator.kt @@ -0,0 +1,62 @@ +/* + * ============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 org.onap.ves.HVRanMeasFieldsV5.HVRanMeasFields.HVRanMeasPayload +import org.onap.ves.HVRanMeasFieldsV5.HVRanMeasFields.HVRanMeasPayload.PMObject +import org.onap.ves.HVRanMeasFieldsV5.HVRanMeasFields.HVRanMeasPayload.PMObject.HVRanMeas +import java.util.* + +internal class PayloadGenerator { + + private val randomGenerator = Random() + + fun generatePayload(numOfCountPerMeas: Long = 2, numOfMeasPerObject: Int = 2): HVRanMeasPayload { + val pmObject = generatePmObject(numOfCountPerMeas, numOfMeasPerObject) + return HVRanMeasPayload.newBuilder() + .addPmObject(pmObject) + .build() + } + + private fun generatePmObject(numOfCountPerMeas: Long, numOfMeasPerObject: Int): PMObject { + val hvRanMeasList = MutableList(numOfMeasPerObject) { generateHvRanMeas(numOfCountPerMeas) } + val finalUriName = URI_BASE_NAME + randomGenerator.nextInt(UPPER_URI_NUMBER_BOUND) + return HVRanMeasPayload.PMObject.newBuilder() + .setUri(finalUriName) + .addAllHvRanMeas(hvRanMeasList.asIterable()) + .build() + } + + private fun generateHvRanMeas(numOfCountPerMeas: Long): HVRanMeas { + return HVRanMeasPayload.PMObject.HVRanMeas.newBuilder() + .setMeasurementId(randomGenerator.nextInt()) + .addAllCounterSubid(Iterable { randomGenerator.ints(numOfCountPerMeas).iterator() }) + .addAllCounterValue(Iterable { randomGenerator.longs(numOfCountPerMeas).iterator() }) + .setSuspectFlagIncomplete(false) + .setSuspectFlagOutOfSync(false) + .build() + } + + companion object { + private const val URI_BASE_NAME = "sample/uri" + private const val UPPER_URI_NUMBER_BOUND = 10_000 + } + +} diff --git a/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/MessageGeneratorImplTest.kt b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/MessageGeneratorImplTest.kt new file mode 100644 index 00000000..07027173 --- /dev/null +++ b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/MessageGeneratorImplTest.kt @@ -0,0 +1,84 @@ +/* + * ============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.impl + +import com.google.protobuf.ByteString +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.ves.message.generator.api.MessageGenerator +import org.onap.dcae.collectors.veshv.ves.message.generator.config.MessageParameters +import org.onap.ves.VesEventV5 +import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader.Domain.HVRANMEAS +import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader.Priority.MEDIUM +import reactor.test.test + +const val SAMPLE_START_EPOCH: Long = 120034455 +const val SAMPLE_LAST_EPOCH: Long = 120034455 + +/** + * @author Jakub Dudycz + * @since June 2018 + */ +object MessageGeneratorImplTest : Spek({ + describe("message factory") { + + val generator = MessageGenerator.INSTANCE + + given("only common header") { + it("should return infinite flux") { + val limit = 1000L + generator.createMessageFlux(getSampleMessageParameters()).take(limit).test() + .expectNextCount(limit) + .verifyComplete() + } + } + given("common header and messages amount") { + it("should return message flux of specified size") { + generator.createMessageFlux((getSampleMessageParameters(5))).test() + .expectNextCount(5) + .verifyComplete() + } + } + } +}) + +fun getSampleMessageParameters(amount: Long = -1): MessageParameters { + val commonHeader = VesEventV5.VesEvent.CommonEventHeader.newBuilder() + .setVersion("sample-version") + .setDomain(HVRANMEAS) + .setSequence(1) + .setPriority(MEDIUM) + .setEventId("sample-event-id") + .setEventName("sample-event-name") + .setEventType("sample-event-type") + .setStartEpochMicrosec(SAMPLE_START_EPOCH) + .setLastEpochMicrosec(SAMPLE_LAST_EPOCH) + .setNfNamingCode("sample-nf-naming-code") + .setNfcNamingCode("sample-nfc-naming-code") + .setReportingEntityId("sample-reporting-entity-id") + .setReportingEntityName(ByteString.copyFromUtf8("sample-reporting-entity-name")) + .setSourceId(ByteString.copyFromUtf8("sample-source-id")) + .setSourceName("sample-source-name") + .build() + + return MessageParameters(commonHeader, amount) +} diff --git a/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/PayloadGeneratorTest.kt b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/PayloadGeneratorTest.kt new file mode 100644 index 00000000..9760208f --- /dev/null +++ b/hv-collector-ves-message-generator/src/test/kotlin/org/onap/dcae/collectors/veshv/ves/message/generator/impl/impl/PayloadGeneratorTest.kt @@ -0,0 +1,75 @@ +/* + * ============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.impl + +import org.jetbrains.spek.api.Spek +import org.jetbrains.spek.api.dsl.given +import org.jetbrains.spek.api.dsl.it +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.spek.api.dsl.on +import org.onap.dcae.collectors.veshv.ves.message.generator.impl.PayloadGenerator + +private const val DEFAULT_MEASUREMENTS_NUMBER = 2 +private const val DEFAULT_COUNTERS_NUMBER = 2 + +private val uriRegex = """sample/uri(\d+)""".toRegex() + +object PayloadGeneratorTest : Spek({ + + given("payload factory object") { + val payloadGenerator = PayloadGenerator() + + on("two generated payloads") { + val generatedPayload0 = payloadGenerator.generatePayload() + val generatedPayload1 = payloadGenerator.generatePayload() + it("URIs should have different names") { + val matchResult0 = uriRegex.find(generatedPayload0.getPmObject(0).uri)!!.value + val matchResult1 = uriRegex.find(generatedPayload1.getPmObject(0).uri)!!.value + assertThat(matchResult0 != matchResult1).isTrue() + } + } + + on("call with default parameters") { + val generatedPayload = payloadGenerator.generatePayload() + it("should contain default numbers of measurements") { + assertThat(generatedPayload.getPmObject(0).hvRanMeasCount).isEqualTo(DEFAULT_MEASUREMENTS_NUMBER) + } + it("should contain default numbers of counters in measurement") { + assertThat(generatedPayload.getPmObject(0).getHvRanMeas(0).counterSubidCount).isEqualTo(DEFAULT_COUNTERS_NUMBER) + } + } + + on("call with specified parameters") { + val numOfCountPerMeas: Long = 5 + val numOfMeasPerObject: Int = 10 + val generatedPayload = payloadGenerator.generatePayload(numOfCountPerMeas, numOfMeasPerObject) + it("should contain specified number of measurements") { + assertThat(generatedPayload.getPmObject(0).hvRanMeasCount).isEqualTo(numOfMeasPerObject) + } + it("measurement should contain specified number of counters") { + assertThat(generatedPayload.getPmObject(0).hvRanMeasList + .filter { numOfCountPerMeas.toInt() == it.counterSubidCount } + .size) + .isEqualTo(numOfMeasPerObject) + } + + } + } +}) -- cgit 1.2.3-korg