aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBogumil Zebek <bogumil.zebek@nokia.com>2021-03-09 12:54:38 +0100
committerZebek Bogumil <bogumil.zebek@nokia.com>2021-03-10 09:31:58 +0100
commit4af5241ab25b0103d8ea680789aaf9a8696dfc75 (patch)
tree36ccae11ebf094aa1ddd65df309b7531ce0db1ff
parentc9975cb96ba4e0208e72399ed80f909beb95d9d9 (diff)
Move pnf simulator to the new repo
In the first phase we renamed project from pnf simulator to vesclient. Next steps: package rename, update Readme.md, upgrade project dependencies. Issue-ID: INT-1869 Signed-off-by: Bogumil Zebek<bogumil.zebek@nokia.com> Change-Id: I7714792f9739eb746c9c533e8ef41b9618a3a1d9
-rw-r--r--.gitignore17
-rw-r--r--Dockerfile18
-rw-r--r--Makefile13
-rw-r--r--README.md436
-rw-r--r--certificates/AAF_RootCA.crt31
-rw-r--r--certificates/dcaelocal.crt20
-rw-r--r--config/config.json9
-rw-r--r--config/mongo_db_schema_creation.py48
-rw-r--r--config/requirements.txt1
-rw-r--r--db/pnf_simulator.js28
-rw-r--r--deployment/PnP_PNF_sim_heat_template.yml118
-rw-r--r--docker-compose.yml40
-rw-r--r--integration/pom.xml128
-rw-r--r--integration/src/main/java/org/onap/pnfsimulator/integration/Main.java35
-rw-r--r--integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java71
-rw-r--r--integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java36
-rw-r--r--integration/src/main/resources/application.properties1
-rw-r--r--integration/src/main/resources/keystorebin0 -> 2196 bytes
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java234
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java161
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java269
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java151
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java175
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java36
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java57
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java80
-rw-r--r--integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java90
-rw-r--r--integration/src/test/resources/application.properties6
-rw-r--r--integration/src/test/resources/templates/cmNotification.json32
-rw-r--r--integration/src/test/resources/templates/notification.json45
-rw-r--r--integration/src/test/resources/templates/overwrite_template.json6
-rw-r--r--integration/src/test/resources/templates/overwritten_template.json6
-rw-r--r--integration/src/test/resources/templates/registration.json36
-rw-r--r--integration/src/test/resources/templates/search/complicated_template.json43
-rw-r--r--integration/src/test/resources/templates/search/simple_template.json12
-rw-r--r--integration/src/test/resources/templates/search/template_with_array.json23
-rw-r--r--integration/src/test/resources/templates/search/template_with_booleans.json12
-rw-r--r--integration/src/test/resources/templates/search/template_with_floats.json13
-rw-r--r--integration/src/test/resources/templates/search/template_with_ints.json12
-rw-r--r--integration/src/test/resources/templates/upload_template.json6
-rw-r--r--lombok.config2
-rw-r--r--pom.xml498
-rw-r--r--src/assembly/resources.xml57
-rw-r--r--src/main/java/org/onap/pnfsimulator/Main.java59
-rw-r--r--src/main/java/org/onap/pnfsimulator/SwaggerConfig.java46
-rw-r--r--src/main/java/org/onap/pnfsimulator/db/Row.java39
-rw-r--r--src/main/java/org/onap/pnfsimulator/db/Storage.java41
-rw-r--r--src/main/java/org/onap/pnfsimulator/event/EventData.java67
-rw-r--r--src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java26
-rw-r--r--src/main/java/org/onap/pnfsimulator/event/EventDataService.java65
-rw-r--r--src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java39
-rw-r--r--src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java111
-rw-r--r--src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java44
-rw-r--r--src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java81
-rw-r--r--src/main/java/org/onap/pnfsimulator/logging/MdcVariables.java35
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java241
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/TemplateController.java112
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java48
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java42
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java46
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java55
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java38
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java35
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java42
-rw-r--r--src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java62
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java51
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java29
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java54
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java26
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java47
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java134
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java129
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java74
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java28
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java80
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java132
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java53
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java29
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java50
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java45
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java27
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java119
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java41
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java53
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java46
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java104
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java40
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java32
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java48
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java45
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java76
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java65
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java73
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java80
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java99
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java120
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java38
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java49
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java26
-rw-r--r--src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java52
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java74
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/Template.java92
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java26
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/TemplateService.java81
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java28
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java104
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java95
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java103
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java45
-rw-r--r--src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java40
-rw-r--r--src/main/resources/application.properties18
-rw-r--r--src/main/resources/logback.xml55
-rw-r--r--src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java133
-rw-r--r--src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java71
-rw-r--r--src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java125
-rw-r--r--src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java329
-rw-r--r--src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java256
-rw-r--r--src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java38
-rw-r--r--src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java66
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/DbTemplateReaderTest.java81
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java79
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java67
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java67
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java65
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java66
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java66
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java69
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java66
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java68
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java306
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java82
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java308
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java164
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java51
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacerTest.java174
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactoryTest.java98
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java157
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/HttpTestUtils.java55
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactoryTest.java141
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacadeTest.java35
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryTest.java143
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverterTest.java44
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactoryTest.java61
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeywordTest.java48
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java90
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java148
-rw-r--r--src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java104
-rw-r--r--src/test/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizerTest.java53
-rw-r--r--src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java152
-rw-r--r--src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java166
-rw-r--r--src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java160
-rw-r--r--src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java75
-rw-r--r--src/test/resources/application.properties2
-rw-r--r--src/test/resources/certificates/client.p12bin0 -> 2685 bytes
-rw-r--r--src/test/resources/certificates/client.pass1
-rw-r--r--src/test/resources/certificates/client_invalid.pass1
-rw-r--r--src/test/resources/certificates/truststorebin0 -> 1455 bytes
-rw-r--r--src/test/resources/certificates/truststore.pass1
-rw-r--r--src/test/resources/certificates/truststore_invalid.pass1
-rw-r--r--src/test/resources/logback-test.xml55
-rw-r--r--src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json12
-rw-r--r--src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json1
-rw-r--r--src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json86
-rw-r--r--store/cert.p12bin0 -> 2685 bytes
-rw-r--r--store/p12.pass1
-rw-r--r--store/trust.jksbin0 -> 1455 bytes
-rw-r--r--store/truststore.pass1
-rw-r--r--templates/cmNotification.json32
-rw-r--r--templates/measurement.json44
-rw-r--r--templates/notification.json42
-rw-r--r--templates/notificationHttpServer.json52
-rw-r--r--templates/registration.json33
-rw-r--r--version.properties13
173 files changed, 12346 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..01974a7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+# Compiled class files
+*.class
+
+# Log files
+*.log
+
+# Environment configurations
+.classpath
+.project
+.settings
+.vscode
+.idea
+*.iml
+
+# folders
+target
+logs
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..ae26b36
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+FROM docker.io/openjdk:11-jre-slim
+COPY --from=python:3.6 / /
+
+ARG VERSION=${version}
+
+ADD target/libs /app/libs
+ADD config /opt/db/config
+ADD ./templates /app/templates
+ADD ./src/main/resources/application.properties /app/application.properties
+ADD target/vesclient-${VERSION}.jar /app/vesclient.jar
+CMD apk update
+CMD apk add ca-certificates
+RUN python -m pip install -r /opt/db/config/requirements.txt
+ADD certificates /usr/local/share/ca-certificates/
+RUN update-ca-certificates
+CMD python /opt/db/config/mongo_db_schema_creation.py \
+ && if [ -f /app/store/trust.pass ]; then cp /app/store/trust.pass /app/store/truststore.pass; fi \
+ && java -Dspring.config.location=file:/app/application.properties -cp /app/libs/*:/app/vesclient.jar org.onap.pnfsimulator.Main \
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b851bcb
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+all: start
+
+.PHONY: start
+
+start:
+ @echo "##### Start Ves client #####"
+ docker-compose up -d
+ @echo "##### DONE #####"
+
+stop:
+ @echo "##### Stop Ves client #####"
+ docker-compose down
+ @echo "##### DONE #####"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fffb368
--- /dev/null
+++ b/README.md
@@ -0,0 +1,436 @@
+# VES Client Simulator
+Simulator that generates VES events related to PNF PNP integration.
+
+## Usage of simulator
+### Setting up
+Preferred way to start simulator is to use `docker-compose up -d` command.
+All required docker images will be downloaded from ONAP Nexus, however there is a possibility to build those
+images locally. It can be achieved by invoking `mvn clean install -P docker` from top directory.
+
+### API
+Simulator provides REST endpoints which can be used to trigger sending events to VES.
+
+*Periodic event sending*
+To trigger sending use following endpoint *http://<simulator_ip>:5000/simulator/start*.
+Supported method: *POST*
+Headers:
+ - Content-Type - application/json
+Parameters:
+
+ simulatorParams:
+ repeatCount - determines how many events will be sent
+ repeatInterval - time (in seconds) between events
+ vesServerUrl - valid path to VES Collector
+ templateName - name of template file (check *Templates* section)
+ patch - part of event which will be merged into template
+ variables - correct json containing variables to merge with patched template
+
+
+Sample Request:
+
+ {
+ "simulatorParams": {
+ "repeatCount": 5,
+ "repeatInterval": 2,
+ "vesServerUrl": "http://VES-HOST:8080/eventListener/v7"
+ },
+ "templateName": "validExampleMeasurementEvent.json",
+ "patch": {
+ "event": {
+ "commonEventHeader": {
+ "eventId": "PATCHED_eventId",
+ "sourceName": "PATCHED_sourceName",
+ "version": 3.0
+ }
+ }
+ },
+ "variables": {
+ "dn":"Abcd",
+ "anyObject": {
+ "key": "value"
+ }
+ }
+ }
+
+*One-time event sending*
+Enables direct, immediate event sending without need to have template deployed on backend.
+Keywords are supported,thus once passed, will also be substituted with proper strings.
+Passed event body must be valid and complete event according to VES Collector interface.
+To trigger sending use following endpoint *http://<simulator_ip>:5000/simulator/event*.
+After sending event, response message from VES will be passed as response message from Simulator.
+Thanks to that when sending one-time event user will receive information about request.
+This is helpful when authentication fail or VES response with "Forbidden" when using http instead of https.
+In a situation when given URL address is not pointing to VES, Simulator response with status ```421```
+and information about communication problem.
+
+Supported method: *POST*
+Headers:
+ - Content-Type - application/json
+Parameters:
+
+ vesServerUrl - valid URL to VES Collector event listener
+ event - body of event to be sent directly to VES Collector (it can contain keyword expressions)
+
+
+Sample Request:
+
+ {
+ "vesServerUrl": "http://VES-HOST:8080/eventListener/v7",
+ "event": {
+ "commonEventHeader": {
+ "eventId": "#RandomString(20)",
+ "sourceName": "PATCHED_sourceName",
+ "version": 3.0
+ }
+ }
+ }
+
+### Changing simulator configuration
+Utility of default configuration has been introduced so as to facilitate sending requests. so far only vesServerUrl states default simulator configuration.
+On simulator startup, vesServerUrl is initialized with default value, but must be replaced with correct VES server url by user.
+Once vesServerUrl is properly set on simulator, this parameter does not need to be incorporated into every trigger event request.
+If user does not provide vesServerUrl in trigger request, default value will be used.
+If use does provide vesServerUrl in trigger request, then passed value will be used instead of default one (default value will not be overwritten by provided one).
+
+It is possible to get and update configuration (current target vesServerUrl) using offered REST API - */simulator/config* endpoint is exposed for that.
+To get current configuration *GET* method must be used.
+To update vesServerUrl *PUT* method is used, example request:
+
+ {
+ "vesServerUrl": "http://10.154.164.117:8080/eventListener/v7"
+ }
+
+Note: passed vesServerUrl must be wellformed URL.
+
+### Templates
+Template is a draft event. Merging event with patch will result in valid VES event. Template itself should be a correct VES event as well as valid json object.
+In order to apply custom template, just copy it to ./templates directory.
+*notification.json* and *registration.json* are available by default in *./templates* directory.
+
+#### Template management
+The simulator provides means for managing templates. Supported actions: adding, editing (overriding) and deleting are available via HTTP endpoint */template*
+
+```GET /template/list```
+Lists all templates known to the simulator.
+
+```GET /template/get/{name}```
+Gets template content based on *name* path variable.
+
+```POST /template/upload?override=true```
+Saves template content under *name* path variable. The non-mandatory parameter *override* allows overwriting an existing template.
+
+Sample payload:
+```
+{
+ "name": "someTemplate",
+ "template": {
+ "commonEventHeader": {
+ "domain": "notification",
+ "eventName": "vFirewallBroadcastPackets"
+ },
+ "notificationFields": {
+ "arrayOfNamedHashMap": [{
+ "name": "A20161221.1031-1041.bin.gz",
+ "hashMap": {
+ "fileformatType": "org.3GPP.32.435#measCollec"
+ }
+ }]
+ }
+ }
+}
+```
+
+### Searching for key-value conditions in stored templates
+Simulator allows to search through stored templates and retrieve names of those that satisfy given criteria passed in form of key-value pairs (See examples below).
+Following data types are supported in search as values:
+-integer
+-string
+-double
+-boolean
+Searching for null values as well as incorporating regex expression with intention to find a match is not supported.
+Search expression must be a valid JSON, thus no duplicated keys are allowed - user could specify the same parameter multiple times, but only last occurrence will be applied to query.
+Example search expression:
+
+{"domain": "notification", "sequence": 1, "startEpochMicrosec": 1531616794, "sampleDouble": 2.5}
+
+will find all templates that contain all of passed key-value entries. There is an AND condition beetwen given criteria - all of them must be satisfied to qualify template as matching item.
+ Keys of search expressions are searched in case insensitive way as well as string values.
+Where it comes to values of numerical and boolean type exact match is expected.
+
+API usage:
+
+```POST /template/search```
+Produces query that returns templates that contain searched criteria
+
+Sample payload:
+```
+{
+ "searchExpr": {
+ "domain": "notification",
+ "sequence": 1,
+ "startEpochMicrosec": 1531616794,
+ "sampleDouble": 2.5
+ }
+}
+```
+Sample response:
+```
+[notification.json]
+```
+
+
+Note: Manually deployed templates, or actually existing ones, but modified inside the templates catalog '/app/templates', will be automatically synchronized with schemas stored inside the database. That means that a user can dynamically change the template content using vi editor at simulator container, as well as use any editor at any machine and then push the changes to the template folder. All the changes will be processed 'on the fly' and accessible via the rest API.
+
+### Periodic events
+Simulator has ability to send event periodically. Rest API support parameters:
+* repeatCount - count of times that event will be sent to VES
+* repeatInterval - interval (in second) between two events.
+(Checkout example to see how to use them)
+
+### Patching
+User is able to provide patch in request, which will be merged into template.
+
+Warning: Patch should be a valid json object (no json primitives nor json arrays are allowed as a full body of patch).
+
+This mechanism allows to override part of template.
+If in "patch" section there are additional parameters (absent in template), those parameters with values will be added to event.
+Patching mechanism supports also keywords that enables automatic value generation of appropriate type
+
+### Keyword support
+Simulator supports corresponding keywords:
+- \#RandomInteger(start,end) - substitutes keyword with random positive integer within given range (range borders inclusive)
+- \#RandomPrimitiveInteger(start,end) - the same as #RandomInteger(start,end), but returns long as result
+- \#RandomInteger - substitutes keyword with random positive integer
+- \#RandomString(length) - substitutes keyword with random ASCII string with specified length
+- \#RandomString - substitutes keyword with random ASCII string with length of 20 characters
+- \#Timestamp - substitutes keyword with current timestamp in epoch (calculated just before sending event)
+- \#TimestampPrimitive - the same as \#Timestamp, but returns long as result
+- \#Increment - substitutes keyword with positive integer starting from 1 - for each consecutive event, value of increment property is incremented by 1
+
+Additional hints and restrictions:
+All keywords without 'Primitive' in name return string as result. To specify keyword with 2 arguments e.g. #RandomInteger(start,end) no whitespaces between arguments are allowed.
+Maximal value of arguments for RandomInteger is limited to the java integer range. Minimal is always 0. (Negative values are prohibited and wont be treated as a correct parts of keyword).
+RandomInteger with parameters will automatically find minimal and maximal value form the given attributes so no particular order of those is expected.
+
+How does it work?
+When user does't want to fill in parameter values that are not relevant from user perspective but are mandatory by end system, then keyword feature should be used.
+In template, keyword strings are substituted in runtime with appropriate values autogenerated by simulator.
+Example can be shown below:
+
+Example template with keywords:
+
+ {
+ "event": {
+ "commonEventHeader": {
+ "eventId": "123#RandomInteger(8,8)",
+ "eventType": "pnfRegistration",
+ "startEpochMicrosec": "#Timestamp",
+ "vesEventListenerVersion": "7.0.1",
+ "lastEpochMicrosec": 1539239592379
+ },
+ "pnfRegistrationFields": {
+ "pnfRegistrationFieldsVersion":"2.0",
+ "serialNumber": "#RandomString(7)",
+ "vendorName": "Nokia",
+ "oamV4IpAddress": "val3",
+ "oamV6IpAddress": "val4"
+ }
+ }
+ }
+
+Corresponding result of keyword substitution (event that will be sent):
+
+ {
+ "event": {
+ "commonEventHeader": {
+ "eventId": "1238",
+ "eventType": "pnfRegistration",
+ "startEpochMicrosec": "154046405117",
+ "vesEventListenerVersion": "7.0.1",
+ "lastEpochMicrosec": 1539239592379
+ },
+ "pnfRegistrationFields": {
+ "pnfRegistrationFieldsVersion":"2.0",
+ "serialNumber": "6061ZW3",
+ "vendorName": "Nokia",
+ "oamV4IpAddress": "val3",
+ "oamV6IpAddress": "val4"
+ }
+ }
+ }
+
+### In place variables support
+Simulator supports dynamic keywords e.g. #dN to automatically substitute selected phrases in defined json schema.
+Keywords have to be specified as separate json values, so no mixing keywords inside textual fields are acceptable. Current implementation
+supports placing variables in json templates as well as in patches latter sent as part of the requests.
+
+####Example:
+
+Request:
+```json
+{
+ "simulatorParams": {
+ "repeatCount": 1,
+ "repeatInterval": 1,
+ "vesServerUrl": "http://ves:5123"
+ },
+ "templateName": "cmNotification.json",
+ "patch": {},
+ "variables": {
+ "dN": "NRNB=5, NRCEL=1234",
+ "attributeList": {
+ "threshXHighQ": "50",
+ "threshXHighP": "52"
+ }
+ }
+}
+```
+
+cmNotification.json template is installed automatically after startup of the simulator but can be found also in repository in 'templates' folder:
+```json
+{
+ "event": {
+ "otherFields": {
+ "otherFieldsVersion": "3.0",
+ "jsonObjects": [
+ {
+ "objectName": "CustomNotification",
+ "objectInstances": [
+ {
+ "objectInstance": {
+ "cm3gppNotifyFields": {
+ "dN": "#dN",
+ "notificationType": "notifyMOIAttributeValueChange",
+ "notificationId": "notificationID123121312323",
+ "sourceIndicator": "sONOperation",
+ "eventTime": "#Timestamp",
+ "systemDN": "NRNB=5",
+ "attributeList": "#attributeList",
+ "correlatedNotifications": {
+ "notificationID-notifyMOIAttributeValueChange": "sONOperation"
+ },
+ "additionalText": "sometext",
+ "cm3gppNotifyFieldsVersion": "1.0"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
+```
+
+Expected output of such request (body of an event being send to a ves) should be as follows:
+```json
+{
+ "event": {
+ "otherFields": {
+ "otherFieldsVersion": "3.0",
+ "jsonObjects": [{
+ "objectName": "CustomNotification",
+ "objectInstances": [{
+ "objectInstance": {
+ "cm3gppNotifyFields": {
+ "dN": "NRNB=5, NRCEL=1234",
+ "notificationType": "notifyMOIAttributeValueChange",
+ "notificationId": "notificationID123121312323",
+ "sourceIndicator": "sONOperation",
+ "eventTime": "1571306716",
+ "systemDN": "NRNB=5",
+ "attributeList": {
+ "threshXHighQ": "50",
+ "threshXHighP": "52"
+ },
+ "correlatedNotifications": {
+ "notificationID-notifyMOIAttributeValueChange": "sONOperation"
+ },
+ "additionalText": "sometext",
+ "cm3gppNotifyFieldsVersion": "1.0"
+ }
+ }
+ }]
+ }]
+ }
+ }
+}
+```
+
+### Logging
+Every start of simulator will generate new logs that can be found in docker pnf-simualtor container under path:
+/var/log/ONAP/pnfsimulator/pnfsimulator_output.log
+
+### Swagger
+Detailed view of simulator REST API is available via Swagger UI
+Swagger UI is available on *http://<simulator_ip>:5000/swagger-ui.html*
+
+### History
+User is able to view events history.
+In order to browse history, go to *http://<simulator_ip>:8081/db/pnf_simulator/eventData*
+
+### TLS Support
+Simulator is able to communicate with VES using HTTPS protocol.
+CA certificates are incorporated into simulator docker image, thus no additional actions are required from user.
+
+Certificates can be found in docker container under path: */usr/local/share/ca-certificates/*
+
+Simulator works with VES that uses both self-signed certificate (already present in keystore) and VES integrated to AAF.
+
+Certification loading can be disabled by setting environment variable ```USE_CERTIFICATE_FOR_AUTHORIZATION``` to false.
+Once certificate are not used for authorization, user can set up VES url using username and password.
+
+ {
+ "vesServerUrl": "http://<user>:<password>@<ves_url>:<port>/eventListener/v7"
+ }
+
+## Developers Guide
+
+### Integration tests
+Integration tests are located in folder 'integration'. Tests are using docker-compose from root folder.
+This docker-compose has pnfsimulator image set on nexus3.onap.org:10003/onap/pnf-simulator:1.0.1-SNAPSHOT.
+To test your local changes before running integration tests please build project using:
+
+ 'mvn clean install -P docerk'
+
+then go to 'integration' folder and run:
+
+ 'mvn test'
+
+### Client certificate authentication
+Simulator can cooperate with VES server in different security types in particular ```auth.method=certBasicAuth``` which means that it needs to authenticate using client private certificate.
+
+Warning: according to VES implementation which uses certificate with Common Name set to DCAELOCAL we decided not to use strict hostname verification, so at least this parameter is skipped during checking of the client certificate.
+
+#### How to generate client correct keystore for pnf-simulator
+ The Root CA cert is available in certs folder in VES repository. The password for rootCA.key is collector.
+
+ The procedure of generating client's certificate:
+ 1. Generate a private key for the SSL client: ```openssl genrsa -out client.key 2048```
+ 2. Use the client’s private key to generate a cert request: ```openssl req -new -key client.key -out client.csr```
+ 3. Issue the client certificate using the cert request and the CA cert/key: ```openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 500 -sha256```
+ 4. Convert the client certificate and private key to pkcs#12 format: ```openssl pkcs12 -export -inkey client.key -in client.crt -out client.p12```
+ 5. Copy pkcs file into pnf simulators folder: ```/app/store/```
+
+#### How to generate correct truststore for pnf-simulator
+ Create truststore with rootCA.crt:
+ 1. ```keytool -import -file rootCA.crt -alias firstCA -keystore trustStore```
+ 2. Copy truststore to ```/app/store/```
+
+#### Testing keystore with real/mocked ves server
+```curl --cacert rootCA.crt --cert client.crt --key client.key https://VES_SECURED_URL -d "{}" -X POST -H "Content-type: application/json" -kv```
+
+#### How to refresh configuration of app
+Depending on your needs, you are able to change client certificate, replace trustStore to accept new server certificate change keystore and truststore passwords or completely disable client cert authentication.
+
+For this purpose:
+1. Go to the pnf simulator container into the /app folder.
+2. If you want to replace keystore or truststore put them into the /app/store folder.
+3. Edit /app/application.properties file as follow:
+- ssl.clientCertificateEnabled=true (to disable/enable client authentication)
+- ssl.strictHostnameVerification=true (to disable/enable hostname verification)
+- ssl.clientCertificatePath=/app/store/client.p12 (to replace with keystore file)
+- ssl.clientCertificatePasswordPath=/app/store/keystore.pass (to replace with keystore password file)
+- ssl.trustStorePath=/app/store/trustStore (to replace with truststore file)
+- ssl.trustStorePasswordPath=/app/store/truststore.pass (to replace with truststore password file)
+4. Refresh configuration by sending simple POST request to correct actuator endpoint at: ```curl http://localhost:5001/refresh -H 'Content-type: application/json' -X POST --data '{}'```
diff --git a/certificates/AAF_RootCA.crt b/certificates/AAF_RootCA.crt
new file mode 100644
index 0000000..e9a50d7
--- /dev/null
+++ b/certificates/AAF_RootCA.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFPjCCAyagAwIBAgIJAJ6u7cCnzrWdMA0GCSqGSIb3DQEBCwUAMCwxDjAMBgNV
+BAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJVUzAeFw0xODA0MDUx
+NDE1MjhaFw0zODAzMzExNDE1MjhaMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQK
+DARPTkFQMQswCQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAMA5pkgRs7NhGG4ew5JouhyYakgYUyFaG121+/h8qbSdt0hVQv56+EA41Yq7
+XGie7RYDQK9NmAFF3gruE+6X7wvJiChp+Cyd7sFMnb65uWhxEdxWTM2BJFrgfzUn
+H8ZCxgaCo3XH4PzlKRy2LQQJEJECwl/RZmRCXijMt5e9h8XoZY/fKkKcZZUsWNCM
+pTo266wjvA9MXLmdgReRj0+vrCjrNqy+htwJDztoiHWiYPqT6o8EvGcgjNqjlZx7
+NUNf8MfLDByqKF6+wRbHv1GKjn3/Vijd45Fv8riyRYROiFanvbV6jIfBkv8PZbXg
+2VDWsYsgp8NAvMxK+iV8cO+Ck3lBI2GOPZbCEqpPVTYbLUz6sczAlCXwQoPzDIZY
+wYa3eR/gYLY1gP2iEVHORag3bLPap9ZX5E8DZkzTNTjovvLk8KaCmfcaUMJsBtDd
+ApcUitz10cnRyZc1sX3gE1f3DpzQM6t9C5sOVyRhDcSrKqqwb9m0Ss04XAS9FsqM
+P3UWYQyqDXSxlUAYaX892u8mV1hxnt2gjb22RloXMM6TovM3sSrJS0wH+l1nznd6
+aFXftS/G4ZVIVZ/LfT1is4StoyPWZCwwwly1z8qJQ/zhip5NgZTxQw4mi7ww35DY
+PdAQOCoajfSvFjqslQ/cPRi/MRCu079heVb5fQnnzVtnpFQRAgMBAAGjYzBhMB0G
+A1UdDgQWBBRTVTPyS+vQUbHBeJrBKDF77+rtSTAfBgNVHSMEGDAWgBRTVTPyS+vQ
+UbHBeJrBKDF77+rtSTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAN
+BgkqhkiG9w0BAQsFAAOCAgEAPx/IaK94n02wPxpnYTy+LVLIxwdq/kawNd6IbiMz
+L87zmNMDmHcGbfoRCj8OkhuggX9Lx1/CkhpXimuYsZOFQi5blr/u+v4mIbsgbmi9
+7j+cUHDP0zLycvSvxKHty51LwmaX9a4wkJl5zBU4O1sd/H9tWcEmwJ39ltKoBKBx
+c94Zc3iMm5ytRWGj+0rKzLDAXEWpoZ5bE5PLJauA6UDCxDLfs3FwhbS7uDggxYvf
+jySF5FCNET94oJ+m8s7VeHvoa8iPGKvXrIqdd7XDHnqJJlVKr7m9S0fMbyEB8ci2
+RtOXDt93ifY1uhoEtEykn4dqBSp8ezvNMnwoXdYPDvTd9uCAFeWFLVreBAWxd25h
+PsBTkZA5hpa/rA+mKv6Af4VBViYr8cz4dZCsFChuioVebe9ighrfjB//qKepFjPF
+CyjzKN1u0JKm/2x/ORqxkTONG8p3uDwoIOyimUcTtTMv42bfYD88RKakqSFXE9G+
+Z0LlaKABqfjK49o/tsAp+c5LoNlYllKhnetO3QAdraHwdmC36BhoghzR1jpX751A
+cZn2VH3Q4XKyp01cJNCJIrua+A+bx6zh3RyW6zIIkbRCbET+UD+4mr8WIcSE3mtR
+ZVlnhUDO4z9//WKMVzwS9Rh8/kuszrGFI1KQozXCHLrce3YP6RYZfOed79LXaRwX
+dYY=
+-----END CERTIFICATE-----
diff --git a/certificates/dcaelocal.crt b/certificates/dcaelocal.crt
new file mode 100644
index 0000000..1be5a6f
--- /dev/null
+++ b/certificates/dcaelocal.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSDCCAjCgAwIBAgIEWAkZ5jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJV
+UzELMAkGA1UECBMCTkoxEzARBgNVBAcTCk1pZGRsZXRvd24xDTALBgNVBAoTBERD
+QUUxEjAQBgNVBAsTCU9QRU4tRENBRTESMBAGA1UEAxMJRENBRUxPQ0FMMB4XDTE2
+MTAyMDE5MjQyMloXDTE3MDExODE5MjQyMlowZjELMAkGA1UEBhMCVVMxCzAJBgNV
+BAgTAk5KMRMwEQYDVQQHEwpNaWRkbGV0b3duMQ0wCwYDVQQKEwREQ0FFMRIwEAYD
+VQQLEwlPUEVOLURDQUUxEjAQBgNVBAMTCURDQUVMT0NBTDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALoR0omXk1Xou3TdDydwhCF9V0ZSgQtMlMr8qYxe
+wLg/UGZbTea5HHqBmjWTVEKFGea7V7pnEiGWCPftIy/4D8ZSDaEQQ0WYCf6jNxeI
+T6PSiM+db/TwPToqPNMQwoftpsAEkJEJFB9rgUXoDD9FY5kUQW+fYOLyUeOb/rDE
+cRnSZX2qp1M/jAm1puIeNQcqiPExOMHqnN2bIgAZoHaFucdyOQUxuhIAgxoqe8Zt
+s451hm94g42F92I8KLy4EyOhXmSMjaLmgOqdjOPyBubOde4R39+6KAyQNGAnm5I4
+xq2J80R7qU0+4nnfjs2ScfAB/HUsWoVaGr9Ii4e34CW8JG8CAwEAATANBgkqhkiG
+9w0BAQUFAAOCAQEARqQmWg1gtwbgPbamWy0vdNWLQZm78y1ETR0ro9cazD25sD5/
+anDJ2RA97pGQFgncAI+Fzg4YygWBIext0OE92wQeKaHkxSujAe09F0wPcwc00Vyq
+NtBPcP17n18FkpFW1hkurlWiHOpGDRW2MmwhLj4lSFJmxMBAbzlfKrTBgj116UT+
+d4AGyuovS4LkmBWYFN//yoddGyrO26ar1M9ORdbDkjzOK4DkioTx3bwbdKPW7V4a
++Ns1KDFZ7FpjcWPZc6uDV4lBIhNUZuQZLy5hWBUeNhh4i2lL6xMrPzRa5kV1M7og
+ipv/ReVCixJqsGhx+8I4OPUbPoUYzRF+JmYUzA==
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/config/config.json b/config/config.json
new file mode 100644
index 0000000..af45632
--- /dev/null
+++ b/config/config.json
@@ -0,0 +1,9 @@
+{
+ "simulatorParams": {
+ "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7",
+ "repeatInterval": 10,
+ "repeatCount": 2
+ },
+ "templateName": "notification.json",
+ "patch": {}
+}
diff --git a/config/mongo_db_schema_creation.py b/config/mongo_db_schema_creation.py
new file mode 100644
index 0000000..3e79805
--- /dev/null
+++ b/config/mongo_db_schema_creation.py
@@ -0,0 +1,48 @@
+## ============LICENSE_START=======================================================
+## mongo_db_schema_creation
+## ================================================================================
+## Copyright (C) 2020 Nokia. All rights reserved.
+## ================================================================================
+## 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=========================================================
+
+from pymongo import MongoClient
+import argparse
+
+parser = argparse.ArgumentParser(description='Script creates configuration in pnf simulator mongodb if it doesn\'t exists.')
+args = parser.parse_args()
+
+MONGO_DB_PASSWORD = "zXcVbN123!"
+
+def create_db_with_user_permissions(client):
+ client.pnf_simulator.add_user( 'pnf_simulator_user', MONGO_DB_PASSWORD, roles= [{'role':'readWrite', 'db':'pnf_simulator'},{'role':'dbAdmin', 'db':'pnf_simulator'}])
+
+def init_mongo_db(client, col_list):
+ if 'simulatorConfig' not in col_list:
+ client.pnf_simulator.simulatorConfig.insert_one({"vesServerUrl": "https://dcae-ves-collector.onap:8443/eventListener/v7"})
+ if 'template' not in col_list:
+ client.pnf_simulator.create_collection('template')
+ if 'flatTemplatesView' not in col_list:
+ client.pnf_simulator.create_collection("flatTemplatesView", viewOn="template",pipeline=[{"$project":{"keyValues":{"$objectToArray": "$$ROOT.flatContent"}}}])
+
+
+if __name__ == "__main__":
+ client = MongoClient(host='mongo',
+ port=27017,
+ username='root',
+ password=MONGO_DB_PASSWORD,
+ authSource="admin")
+ col_list=client.pnf_simulator.list_collection_names()
+ create_db_with_user_permissions(client)
+ init_mongo_db(client, col_list)
+ print("Following colections are present in simualtor db: " , client.pnf_simulator.list_collection_names())
diff --git a/config/requirements.txt b/config/requirements.txt
new file mode 100644
index 0000000..12a7e47
--- /dev/null
+++ b/config/requirements.txt
@@ -0,0 +1 @@
+pymongo==3.11.0 \ No newline at end of file
diff --git a/db/pnf_simulator.js b/db/pnf_simulator.js
new file mode 100644
index 0000000..f5a03c3
--- /dev/null
+++ b/db/pnf_simulator.js
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+const res = [
+ db.createUser({ user: 'pnf_simulator_user', pwd: 'zXcVbN123!', roles: ['readWrite', 'dbAdmin'] }),
+ db.simulatorConfig.insert({"vesServerUrl": "http://xdcae-ves-collector.onap:8080/eventListener/v7"}),
+ db.createCollection("template"),
+ db.createView("flatTemplatesView", "template", [{"$project":{"keyValues":{"$objectToArray": "$$ROOT.flatContent"}}}])
+];
+
+printjson(res);
diff --git a/deployment/PnP_PNF_sim_heat_template.yml b/deployment/PnP_PNF_sim_heat_template.yml
new file mode 100644
index 0000000..6f9b5f0
--- /dev/null
+++ b/deployment/PnP_PNF_sim_heat_template.yml
@@ -0,0 +1,118 @@
+description: Heat template that deploys PnP PNF simulator
+heat_template_version: '2013-05-23'
+parameters:
+ flavor_name: {description: Type of instance (flavor) to be used, label: Flavor,
+ type: string}
+ image_name: {description: Image to be used for compute instance, label: Image name
+ or ID, type: string}
+ key_name: {description: Public/Private key pair name, label: Key pair name, type: string}
+ public_net_id: {description: Public network that enables remote connection to VNF,
+ label: Public network name or ID, type: string}
+ private_net_id: {type: string, description: Private network id, label: Private network name or ID}
+ private_subnet_id: {type: string, description: Private subnet id, label: Private subnetwork name or ID}
+ proxy: {type: string, description: Proxy, label: Proxy, default: ""}
+resources:
+ PNF_PnP_simualtor:
+ type: OS::Nova::Server
+ properties:
+ key_name: { get_param: key_name }
+ image: { get_param: image_name }
+ flavor: { get_param: flavor_name }
+ networks:
+ - port: { get_resource: PNF_PnP_simualtor_port0 }
+ user_data_format: RAW
+ user_data:
+ str_replace:
+ template: |
+ #!/bin/bash
+
+ set_versions () {
+ DOCKER_COMPOSE_VERSION=1.22.0
+ }
+
+
+ enable_root_ssh () {
+ sed -i 's/PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
+ sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
+ service sshd restart
+ echo -e "arthur\narthur" | passwd root
+ }
+
+ update_os () {
+ dnf -y install fedora-upgrade
+ }
+
+ docker_remove () {
+ dnf -y remove docker \
+ docker-client \
+ docker-client-latest \
+ docker-common \
+ docker-latest \
+ docker-latest-logrotate \
+ docker-logrotate \
+ docker-selinux \
+ docker-engine-selinux \
+ docker-engine
+ }
+
+ docker_install_and_configure () {
+ dnf -y install dnf-plugins-core
+ dnf config-manager \
+ --add-repo \
+ https://download.docker.com/linux/fedora/docker-ce.repo
+ dnf -y install docker-ce
+ systemctl start docker
+ mkdir -p /etc/systemd/system/docker.service.d/
+ cat > /etc/systemd/system/docker.service.d/override.conf<< EOF
+ [Service]
+ Environment="HTTP_PROXY=$proxy"
+ Environment="HTTPS_PROXY=$proxy"
+ EOF
+ systemctl daemon-reload
+ systemctl restart docker
+ }
+ docker_compose_install () {
+ curl -L https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
+ chmod +x /usr/local/bin/docker-compose
+ }
+ pnf_sim_file_checkout () {
+ cd /root; git clone https://gerrit.onap.org/r/integration
+ printf "{\n "simulatorParams": {\n "vesServerUrl": "http://VES-HOST:VES-PORT/eventListener/v7",\n "testDuration": "10",\n "messageInterval": "1"\n },\n "commonEventHeaderParams": {\n "eventName": "pnfRegistration_Nokia_5gDu",\n "nfNamingCode": "gNB",\n "nfcNamingCode": "oam",\n "sourceName": "NOK6061ZW3",\n "sourceId": "val13",\n "reportingEntityName": "NOK6061ZW3"\n },\n "pnfRegistrationParams": {\n "serialNumber": "6061ZW3",\n "vendorName": "Nokia",\n "oamV4IpAddress": "val3",\n "oamV6IpAddress": "val4",\n "unitFamily": "BBU",\n "modelNumber": "val6",\n "softwareVersion": "val7",\n "unitType": "val8"\n }\n}" > integration/test/mocks/pnfsimulator/config/config.json
+ }
+
+ start_simulator () {
+ docker login -u docker -p docker nexus3.onap.org:10003
+ cd ~/integration/test/mocks/pnfsimulator
+ ./simulator.sh start
+ }
+
+ set_versions
+ enable_root_ssh
+ update_os
+ docker_remove
+ docker_install_and_configure
+ docker_compose_install
+ pnf_sim_file_checkout
+ start_simulator
+ params:
+ $proxy: { get_param: proxy }
+ PNF_PnP_simualtor_port0:
+ type: OS::Neutron::Port
+ properties:
+ network_id: { get_param: private_net_id }
+ security_groups:
+ - default
+ fixed_ips:
+ - subnet_id: { get_param: private_subnet_id }
+ PNF_PnP_simualtor_public:
+ type: OS::Neutron::FloatingIP
+ properties:
+ floating_network_id: { get_param: public_net_id }
+ port_id: { get_resource: PNF_PnP_simualtor_port0 }
+outputs:
+ PNF_PnP_simualtor_private_ip:
+ description: IP address of PNF_PnP_simualtor in private network
+ value: { get_attr: [ PNF_PnP_simualtor, first_address ] }
+ PNF_PnP_simualtor_public_ip:
+ description: Floating IP address of PNF_PnP_simualtor in public network
+ value: { get_attr: [ PNF_PnP_simualtor_public, floating_ip_address ] }
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..2e1f3b7
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,40 @@
+version: '3'
+
+services:
+
+ mongo:
+ image: mongo
+ restart: always
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: zXcVbN123!
+ MONGO_INITDB_DATABASE: pnf_simulator
+ volumes:
+ - ./db:/docker-entrypoint-initdb.d
+ ports:
+ - "27017:27017"
+
+ mongo-express:
+ image: mongo-express
+ restart: always
+ ports:
+ - "8081:8081"
+ environment:
+ ME_CONFIG_MONGODB_ADMINUSERNAME: root
+ ME_CONFIG_MONGODB_ADMINPASSWORD: zXcVbN123!
+
+ pnf-simulator:
+ image: onap/org.onap.integration.nfsimulator.vesclient
+ ports:
+ - "5000:5000"
+ environment:
+ USE_CERTIFICATE_FOR_AUTHORIZATION: "true"
+ volumes:
+ - ./logs:/var/log
+ - ./templates:/app/templates
+ - ./store:/app/store
+ - ./src/main/resources/application.properties:/app/application.properties
+ restart: on-failure
+ depends_on:
+ - mongo
+ - mongo-express
diff --git a/integration/pom.xml b/integration/pom.xml
new file mode 100644
index 0000000..e56d838
--- /dev/null
+++ b/integration/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. All rights reserved.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.integration.nfsimulator</groupId>
+ <artifactId>vesclient</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>pnf-simulator-integration</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <name>vesclient-integration</name>
+
+ <repositories>
+ <repository>
+ <id>dl.bintray.com</id>
+ <url>https://dl.bintray.com/palantir/releases</url>
+ </repository>
+ </repositories>
+
+ <properties>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <rest-assured.version>3.2.0</rest-assured.version>
+ <mongo-java-driver.version>3.9.1</mongo-java-driver.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <version>${rest-assured.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ <version>${mongo-java-driver.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.palantir.docker.compose</groupId>
+ <artifactId>docker-compose-rule-junit4</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <executions>
+ <execution>
+ <id>onap-license</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>onap-java-style</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.17</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <!--Execute only suites from the test folder-->
+ <include>**/*Suite.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java b/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java
new file mode 100644
index 0000000..7288c2a
--- /dev/null
+++ b/integration/src/main/java/org/onap/pnfsimulator/integration/Main.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@SpringBootApplication
+@EnableAsync
+public class Main {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Main.class, args);
+ }
+}
+
+
diff --git a/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java
new file mode 100644
index 0000000..304df60
--- /dev/null
+++ b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorController.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RequestMapping("ves-simulator")
+@RestController
+public class VesSimulatorController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(VesSimulatorController.class);
+ private final VesSimulatorService vesSimulatorService;
+ private final Gson gson;
+ private final ResponseEntity<String> response = ResponseEntity
+ .status(HttpStatus.ACCEPTED)
+ .body("Accepted");
+
+ @Autowired
+ public VesSimulatorController(VesSimulatorService vesSimulatorService, Gson gson) {
+ this.vesSimulatorService = vesSimulatorService;
+ this.gson = gson;
+ }
+
+ @PostMapping("eventListener/v5")
+ public ResponseEntity<String> sendEventToDmaapV5(@RequestBody String body) {
+ JsonObject jsonObject = getJsonObjectFromBody(body);
+ vesSimulatorService.sendEventToDmaapV5(jsonObject);
+ return response;
+ }
+
+ @PostMapping("eventListener/v7")
+ public ResponseEntity<String> sendEventToDmaapV7(@RequestBody String body) {
+ JsonObject jsonObject = getJsonObjectFromBody(body);
+ vesSimulatorService.sendEventToDmaapV7(jsonObject);
+ return response;
+ }
+
+ private JsonObject getJsonObjectFromBody(@RequestBody String body) {
+ LOGGER.info(String.format("Received event: %s", body));
+ return gson.fromJson(body, JsonObject.class);
+ }
+}
diff --git a/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java
new file mode 100644
index 0000000..65e5d3e
--- /dev/null
+++ b/integration/src/main/java/org/onap/pnfsimulator/integration/VesSimulatorService.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import com.google.gson.JsonObject;
+import org.springframework.stereotype.Service;
+
+@Service
+public class VesSimulatorService {
+
+ void sendEventToDmaapV5(JsonObject jsonObject) {
+ //JUST FOR TESTING PURPOSE
+ }
+
+ void sendEventToDmaapV7(JsonObject jsonObject) {
+ //JUST FOR TESTING PURPOSE
+ }
+}
diff --git a/integration/src/main/resources/application.properties b/integration/src/main/resources/application.properties
new file mode 100644
index 0000000..205ed95
--- /dev/null
+++ b/integration/src/main/resources/application.properties
@@ -0,0 +1 @@
+server.port=8000 \ No newline at end of file
diff --git a/integration/src/main/resources/keystore b/integration/src/main/resources/keystore
new file mode 100644
index 0000000..26a16f7
--- /dev/null
+++ b/integration/src/main/resources/keystore
Binary files differ
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java
new file mode 100644
index 0000000..323243c
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/BasicAvailabilityTest.java
@@ -0,0 +1,234 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import static io.restassured.RestAssured.given;
+import static io.restassured.RestAssured.when;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
+
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.UUID;
+
+import io.restassured.response.Response;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.internal.util.Timer;
+import org.mockito.internal.verification.VerificationOverTimeImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT)
+public class BasicAvailabilityTest {
+
+ private static final int VERIFICATION_TIMEOUT_MILLIS = 10000;
+
+ @Autowired
+ VesSimulatorController vesSimulatorController;
+
+ @Autowired
+ VesSimulatorService vesSimulatorService;
+
+ private final String ACTION_START = "start";
+
+ private String currenVesSimulatorIp;
+
+ @Before
+ public void setUp() throws Exception {
+ currenVesSimulatorIp = getCurrentIpAddress();
+ }
+
+ @After
+ public void tearDown() {
+ Mockito.reset(vesSimulatorService);
+ }
+
+ @Test
+ public void simulatorShouldFailWhenTriggeredNonexistentTemplate() {
+ //given
+ String startUrl = prepareRequestUrl(ACTION_START);
+ String body = "{\n"
+ + "\"templateName\": \"any_nonexistent_template.json\",\n"
+ + "\"patch\":{},\n"
+ + "\"simulatorParams\": {\n"
+ + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"repeatInterval\": 1,\n"
+ + "\"repeatCount\": 1\n"
+ + "}\n"
+ + "}";
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(startUrl)
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST.value())
+ .body("message", equalTo("Cannot start simulator - template any_nonexistent_template.json not found."));
+ }
+
+ @Test
+ public void whenTriggeredSimulatorShouldSendSingleEventToVes() {
+ //given
+ String startUrl = prepareRequestUrl(ACTION_START);
+ String body = "{\n"
+ + "\"templateName\": \"notification.json\",\n"
+ + "\"patch\":{},\n"
+ + "\"simulatorParams\": {\n"
+ + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"repeatInterval\": 1,\n"
+ + "\"repeatCount\": 1\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(startUrl)
+ .then()
+ .statusCode(HttpStatus.OK.value())
+ .body("message", equalTo("Request started"));
+
+ Mockito.verify(vesSimulatorService,
+ Mockito.timeout(VERIFICATION_TIMEOUT_MILLIS))
+ .sendEventToDmaapV5(parameterCaptor.capture());
+
+ assertThat(parameterCaptor.getValue()
+ .getAsJsonObject("event")
+ .getAsJsonObject("commonEventHeader")
+ .get("domain").getAsString()).isEqualTo("notification");
+ }
+
+ @Test
+ public void simulatorShouldCorrectlyRespondOnCancellAllEvent() {
+ //given
+ String ACTION_CANCEL_ALL = "cancel";
+ String cancelAllUrl = prepareRequestUrl(ACTION_CANCEL_ALL);
+
+ //when
+ when()
+ .post(cancelAllUrl)
+ .then()
+ .statusCode(HttpStatus.OK.value())
+ .body("message", equalTo("Event(s) was cancelled"));
+
+ }
+
+ @Test
+ public void simulatorBeAbleToUseNewlyAddedTemplate() throws IOException {
+ //given
+ String templateBody = "{\"fake\":\"template\"}\n";
+ String fileName = UUID.randomUUID() + ".json";
+ String requestBody = "{\n"
+ + "\"templateName\": \"" + fileName + "\",\n"
+ + "\"patch\":{},\n"
+ + "\"simulatorParams\": {\n"
+ + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"repeatInterval\": 1,\n"
+ + "\"repeatCount\": 1\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ Path newFile = Files.createFile(Paths.get("..", "templates", fileName));
+ Files.write(newFile, templateBody.getBytes());
+
+ Response postResponse = given()
+ .contentType("application/json")
+ .body(requestBody)
+ .when()
+ .post(prepareRequestUrl(ACTION_START));
+
+ Files.delete(newFile);
+
+ //then
+ assertThat(postResponse.statusCode()).isEqualTo(HttpStatus.OK.value());
+ Mockito.verify(vesSimulatorService, Mockito.timeout(VERIFICATION_TIMEOUT_MILLIS))
+ .sendEventToDmaapV5(parameterCaptor.capture());
+ assertThat(parameterCaptor.getValue()
+ .get("fake").getAsString()).isEqualTo("template");
+
+ }
+
+ @Test
+ public void whenTriggeredSimulatorShouldSendGivenAmountOfEventsToVes() {
+ //given
+ String startUrl = prepareRequestUrl(ACTION_START);
+ String body = "{\n"
+ + "\"templateName\": \"notification.json\",\n"
+ + "\"patch\":{},\n"
+ + "\"simulatorParams\": {\n"
+ + "\"vesServerUrl\": \"https://" + currenVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"repeatInterval\": 1,\n"
+ + "\"repeatCount\": 4\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(startUrl)
+ .then()
+ .statusCode(HttpStatus.OK.value())
+ .body("message", equalTo("Request started"));
+
+ VerificationOverTimeImpl verificator = new VerificationOverTimeImpl(100, Mockito.times(4), false, new Timer(6000));
+ Mockito.verify(vesSimulatorService, verificator).sendEventToDmaapV5(parameterCaptor.capture());
+
+ for (JsonObject value : parameterCaptor.getAllValues()) {
+ assertThat(value
+ .getAsJsonObject("event")
+ .getAsJsonObject("commonEventHeader")
+ .get("domain").getAsString()).isEqualTo("notification");
+ }
+ }
+
+ private String prepareRequestUrl(String action) {
+ return "http://0.0.0.0:5000/simulator/" + action;
+ }
+
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java
new file mode 100644
index 0000000..50ad1cd
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/OptionalTemplatesTest.java
@@ -0,0 +1,161 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.onap.pnfsimulator.integration.TestUtils.COMMON_EVENT_HEADER;
+import static org.onap.pnfsimulator.integration.TestUtils.PATCHED;
+import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL;
+import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
+
+import com.google.gson.JsonObject;
+import java.time.Instant;
+import java.net.UnknownHostException;
+
+import org.assertj.core.api.Assertions;
+import org.bson.Document;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT)
+public class OptionalTemplatesTest {
+
+ @Autowired
+ private VesSimulatorService vesSimulatorService;
+
+ private String currentVesSimulatorIp;
+
+ @Before
+ public void setUp() throws Exception {
+ currentVesSimulatorIp = getCurrentIpAddress();
+ }
+
+ @After
+ public void tearDown() {
+ Mockito.reset(vesSimulatorService);
+ }
+
+ @Test
+ public void whenTriggeredSimulatorWithoutTemplateShouldSendSingleEventToVes() {
+ //given
+ long currentTimestamp = Instant.now().getEpochSecond();
+
+ String body = "{\n"
+ + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"event\": { \n"
+ + "\"commonEventHeader\": {\n"
+ + "\"eventId1\": \"#RandomString(20)\",\n"
+ + "\"eventId2\": \"#RandomInteger(10,10)\",\n"
+ + "\"eventId3\": \"#Increment\",\n"
+ + "\"eventId4\": \"#RandomPrimitiveInteger(10,10)\",\n"
+ + "\"eventId5\": \"#TimestampPrimitive\",\n"
+ + "\"sourceName\": \"Single_sourceName\",\n"
+ + "\"version\": 3"
+ + "}\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(SINGLE_EVENT_URL)
+ .then()
+ .statusCode(HttpStatus.ACCEPTED.value())
+ .body("message", equalTo("Accepted"));
+
+ //then
+ long afterExecution = Instant.now().getEpochSecond();
+ Mockito.verify(vesSimulatorService,
+ Mockito.timeout(3000))
+ .sendEventToDmaapV5(parameterCaptor.capture());
+
+ JsonObject value = parameterCaptor.getValue();
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("sourceName").getAsString()).isEqualTo("Single_sourceName");
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("eventId1").getAsString()).hasSize(20);
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("eventId2").getAsString()).isEqualTo("10");
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("eventId3").getAsString()).isEqualTo("1");
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("eventId4").getAsInt()).isEqualTo(10);
+ assertThat(value
+ .getAsJsonObject(COMMON_EVENT_HEADER)
+ .get("eventId5").getAsLong()).isBetween(currentTimestamp, afterExecution);
+ }
+
+ @Test
+ public void whenTriggeredSimulatorWithoutTemplateEventShouldBeVisibleInDB() throws UnknownHostException {
+ //given
+ String body = "{\n"
+ + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"event\": { \n"
+ + "\"commonEventHeader\": {\n"
+ + "\"sourceName\": \"HistoricalEvent\",\n"
+ + "\"version\": 3"
+ + "}\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(SINGLE_EVENT_URL)
+ .then()
+ .statusCode(HttpStatus.ACCEPTED.value())
+ .body("message", equalTo("Accepted"));
+
+ //then
+ Mockito.verify(vesSimulatorService,
+ Mockito.timeout(3000))
+ .sendEventToDmaapV5(parameterCaptor.capture());
+
+ Document sourceNameInMongoDB = findSourceNameInMongoDB();
+ Assertions.assertThat(sourceNameInMongoDB.get(PATCHED))
+ .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}");
+ }
+
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java
new file mode 100644
index 0000000..9d4ff3b
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/SearchInTemplatesTest.java
@@ -0,0 +1,269 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import static io.restassured.RestAssured.given;
+import static java.nio.file.Files.readAllBytes;
+
+import io.restassured.http.Header;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.hamcrest.Matchers;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.util.ResourceUtils;
+
+public class SearchInTemplatesTest {
+
+ private static final String UPLOAD = "upload";
+ private static final String SEARCH = "search";
+ private static final String APPLICATION_JSON = "application/json";
+ private static final String CONTENT_TYPE = "Content-Type";
+
+ @BeforeClass
+ public static void setUp() throws IOException {
+ for (File file : readFileFromTemplatesFolder()) {
+ byte[] body = readAllBytes(file.toPath());
+
+ given()
+ .body(body)
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(UPLOAD) + "?override=true")
+ .then()
+ .statusCode(201);
+ }
+ }
+
+ @Test
+ public void shouldFindNothingWhenNonexistentValueIsProvided(){
+ given()
+ .body("{\"searchExpr\": { \"child3\": \"nonexistentValue\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.empty());
+ }
+
+ @Test
+ public void shouldFindNothingWhenNonexistentKeyIsProvided(){
+ given()
+ .body("{\"searchExpr\": { \"nonexistentKey\": \"Any value 1\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.empty());
+ }
+
+ @Test
+ public void shouldFindNothingWhenPartOfKeyIsProvided(){
+ given()
+ .body("{\"searchExpr\": { \"child\": \"Any value 1\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.empty());
+ }
+
+ @Test
+ public void shouldFindNothingWhenPartOfValueIsProvided(){
+ given()
+ .body("{\"searchExpr\": { \"child5\": \"Any\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.empty());
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForString(){
+ given()
+ .body("{\"searchExpr\": { \"child1\": \"Any value 1\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json", "complicated_template.json", "simple_template.json"));
+
+ given()
+ .body("{\"searchExpr\": { \"child2\": \"any value 4\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForManyStrings(){
+ given()
+ .body("{\"searchExpr\": { \"child1\": \"Any value 1\", \"child2\": \"any value 2\"}}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("simple_template.json", "complicated_template.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForStarSign(){
+ given()
+ .body("{\"searchExpr\": { \"child2\": \"*\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("complicated_template.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForQuestionMark(){
+ given()
+ .body("{\"searchExpr\": { \"child1\": \"?\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("complicated_template.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForBrackets(){
+ given()
+ .body("{\"searchExpr\": { \"parent2\": \"[]\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json"));
+ }
+
+ @Test
+ public void shouldInformThatSearchForNullsIsProhibited(){
+ given()
+ .body("{\"searchExpr\": { \"child3\": null }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForURI(){
+ given()
+ .body("{\"searchExpr\": { \"child3\": \"https://url.com?param1=test&param2=*\" }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("complicated_template.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForFloats(){
+ given()
+ .body("{\"searchExpr\": { \"child2\": 4.44 }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json"));
+
+ given()
+ .body("{\"searchExpr\": { \"child5\": 4.4 }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("complicated_template.json", "template_with_floats.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForIntegers(){
+ given()
+ .body("{\"searchExpr\": { \"child2\": 1 }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json", "template_with_ints.json"));
+
+ given()
+ .body("{\"searchExpr\": { \"child2\": 4 }}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_array.json"));
+ }
+
+ @Test
+ public void shouldBeAbleToSearchForBooleans(){
+ given()
+ .body("{\"searchExpr\": { \"child4\": true}}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_booleans.json"));
+
+ given()
+ .body("{\"searchExpr\": { \"parent2\": false}}")
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(SEARCH))
+ .then()
+ .statusCode(200)
+ .body("", Matchers.hasItems("template_with_booleans.json"));
+ }
+
+
+ private static String prepareRequestUrl(String action) {
+ return "http://0.0.0.0:5000/template/" + action;
+ }
+
+ private static File[] readFileFromTemplatesFolder() throws FileNotFoundException {
+ return ResourceUtils.getFile("classpath:templates/search").listFiles();
+ }
+
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java
new file mode 100644
index 0000000..3ad1385
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/SingleEventTest.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import com.google.gson.JsonObject;
+import org.assertj.core.api.Assertions;
+import org.bson.Document;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.net.UnknownHostException;
+import java.util.List;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.stringContainsInOrder;
+import static org.onap.pnfsimulator.integration.TestUtils.PATCHED;
+import static org.onap.pnfsimulator.integration.TestUtils.SINGLE_EVENT_URL;
+import static org.onap.pnfsimulator.integration.TestUtils.findSourceNameInMongoDB;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+public class SingleEventTest {
+
+ @Autowired
+ private VesSimulatorService vesSimulatorService;
+
+ private String currentVesSimulatorIp;
+
+ @Before
+ public void setUp() throws Exception {
+ currentVesSimulatorIp = getCurrentIpAddress();
+ }
+
+ @After
+ public void tearDown() {
+ Mockito.reset(vesSimulatorService);
+ }
+
+ @Test
+ public void whenTriggeredSimulatorWithWrongVesAddressInformationShouldBeReturned() {
+ //given
+ String body = "{\n"
+ + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":8080/ves-simulator/eventListener/v5\",\n"
+ + "\"event\": { \n"
+ + "\"commonEventHeader\": {\n"
+ + "\"sourceName\": \"HistoricalEvent\",\n"
+ + "\"version\": 3"
+ + "}\n"
+ + "}\n"
+ + "}";
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(SINGLE_EVENT_URL)
+ .then()
+ .statusCode(421)
+ .body("message",
+ equalTo(
+ "Fail to connect with ves: Connect to "+currentVesSimulatorIp+":8080 " +
+ "[/"+currentVesSimulatorIp+"] " +
+ "failed: Connection refused (Connection refused)"));
+ }
+
+ @Test
+ public void whenTriggeredSimulatorWithWrongEventShouldReturnedError() {
+ //given
+ String body = "{\n"
+ + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"event\": { \n"
+ + "this is not JSON {}"
+ + "}\n"
+ + "}";
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(SINGLE_EVENT_URL)
+ .then()
+ .statusCode(HttpStatus.BAD_REQUEST.value())
+ .body("message",
+ stringContainsInOrder(List.of("JSON parse error:","Unexpected character ('t' (code 116)):"))
+ );
+ }
+
+ @Test
+ public void whenTriggeredSimulatorWithUsernameAndPasswordInUrlVesShouldAcceptRequest() throws UnknownHostException {
+ //given
+ String body = "{\n"
+ + "\"vesServerUrl\": \"https://user1:pass1@" + currentVesSimulatorIp + ":9443/ves-simulator/eventListener/v5\",\n"
+ + "\"event\": { \n"
+ + "\"commonEventHeader\": {\n"
+ + "\"sourceName\": \"HistoricalEvent\",\n"
+ + "\"version\": 3"
+ + "}\n"
+ + "}\n"
+ + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ //when
+ given()
+ .contentType("application/json")
+ .body(body)
+ .when()
+ .post(SINGLE_EVENT_URL)
+ .then()
+ .statusCode(HttpStatus.ACCEPTED.value())
+ .body("message", equalTo("Accepted"));
+
+ //then
+ Mockito.verify(vesSimulatorService,
+ Mockito.timeout(3000))
+ .sendEventToDmaapV5(parameterCaptor.capture());
+
+ Document sourceNameInMongoDB = findSourceNameInMongoDB();
+ Assertions.assertThat(sourceNameInMongoDB.get(PATCHED))
+ .isEqualTo("{\"commonEventHeader\":{\"sourceName\":\"HistoricalEvent\",\"version\":3}}");
+ }
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java
new file mode 100644
index 0000000..7e74dd4
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/TemplatesManagementTest.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import static io.restassured.RestAssured.given;
+
+import io.restassured.http.Header;
+import io.restassured.path.json.JsonPath;
+import io.restassured.path.json.config.JsonPathConfig;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import org.hamcrest.Matchers;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.util.ResourceUtils;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class}, webEnvironment = WebEnvironment.DEFINED_PORT)
+public class TemplatesManagementTest {
+
+ private static final String LIST_URL = "list";
+ private static final String GET_URL = "get/";
+ private static final String UPLOAD = "upload";
+ private static final String NOTIFICATION_JSON = "notification.json";
+ private static final String REGISTRATION_JSON = "registration.json";
+ private static final String UPLOAD_TEMPLATE_JSON = "upload_template.json";
+ private static final String OVERWRITE_TEMPLATE_JSON = "overwrite_template.json";
+ private static final String OVERWRITTEN_TEMPLATE_JSON = "overwritten_template.json";
+ private static final String APPLICATION_JSON = "application/json";
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String FORCE_FLAG = "?override=true";
+ private static final String CONTENT = "content";
+ private static final String TEMPLATE = "template";
+ private static final String ID = "id";
+
+ @Test
+ public void whenCallingGetShouldReceiveNotificationTemplate() throws IOException {
+ given()
+ .when()
+ .get(prepareRequestUrl(GET_URL) + NOTIFICATION_JSON)
+ .then()
+ .statusCode(200)
+ .body(ID, Matchers.equalTo(NOTIFICATION_JSON))
+ .body(CONTENT, Matchers.equalTo(readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT)));
+ }
+
+ @Test
+ public void whenCallingGetShouldReceiveRegistrationTemplate() throws IOException {
+ given()
+ .when()
+ .get(prepareRequestUrl(GET_URL) + REGISTRATION_JSON)
+ .then()
+ .statusCode(200)
+ .body(ID, Matchers.equalTo(REGISTRATION_JSON))
+ .body(CONTENT, Matchers.equalTo(readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT)));
+ }
+
+ @Test
+ public void whenCallingListShouldReceiveAllPredefinedTemplates() throws IOException {
+ Map<Object, Object> registration = readTemplateFromResources(REGISTRATION_JSON).getMap(CONTENT);
+ Map<Object, Object> notification = readTemplateFromResources(NOTIFICATION_JSON).getMap(CONTENT);
+
+ given()
+ .when()
+ .get(prepareRequestUrl(LIST_URL))
+ .then()
+ .statusCode(200)
+ .body(CONTENT, Matchers.<Map>hasItems(
+ registration,
+ notification
+ ));
+ }
+
+ @Test
+ public void whenCallingUploadAndGetShouldReceiveNewTemplate() throws IOException {
+ byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(UPLOAD_TEMPLATE_JSON));
+
+ given()
+ .body(body)
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(UPLOAD))
+ .then()
+ .statusCode(201);
+
+ given()
+ .when()
+ .get(prepareRequestUrl(GET_URL) + UPLOAD_TEMPLATE_JSON)
+ .then()
+ .statusCode(200)
+ .body(ID, Matchers.equalTo(UPLOAD_TEMPLATE_JSON))
+ .body(CONTENT, Matchers.equalTo(readTemplateFromResources(UPLOAD_TEMPLATE_JSON).getMap(TEMPLATE)));
+ }
+
+ @Test
+ public void whenCallingOverrideAndGetShouldReceiveNewTemplate() throws IOException, JSONException {
+ byte[] body = Files.readAllBytes(readFileFromTemplatesFolder(OVERWRITE_TEMPLATE_JSON));
+
+ given()
+ .body(body)
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(UPLOAD))
+ .then()
+ .statusCode(201);
+
+ JSONObject overwrittenBody = new JSONObject(new String(body));
+ JSONObject overwrittenTemplate = new JSONObject("{\"field1\": \"overwritten_field1\"}");
+ overwrittenBody.put(TEMPLATE, overwrittenTemplate);
+
+ given()
+ .body(overwrittenBody.toString().getBytes())
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(UPLOAD))
+ .then()
+ .statusCode(409);
+
+ given()
+ .body(overwrittenBody.toString().getBytes())
+ .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
+ .when()
+ .post(prepareRequestUrl(UPLOAD + FORCE_FLAG))
+ .then()
+ .statusCode(201);
+
+ given()
+ .when()
+ .get(prepareRequestUrl(GET_URL) + OVERWRITE_TEMPLATE_JSON)
+ .then()
+ .statusCode(200)
+ .body(ID, Matchers.equalTo(OVERWRITE_TEMPLATE_JSON))
+ .body(CONTENT, Matchers.equalTo(readTemplateFromResources(OVERWRITTEN_TEMPLATE_JSON).getMap(CONTENT)));
+ }
+
+ private String prepareRequestUrl(String action) {
+ return "http://0.0.0.0:5000/template/" + action;
+ }
+
+ private JsonPath readTemplateFromResources(String templateName) throws IOException {
+ byte[] content = Files.readAllBytes(readFileFromTemplatesFolder(templateName));
+ return new JsonPath(new String(content)).using(new JsonPathConfig("UTF-8"));
+ }
+
+ private Path readFileFromTemplatesFolder(String templateName) throws FileNotFoundException {
+ return ResourceUtils.getFile("classpath:templates/"+templateName).toPath();
+ }
+
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java
new file mode 100644
index 0000000..19ae050
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/TestConfiguration.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration;
+
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+@Configuration
+public class TestConfiguration {
+
+ @Bean
+ @Primary
+ VesSimulatorService provideVesSimulatorService() {
+ return Mockito.mock(VesSimulatorService.class);
+ }
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java b/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java
new file mode 100644
index 0000000..f7df5e9
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/TestUtils.java
@@ -0,0 +1,57 @@
+package org.onap.pnfsimulator.integration;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoCursor;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+import java.net.Inet4Address;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Collections;
+
+public class TestUtils {
+
+ private TestUtils() {}
+
+ public static final String PNF_SIMULATOR_DB = "pnf_simulator";
+ public static final String COMMON_EVENT_HEADER = "commonEventHeader";
+ public static final String PNF_SIMULATOR_DB_PSWD = "zXcVbN123!";
+ public static final String PNF_SIMULATOR_DB_USER = "pnf_simulator_user";
+ public static final String PATCHED = "patched";
+ public static final String SINGLE_EVENT_URL = "http://0.0.0.0:5000/simulator/event";
+
+ public static Document findSourceNameInMongoDB() throws UnknownHostException {
+ MongoCredential credential = MongoCredential
+ .createCredential(PNF_SIMULATOR_DB_USER, PNF_SIMULATOR_DB, PNF_SIMULATOR_DB_PSWD.toCharArray());
+ MongoClient mongoClient = new MongoClient(new ServerAddress(Inet4Address.getLocalHost(), 27017),
+ credential, MongoClientOptions.builder().build());
+ MongoDatabase pnfSimulatorDb = mongoClient.getDatabase(PNF_SIMULATOR_DB);
+ MongoCollection<Document> table = pnfSimulatorDb.getCollection("eventData");
+ Document searchQuery = new Document();
+ searchQuery.put(PATCHED, new Document("$regex", ".*" + "HistoricalEvent" + ".*"));
+ FindIterable<Document> findOfPatched = table.find(searchQuery);
+ Document dbObject = null;
+ MongoCursor<Document> cursor = findOfPatched.iterator();
+ if (cursor.hasNext()) {
+ dbObject = cursor.next();
+ }
+ return dbObject;
+ }
+
+ public static String getCurrentIpAddress() throws SocketException {
+ return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
+ .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
+ .filter(ip -> ip instanceof Inet4Address)
+ .map(e -> (Inet4Address) e)
+ .findFirst()
+ .orElseThrow(RuntimeException::new)
+ .getHostAddress();
+ }
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java b/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java
new file mode 100644
index 0000000..ae7970c
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/VariablesReplacement.java
@@ -0,0 +1,80 @@
+package org.onap.pnfsimulator.integration;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.onap.pnfsimulator.integration.TestUtils.getCurrentIpAddress;
+
+import com.google.gson.JsonObject;
+import java.net.Inet4Address;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Main.class, TestConfiguration.class},
+ webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+public class VariablesReplacement {
+
+ @Autowired
+ private VesSimulatorService vesSimulatorService;
+
+ private String currentVesSimulatorIp;
+
+ @Before
+ public void setUp() throws Exception {
+ currentVesSimulatorIp = getCurrentIpAddress();
+ }
+
+ @Test
+ public void whenTriggeredSimulatorShouldReplaceStringKeyword() {
+ String startUrl = prepareRequestUrl();
+ String body = "{\n" + "\"templateName\": \"cmNotification.json\",\n" + "\"patch\":{},\n" + "\"variables\":{\n"
+ + "\"dN\": \"NRNB=5, NRCEL=1234\",\n" + "\"attributeList\":{\n"
+ + "\"threshXHighQ\": \"50\",\n" + "\"threshXHighP\": \"52\"\n" + "}\n" + "},\n"
+ + "\"simulatorParams\": {\n" + "\"vesServerUrl\": \"https://" + currentVesSimulatorIp
+ + ":9443/ves-simulator/eventListener/v5\",\n" + "\"repeatInterval\": 1,\n"
+ + "\"repeatCount\": 1\n" + "}\n" + "}";
+ ArgumentCaptor<JsonObject> parameterCaptor = ArgumentCaptor.forClass(JsonObject.class);
+
+ given().contentType("application/json").body(body).when().post(startUrl).then().statusCode(200)
+ .body("message", equalTo("Request started"));
+
+ Mockito.verify(vesSimulatorService, Mockito.timeout(3000)).sendEventToDmaapV5(parameterCaptor.capture());
+
+ assertAttributeList(parameterCaptor);
+ assertDn(parameterCaptor);
+ }
+
+ private void assertDn(ArgumentCaptor<JsonObject> parameterCaptor) {
+ String dn = parameterCaptor.getValue().getAsJsonObject("event").getAsJsonObject("otherFields")
+ .getAsJsonArray("jsonObjects").get(0)
+ .getAsJsonObject().getAsJsonArray("objectInstances")
+ .get(0).getAsJsonObject().getAsJsonObject("objectInstance")
+ .getAsJsonObject("cm3gppNotifyFields").getAsJsonPrimitive("dN").getAsString();
+ assertThat(dn).isEqualTo("NRNB=5, NRCEL=1234");
+ }
+
+ private void assertAttributeList(ArgumentCaptor<JsonObject> parameterCaptor) {
+ JsonObject attributeList = parameterCaptor.getValue().getAsJsonObject("event").getAsJsonObject("otherFields")
+ .getAsJsonArray("jsonObjects").get(0).getAsJsonObject()
+ .getAsJsonArray("objectInstances").get(0).getAsJsonObject()
+ .getAsJsonObject("objectInstance").getAsJsonObject("cm3gppNotifyFields")
+ .getAsJsonObject("attributeList");
+ assertThat(attributeList.get("threshXHighQ").getAsString()).isEqualTo("50");
+ assertThat(attributeList.get("threshXHighP").getAsString()).isEqualTo("52");
+ }
+
+ private String prepareRequestUrl() {
+ return "http://0.0.0.0:5000/simulator/start";
+ }
+
+}
diff --git a/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java b/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java
new file mode 100644
index 0000000..f6a4c24
--- /dev/null
+++ b/integration/src/test/java/org/onap/pnfsimulator/integration/suites/DockerBasedTestsSuite.java
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.integration.suites;
+
+import com.palantir.docker.compose.DockerComposeRule;
+import com.palantir.docker.compose.connection.waiting.HealthChecks;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import org.onap.pnfsimulator.integration.BasicAvailabilityTest;
+import org.onap.pnfsimulator.integration.OptionalTemplatesTest;
+import org.onap.pnfsimulator.integration.SearchInTemplatesTest;
+import org.onap.pnfsimulator.integration.SingleEventTest;
+import org.onap.pnfsimulator.integration.TemplatesManagementTest;
+import org.onap.pnfsimulator.integration.VariablesReplacement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+
+import static io.restassured.RestAssured.given;
+
+@RunWith(Suite.class)
+@SuiteClasses({BasicAvailabilityTest.class, TemplatesManagementTest.class, OptionalTemplatesTest.class,
+ SearchInTemplatesTest.class, VariablesReplacement.class, SingleEventTest.class})
+public class DockerBasedTestsSuite {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DockerBasedTestsSuite.class);
+
+ private static final String HEALTH_CHECK_ADDRESS = "http://0.0.0.0:5000/health";
+ private static final int RETRY_COUNT = 10;
+ private static final int RETRY_INTERVAL = 1000;
+
+ @ClassRule
+ public static DockerComposeRule docker = DockerComposeRule.builder()
+ .file("../docker-compose.yml")
+ .waitingForService("pnf-simulator", HealthChecks.toHaveAllPortsOpen())
+ .waitingForService("mongo", HealthChecks.toHaveAllPortsOpen())
+ .build();
+
+ @BeforeClass
+ public static void waitForPnfSimulatorToBeHealthy() throws InterruptedException {
+ boolean isHealthy = false;
+ int retry = 0;
+ while (!isHealthy && retry < RETRY_COUNT) {
+ retry++;
+ LOGGER.info("Checking PNF health, try {} out of {}", retry, RETRY_COUNT);
+ isHealthy = performHealthCheck();
+ if (isHealthy) {
+ LOGGER.info("PNF is healthy");
+ } else {
+ LOGGER.info("PNF no healthy retrying in {}", RETRY_COUNT);
+ Thread.sleep(RETRY_INTERVAL);
+ }
+ }
+ }
+
+ private static boolean performHealthCheck() {
+ boolean isUp = false;
+ try {
+ int statusCode = given().get(HEALTH_CHECK_ADDRESS).getStatusCode();
+ if (statusCode == HttpStatus.OK.value()) {
+ isUp = true;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return isUp;
+ }
+
+}
diff --git a/integration/src/test/resources/application.properties b/integration/src/test/resources/application.properties
new file mode 100644
index 0000000..c3e1472
--- /dev/null
+++ b/integration/src/test/resources/application.properties
@@ -0,0 +1,6 @@
+server.port=9443
+security.require-ssl=true
+server.ssl.key-store=src/main/resources/keystore
+server.ssl.key-store-password=collector
+server.ssl.keyStoreType=JKS
+server.ssl.keyAlias=tomcat \ No newline at end of file
diff --git a/integration/src/test/resources/templates/cmNotification.json b/integration/src/test/resources/templates/cmNotification.json
new file mode 100644
index 0000000..750ce30
--- /dev/null
+++ b/integration/src/test/resources/templates/cmNotification.json
@@ -0,0 +1,32 @@
+{
+ "event": {
+ "otherFields": {
+ "otherFieldsVersion": "3.0",
+ "jsonObjects": [
+ {
+ "objectName": "CustomNotification",
+ "objectInstances": [
+ {
+ "objectInstance": {
+ "cm3gppNotifyFields": {
+ "dN": "#dN",
+ "notificationType": "notifyMOIAttributeValueChange",
+ "notificationId": "notificationID123121312323",
+ "sourceIndicator": "sONOperation",
+ "eventTime": "#Timestamp",
+ "systemDN": "NRNB=5",
+ "attributeList": "#attributeList",
+ "correlatedNotifications": {
+ "notificationID-notifyMOIAttributeValueChange": "sONOperation"
+ },
+ "additionalText": "sometext",
+ "cm3gppNotifyFieldsVersion": "1.0"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/notification.json b/integration/src/test/resources/templates/notification.json
new file mode 100644
index 0000000..0b4ff2e
--- /dev/null
+++ b/integration/src/test/resources/templates/notification.json
@@ -0,0 +1,45 @@
+{
+ "id": "notification.json",
+ "content": {
+ "event": {
+ "commonEventHeader": {
+ "domain": "notification",
+ "eventName": "vFirewallBroadcastPackets",
+ "eventId": "4cfc-91cf-31a46",
+ "priority": "Normal",
+ "reportingEntityName": "myVNF",
+ "sequence": 1,
+ "sourceName": "ClosedLoopVNF",
+ "startEpochMicrosec": 1531616794,
+ "lastEpochMicrosec": 1531719042,
+ "vesEventListenerVersion": "7.0.1",
+ "version": "4.0.1"
+ },
+ "notificationFields": {
+ "changeIdentifier": "PM_MEAS_FILES",
+ "changeType": "FileReady",
+ "arrayOfNamedHashMap": [
+ {
+ "name": "A20161221.1031-1041.bin.gz",
+ "hashMap": {
+ "fileformatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10",
+ "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz",
+ "compression": "gzip"
+ }
+ },
+ {
+ "name": "A20161222.1042-1102.bin.gz",
+ "hashMap": {
+ "fileFormatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10",
+ "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz",
+ "compression": "gzip"
+ }
+ }
+ ],
+ "notificationFieldsVersion": "2.0"
+ }
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/overwrite_template.json b/integration/src/test/resources/templates/overwrite_template.json
new file mode 100644
index 0000000..55bf763
--- /dev/null
+++ b/integration/src/test/resources/templates/overwrite_template.json
@@ -0,0 +1,6 @@
+{
+ "name": "overwrite_template.json",
+ "template": {
+ "field1": "field1"
+ }
+}
diff --git a/integration/src/test/resources/templates/overwritten_template.json b/integration/src/test/resources/templates/overwritten_template.json
new file mode 100644
index 0000000..28e7381
--- /dev/null
+++ b/integration/src/test/resources/templates/overwritten_template.json
@@ -0,0 +1,6 @@
+{
+ "id": "overwrite_template.json",
+ "content": {
+ "field1": "overwritten_field1"
+ }
+}
diff --git a/integration/src/test/resources/templates/registration.json b/integration/src/test/resources/templates/registration.json
new file mode 100644
index 0000000..8b7908e
--- /dev/null
+++ b/integration/src/test/resources/templates/registration.json
@@ -0,0 +1,36 @@
+{
+ "id": "registration.json",
+ "content": {
+ "event": {
+ "commonEventHeader": {
+ "eventId": "registration_39239592",
+ "eventType": "pnfRegistration",
+ "reportingEntityName": "NOK6061ZW3",
+ "domain": "pnfRegistration",
+ "nfcNamingCode": "oam",
+ "sequence": 0,
+ "sourceId": "val13",
+ "internalHeaderFields": {},
+ "priority": "Normal",
+ "sourceName": "NOK6061ZW3",
+ "eventName": "pnfRegistration_Nokia_5gDu",
+ "version": "4.0.1",
+ "nfNamingCode": "gNB",
+ "startEpochMicrosec": 1539239592379,
+ "vesEventListenerVersion": "7.0.1",
+ "lastEpochMicrosec": 1539239592379
+ },
+ "pnfRegistrationFields": {
+ "pnfRegistrationFieldsVersion": "2.0",
+ "serialNumber": "6061ZW3",
+ "vendorName": "Nokia",
+ "oamV4IpAddress": "val3",
+ "oamV6IpAddress": "val4",
+ "unitFamily": "BBU",
+ "modelNumber": "val6",
+ "softwareVersion": "val7",
+ "unitType": "val8"
+ }
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/search/complicated_template.json b/integration/src/test/resources/templates/search/complicated_template.json
new file mode 100644
index 0000000..962600d
--- /dev/null
+++ b/integration/src/test/resources/templates/search/complicated_template.json
@@ -0,0 +1,43 @@
+{
+ "name": "complicated_template.json",
+ "template": {
+ "parent": {
+ "child1": "Any value 1",
+ "child2": {
+ "parent": {
+ "child1": "Any value 1",
+ "child2": "Any value 2",
+ "child3": {
+ "child4": "Any value 4"
+ },
+ "child4": [
+ "Any value 1",
+ "Any value 2, Any value 3"
+ ],
+ "child5": [
+ "Any value 4",
+ 1,
+ 2,
+ 4.4,
+ {
+ "child6": [
+ 1,
+ 2,
+ 4.4
+ ]
+ }
+ ]
+ }
+ },
+ "child3": {
+ "child4": "Any value 4"
+ }
+ },
+ "parent2": "Any value 2",
+ "parent3": {
+ "child1": "?",
+ "child2": "*",
+ "child3": "https://url.com?param1=test&param2=*"
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/search/simple_template.json b/integration/src/test/resources/templates/search/simple_template.json
new file mode 100644
index 0000000..d209a9e
--- /dev/null
+++ b/integration/src/test/resources/templates/search/simple_template.json
@@ -0,0 +1,12 @@
+{
+ "name": "simple_template.json",
+ "template": {
+ "parent": {
+ "child1": "Any value 1",
+ "child2": "Any value 2",
+ "child3": {
+ "child4": "Any value 4"
+ }
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/search/template_with_array.json b/integration/src/test/resources/templates/search/template_with_array.json
new file mode 100644
index 0000000..0ed4326
--- /dev/null
+++ b/integration/src/test/resources/templates/search/template_with_array.json
@@ -0,0 +1,23 @@
+{
+ "name": "template_with_array.json",
+ "template": {
+ "parent": {
+ "child1": [
+ {
+ "child1": "Any value 1",
+ "child2": [
+ 4,
+ 4.44
+ ]
+ }
+ ],
+ "child2": [
+ 1,
+ "Any value 4",
+ 3.3,
+ 5
+ ]
+ },
+ "parent2": "[]"
+ }
+}
diff --git a/integration/src/test/resources/templates/search/template_with_booleans.json b/integration/src/test/resources/templates/search/template_with_booleans.json
new file mode 100644
index 0000000..4954663
--- /dev/null
+++ b/integration/src/test/resources/templates/search/template_with_booleans.json
@@ -0,0 +1,12 @@
+{
+ "name": "template_with_booleans.json",
+ "template": {
+ "parent": {
+ "child1": true,
+ "child3": {
+ "child4": true
+ }
+ },
+ "parent2": false
+ }
+}
diff --git a/integration/src/test/resources/templates/search/template_with_floats.json b/integration/src/test/resources/templates/search/template_with_floats.json
new file mode 100644
index 0000000..2b8caf4
--- /dev/null
+++ b/integration/src/test/resources/templates/search/template_with_floats.json
@@ -0,0 +1,13 @@
+{
+ "name": "template_with_floats.json",
+ "template": {
+ "parent": {
+ "child1": 6.4,
+ "child2": 1.2,
+ "child3": {
+ "child5": 4.4,
+ "child2": "1"
+ }
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/search/template_with_ints.json b/integration/src/test/resources/templates/search/template_with_ints.json
new file mode 100644
index 0000000..369b0b4
--- /dev/null
+++ b/integration/src/test/resources/templates/search/template_with_ints.json
@@ -0,0 +1,12 @@
+{
+ "name": "template_with_ints.json",
+ "template": {
+ "parent": {
+ "child1": 6,
+ "child2": 1,
+ "child3": {
+ "child4": 4
+ }
+ }
+ }
+}
diff --git a/integration/src/test/resources/templates/upload_template.json b/integration/src/test/resources/templates/upload_template.json
new file mode 100644
index 0000000..df3ae28
--- /dev/null
+++ b/integration/src/test/resources/templates/upload_template.json
@@ -0,0 +1,6 @@
+{
+ "name": "upload_template.json",
+ "template": {
+ "field1": "field1"
+ }
+}
diff --git a/lombok.config b/lombok.config
new file mode 100644
index 0000000..a23edb4
--- /dev/null
+++ b/lombok.config
@@ -0,0 +1,2 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true \ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..546d44a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,498 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. All rights reserved.
+ ================================================================================
+ 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=========================================================
+ -->
+
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.integration.simulators.nf-simulator.ves-client</groupId>
+ <artifactId>vesclient</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <name>vesclient</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
+ <simulator.main.class>org.onap.pnfsimulator.Main</simulator.main.class>
+ <docker.image.tag>latest</docker.image.tag>
+ <dependency.directory.name>libs</dependency.directory.name>
+ <dependency.directory.location>${project.build.directory}/${dependency.directory.name}
+ </dependency.directory.location>
+ <onap.nexus.dockerregistry.daily>nexus3.onap.org:10003</onap.nexus.dockerregistry.daily>
+ <onap.nexus.url>http://nexus3.onap.org</onap.nexus.url>
+ <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
+ <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
+ <git-commit-id-plugin.version>2.2.4</git-commit-id-plugin.version>
+ <maven-surefire-plugin.version>2.19</maven-surefire-plugin.version>
+ <junit-platform-surefire-provider.version>1.1.1</junit-platform-surefire-provider.version>
+
+
+ <nexusproxy>https://nexus.onap.org</nexusproxy>
+ <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath>
+ <releaseNexusPath>/content/repositories/releases/</releaseNexusPath>
+ <stagingNexusPath>/content/repositories/staging/</stagingNexusPath>
+ <docker-image.namespace>onap</docker-image.namespace>
+ <docker-image.name.prefix>org.onap.integration.nfsimulator</docker-image.name.prefix>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <docker-maven-plugin.version>0.31.0</docker-maven-plugin.version>
+ <skipDockerPush>true</skipDockerPush>
+ <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml
+ </sonar.coverage.jacoco.xmlReportPaths>
+
+ <!-- Compile DEPENDENCIES VERSION -->
+
+ <maven-checkstyle-plugin.version>2.17</maven-checkstyle-plugin.version>
+ <docker-maven-plugin-io-fabric.version>0.31.0</docker-maven-plugin-io-fabric.version>
+ <spring-boot-starter.version>2.1.6.RELEASE</spring-boot-starter.version>
+ <spring-boot-starter-web.version>2.1.6.RELEASE</spring-boot-starter-web.version>
+ <spring-boot-starter-websocket.version>2.1.6.RELEASE</spring-boot-starter-websocket.version>
+ <spring-boot-starter-actuator.version>2.1.0.RELEASE</spring-boot-starter-actuator.version>
+ <spring-boot-starter-data-mongodb.version>2.1.0.RELEASE</spring-boot-starter-data-mongodb.version>
+ <spring-cloud-config-client.version>2.1.4.RELEASE</spring-cloud-config-client.version>
+ <lombok.version>1.18.2</lombok.version>
+ <jnc.version>1.0</jnc.version>
+ <spring-kafka.version>2.2.7.RELEASE</spring-kafka.version>
+ <commons-cli.version>1.4</commons-cli.version>
+ <javax.websocket-api.version>1.1</javax.websocket-api.version>
+ <apache.httpclient.version>4.5.6</apache.httpclient.version>
+ <httpmime.version>4.5.6</httpmime.version>
+ <springfox-swagger2.version>2.9.2</springfox-swagger2.version>
+ <springfox-swagger-ui.version>2.9.2</springfox-swagger-ui.version>
+ <logback-core.version>1.2.3</logback-core.version>
+ <slf4j-api.version>1.7.25</slf4j-api.version>
+ <commons-io.version>2.6</commons-io.version>
+ <json.version>20180130</json.version>
+ <gson.version>2.8.2</gson.version>
+ <commons-lang3.version>3.7</commons-lang3.version>
+ <jackson-datatype-jdk8.version>2.9.7</jackson-datatype-jdk8.version>
+ <jackson-datatype-jsr310.version>2.9.7</jackson-datatype-jsr310.version>
+ <vavr-match.version>0.9.2</vavr-match.version>
+ <vavr.version>0.9.2</vavr.version>
+ <quartz.version>2.2.1</quartz.version>
+ <quartz-jobs.version>2.2.1</quartz-jobs.version>
+ <guava.version>21.0</guava.version>
+ <logback-classic.version>1.2.3</logback-classic.version>
+ <sonar-maven-plugin.version>3.7.0.1746</sonar-maven-plugin.version>
+
+ <!-- TEST DEPENDENCIES VERSION -->
+
+ <assertj-core.version>3.9.1</assertj-core.version>
+ <mockito-core.version>2.18.3</mockito-core.version>
+ <junit-jupiter-engine.version>5.3.1</junit-jupiter-engine.version>
+ <junit-vintage-engine.version>5.3.1</junit-vintage-engine.version>
+ <junit.version>4.12</junit.version>
+ <spring.boot.version>2.1.6.RELEASE</spring.boot.version>
+ <spring.kafka.version>2.2.7.RELEASE</spring.kafka.version>
+ <before-after-spring-test-runner.version>0.1.0</before-after-spring-test-runner.version>
+ <docker-compose-rule-junit4.version>0.34.0</docker-compose-rule-junit4.version>
+ <spring-test.version>5.0.4.RELEASE</spring-test.version>
+ <junit-jupiter-migrationsupport.version>5.1.0</junit-jupiter-migrationsupport.version>
+ <jsonassert.version>1.5.0</jsonassert.version>
+
+ <skip-integration-tests>true</skip-integration-tests>
+ <skip-unit-tests>false</skip-unit-tests>
+
+ </properties>
+
+ <dependencies>
+
+ <!-- Compile DEPENDENCIES -->
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ <version>${spring-boot-starter.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <version>${spring-boot-starter-web.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-mongodb</artifactId>
+ <version>${spring-boot-starter-data-mongodb.version}</version>
+ </dependency>
+<!-- <dependency>-->
+<!-- <groupId>org.springframework.boot</groupId>-->
+<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
+<!-- <version>${spring-boot-starter-actuator.version}</version>-->
+<!-- </dependency>-->
+ <dependency>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-config-client</artifactId>
+ <version>${spring-cloud-config-client.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ <version>${lombok.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback-classic.version}</version>
+ </dependency>
+<!-- <dependency>-->
+<!-- <groupId>ch.qos.logback</groupId>-->
+<!-- <artifactId>logback-core</artifactId>-->
+<!-- <version>${logback-classic.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>org.slf4j</groupId>-->
+<!-- <artifactId>slf4j-api</artifactId>-->
+<!-- <version>${slf4j-api.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>commons-io</groupId>-->
+<!-- <artifactId>commons-io</artifactId>-->
+<!-- <version>${commons-io.version}</version>-->
+<!-- </dependency>-->
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>${json.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${gson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${apache.httpclient.version}</version>
+ </dependency>
+<!-- <dependency>-->
+<!-- <groupId>com.google.guava</groupId>-->
+<!-- <artifactId>guava</artifactId>-->
+<!-- <version>${guava.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>commons-cli</groupId>-->
+<!-- <artifactId>commons-cli</artifactId>-->
+<!-- <version>${commons-cli.version}</version>-->
+<!-- </dependency>-->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>${commons-lang3.version}</version>
+ </dependency>
+
+<!-- <dependency>-->
+<!-- <groupId>com.fasterxml.jackson.datatype</groupId>-->
+<!-- <artifactId>jackson-datatype-jdk8</artifactId>-->
+<!-- <version>${jackson-datatype-jdk8.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>com.fasterxml.jackson.datatype</groupId>-->
+<!-- <artifactId>jackson-datatype-jsr310</artifactId>-->
+<!-- <version>${jackson-datatype-jsr310.version}</version>-->
+<!-- </dependency>-->
+ <dependency>
+ <groupId>io.vavr</groupId>
+ <artifactId>vavr-match</artifactId>
+ <version>${vavr-match.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.vavr</groupId>
+ <artifactId>vavr</artifactId>
+ <version>${vavr.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <version>${springfox-swagger2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <version>${springfox-swagger-ui.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <version>${quartz.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz-jobs</artifactId>
+ <version>${quartz-jobs.version}</version>
+ </dependency>
+
+ <!-- TEST DEPENDENCIES -->
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ <version>${junit-jupiter-engine.version}</version>
+ </dependency>
+<!-- <dependency>-->
+<!-- <groupId>org.junit.jupiter</groupId>-->
+<!-- <artifactId>junit-jupiter-migrationsupport</artifactId>-->
+<!-- <scope>test</scope>-->
+<!-- <version>${junit-jupiter-migrationsupport.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>org.skyscreamer</groupId>-->
+<!-- <artifactId>jsonassert</artifactId>-->
+<!-- <scope>test</scope>-->
+<!-- <version>${jsonassert.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>org.assertj</groupId>-->
+<!-- <artifactId>assertj-core</artifactId>-->
+<!-- <scope>test</scope>-->
+<!-- <version>${assertj-core.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>org.mockito</groupId>-->
+<!-- <artifactId>mockito-core</artifactId>-->
+<!-- <scope>test</scope>-->
+<!-- <version>${mockito-core.version}</version>-->
+<!-- </dependency>-->
+<!-- <dependency>-->
+<!-- <groupId>org.springframework</groupId>-->
+<!-- <artifactId>spring-test</artifactId>-->
+<!-- <scope>test</scope>-->
+<!-- <version>${spring-test.version}</version>-->
+<!-- </dependency>-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <version>${spring.boot.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptor>src/assembly/resources.xml</descriptor>
+ <finalName>${project.artifactId}-${project.version}</finalName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${maven.compiler.source}</source>
+ <target>${maven.compiler.target}</target>
+ <showWarnings>true</showWarnings>
+ <showDeprecation>true</showDeprecation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>${maven-jar-plugin.version}</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Main-Class>${simulator.main.class}</Main-Class>
+ <Build-Time>${maven.build.timestamp}</Build-Time>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <version>${git-commit-id-plugin.version}</version>
+ <executions>
+ <execution>
+ <id>get-commit-info</id>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
+ <generateGitPropertiesFile>true</generateGitPropertiesFile>
+ <includeOnlyProperties>git.commit.id.abbrev</includeOnlyProperties>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-surefire-provider</artifactId>
+ <version>${junit-platform-surefire-provider.version}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <skipTests>${skip-unit-tests}</skipTests>
+ <detail>true</detail>
+ <printSummary>true</printSummary>
+ <useSystemClassLoader>false</useSystemClassLoader>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <outputDirectory>${dependency.directory.location}</outputDirectory>
+ <includeScope>runtime</includeScope>
+ <silent>true</silent>
+ </configuration>
+ <executions>
+ <execution>
+ <id>copy-external-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>prepare-agent</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>report</id>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <dataFile>${project.build.directory}/code-coverage/jacoco.exec</dataFile>
+ <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <properties>
+ <os.detected.name>linux</os.detected.name>
+ <os.detected.arch>x86_64</os.detected.arch>
+ <os.detected.classifier>${os.detected.name}-${os.detected.arch}</os.detected.classifier>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>${docker-maven-plugin.version}</version>
+ <executions>
+ <execution>
+ <id>docker-build-image</id>
+ <phase>package</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>docker-push-image</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>push</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <skipPush>${skipDockerPush}</skipPush>
+ <verbose>true</verbose>
+ <imagePullPolicy>IfNotPresent</imagePullPolicy>
+ <images>
+ <image>
+ <alias>${project.artifactId}</alias>
+ <name>${docker-image.namespace}/${docker-image.name.prefix}.${artifactId}</name>
+ <registry>${onap.nexus.dockerregistry.daily}</registry>
+ <build>
+ <dockerFileDir>${project.basedir}</dockerFileDir>
+ <tags>
+ <tag>${project.version}-STAGE-${maven.build.timestamp}Z</tag>
+ </tags>
+ </build>
+ </image>
+ </images>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <distributionManagement>
+ <repository>
+ <id>ecomp-releases</id>
+ <name>Integration simulators Release Repository</name>
+ <url>${nexusproxy}${releaseNexusPath}</url>
+ </repository>
+ <snapshotRepository>
+ <id>ecomp-snapshots</id>
+ <name>Integration simulators Snapshot Repository</name>
+ <url>${nexusproxy}${snapshotNexusPath}</url>
+ </snapshotRepository>
+ <site>
+ <id>ecomp-site</id>
+ <url>dav:${nexusproxy}${sitePath}</url>
+ </site>
+ </distributionManagement>
+
+</project>
diff --git a/src/assembly/resources.xml b/src/assembly/resources.xml
new file mode 100644
index 0000000..35dd3b2
--- /dev/null
+++ b/src/assembly/resources.xml
@@ -0,0 +1,57 @@
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. All rights reserved.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<assembly>
+ <id>resources</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>simulator.sh</include>
+ </includes>
+ <lineEnding>unix</lineEnding>
+ <fileMode>0755</fileMode>
+ </fileSet>
+ <fileSet>
+ <includes>
+ <include>docker-compose.yml</include>
+ </includes>
+ <lineEnding>unix</lineEnding>
+ <fileMode>0644</fileMode>
+ </fileSet>
+ <fileSet>
+ <directory>config</directory>
+ <outputDirectory>config</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>deployment</directory>
+ <outputDirectory>deployment</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/src/main/java/org/onap/pnfsimulator/Main.java b/src/main/java/org/onap/pnfsimulator/Main.java
new file mode 100644
index 0000000..708f27f
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/Main.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator;
+
+import javax.annotation.PostConstruct;
+
+import org.onap.pnfsimulator.filesystem.WatcherService;
+import org.onap.pnfsimulator.template.FsToDbTemplateSynchronizer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@SpringBootApplication
+@EnableAsync
+public class Main {
+
+ private final WatcherService watcherService;
+ private final FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer;
+
+ @Autowired
+ public Main(WatcherService watcherService,
+ FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer) {
+ this.watcherService = watcherService;
+ this.fsToDbTemplateSynchronizer = fsToDbTemplateSynchronizer;
+ }
+
+ // We are excluding this line in Sonar due to fact that
+ // Spring is handling arguments
+ public static void main(String[] args) { // NOSONAR
+ SpringApplication.run(Main.class, args);
+ }
+
+ @PostConstruct
+ public void createWatchers() {
+ fsToDbTemplateSynchronizer.synchronize();
+ watcherService.createWatcher();
+ }
+}
+
+
diff --git a/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java b/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java
new file mode 100644
index 0000000..b6c6187
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/SwaggerConfig.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator;
+
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableConfigurationProperties(SslAuthenticationHelper.class)
+@EnableSwagger2
+public class SwaggerConfig {
+
+ @Bean
+ public Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("org.onap.pnfsimulator"))
+ .paths(PathSelectors.any())
+ .build();
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/db/Row.java b/src/main/java/org/onap/pnfsimulator/db/Row.java
new file mode 100644
index 0000000..12745bf
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/db/Row.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.db;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Field;
+
+public abstract class Row {
+ @Id
+ @Field("_id")
+ @Getter
+ @Setter
+ private String id;
+
+
+ public String getId() {
+ return id;
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/db/Storage.java b/src/main/java/org/onap/pnfsimulator/db/Storage.java
new file mode 100644
index 0000000..ad98ce0
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/db/Storage.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.db;
+
+import com.google.gson.JsonObject;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface Storage<T extends Row> {
+
+ List<T> getAll();
+
+ Optional<T> get(String rowId);
+
+ void persist(T row);
+
+ boolean tryPersistOrOverwrite(T row, boolean overwrite);
+
+ void delete(String rowId);
+
+ List<String> getIdsByContentCriteria(JsonObject queryJson);
+}
diff --git a/src/main/java/org/onap/pnfsimulator/event/EventData.java b/src/main/java/org/onap/pnfsimulator/event/EventData.java
new file mode 100644
index 0000000..ff85367
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/event/EventData.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.event;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Field;
+
+@Builder
+@Getter
+@Setter
+@ToString(exclude = "incrementValue")
+public class EventData {
+ @Id
+ private String id;
+
+ @Field("template")
+ @JsonInclude
+ private String template;
+
+ @Field("patched")
+ @JsonInclude
+ private String patched;
+
+ @Field("input")
+ @JsonInclude
+ private String input;
+
+ @Field("keywords")
+ @JsonInclude
+ private String keywords;
+
+ @Field("incrementValue")
+ @JsonInclude
+ private int incrementValue;
+
+ protected EventData(String id, String template, String patched, String input, String keywords, int incrementValue) {
+ this.id = id;
+ this.template = template;
+ this.patched = patched;
+ this.input = input;
+ this.keywords = keywords;
+ this.incrementValue = incrementValue;
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java b/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java
new file mode 100644
index 0000000..d1a66ab
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/event/EventDataRepository.java
@@ -0,0 +1,26 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.event;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+public interface EventDataRepository extends MongoRepository<EventData, String> {
+}
diff --git a/src/main/java/org/onap/pnfsimulator/event/EventDataService.java b/src/main/java/org/onap/pnfsimulator/event/EventDataService.java
new file mode 100644
index 0000000..266d56b
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/event/EventDataService.java
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.event;
+
+import com.google.gson.JsonObject;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EventDataService {
+ private final EventDataRepository repository;
+
+ @Autowired
+ public EventDataService(EventDataRepository repository) {
+ this.repository = repository;
+ }
+
+ private EventData persistEventData(String templateString, String patchedString, String inputString, String keywordsString) {
+ EventData eventData = EventData.builder()
+ .template(templateString)
+ .patched(patchedString)
+ .input(inputString)
+ .keywords(keywordsString)
+ .build();
+ return repository.save(eventData);
+ }
+
+ public EventData persistEventData(JsonObject templateJson, JsonObject patchedJson, JsonObject inputJson,
+ JsonObject keywordsJson) {
+ return persistEventData(templateJson.toString(),
+ patchedJson.toString(),
+ inputJson.toString(),
+ keywordsJson.toString());
+ }
+
+ public List<EventData> getAllEvents() {
+ return repository.findAll();
+ }
+
+ public Optional<EventData> getById(String id) {
+ return repository.findById(id);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java
new file mode 100644
index 0000000..3535e33
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherConfig.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+@Configuration
+public class WatcherConfig {
+
+ @Bean
+ public TaskExecutor watcherTaskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setThreadNamePrefix("pnfsimulator_fs_watcher");
+ executor.initialize();
+ return executor;
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java
new file mode 100644
index 0000000..c03491a
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessor.java
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchEvent.Kind;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import lombok.extern.slf4j.Slf4j;
+import org.bson.BSONException;
+import org.bson.json.JsonParseException;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.template.Template;
+import org.bson.Document;
+
+@Slf4j
+public enum WatcherEventProcessor {
+ CREATED(StandardWatchEventKinds.ENTRY_CREATE) {
+ @Override
+ public void processEvent(Path path, Storage<Template> storage) throws IOException {
+ String content = getContent(path);
+ String fileName = path.getFileName().toString();
+ Document documentsContent = Document.parse(content);
+ storage.persist(new Template(fileName, documentsContent, Instant.now().getNano()));
+ log.info("DB record created for template: " + fileName);
+ }
+ },
+ MODIFIED(StandardWatchEventKinds.ENTRY_MODIFY) {
+ @Override
+ public void processEvent(Path path, Storage<Template> storage) throws IOException {
+ String fileName = path.getFileName().toString();
+ String content = getContent(path);
+ Document documentsContent = Document.parse(content);
+ Template template = storage.get(fileName).orElse(new Template(fileName, documentsContent, Instant.now().getNano()));
+ template.setContent(documentsContent);
+ storage.persist(template);
+ log.info("DB record modified for template: " + fileName);
+ }
+ },
+ DELETED(StandardWatchEventKinds.ENTRY_DELETE) {
+ @Override
+ public void processEvent(Path path, Storage<Template> storage) {
+ String fileName = path.getFileName().toString();
+ storage.delete(fileName);
+ log.info("DB record deleted for template: " + fileName);
+ }
+ };
+
+ private final Kind<Path> pathKind;
+
+ String getContent(Path path) throws IOException {
+ try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
+ return lines.collect(Collectors.joining(System.lineSeparator()));
+ } catch (IOException e) {
+ log.error("Could not get content due to: " + e.getMessage() + " " + e.getCause(), e);
+ throw e;
+ }
+ }
+
+ WatcherEventProcessor(Kind<Path> pathKind) {
+ this.pathKind = pathKind;
+ }
+
+ public abstract void processEvent(Path templateName, Storage<Template> storage) throws IOException;
+
+ static void process(WatchEvent<?> event, Storage<Template> storage, Path templatesDir) {
+ Optional<WatcherEventProcessor> watcherEventProcessor = getWatcherEventProcessor(event);
+ watcherEventProcessor.ifPresent(processor -> {
+ try {
+ final Path templatePath = templatesDir.resolve((Path) event.context());
+ processor.processEvent(templatePath, storage);
+ } catch (IOException e) {
+ log.error("Error during processing DB record for template.", e);
+ } catch (BSONException | JsonParseException e) {
+ log.error("Invalid JSON format provided for template.", e);
+ }
+ });
+ }
+
+ private static Optional<WatcherEventProcessor> getWatcherEventProcessor(WatchEvent<?> event) {
+ return Arrays.stream(values()).filter(value -> value.pathKind.equals(event.kind())).findFirst();
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java
new file mode 100644
index 0000000..26b684d
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherService.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.stereotype.Service;
+
+@Service
+public class WatcherService {
+
+ private TaskExecutor taskExecutor;
+ private ApplicationContext applicationContext;
+
+ @Autowired
+ public WatcherService(ApplicationContext applicationContext, TaskExecutor taskExecutor) {
+ this.taskExecutor = taskExecutor;
+ this.applicationContext = applicationContext;
+ }
+
+ public void createWatcher() {
+ taskExecutor.execute(applicationContext.getBean(WatcherThread.class));
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java
new file mode 100644
index 0000000..a202b1f
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/filesystem/WatcherThread.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.template.Template;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WatcherThread implements Runnable {
+
+ private final WatchService watchService;
+ private final Storage<Template> storage;
+ private final Path templatesDir;
+
+ WatcherThread(String templatesDir, WatchService watchService, Storage<Template> storage) throws IOException {
+ this.watchService = watchService;
+ this.storage = storage;
+ this.templatesDir = Paths.get(templatesDir);
+ registerDirectory(this.templatesDir);
+ }
+
+ @Autowired
+ public WatcherThread(@Value("${templates.dir}") String templatesDir, Storage<Template> storage) throws IOException {
+ this(templatesDir, FileSystems.getDefault().newWatchService(), storage);
+ }
+
+ private void registerDirectory(Path path) throws IOException {
+ path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
+ StandardWatchEventKinds.ENTRY_MODIFY);
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ WatchKey key;
+ try {
+ key = watchService.take();
+ for (WatchEvent<?> event : key.pollEvents()) {
+ WatcherEventProcessor.process(event, storage, templatesDir);
+ }
+ key.reset();
+ } catch (InterruptedException e) {
+ log.error("Watch service interrupted.", e.getMessage());
+ Thread.currentThread().interrupt();
+ return;
+ }
+
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/logging/MdcVariables.java b/src/main/java/org/onap/pnfsimulator/logging/MdcVariables.java
new file mode 100644
index 0000000..4feb168
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/logging/MdcVariables.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.logging;
+
+public final class MdcVariables {
+
+ public static final String X_ONAP_REQUEST_ID = "X-ONAP-RequestID";
+ public static final String X_INVOCATION_ID = "X-InvocationID";
+ public static final String REQUEST_ID = "RequestID";
+ public static final String INVOCATION_ID = "InvocationID";
+ public static final String INSTANCE_UUID = "InstanceUUID";
+ public static final String RESPONSE_CODE = "ResponseCode";
+ public static final String SERVICE_NAME = "ServiceName";
+
+ private MdcVariables() {
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java b/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java
new file mode 100644
index 0000000..f2c70dd
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/SimulatorController.java
@@ -0,0 +1,241 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.JsonSyntaxException;
+import org.json.JSONException;
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataService;
+import org.onap.pnfsimulator.rest.model.FullEvent;
+import org.onap.pnfsimulator.rest.model.SimulatorRequest;
+import org.onap.pnfsimulator.rest.util.DateUtil;
+import org.onap.pnfsimulator.rest.util.ResponseBuilder;
+import org.onap.pnfsimulator.simulator.SimulatorService;
+import org.onap.pnfsimulator.simulator.client.HttpResponseAdapter;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig;
+import org.quartz.SchedulerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.onap.pnfsimulator.logging.MdcVariables.INSTANCE_UUID;
+import static org.onap.pnfsimulator.logging.MdcVariables.INVOCATION_ID;
+import static org.onap.pnfsimulator.logging.MdcVariables.REQUEST_ID;
+import static org.onap.pnfsimulator.logging.MdcVariables.RESPONSE_CODE;
+import static org.onap.pnfsimulator.logging.MdcVariables.SERVICE_NAME;
+import static org.onap.pnfsimulator.logging.MdcVariables.X_INVOCATION_ID;
+import static org.onap.pnfsimulator.logging.MdcVariables.X_ONAP_REQUEST_ID;
+import static org.onap.pnfsimulator.rest.util.ResponseBuilder.MESSAGE;
+import static org.onap.pnfsimulator.rest.util.ResponseBuilder.TIMESTAMP;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.springframework.http.HttpStatus.NOT_FOUND;
+import static org.springframework.http.HttpStatus.OK;
+
+@RestController
+@RequestMapping("/simulator")
+public class SimulatorController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorController.class);
+ private static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+ private static final String INCORRECT_TEMPLATE_MESSAGE = "Cannot start simulator, template %s is not in valid format: %s";
+ private static final String NOT_EXISTING_TEMPLATE = "Cannot start simulator - template %s not found.";
+ private static final String BREAKING_CHARACTER_REGEX = "[\n|\r|\t]";
+ private final DateFormat responseDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss,SSS");
+ private final SimulatorService simulatorService;
+ private EventDataService eventDataService;
+
+ @Autowired
+ public SimulatorController(SimulatorService simulatorService,
+ EventDataService eventDataService) {
+ this.simulatorService = simulatorService;
+ this.eventDataService = eventDataService;
+ }
+
+ /**
+ * @deprecated
+ */
+ @PostMapping("test")
+ @Deprecated
+ public ResponseEntity<Map<String, Object>> test(@Valid @RequestBody SimulatorRequest simulatorRequest) {
+ MDC.put("test", "test");
+ String simulatorRequestString = simulatorRequest.toString();
+ LOGGER.info(ENTRY, simulatorRequestString);
+ return buildResponse(OK, ImmutableMap.of(MESSAGE, "message1234"));
+ }
+
+ @PostMapping(value = "start")
+ public ResponseEntity<Map<String, Object>> start(@RequestHeader HttpHeaders headers,
+ @Valid @RequestBody SimulatorRequest triggerEventRequest) {
+ logContextHeaders(headers, "/simulator/start");
+ LOGGER.info(ENTRY, "Simulator started");
+
+ try {
+ return processRequest(triggerEventRequest);
+
+ } catch (JSONException | JsonSyntaxException e) {
+ MDC.put(RESPONSE_CODE, BAD_REQUEST.toString());
+ LOGGER.warn("Cannot trigger event, invalid json format: {}", e.getMessage());
+ LOGGER.debug("Received json has invalid format", e);
+ return buildResponse(BAD_REQUEST, ImmutableMap.of(MESSAGE, String
+ .format(INCORRECT_TEMPLATE_MESSAGE, triggerEventRequest.getTemplateName(),
+ e.getMessage())));
+ } catch (GeneralSecurityException e) {
+ MDC.put(RESPONSE_CODE, INTERNAL_SERVER_ERROR.toString());
+ LOGGER.error("Client certificate validation failed: {}", e.getMessage());
+ return buildResponse(INTERNAL_SERVER_ERROR,
+ ImmutableMap.of(MESSAGE, "Invalid or misconfigured client certificate"));
+ } catch (IOException e) {
+ MDC.put(RESPONSE_CODE, BAD_REQUEST.toString());
+ LOGGER.warn("Json validation failed: {}", e.getMessage());
+ return buildResponse(BAD_REQUEST,
+ ImmutableMap.of(MESSAGE, String.format(NOT_EXISTING_TEMPLATE, triggerEventRequest.getTemplateName())));
+ } catch (Exception e) {
+ MDC.put(RESPONSE_CODE, INTERNAL_SERVER_ERROR.toString());
+ LOGGER.error("Cannot trigger event - unexpected exception", e);
+ return buildResponse(INTERNAL_SERVER_ERROR,
+ ImmutableMap.of(MESSAGE, "Unexpected exception: " + e.getMessage()));
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ /**
+ * @deprecated
+ */
+ @GetMapping("all-events")
+ @Deprecated
+ public ResponseEntity<Map<String, Object>> allEvents() {
+ List<EventData> eventDataList = eventDataService.getAllEvents();
+ StringBuilder sb = new StringBuilder();
+ eventDataList.forEach(e -> sb.append(e).append(System.lineSeparator()));
+
+ return ResponseBuilder
+ .status(OK).put(MESSAGE, sb.toString())
+ .build();
+ }
+
+ @GetMapping("config")
+ public ResponseEntity<Map<String, Object>> getConfig() {
+ SimulatorConfig configToGet = simulatorService.getConfiguration();
+ return buildResponse(OK, ImmutableMap.of("simulatorConfig", configToGet));
+ }
+
+ @PutMapping("config")
+ public ResponseEntity<Map<String, Object>> updateConfig(@Valid @RequestBody SimulatorConfig newConfig) {
+ SimulatorConfig updatedConfig = simulatorService.updateConfiguration(newConfig);
+ return buildResponse(OK, ImmutableMap.of("simulatorConfig", updatedConfig));
+ }
+
+ @PostMapping("cancel/{jobName}")
+ public ResponseEntity<Map<String, Object>> cancelEvent(@PathVariable String jobName) throws SchedulerException {
+ String jobNameNoBreakingCharacters = replaceBreakingCharacters(jobName);
+ LOGGER.info(ENTRY, "Cancel called on {}.", jobNameNoBreakingCharacters);
+ boolean isCancelled = simulatorService.cancelEvent(jobName);
+ return createCancelEventResponse(isCancelled);
+ }
+
+ @PostMapping("cancel")
+ public ResponseEntity<Map<String, Object>> cancelAllEvent() throws SchedulerException {
+ LOGGER.info(ENTRY, "Cancel called on all jobs");
+ boolean isCancelled = simulatorService.cancelAllEvents();
+ return createCancelEventResponse(isCancelled);
+ }
+
+ @PostMapping("event")
+ public ResponseEntity<Map<String, Object>> sendEventDirectly(@RequestHeader HttpHeaders headers, @Valid @RequestBody FullEvent event)
+ throws IOException, GeneralSecurityException {
+ logContextHeaders(headers, "/simulator/event");
+ LOGGER.info(ENTRY, "Trying to send one-time event directly to VES Collector");
+ HttpResponseAdapter response = simulatorService.triggerOneTimeEvent(event);
+ return buildResponse(response);
+ }
+
+ private String replaceBreakingCharacters(String jobName) {
+ return jobName.replaceAll(BREAKING_CHARACTER_REGEX, "_");
+ }
+
+ private ResponseEntity<Map<String, Object>> processRequest(SimulatorRequest triggerEventRequest)
+ throws IOException, SchedulerException, GeneralSecurityException {
+
+ String jobName = simulatorService.triggerEvent(triggerEventRequest);
+ MDC.put(RESPONSE_CODE, OK.toString());
+ return buildResponse(OK, ImmutableMap.of(MESSAGE, "Request started", "jobName", jobName));
+ }
+
+ private ResponseEntity<Map<String, Object>> buildResponse(HttpStatus endStatus, Map<String, Object> parameters) {
+ ResponseBuilder builder = ResponseBuilder
+ .status(endStatus)
+ .put(TIMESTAMP, DateUtil.getTimestamp(responseDateFormat));
+ parameters.forEach(builder::put);
+ return builder.build();
+ }
+
+ private ResponseEntity<Map<String, Object>> buildResponse(HttpResponseAdapter response) {
+ HttpStatus status = HttpStatus.valueOf(response.getCode());
+ Map<String, Object> parameters;
+ if (response.getMessage().isEmpty()) {
+ parameters = Map.of(MESSAGE, "One-time direct event sent successfully");
+ } else {
+ parameters = Map.of(MESSAGE, response.getMessage());
+ }
+ return buildResponse(status, parameters);
+ }
+
+ private void logContextHeaders(HttpHeaders headers, String serviceName) {
+ MDC.put(REQUEST_ID, headers.getFirst(X_ONAP_REQUEST_ID));
+ MDC.put(INVOCATION_ID, headers.getFirst(X_INVOCATION_ID));
+ MDC.put(INSTANCE_UUID, UUID.randomUUID().toString());
+ MDC.put(SERVICE_NAME, serviceName);
+ }
+
+ private ResponseEntity<Map<String, Object>> createCancelEventResponse(boolean isCancelled) {
+ if (isCancelled) {
+ return buildResponse(OK, ImmutableMap.of(MESSAGE, "Event(s) was cancelled"));
+ } else {
+ return buildResponse(NOT_FOUND, ImmutableMap.of(MESSAGE, "Simulator was not able to cancel event(s)"));
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java b/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java
new file mode 100644
index 0000000..8f8fee7
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/TemplateController.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Optional;
+import javax.validation.Valid;
+
+import com.google.gson.Gson;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.rest.model.TemplateRequest;
+import org.onap.pnfsimulator.rest.model.SearchExp;
+import org.onap.pnfsimulator.template.Template;
+import org.onap.pnfsimulator.template.search.IllegalJsonValueException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
+
+
+@RestController
+@RequestMapping("/template")
+public class TemplateController {
+ static final String TEMPLATE_NOT_FOUND_MSG = "A template with given name does not exist";
+ static final String CANNOT_OVERRIDE_TEMPLATE_MSG = "Cannot overwrite existing template. Use override=true to override";
+ private final Storage<Template> service;
+
+ @Autowired
+ public TemplateController(Storage<Template> service) {
+ this.service = service;
+ }
+
+ @GetMapping("list")
+ public ResponseEntity<List<Template>> list() {
+ return new ResponseEntity<>(service.getAll(), HttpStatus.OK);
+ }
+
+ @GetMapping("get/{templateName}")
+ public ResponseEntity<String> get(@PathVariable String templateName) {
+ Optional<Template> template = service.get(templateName);
+ return template
+ .map(this::createTemplateResponse)
+ .orElse(this.createTemplateNotFoundResponse());
+ }
+
+ private ResponseEntity<String> createTemplateResponse(Template template) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
+ return new ResponseEntity<>(new Gson().toJson(template),headers, HttpStatus.OK);
+ }
+
+ private ResponseEntity<String> createTemplateNotFoundResponse() {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.TEXT_PLAIN);
+ return new ResponseEntity<>(TEMPLATE_NOT_FOUND_MSG, headers, HttpStatus.NOT_FOUND);
+ }
+
+ @PostMapping("upload")
+ public ResponseEntity<String> upload(
+ @RequestBody @Valid TemplateRequest templateRequest,
+ @RequestParam(required = false) boolean override) {
+ String msg = "";
+ HttpStatus status = HttpStatus.CREATED;
+ Template template = new Template(templateRequest.getName(), templateRequest.getTemplate(), Instant.now().getNano());
+ if (!service.tryPersistOrOverwrite(template, override)) {
+ status = HttpStatus.CONFLICT;
+ msg = CANNOT_OVERRIDE_TEMPLATE_MSG;
+ }
+ return new ResponseEntity<>(msg, status);
+ }
+
+ @PostMapping("search")
+ public ResponseEntity<List<String>> searchByCriteria(@RequestBody SearchExp queryJson) {
+ try {
+ List<String> templateNames = service.getIdsByContentCriteria(queryJson.getSearchExpr());
+ return new ResponseEntity<>(templateNames, HttpStatus.OK);
+ } catch (IllegalJsonValueException ex) {
+ throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format("Try again with correct parameters. Cause: %s", ex.getMessage()), ex);
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java b/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java
new file mode 100644
index 0000000..77d9b3d
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/model/FullEvent.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * FULL-EVENT
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.model;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.gson.JsonObject;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer;
+import org.springframework.lang.Nullable;
+
+import javax.validation.constraints.NotNull;
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@ToString
+@EqualsAndHashCode
+public class FullEvent {
+
+ @Nullable
+ private String vesServerUrl;
+
+ @NotNull
+ @JsonDeserialize(using = JsonObjectDeserializer.class)
+ private JsonObject event;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java b/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java
new file mode 100644
index 0000000..41d112f
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/model/SearchExp.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.model;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.gson.JsonObject;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+public class SearchExp {
+
+ @NotNull
+ @JsonDeserialize(using = JsonObjectDeserializer.class)
+ private JsonObject searchExpr;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java b/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java
new file mode 100644
index 0000000..787583e
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorParams.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.model;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import org.springframework.lang.Nullable;
+
+@Getter
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class SimulatorParams {
+
+ @NotNull
+ private String vesServerUrl;
+
+ @Nullable
+ private Integer repeatInterval;
+
+ @Nullable
+ private Integer repeatCount;
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java b/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java
new file mode 100644
index 0000000..d00b311
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/model/SimulatorRequest.java
@@ -0,0 +1,55 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.model;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.gson.JsonObject;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.pnfsimulator.rest.util.JsonObjectDeserializer;
+import org.springframework.lang.Nullable;
+
+@Getter
+@ToString
+@EqualsAndHashCode
+@AllArgsConstructor
+@NoArgsConstructor
+public class SimulatorRequest {
+
+ @NotNull
+ private SimulatorParams simulatorParams;
+
+ @NotNull
+ private String templateName;
+
+ @Nullable
+ @JsonDeserialize(using = JsonObjectDeserializer.class)
+ private JsonObject patch;
+
+ @Nullable
+ @JsonDeserialize(using = JsonObjectDeserializer.class)
+ private JsonObject variables;
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java b/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java
new file mode 100644
index 0000000..f1e0243
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/model/TemplateRequest.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.bson.Document;
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@ToString
+public class TemplateRequest {
+ private String name;
+ private Document template;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java b/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java
new file mode 100644
index 0000000..9a5c9ca
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/util/DateUtil.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.util;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+public final class DateUtil {
+
+ private DateUtil() {
+ }
+
+ public static String getTimestamp(DateFormat dateFormat) {
+
+ return dateFormat.format(new Date());
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java b/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java
new file mode 100644
index 0000000..f89c4a7
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/util/JsonObjectDeserializer.java
@@ -0,0 +1,42 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.util;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+
+public class JsonObjectDeserializer extends JsonDeserializer<JsonObject> {
+ private Gson gson = new Gson();
+
+ @Override
+ public JsonObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
+ ObjectCodec oc = jsonParser.getCodec();
+ JsonNode node = oc.readTree(jsonParser);
+ return gson.fromJson(node.toString(), JsonObject.class);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java b/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java
new file mode 100644
index 0000000..1fdd7cf
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/rest/util/ResponseBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+public class ResponseBuilder {
+
+ public static final String TIMESTAMP = "timestamp";
+ public static final String MESSAGE = "message";
+ public static final String SIMULATOR_STATUS = "simulatorStatus";
+ public static final String REMAINING_TIME = "remainingTime";
+
+ private HttpStatus httpStatus;
+ private Map<String, Object> body = new LinkedHashMap<>();
+
+ private ResponseBuilder(HttpStatus httpStatus) {
+ this.httpStatus = httpStatus;
+ }
+
+ public static ResponseBuilder status(HttpStatus httpStatus) {
+
+ return new ResponseBuilder(httpStatus);
+ }
+
+ public ResponseBuilder put(String key, Object value) {
+
+ body.put(key, value);
+ return this;
+ }
+
+ public ResponseEntity<Map<String,Object>> build() {
+
+ if (body.isEmpty()) {
+ return ResponseEntity.status(httpStatus).build();
+ }
+
+ return ResponseEntity.status(httpStatus).body(body);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java
new file mode 100644
index 0000000..878591b
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/DbTemplateReader.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+
+import org.onap.pnfsimulator.template.Template;
+import org.onap.pnfsimulator.template.TemplateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DbTemplateReader implements TemplateReader {
+ private final TemplateService service;
+ private final Gson gson;
+
+ @Autowired
+ public DbTemplateReader(TemplateService service, Gson gson) {
+ this.service = service;
+ this.gson = gson;
+ }
+
+ @Override
+ public JsonObject readTemplate(String templateName) throws IOException {
+ Template template = service.get(templateName).orElseThrow(() -> new IOException("Template does not exist"));
+ JsonElement jsonElement = gson.toJsonTree(template.getContent());
+ return jsonElement.getAsJsonObject();
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java b/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java
new file mode 100644
index 0000000..01f6508
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/EventNotFoundException.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+public class EventNotFoundException extends RuntimeException {
+ private static final String NOT_FOUND = "Not found an event with id: ";
+
+ public EventNotFoundException(String eventId) {
+ super(NOT_FOUND + eventId);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java
new file mode 100644
index 0000000..a405a2e
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/FilesystemTemplateReader.java
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class FilesystemTemplateReader implements TemplateReader {
+
+ private final Path templatesDir;
+ private final Gson gson;
+
+ @Autowired
+ FilesystemTemplateReader(@Value("${templates.dir}") String templatesDir, Gson gson) {
+ this.templatesDir = Paths.get(templatesDir);
+ this.gson = gson;
+ }
+
+ public JsonObject readTemplate(String templateFileName) throws IOException {
+ Path absTemplateFilePath = templatesDir.resolve(templateFileName);
+ try (Stream<String> lines = Files.lines(absTemplateFilePath)) {
+ String content = lines.collect(Collectors.joining("\n"));
+ return gson.fromJson(content, JsonObject.class);
+ }
+ }
+}
+
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java
new file mode 100644
index 0000000..4a7cf02
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProvider.java
@@ -0,0 +1,26 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+@FunctionalInterface
+public interface IncrementProvider {
+ int getAndIncrement(String id);
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java
new file mode 100644
index 0000000..9d4d3ec
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/IncrementProviderImpl.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class IncrementProviderImpl implements IncrementProvider {
+ private final EventDataRepository repository;
+
+ @Autowired
+ public IncrementProviderImpl(EventDataRepository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ public int getAndIncrement(String id) {
+ EventData eventData = repository.findById(id)
+ .orElseThrow(() -> new EventNotFoundException(id));
+ int value = eventData.getIncrementValue() + 1;
+ eventData.setIncrementValue(value);
+ repository.save(eventData);
+ return value;
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java b/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java
new file mode 100644
index 0000000..da0026a
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/JsonTokenProcessor.java
@@ -0,0 +1,134 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public enum JsonTokenProcessor {
+ STRING(JsonToken.STRING) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ String originalString = reader.nextString();
+ if (keywordsExtractor.isPrimitive(originalString)) {
+ writer.value(keywordsExtractor.substitutePrimitiveKeyword(originalString));
+ } else {
+ String possibleSubstitution = Arrays.stream(originalString.split(" "))
+ .map(singleWord -> keywordsExtractor.substituteStringKeyword(singleWord, incrementValue)).collect(
+ Collectors.joining(" "));
+ writer.value(originalString.equals(possibleSubstitution) ? originalString : possibleSubstitution);
+ }
+ }
+ },
+ BEGIN_ARRAY(JsonToken.BEGIN_ARRAY) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ reader.beginArray();
+ writer.beginArray();
+ }
+ },
+ END_ARRAY(JsonToken.END_ARRAY) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ reader.endArray();
+ writer.endArray();
+ }
+ },
+ BEGIN_OBJECT(JsonToken.BEGIN_OBJECT) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ reader.beginObject();
+ writer.beginObject();
+ }
+ },
+ END_OBJECT(JsonToken.END_OBJECT) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ reader.endObject();
+ writer.endObject();
+ }
+ },
+ NAME(JsonToken.NAME) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ writer.name(reader.nextName());
+ }
+ },
+ NUMBER(JsonToken.NUMBER) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ writer.value(new BigDecimal(reader.nextString()));
+ }
+ },
+ BOOLEAN(JsonToken.BOOLEAN) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ writer.value(reader.nextBoolean());
+ }
+ },
+ NULL(JsonToken.NULL) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ reader.nextNull();
+ writer.nullValue();
+ }
+ },
+ END_DOCUMENT(JsonToken.END_DOCUMENT) {
+ @Override
+ void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor)
+ throws IOException {
+ // do nothing
+ }
+ };
+
+ private JsonToken jsonToken;
+
+ JsonTokenProcessor(JsonToken jsonToken) {
+ this.jsonToken = jsonToken;
+ }
+
+ boolean isProcessorFor(JsonToken jsonToken) {
+ return this.jsonToken == jsonToken;
+ }
+
+ abstract void process(JsonReader reader, JsonWriter writer, int incrementValue, KeywordsExtractor keywordsExtractor) throws IOException;
+
+ private static final String INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN = "Invalid json body. Unsupported JsonToken.";
+
+ static JsonTokenProcessor getProcessorFor(JsonToken jsonToken) throws IOException {
+ return Arrays.stream(JsonTokenProcessor.values()).filter(processor -> processor.isProcessorFor(jsonToken)).findFirst()
+ .orElseThrow(() -> new IOException(INVALID_JSON_BODY_UNSUPPORTED_JSON_TOKEN));
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java
new file mode 100644
index 0000000..2dc52a1
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsExtractor.java
@@ -0,0 +1,129 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static io.vavr.API.$;
+import static io.vavr.API.Case;
+import static io.vavr.API.Match;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getEpochSecond;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedInteger;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomInteger;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomLimitedString;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomString;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getRandomPrimitiveInteger;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.getTimestampPrimitive;
+import static org.onap.pnfsimulator.simulator.keywords.NonParameterKeywordPatterns.$nonParameterKeyword;
+import static org.onap.pnfsimulator.simulator.keywords.SingleParameterKeywordPatterns.$singleParameterKeyword;
+import static org.onap.pnfsimulator.simulator.keywords.TwoParameterKeywordPatterns.$twoParameterKeyword;
+
+import io.vavr.API.Match.Pattern1;
+import org.onap.pnfsimulator.simulator.keywords.Keyword;
+import org.onap.pnfsimulator.simulator.keywords.NonParameterKeyword;
+import org.onap.pnfsimulator.simulator.keywords.SingleParameterKeyword;
+import org.onap.pnfsimulator.simulator.keywords.TwoParameterKeyword;
+import org.springframework.stereotype.Component;
+
+@Component
+public class KeywordsExtractor {
+
+ String substituteStringKeyword(String text, int increment) {
+ return Match(text).of(
+ Case(isRandomStringParamKeyword(),
+ spk -> spk.substituteKeyword(getRandomString().apply(spk.getAdditionalParameter()))
+ ),
+ Case(isRandomStringNonParamKeyword(),
+ npk -> npk.substituteKeyword(getRandomLimitedString().apply())
+ ),
+ Case(isRandomIntegerParamKeyword(),
+ tpk -> tpk.substituteKeyword(getRandomInteger().apply(
+ tpk.getAdditionalParameter1(),
+ tpk.getAdditionalParameter2()
+ )
+ )
+ ),
+ Case(isRandomIntegerNonParamKeyword(),
+ npk -> npk.substituteKeyword(getRandomLimitedInteger().apply())
+ ),
+ Case(isIncrementKeyword(),
+ ik -> ik.substituteKeyword(String.valueOf(increment))
+ ),
+ Case(isTimestampNonParamKeyword(),
+ npk -> npk.substituteKeyword(getEpochSecond().apply())
+ ),
+ Case(
+ $(),
+ () -> text
+ ));
+ }
+
+ Long substitutePrimitiveKeyword(String text) {
+ return Match(text).of(
+ Case(isRandomPrimitiveIntegerParamKeyword(),
+ tpk ->
+ getRandomPrimitiveInteger().apply(tpk.getAdditionalParameter1(), tpk.getAdditionalParameter2())),
+ Case(isTimestampPrimitiveNonParamKeyword(),
+ tpk ->
+ getTimestampPrimitive().apply()),
+ Case(
+ $(),
+ () -> 0L
+ ));
+ }
+
+ boolean isPrimitive(String text) {
+ return Match(text).of(
+ Case(isRandomPrimitiveIntegerParamKeyword(), () -> true),
+ Case(isTimestampPrimitiveNonParamKeyword(), () -> true),
+ Case($(), () -> false));
+ }
+
+ private Pattern1<String, SingleParameterKeyword> isRandomStringParamKeyword() {
+ return $singleParameterKeyword($(spk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(spk, "RandomString")));
+ }
+
+ private Pattern1<String, NonParameterKeyword> isRandomStringNonParamKeyword() {
+ return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomString")));
+ }
+
+ private Pattern1<String, NonParameterKeyword> isIncrementKeyword() {
+ return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Increment")));
+ }
+
+ private Pattern1<String, TwoParameterKeyword> isRandomIntegerParamKeyword() {
+ return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomInteger")));
+ }
+
+ private Pattern1<String, TwoParameterKeyword> isRandomPrimitiveIntegerParamKeyword() {
+ return $twoParameterKeyword($(tpk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(tpk, "RandomPrimitiveInteger")));
+ }
+
+ private Pattern1<String, NonParameterKeyword> isTimestampPrimitiveNonParamKeyword() {
+ return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "TimestampPrimitive")));
+ }
+
+ private Pattern1<String, NonParameterKeyword> isRandomIntegerNonParamKeyword() {
+ return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "RandomInteger")));
+ }
+
+ private Pattern1<String, NonParameterKeyword> isTimestampNonParamKeyword() {
+ return $nonParameterKeyword($(npk -> Keyword.IS_MATCHING_KEYWORD_NAME.apply(npk, "Timestamp")));
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java
new file mode 100644
index 0000000..ac80647
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandler.java
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class KeywordsHandler {
+
+ private KeywordsExtractor keywordsExtractor;
+ private IncrementProvider incrementProvider;
+
+ public KeywordsHandler(KeywordsExtractor keywordsExtractor, IncrementProvider incrementProvider) {
+ this.keywordsExtractor = keywordsExtractor;
+ this.incrementProvider = incrementProvider;
+ }
+
+ public JsonElement substituteKeywords(JsonElement jsonBody, String jobId) {
+ int counter = incrementProvider.getAndIncrement(jobId);
+ try (
+ JsonReader reader = new JsonReader(new StringReader(jsonBody.toString()));
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ ) {
+ modify(reader, jsonWriter, counter);
+ return new Gson().fromJson(stringWriter.getBuffer().toString(), JsonElement.class);
+ } catch (IOException e) {
+ throw new KeywordsHandlerException(e);
+ }
+ }
+
+ private void modify(JsonReader reader, JsonWriter writer, int incrementValue) throws IOException {
+ JsonTokenProcessor jsonTokenProcessor;
+ do {
+ JsonToken token = reader.peek();
+ jsonTokenProcessor = JsonTokenProcessor.getProcessorFor(token);
+ jsonTokenProcessor.process(reader, writer, incrementValue, keywordsExtractor);
+ } while (isJsonProcessingFinished(jsonTokenProcessor));
+ }
+
+ private boolean isJsonProcessingFinished(JsonTokenProcessor jsonTokenProcessor) {
+ return !jsonTokenProcessor.isProcessorFor(JsonToken.END_DOCUMENT);
+ }
+
+}
+
+
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java
new file mode 100644
index 0000000..9685bc3
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsHandlerException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+public class KeywordsHandlerException extends RuntimeException {
+
+ public KeywordsHandlerException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java
new file mode 100644
index 0000000..3bcfa5b
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/KeywordsValueProvider.java
@@ -0,0 +1,80 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import io.vavr.Function0;
+import io.vavr.Function1;
+import io.vavr.Function2;
+
+import java.time.Instant;
+import java.util.Random;
+
+import org.apache.commons.lang3.RandomStringUtils;
+
+class KeywordsValueProvider {
+
+ private KeywordsValueProvider() {
+ }
+
+ static final int DEFAULT_STRING_LENGTH = 20;
+ public static final int RANDOM_INTEGER_MAX_LIMITATION = 9;
+ public static final int RANDOM_INTEGER_MIN_LIMITATION = 0;
+
+ private static Function2<Integer, Integer, Integer> bigger = (left, right) -> left >= right ? left : right;
+ private static Function2<Integer, Integer, Integer> smaller = (left, right) -> left < right ? left : right;
+ private static Function2<Integer, Integer, Integer> randomPrimitiveIntegerFromSortedRange = (min, max) -> new Random().nextInt(max - min + 1) + min;
+ private static Function2<Integer, Integer, String> randomIntegerFromSortedRange = (min, max) -> Integer.toString(new Random().nextInt(max - min + 1) + min);
+
+ private static Function1<Integer, String> randomString = RandomStringUtils::randomAscii;
+ private static Function2<Integer, Integer, String> randomInteger = (left, right) -> randomIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right));
+ private static Function0<String> randomLimitedInteger = () -> randomInteger.apply(RANDOM_INTEGER_MIN_LIMITATION, RANDOM_INTEGER_MAX_LIMITATION);
+ private static Function0<String> randomLimitedString = () -> RandomStringUtils.randomAscii(DEFAULT_STRING_LENGTH);
+ private static Function0<String> epochSecond = () -> Long.toString(Instant.now().getEpochSecond());
+ private static Function2<Integer, Integer, Long> randomPrimitiveInteger = (left, right) -> randomPrimitiveIntegerFromSortedRange.apply(smaller.apply(left, right), bigger.apply(left, right)).longValue();
+ private static Function0<Long> timestampPrimitive = () -> Instant.now().getEpochSecond();
+
+ public static Function1<Integer, String> getRandomString() {
+ return randomString;
+ }
+
+ public static Function2<Integer, Integer, String> getRandomInteger() {
+ return randomInteger;
+ }
+
+ public static Function0<String> getRandomLimitedInteger() {
+ return randomLimitedInteger;
+ }
+
+ public static Function0<String> getRandomLimitedString() {
+ return randomLimitedString;
+ }
+
+ public static Function0<String> getEpochSecond() {
+ return epochSecond;
+ }
+
+ public static Function2<Integer, Integer, Long> getRandomPrimitiveInteger() {
+ return randomPrimitiveInteger;
+ }
+
+ public static Function0<Long> getTimestampPrimitive() {
+ return timestampPrimitive;
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java b/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java
new file mode 100644
index 0000000..218dbc8
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/SimulatorService.java
@@ -0,0 +1,132 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.common.base.Strings;
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataService;
+import org.onap.pnfsimulator.rest.model.FullEvent;
+import org.onap.pnfsimulator.rest.model.SimulatorParams;
+import org.onap.pnfsimulator.rest.model.SimulatorRequest;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapter;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl;
+import org.onap.pnfsimulator.simulator.client.HttpResponseAdapter;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.onap.pnfsimulator.simulator.scheduler.EventScheduler;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfigService;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Optional;
+
+@Service
+public class SimulatorService {
+
+ private final TemplatePatcher templatePatcher;
+ private final TemplateVariablesReplacer templateVariablesReplacer;
+ private final TemplateReader templateReader;
+ private final EventDataService eventDataService;
+ private final EventScheduler eventScheduler;
+ private final SslAuthenticationHelper sslAuthenticationHelper;
+ private SimulatorConfigService simulatorConfigService;
+ private static final JsonObject EMPTY_JSON_OBJECT = new JsonObject();
+
+ @Autowired
+ public SimulatorService(
+ TemplatePatcher templatePatcher,
+ TemplateReader templateReader,
+ EventScheduler eventScheduler,
+ EventDataService eventDataService,
+ SimulatorConfigService simulatorConfigService,
+ TemplateVariablesReplacer templateVariablesReplacer,
+ SslAuthenticationHelper sslAuthenticationHelper) {
+ this.templatePatcher = templatePatcher;
+ this.templateReader = templateReader;
+ this.eventDataService = eventDataService;
+ this.eventScheduler = eventScheduler;
+ this.simulatorConfigService = simulatorConfigService;
+ this.templateVariablesReplacer = templateVariablesReplacer;
+ this.sslAuthenticationHelper = sslAuthenticationHelper;
+ }
+
+ public String triggerEvent(SimulatorRequest simulatorRequest) throws IOException, SchedulerException, GeneralSecurityException {
+ String templateName = simulatorRequest.getTemplateName();
+ SimulatorParams simulatorParams = simulatorRequest.getSimulatorParams();
+ JsonObject template = templateReader.readTemplate(templateName);
+ JsonObject input = Optional.ofNullable(simulatorRequest.getPatch()).orElse(new JsonObject());
+ JsonObject patchedJson = templatePatcher
+ .mergeTemplateWithPatch(template, input);
+ JsonObject variables = Optional.ofNullable(simulatorRequest.getVariables()).orElse(new JsonObject());
+ JsonObject patchedJsonWithVariablesSubstituted = templateVariablesReplacer.substituteVariables(patchedJson, variables);
+
+ JsonObject keywords = new JsonObject();
+
+ EventData eventData = eventDataService.persistEventData(template, patchedJsonWithVariablesSubstituted, input, keywords);
+
+ String targetVesUrl = getDefaultUrlIfNotProvided(simulatorParams.getVesServerUrl());
+ return eventScheduler
+ .scheduleEvent(targetVesUrl, Optional.ofNullable(simulatorParams.getRepeatInterval()).orElse(1),
+ Optional.ofNullable(simulatorParams.getRepeatCount()).orElse(1), simulatorRequest.getTemplateName(),
+ eventData.getId(),
+ patchedJsonWithVariablesSubstituted);
+ }
+
+ public HttpResponseAdapter triggerOneTimeEvent(FullEvent event) throws IOException, GeneralSecurityException {
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), id -> 1);
+ JsonObject withKeywordsSubstituted = keywordsHandler.substituteKeywords(event.getEvent(), "").getAsJsonObject();
+
+ HttpClientAdapter client = createHttpClientAdapter(event.getVesServerUrl());
+ eventDataService.persistEventData(EMPTY_JSON_OBJECT, withKeywordsSubstituted, event.getEvent(), EMPTY_JSON_OBJECT);
+
+ return client.send(withKeywordsSubstituted.toString());
+ }
+
+ public SimulatorConfig getConfiguration() {
+ return simulatorConfigService.getConfiguration();
+ }
+
+ public SimulatorConfig updateConfiguration(SimulatorConfig newConfig) {
+ return simulatorConfigService.updateConfiguration(newConfig);
+ }
+
+ public boolean cancelAllEvents() throws SchedulerException {
+ return eventScheduler.cancelAllEvents();
+ }
+
+ public boolean cancelEvent(String jobName) throws SchedulerException {
+ return eventScheduler.cancelEvent(jobName);
+ }
+
+ HttpClientAdapter createHttpClientAdapter(String vesServerUrl) throws IOException, GeneralSecurityException {
+ String targetVesUrl = getDefaultUrlIfNotProvided(vesServerUrl);
+ return new HttpClientAdapterImpl(targetVesUrl, sslAuthenticationHelper);
+ }
+
+ private String getDefaultUrlIfNotProvided(String vesUrlSimulatorParam) {
+ return Strings.isNullOrEmpty(vesUrlSimulatorParam)
+ ? simulatorConfigService.getConfiguration().getVesServerUrl().toString() : vesUrlSimulatorParam;
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java
new file mode 100644
index 0000000..1114d3c
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplatePatcher.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+class TemplatePatcher {
+
+ JsonObject mergeTemplateWithPatch(JsonObject templateJson, JsonObject patchJson) {
+ JsonObject template = templateJson.deepCopy();
+ patchTemplateNode(template, patchJson);
+ return template;
+ }
+
+ private void patchTemplateNode(JsonObject templateJson, JsonObject patchJson) {
+ for (Map.Entry<String, JsonElement> stringJsonElementEntry : patchJson.entrySet()) {
+ String patchKey = stringJsonElementEntry.getKey();
+ JsonElement patchValue = stringJsonElementEntry.getValue();
+ JsonElement templateElement = templateJson.get(patchKey);
+
+ if (!patchValue.isJsonObject() || templateElement == null || !templateElement.isJsonObject()) {
+ templateJson.remove(patchKey);
+ templateJson.add(patchKey, patchValue);
+ } else {
+ patchTemplateNode(templateElement.getAsJsonObject(), patchValue.getAsJsonObject());
+ }
+
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java
new file mode 100644
index 0000000..2471c08
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplateReader.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+
+public interface TemplateReader {
+ JsonObject readTemplate(String templateName) throws IOException;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java b/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java
new file mode 100644
index 0000000..eb0b141
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacer.java
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.Map.Entry;
+
+import lombok.val;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TemplateVariablesReplacer {
+ private static final Gson GSON = new Gson();
+ private static final String OBJECT_KEYWORD_MARK = "#";
+ private static final String ESCAPED_QUOTE = "\"";
+ private static final String STRING_KEYWORD_MARK = ESCAPED_QUOTE + OBJECT_KEYWORD_MARK + "%s" + ESCAPED_QUOTE;
+
+ JsonObject substituteVariables(JsonObject source, JsonObject variables) {
+ var result = source.toString();
+ for (val variable : variables.entrySet()) {
+ result = substituteVariable(result, variable);
+ }
+ return GSON.fromJson(result, JsonObject.class);
+ }
+
+ private String substituteVariable(String sourceAsString, Entry<String, JsonElement> variable) {
+ return sourceAsString.replaceAll(String.format(STRING_KEYWORD_MARK, variable.getKey()), variable.getValue().toString());
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java
new file mode 100644
index 0000000..36ba922
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactory.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class HttpApacheResponseAdapterFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpApacheResponseAdapterFactory.class);
+
+ public HttpResponseAdapter create(HttpResponse response) {
+ String message;
+ try {
+ message = EntityUtils.toString(response.getEntity());
+ } catch (IllegalArgumentException | IOException e) {
+ LOGGER.warn("Response from VES was empty");
+ message = "";
+ }
+ return new HttpResponseAdapter(response.getStatusLine().getStatusCode(), message);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java
new file mode 100644
index 0000000..8cb6aa2
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapter.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+public interface HttpClientAdapter {
+
+ HttpResponseAdapter send(String content);
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java
new file mode 100644
index 0000000..ba668fc
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImpl.java
@@ -0,0 +1,119 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.HttpClientFactoryFacade;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.UUID;
+
+import static org.onap.pnfsimulator.logging.MdcVariables.REQUEST_ID;
+import static org.onap.pnfsimulator.logging.MdcVariables.X_INVOCATION_ID;
+import static org.onap.pnfsimulator.logging.MdcVariables.X_ONAP_REQUEST_ID;
+
+public class HttpClientAdapterImpl implements HttpClientAdapter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientAdapterImpl.class);
+ private static final String CONTENT_TYPE = "Content-Type";
+ private static final String APPLICATION_JSON = "application/json";
+ private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+ private static final HttpApacheResponseAdapterFactory responseFactory = new HttpApacheResponseAdapterFactory();
+ private final HttpClient client;
+ private final String targetUrl;
+
+ public HttpClientAdapterImpl(String targetUrl, SslAuthenticationHelper sslAuthenticationHelper)
+ throws IOException, GeneralSecurityException {
+ this.client = HttpClientFactoryFacade.create(targetUrl, sslAuthenticationHelper);
+ this.targetUrl = targetUrl;
+ }
+
+ HttpClientAdapterImpl(HttpClient client, String targetUrl) {
+ this.client = client;
+ this.targetUrl = targetUrl;
+ }
+
+ @Override
+ public HttpResponseAdapter send(String content) {
+ HttpResponseAdapter vesResponse;
+ try {
+ HttpResponse response = sendAndRetrieve(content);
+ LOGGER.info(INVOKE, "Message sent, ves response code: {}", response.getStatusLine());
+ vesResponse = responseFactory.create(response);
+ EntityUtils.consumeQuietly(response.getEntity()); //response has to be fully consumed otherwise apache won't release connection
+ } catch (IOException | URISyntaxException e) {
+ LOGGER.warn("Error sending message to ves: {}", e.getMessage(), e.getCause());
+ vesResponse = new HttpResponseAdapter(421, String.format("Fail to connect with ves: %s", e.getMessage()));
+ }
+ return vesResponse;
+ }
+
+ private HttpResponse sendAndRetrieve(String content) throws IOException, URISyntaxException {
+ HttpPost request = createRequest(content);
+ HttpResponse httpResponse = client.execute(request);
+ request.releaseConnection();
+ return httpResponse;
+ }
+
+ private HttpPost createRequest(String content) throws UnsupportedEncodingException, URISyntaxException {
+ LOGGER.info("sending request using address: {}", this.targetUrl);
+ URI targetAddress = new URI(this.targetUrl);
+ HttpPost request = new HttpPost(targetAddress);
+ if(urlContainsUserInfo(targetAddress)) {
+ request.addHeader(HttpHeaders.AUTHORIZATION, getAuthenticationHeaderForUser(targetAddress.getUserInfo()));
+ }
+ StringEntity stringEntity = new StringEntity(content);
+ request.addHeader(CONTENT_TYPE, APPLICATION_JSON);
+ request.addHeader(X_ONAP_REQUEST_ID, MDC.get(REQUEST_ID));
+ request.addHeader(X_INVOCATION_ID, UUID.randomUUID().toString());
+ request.setEntity(stringEntity);
+ return request;
+ }
+
+ private boolean urlContainsUserInfo(URI targetAddress) {
+ return targetAddress.getUserInfo() != null && !targetAddress.getUserInfo().isEmpty();
+ }
+
+ private String getAuthenticationHeaderForUser(String userInfo) {
+ final byte[] encodedUserInfo = Base64.encodeBase64(
+ userInfo.getBytes(StandardCharsets.ISO_8859_1)
+ );
+ return String.format("Basic %s", new String(encodedUserInfo));
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java
new file mode 100644
index 0000000..e78b8a3
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/HttpResponseAdapter.java
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+public class HttpResponseAdapter {
+
+ private final int code;
+ private final String message;
+
+ public HttpResponseAdapter(int code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java
new file mode 100644
index 0000000..72af9e5
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactory.java
@@ -0,0 +1,53 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import javax.net.ssl.SSLContext;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.ssl.SSLContexts;
+
+class CertAuthSslContextFactory {
+
+ private final CertificateReader certificateReader;
+
+ CertAuthSslContextFactory(CertificateReader certificateReader) {
+ this.certificateReader = certificateReader;
+ }
+
+ SSLContext createSslContext(SslAuthenticationHelper sslAuthenticationHelper)
+ throws GeneralSecurityException, IOException {
+ final String keystorePasswordPath = sslAuthenticationHelper.getClientCertificatePasswordPath();
+
+ final KeyStore keystore = certificateReader.read(sslAuthenticationHelper.getClientCertificatePath(),
+ keystorePasswordPath, "PKCS12");
+ final KeyStore truststore = certificateReader.read(sslAuthenticationHelper.getTrustStorePath(),
+ sslAuthenticationHelper.getTrustStorePasswordPath(), "JKS");
+
+ return SSLContexts.custom()
+ .loadKeyMaterial(keystore, certificateReader.readPassword(keystorePasswordPath))
+ .loadTrustMaterial(truststore, new TrustSelfSignedStrategy())
+ .build();
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java
new file mode 100644
index 0000000..a42114b
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+
+class CertificateReader {
+
+ KeyStore read(String certificatePath, String passwordPath, String type) throws GeneralSecurityException, IOException {
+ try (InputStream keyStoreStream = new FileInputStream(certificatePath)) {
+ KeyStore keyStore = KeyStore.getInstance(type);
+ keyStore.load(keyStoreStream, readPassword(passwordPath));
+ return keyStore;
+ }
+ }
+
+ char[] readPassword(String passwordPath) throws IOException {
+ final String password = Files.readString(Path.of(passwordPath));
+ return PasswordConverter.convert(password);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java
new file mode 100644
index 0000000..ca57a64
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java
@@ -0,0 +1,104 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import io.vavr.control.Try;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+class HttpClientFactory {
+ private static final int CONNECTION_TIMEOUT = 1000;
+ private static final RequestConfig CONFIG = RequestConfig.custom()
+ .setConnectTimeout(CONNECTION_TIMEOUT)
+ .setConnectionRequestTimeout(CONNECTION_TIMEOUT)
+ .setSocketTimeout(CONNECTION_TIMEOUT)
+ .build();
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientFactory.class);
+ private final SSLContextFactory sslContextFactory;
+
+ HttpClientFactory(SSLContextFactory sslContextFactory) {
+ this.sslContextFactory = sslContextFactory;
+ }
+
+ HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException {
+ HttpClient client;
+ if (!sslAuthenticationHelper.isClientCertificateEnabled()) {
+ client = "https".equals(new URL(url).getProtocol()) ? createForHttps() : createBasic();
+ } else if (sslAuthenticationHelper.isStrictHostnameVerification()) {
+ client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new DefaultHostnameVerifier());
+ } else {
+ client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new NoopHostnameVerifier());
+ }
+ return client;
+ }
+
+ private HttpClient createForHttps() {
+ return Try.of(this::createSecuredTrustAlways)
+ .onFailure(this::logErrorMessage)
+ .getOrElse(createBasic());
+ }
+
+ private void logErrorMessage(Throwable e) {
+ String message = String.format(
+ "Could not initialize client due to SSL exception: %s. " +
+ "Default client without SSL support will be used instead." +
+ "\nCause: %s",
+ e.getMessage(),
+ e.getCause()
+ );
+ LOGGER.error(message, e);
+ }
+
+
+ private HttpClient createBasic() {
+ return HttpClientBuilder
+ .create()
+ .setDefaultRequestConfig(CONFIG)
+ .build();
+ }
+
+ private HttpClient createSecuredTrustAlways() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+ return createSecured(sslContextFactory.createTrustAlways(), new NoopHostnameVerifier());
+ }
+
+ private HttpClient createSecured(SSLContext trustAlways, HostnameVerifier hostnameVerifier) {
+ return HttpClients.custom()
+ .setSSLContext(trustAlways)
+ .setDefaultRequestConfig(CONFIG)
+ .setSSLHostnameVerifier(hostnameVerifier)
+ .build();
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java
new file mode 100644
index 0000000..dffd635
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import org.apache.http.client.HttpClient;
+
+public class HttpClientFactoryFacade {
+
+ private HttpClientFactoryFacade() {
+ }
+
+ private static final CertificateReader CERTIFICATE_READER = new CertificateReader();
+ private static final CertAuthSslContextFactory CERT_AUTH_SSL_CONTEXT_FACTORY = new CertAuthSslContextFactory(CERTIFICATE_READER);
+ private static final SSLContextFactory SSL_CONTEXT_FACTORY = new SSLContextFactory(CERT_AUTH_SSL_CONTEXT_FACTORY);
+ private static final HttpClientFactory HTTP_CLIENT_FACTORY = new HttpClientFactory(SSL_CONTEXT_FACTORY);
+
+ public static HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException {
+ return HTTP_CLIENT_FACTORY.create(url, sslAuthenticationHelper);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java
new file mode 100644
index 0000000..7a645ae
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java
@@ -0,0 +1,32 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.util.Optional;
+
+class PasswordConverter {
+ private PasswordConverter() {
+ }
+
+ static char[] convert(String password) {
+ return Optional.ofNullable(password).map(String::toCharArray).orElse(null);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java
new file mode 100644
index 0000000..b8dfe6f
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import javax.net.ssl.SSLContext;
+import org.apache.http.conn.ssl.TrustAllStrategy;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.ssl.SSLContextBuilder;
+
+class SSLContextFactory {
+ private static final TrustStrategy TRUST_STRATEGY_ALWAYS = new TrustAllStrategy();
+
+ private final CertAuthSslContextFactory certAuthSslContextFactory;
+
+ SSLContextFactory(CertAuthSslContextFactory certAuthSslContextFactory) {
+ this.certAuthSslContextFactory = certAuthSslContextFactory;
+ }
+ SSLContext create(SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException {
+ return certAuthSslContextFactory.createSslContext(sslAuthenticationHelper);
+ }
+
+ SSLContext createTrustAlways() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
+ return SSLContextBuilder.create().loadTrustMaterial(TRUST_STRATEGY_ALWAYS).build();
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java
new file mode 100644
index 0000000..271ad93
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import java.io.Serializable;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "ssl")
+@RefreshScope
+@Primary
+@Getter
+@Setter
+public class SslAuthenticationHelper implements Serializable {
+
+ private boolean clientCertificateEnabled;
+ private boolean strictHostnameVerification;
+ private String clientCertificatePath;
+ private String clientCertificatePasswordPath;
+ private String trustStorePath;
+ private String trustStorePasswordPath;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java
new file mode 100644
index 0000000..1bb1332
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/Keyword.java
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.keywords;
+
+import io.vavr.Function1;
+import io.vavr.Function2;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
+
+import lombok.Getter;
+
+@Getter
+public class Keyword {
+
+ protected static final String LETTERS_REGEX = "([a-zA-Z]+)";
+ protected static final String NONLETTERS_REGEX = "([^a-zA-Z]+)";
+
+ protected static final Function1<String, String> OPTIONAL =
+ regex -> regex + "?";
+
+ private final String name;
+ private final List<String> meaningfulParts;
+
+ public static final Function2<Keyword, String, Boolean> IS_MATCHING_KEYWORD_NAME = (keyword, key) ->
+ keyword != null && keyword.getName() != null && keyword.getName().equals(key);
+
+ /**
+ * Returns list of independent parts inside the keyword. Current implementation assumes that customer can join keywords with integer values, so
+ * keyword is decomposed to parts then some parts of the keyword is skipped because of replacement process.
+ *
+ * @param matcher - Matcher to check find independent groups inside the keyword
+ * @param skipGroups Informs this method about which groups should be consider as part of the replacement process
+ * @return list of independent parts inside the keywords
+ */
+ static List<String> extractPartsFrom(Matcher matcher, List<Integer> skipGroups) {
+ List<String> parts = new ArrayList<>();
+ for (int i = 1; i <= matcher.groupCount(); i++) {
+ if (matcher.group(i) != null && !skipGroups.contains(i)) {
+ parts.add(matcher.group(i));
+ }
+ }
+ return parts;
+ }
+
+ Keyword(String name, List<String> meaningfulParts) {
+ this.name = name;
+ this.meaningfulParts = meaningfulParts;
+ }
+
+ public String substituteKeyword(String substitution) {
+ return meaningfulParts.stream()
+ .map(part -> part.equals(name) ? substitution : part)
+ .collect(Collectors.joining());
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java
new file mode 100644
index 0000000..5e44550
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/NonParameterKeyword.java
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.keywords;
+
+import io.vavr.Tuple;
+import io.vavr.Tuple1;
+import io.vavr.match.annotation.Patterns;
+import io.vavr.match.annotation.Unapply;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.val;
+
+@Patterns
+@Getter
+@Setter
+public class NonParameterKeyword extends Keyword {
+
+ public static final int KEYWORD_NAME_GROUP = 2;
+
+ private static final String KEYWORD_REGEX = new StringBuilder()
+ .append(OPTIONAL.apply(NONLETTERS_REGEX))
+ .append("#")
+ .append(LETTERS_REGEX)
+ .append("(?!\\()")
+ .append(OPTIONAL.apply(NONLETTERS_REGEX))
+ .toString();
+
+ private NonParameterKeyword(String name, List<String> meaningfulParts) {
+ super(name, meaningfulParts);
+ }
+
+ @Unapply
+ static Tuple1<NonParameterKeyword> nonParameterKeyword(String keyword) {
+ val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword);
+ NonParameterKeyword npk = null;
+ if (matcher.find()) {
+ npk = new NonParameterKeyword(
+ matcher.group(KEYWORD_NAME_GROUP),
+ extractPartsFrom(matcher, Collections.emptyList())
+ );
+ }
+ return Tuple.of(npk);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java
new file mode 100644
index 0000000..b1c38c8
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/SingleParameterKeyword.java
@@ -0,0 +1,73 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.keywords;
+
+import io.vavr.Tuple;
+import io.vavr.Tuple1;
+import io.vavr.match.annotation.Patterns;
+import io.vavr.match.annotation.Unapply;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.val;
+
+@Patterns
+@Getter
+@Setter
+public class SingleParameterKeyword extends Keyword {
+
+ public static final int KEYWORD_NAME_GROUP = 2;
+ public static final int ADDITIONAL_PARAMETER_GROUP = 3;
+
+ private static final String KEYWORD_REGEX = new StringBuilder()
+ .append(OPTIONAL.apply(NONLETTERS_REGEX))
+ .append("#")
+ .append(LETTERS_REGEX)
+ .append("\\((\\d+)\\)")
+ .append(OPTIONAL.apply(NONLETTERS_REGEX))
+ .toString();
+ public static final int SKIPPED_GROUP_NUMBER = 3;
+
+ private Integer additionalParameter;
+
+ private SingleParameterKeyword(String name, List<String> meaningfulParts,
+ Integer additionalParameter) {
+ super(name, meaningfulParts);
+ this.additionalParameter = additionalParameter;
+ }
+
+ @Unapply
+ static Tuple1<SingleParameterKeyword> singleParameterKeyword(String keyword) {
+ val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword);
+ SingleParameterKeyword spk = null;
+ if (matcher.find()) {
+ spk = new SingleParameterKeyword(
+ matcher.group(KEYWORD_NAME_GROUP),
+ extractPartsFrom(matcher, Collections.singletonList(SKIPPED_GROUP_NUMBER)),
+ Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_GROUP))
+ );
+ }
+ return Tuple.of(spk);
+ }
+}
+
+
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java b/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java
new file mode 100644
index 0000000..6fecfa6
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeyword.java
@@ -0,0 +1,80 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.keywords;
+
+import io.vavr.Tuple;
+import io.vavr.Tuple1;
+import io.vavr.match.annotation.Patterns;
+import io.vavr.match.annotation.Unapply;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.val;
+
+@Patterns
+@Getter
+@Setter
+public class TwoParameterKeyword extends Keyword {
+
+ public static final int ADDITIONAL_PARAMETER_1_GROUP = 3;
+ public static final int ADDITIONAL_PARAMETER_2_GROUP = 4;
+ public static final int KEYWORD_NAME_GROUP = 2;
+ protected static final List<Integer> ADDITIONAL_PARAMETERS_GROUPS = Arrays.asList(ADDITIONAL_PARAMETER_1_GROUP, ADDITIONAL_PARAMETER_2_GROUP);
+
+ private static final String NON_LIMITED_NUMBER_REGEX = "\\((\\d+)";
+ private static final String COLON_REGEX = "\\s?,\\s?";
+ private static final String OPTIONAL_NUMBER_PARAM_REGEX = "(\\d+)\\)";
+
+ private static final String KEYWORD_REGEX = OPTIONAL.apply(NONLETTERS_REGEX)
+ + "#"
+ + LETTERS_REGEX
+ + NON_LIMITED_NUMBER_REGEX
+ + COLON_REGEX
+ + OPTIONAL_NUMBER_PARAM_REGEX
+ + OPTIONAL.apply(NONLETTERS_REGEX);
+
+ private Integer additionalParameter1;
+ private Integer additionalParameter2;
+
+ private TwoParameterKeyword(String name, List<String> meaningfulParts, Integer additionalParameter1,
+ Integer additionalParameter2) {
+ super(name, meaningfulParts);
+ this.additionalParameter1 = additionalParameter1;
+ this.additionalParameter2 = additionalParameter2;
+ }
+
+ @Unapply
+ static Tuple1<TwoParameterKeyword> twoParameterKeyword(String keyword) {
+ val matcher = Pattern.compile(KEYWORD_REGEX).matcher(keyword);
+ TwoParameterKeyword tpk = null;
+ if (matcher.find()) {
+ tpk = new TwoParameterKeyword(
+ matcher.group(KEYWORD_NAME_GROUP),
+ extractPartsFrom(matcher, ADDITIONAL_PARAMETERS_GROUPS),
+ Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_1_GROUP)),
+ Integer.parseInt(matcher.group(ADDITIONAL_PARAMETER_2_GROUP))
+ );
+ }
+ return Tuple.of(tpk);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java
new file mode 100644
index 0000000..a467370
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventJob.java
@@ -0,0 +1,99 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.scheduler;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.simulator.KeywordsHandler;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapter;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.security.GeneralSecurityException;
+import java.util.Optional;
+
+public class EventJob implements Job {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(EventJob.class);
+
+ static final String TEMPLATE_NAME = "TEMPLATE_NAME";
+ static final String VES_URL = "VES_URL";
+ static final String BODY = "BODY";
+ static final String CLIENT_ADAPTER = "CLIENT_ADAPTER";
+ static final String KEYWORDS_HANDLER = "KEYWORDS_HANDLER";
+ static final String EVENT_ID = "EVENT_ID";
+
+ @Override
+ public void execute(JobExecutionContext jobExecutionContext) {
+ JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
+ String templateName = jobDataMap.getString(TEMPLATE_NAME);
+ String vesUrl = jobDataMap.getString(VES_URL);
+ JsonObject body = (JsonObject) jobDataMap.get(BODY);
+ String id = jobDataMap.getString(EVENT_ID);
+ Optional<HttpClientAdapter> httpClientAdapter = getHttpClientAdapter(jobDataMap, vesUrl);
+
+ if (httpClientAdapter.isPresent()) {
+ KeywordsHandler keywordsHandler = (KeywordsHandler) jobDataMap.get(KEYWORDS_HANDLER);
+ JsonElement processedBody = keywordsHandler.substituteKeywords(body, id);
+ String processedBodyString = processedBody.toString();
+ String jobKey = jobExecutionContext.getJobDetail().getKey().toString();
+
+ logEventDetails(templateName, vesUrl, body.toString(), jobKey);
+ httpClientAdapter.get().send(processedBodyString);
+ } else {
+ LOGGER.error("Could not send event as client is not available");
+ }
+ }
+
+ private Optional<HttpClientAdapter> getHttpClientAdapter(JobDataMap jobDataMap, String vesUrl) {
+ HttpClientAdapter adapter = null;
+ try {
+ adapter = (HttpClientAdapter) (jobDataMap.containsKey(CLIENT_ADAPTER) ? jobDataMap.get(CLIENT_ADAPTER)
+ : new HttpClientAdapterImpl(vesUrl, new SslAuthenticationHelper()));
+ adapter = (HttpClientAdapter) (
+ jobDataMap.containsKey(CLIENT_ADAPTER)
+ ? jobDataMap.get(CLIENT_ADAPTER)
+ : new HttpClientAdapterImpl(vesUrl, new SslAuthenticationHelper())
+ );
+ } catch (MalformedURLException e) {
+ LOGGER.error("Invalid format of vesServerUr: {}", vesUrl);
+ } catch (IOException | GeneralSecurityException e) {
+ LOGGER.error("Invalid configuration of client certificate");
+ }
+ return Optional.ofNullable(adapter);
+ }
+
+ private void logEventDetails(String templateName, String vesUrl, String body, String jobKey) {
+ LOGGER.info("Job {}:Sending event to {} from template {}",
+ jobKey, vesUrl, templateName);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Job {}: Request body {}", jobKey, body);
+ }
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java
new file mode 100644
index 0000000..5584cb1
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/EventScheduler.java
@@ -0,0 +1,120 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.scheduler;
+
+
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.simulator.KeywordsHandler;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapterImpl;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.quartz.JobBuilder;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SimpleTrigger;
+import org.quartz.TriggerBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.BODY;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.CLIENT_ADAPTER;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.EVENT_ID;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.KEYWORDS_HANDLER;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.TEMPLATE_NAME;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.VES_URL;
+import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
+
+@Component
+public class EventScheduler {
+
+
+ private final Scheduler scheduler;
+ private final KeywordsHandler keywordsHandler;
+ private final SslAuthenticationHelper sslAuthenticationHelper;
+
+ @Autowired
+ public EventScheduler(Scheduler scheduler, KeywordsHandler keywordsHandler, SslAuthenticationHelper sslAuthenticationHelper) {
+ this.scheduler = scheduler;
+ this.keywordsHandler = keywordsHandler;
+ this.sslAuthenticationHelper = sslAuthenticationHelper;
+ }
+
+ public String scheduleEvent(String vesUrl, Integer repeatInterval, Integer repeatCount,
+ String templateName, String eventId, JsonObject body)
+ throws SchedulerException, IOException, GeneralSecurityException {
+
+ JobDetail jobDetail = createJobDetail(vesUrl, templateName, eventId, body);
+ SimpleTrigger trigger = createTrigger(repeatInterval, repeatCount);
+
+ scheduler.scheduleJob(jobDetail, trigger);
+ return jobDetail.getKey().getName();
+ }
+
+ public boolean cancelAllEvents() throws SchedulerException {
+ List<JobKey> jobKeys = getActiveJobsKeys();
+ return scheduler.deleteJobs(jobKeys);
+ }
+
+ public boolean cancelEvent(String jobName) throws SchedulerException {
+ Optional<JobKey> activeJobKey = getActiveJobsKeys().stream().filter(e -> e.getName().equals(jobName)).findFirst();
+ return activeJobKey.isPresent() && scheduler.deleteJob(activeJobKey.get());
+ }
+
+ private SimpleTrigger createTrigger(int interval, int repeatCount) {
+ return TriggerBuilder.newTrigger()
+ .withSchedule(simpleSchedule()
+ .withIntervalInSeconds(interval)
+ .withRepeatCount(repeatCount - 1))
+ .build();
+ }
+
+ private JobDetail createJobDetail(String vesUrl, String templateName, String eventId, JsonObject body) throws IOException, GeneralSecurityException {
+ JobDataMap jobDataMap = new JobDataMap();
+ jobDataMap.put(TEMPLATE_NAME, templateName);
+ jobDataMap.put(VES_URL, vesUrl);
+ jobDataMap.put(EVENT_ID, eventId);
+ jobDataMap.put(KEYWORDS_HANDLER, keywordsHandler);
+ jobDataMap.put(BODY, body);
+ jobDataMap.put(CLIENT_ADAPTER, new HttpClientAdapterImpl(vesUrl, sslAuthenticationHelper));
+
+ return JobBuilder
+ .newJob(EventJob.class)
+ .withDescription(templateName)
+ .usingJobData(jobDataMap)
+ .build();
+ }
+
+ private List<JobKey> getActiveJobsKeys() throws SchedulerException {
+ return scheduler.getCurrentlyExecutingJobs()
+ .stream()
+ .map(JobExecutionContext::getJobDetail)
+ .map(JobDetail::getKey)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java
new file mode 100644
index 0000000..2beb9dc
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulator/scheduler/QuartzConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.scheduler;
+
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+class QuartzConfiguration {
+
+ @Bean
+ Scheduler provideScheduler() throws SchedulerException {
+ StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
+ Scheduler scheduler = stdSchedulerFactory.getScheduler();
+ scheduler.start();
+ return scheduler;
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java
new file mode 100644
index 0000000..0baa477
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfig.java
@@ -0,0 +1,49 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulatorconfig;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Field;
+
+import javax.validation.constraints.NotNull;
+import java.net.URL;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+public class SimulatorConfig {
+
+ @JsonIgnore
+ @Id
+ private String id;
+
+ @NotNull
+ @Field("vesServerUrl")
+ private URL vesServerUrl;
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java
new file mode 100644
index 0000000..5e63ee4
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigRepository.java
@@ -0,0 +1,26 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulatorconfig;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+public interface SimulatorConfigRepository extends MongoRepository<SimulatorConfig, String> {
+}
diff --git a/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java
new file mode 100644
index 0000000..2063351
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigService.java
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulatorconfig;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class SimulatorConfigService {
+
+ private final SimulatorConfigRepository repository;
+
+ @Autowired
+ public SimulatorConfigService(SimulatorConfigRepository repository) {
+ this.repository = repository;
+ }
+
+
+ public SimulatorConfig getConfiguration() {
+ List<SimulatorConfig> configs = repository.findAll();
+ if (configs.isEmpty()) {
+ throw new IllegalStateException("No configuration found in db");
+ }
+ return configs.get(0);
+ }
+
+ public SimulatorConfig updateConfiguration(SimulatorConfig configuration) {
+ SimulatorConfig currentConfig = getConfiguration();
+ currentConfig.setVesServerUrl(configuration.getVesServerUrl());
+ return repository.save(currentConfig);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java b/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java
new file mode 100644
index 0000000..0080813
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizer.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import org.bson.json.JsonParseException;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.filesystem.WatcherEventProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+@Service
+public class FsToDbTemplateSynchronizer {
+
+ private static final String CANNOT_SYNC = "Cannot synchronize templates. Check whether the proper folder exists.";
+ private static final Logger LOGGER = LoggerFactory.getLogger(FsToDbTemplateSynchronizer.class);
+
+ private final String templatesDir;
+ private final Storage<Template> storage;
+
+ @Autowired
+ public FsToDbTemplateSynchronizer(@Value("${templates.dir}") String templatesDir,
+ Storage<Template> storage) {
+ this.templatesDir = templatesDir;
+ this.storage = storage;
+ }
+
+ public void synchronize() {
+ try {
+ processTemplatesFolder();
+ } catch (IOException e) {
+ LOGGER.error(CANNOT_SYNC, e);
+ }
+ }
+
+ private void processTemplatesFolder() throws IOException {
+ try (Stream<Path> walk = Files.walk(Paths.get(templatesDir))) {
+ walk.filter(Files::isRegularFile).forEach(path -> {
+ try {
+ WatcherEventProcessor.MODIFIED.processEvent(path, storage);
+ } catch (IOException | JsonParseException e) {
+ LOGGER
+ .error("Cannot synchronize template: {}", path.getFileName(), e);
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/Template.java b/src/main/java/org/onap/pnfsimulator/template/Template.java
new file mode 100644
index 0000000..121d7d4
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/Template.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.pnfsimulator.db.Row;
+import org.bson.Document;
+import org.onap.pnfsimulator.template.search.JsonUtils;
+import org.springframework.data.mongodb.core.mapping.Field;
+
+@NoArgsConstructor
+@ToString
+public class Template extends Row {
+
+ @Field("content")
+ private Document content;
+
+ @Field("flatContent")
+ private Document flatContent;
+
+ @Field("lmod")
+ private long lmod;
+
+ public Template(String name, Document content, long lmod) {
+ this.setId(name);
+ this.content = content;
+ this.lmod = lmod;
+ this.flatContent = new JsonUtils().flatten(content);
+ }
+
+ public Template(String name, String template, long lmod) {
+ this.setId(name);
+ this.content = Document.parse(template);
+ this.lmod = lmod;
+ this.flatContent = new JsonUtils().flatten(this.content);
+ }
+
+ public void setContent(Document content) {
+ this.content = content;
+ this.flatContent = new JsonUtils().flatten(content);
+ }
+
+ public Document getContent() {
+ return new Document(this.content);
+ }
+
+ @JsonIgnore
+ public Document getFlatContent() {
+ return new Document(this.flatContent);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+ Template template = (Template) object;
+ return Objects.equals(content, template.content)
+ && Objects.equals(getId(), template.getId())
+ && Objects.equals(lmod, template.lmod);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(content, getId());
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java b/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java
new file mode 100644
index 0000000..78c9c77
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/TemplateRepository.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+public interface TemplateRepository extends MongoRepository<Template, String> {
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/TemplateService.java b/src/main/java/org/onap/pnfsimulator/template/TemplateService.java
new file mode 100644
index 0000000..3e245e1
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/TemplateService.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.template.search.TemplateSearchHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+
+@Primary
+@Service
+public class TemplateService implements Storage<Template> {
+
+ private final TemplateRepository templateRepository;
+ private TemplateSearchHelper searchHelper;
+
+
+ @Autowired
+ public TemplateService(TemplateRepository templateRepository, TemplateSearchHelper searchHelper) {
+ this.templateRepository = templateRepository;
+ this.searchHelper = searchHelper;
+ }
+
+ @Override
+ public List<Template> getAll() {
+ return templateRepository.findAll();
+ }
+
+ @Override
+ public Optional<Template> get(String name) {
+ return templateRepository.findById(name);
+ }
+
+ @Override
+ public void persist(Template template) {
+ templateRepository.save(template);
+ }
+
+ @Override
+ public boolean tryPersistOrOverwrite(Template template, boolean overwrite) {
+ if (templateRepository.existsById(template.getId()) && !overwrite) {
+ return false;
+ }
+ templateRepository.save(template);
+ return true;
+ }
+
+ @Override
+ public void delete(String templateName) {
+ templateRepository.deleteById(templateName);
+ }
+
+ @Override
+ public List<String> getIdsByContentCriteria(JsonObject stringQueryJson) {
+ return searchHelper.getIdsOfDocumentMatchingCriteria(stringQueryJson);
+ }
+
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java b/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java
new file mode 100644
index 0000000..1685536
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/IllegalJsonValueException.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search;
+
+public class IllegalJsonValueException extends IllegalArgumentException {
+
+ IllegalJsonValueException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java b/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java
new file mode 100644
index 0000000..b595b4f
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/JsonUtils.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search;
+
+import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.bson.Document;
+
+/**
+ * This util flattens nested json and produces json with keys transformed to form of json path
+ * where default separator between parent object key and object key is ':'
+ * For easing searching of boolean values, they are converted to its string representation
+ */
+public class JsonUtils {
+
+ private static final String DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR = ":";
+ private static final String SEED_PREFIX = "";
+ private static final Gson GSON = new Gson();
+
+ public JsonObject flatten(JsonObject original) {
+ return flattenWithPrefixedKeys(DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR, original.deepCopy(), SEED_PREFIX, new JsonObject());
+ }
+
+ public JsonObject flatten(String parentKeyToKeySeparator, JsonObject original) {
+ return flattenWithPrefixedKeys(parentKeyToKeySeparator, original.deepCopy(), SEED_PREFIX, new JsonObject());
+ }
+
+ public Document flatten(Document original) {
+ return flatten(DEFAULT_PARENT_KEY_TO_OBJECT_KEY_SEPARATOR, original);
+ }
+
+ public Document flatten(String parentKeyToKeySeparator, Document original) {
+ JsonObject originalJsonObject = GSON.fromJson(original.toJson(), JsonObject.class);
+ JsonObject flattenedJson = flatten(parentKeyToKeySeparator, originalJsonObject);
+ return Document.parse(flattenedJson.toString());
+ }
+
+ private JsonObject flattenWithPrefixedKeys(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) {
+ if (topLevelElem.isJsonPrimitive()) {
+ handleJsonPrimitive(topLevelElem, prefix, acc);
+ } else if (topLevelElem.isJsonArray()) {
+ handleJsonArray(parentKeyToKeySeparator, topLevelElem, prefix, acc);
+ } else if (topLevelElem.isJsonObject()) {
+ handleJsonObject(parentKeyToKeySeparator, topLevelElem, prefix, acc);
+ } else {
+ acc.add(prefix, topLevelElem.getAsJsonNull());
+ }
+ return acc.deepCopy();
+ }
+
+ private void handleJsonObject(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) {
+ boolean isEmpty = true;
+ JsonObject thisToplevelObj = topLevelElem.getAsJsonObject();
+ for (String key : thisToplevelObj.keySet()) {
+ isEmpty = false;
+ String keyPrefix = String.format("%s%s%s", prefix, parentKeyToKeySeparator, key);
+ flattenWithPrefixedKeys(parentKeyToKeySeparator, thisToplevelObj.get(key), keyPrefix, acc);
+ }
+ if (isEmpty && !Strings.isNullOrEmpty(prefix)) {
+ acc.add(prefix, new JsonObject());
+ }
+ }
+
+ private void handleJsonArray(String parentKeyToKeySeparator, JsonElement topLevelElem, String prefix, JsonObject acc) {
+ JsonArray asJsonArray = topLevelElem.getAsJsonArray();
+ if (asJsonArray.size() == 0) {
+ acc.add(prefix, new JsonArray());
+ }
+ for (int i = 0; i < asJsonArray.size(); i++) {
+ flattenWithPrefixedKeys(parentKeyToKeySeparator, asJsonArray.get(i), String.format("%s[%s]", prefix, i), acc);
+ }
+ }
+
+ private void handleJsonPrimitive(JsonElement topLevelElem, String prefix, JsonObject acc) {
+ JsonPrimitive jsonPrimitive = topLevelElem.getAsJsonPrimitive();
+ if (jsonPrimitive.isBoolean()) {
+ acc.add(prefix, new JsonPrimitive(jsonPrimitive.getAsString()));
+ } else {
+ acc.add(prefix, topLevelElem.getAsJsonPrimitive());
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java b/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java
new file mode 100644
index 0000000..3f22b1a
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/TemplateSearchHelper.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.template.search.handler.PrimitiveValueCriteriaBuilder;
+import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Component
+public class TemplateSearchHelper {
+ private static final String PARENT_TO_CHILD_KEY_SEPARATOR = ":"; //compliant with flat json stored in db
+ private static final String FLATTENED_JSON_KEY_REGEX = PARENT_TO_CHILD_KEY_SEPARATOR + "%s(?:(\\[[\\d]+\\]))?$";
+ private static final String FLATTENED_TEMPLATES_VIEW = "flatTemplatesView";
+
+ private MongoTemplate mongoTemplate;
+ private PrimitiveValueCriteriaBuilder criteriaBuilder;
+
+ @Autowired
+ public TemplateSearchHelper(MongoTemplate mongoTemplate) {
+ this.mongoTemplate = mongoTemplate;
+ this.criteriaBuilder = new PrimitiveValueCriteriaBuilder();
+ }
+
+ public List<String> getIdsOfDocumentMatchingCriteria(JsonObject jsonCriteria) {
+ if (isNullValuePresentInCriteria(jsonCriteria)) {
+ throw new IllegalJsonValueException("Null values in search criteria are not supported.");
+ }
+ Criteria mongoDialectCriteria = composeCriteria(jsonCriteria);
+ Query query = new Query(mongoDialectCriteria);
+ List<FlatTemplateContent> flatTemplateContents = mongoTemplate.find(query, FlatTemplateContent.class, FLATTENED_TEMPLATES_VIEW);
+ return flatTemplateContents
+ .stream()
+ .map(FlatTemplateContent::getId)
+ .collect(Collectors.toList());
+ }
+
+
+ private Criteria composeCriteria(JsonObject criteria) {
+ Criteria[] criteriaArr = criteria.entrySet()
+ .stream()
+ .map(this::mapEntryCriteriaWithRegex)
+ .toArray(Criteria[]::new);
+ return criteriaArr.length > 0 ? new Criteria().andOperator(criteriaArr) : new Criteria();
+ }
+
+ private Criteria mapEntryCriteriaWithRegex(Map.Entry<String, JsonElement> entry) {
+ Pattern primitiveOrArrayElemKeyRegex = getCaseInsensitive(String.format(FLATTENED_JSON_KEY_REGEX, entry.getKey()));
+ Criteria criteriaForJsonKey = Criteria.where("k").regex(primitiveOrArrayElemKeyRegex);
+ Criteria criteriaWithValue = criteriaBuilder.applyValueCriteriaBasedOnPrimitiveType(criteriaForJsonKey.and("v"), entry.getValue().getAsJsonPrimitive());
+ return Criteria.where("keyValues").elemMatch(criteriaWithValue);
+
+ }
+
+ private boolean isNullValuePresentInCriteria(JsonObject jsonObject) {
+ return jsonObject.entrySet()
+ .stream()
+ .map(Map.Entry::getValue)
+ .anyMatch(JsonElement::isJsonNull);
+ }
+
+ static Pattern getCaseInsensitive(String base) {
+ return Pattern.compile(base, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
+ }
+}
+
+
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java b/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java
new file mode 100644
index 0000000..79d64b7
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilder.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search.handler;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonPrimitive;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * This class is a helper class for constructing apropriate criteria for query send to mongodb based on type of value.
+ * Query is build to search mongodb for templates that contains key-value pairs that satisfy given criteria.
+ * Value is oftype JsonPrimitive, based on its primitive java type following criteria are build to get proper document:
+ * -for string - there is a regex expression that ignores every meta character inside passed argument and searches for exact literal match ignoring case;
+ * -for number - all numbers are treated as double (mongodb number type equivalent)
+ * -for boolean - exact match, used string representation of boolean in search
+ **/
+
+public class PrimitiveValueCriteriaBuilder {
+
+ private final List<ValueTypeHandler> typeHandlers;
+
+ public PrimitiveValueCriteriaBuilder() {
+ typeHandlers = Lists.newArrayList(new StringValueHandler(), new NumberValueHandler(), new BoolValueHandler());
+ }
+
+ public Criteria applyValueCriteriaBasedOnPrimitiveType(Criteria baseCriteria, JsonPrimitive jsonPrimitive) {
+ ValueTypeHandler typeHandler = typeHandlers.stream()
+ .filter(el -> el.isProperTypeHandler(jsonPrimitive))
+ .findFirst()
+ .orElseThrow(() ->
+ new IllegalArgumentException(String.format(
+ "Expected json primitive, but given value: %s is of type: %s and could not be decoded",
+ jsonPrimitive, jsonPrimitive.getClass().toString())));
+ return typeHandler.chainCriteriaForValue(baseCriteria, jsonPrimitive);
+ }
+
+ private interface ValueTypeHandler {
+ boolean isProperTypeHandler(JsonPrimitive value);
+
+ Criteria chainCriteriaForValue(Criteria criteria, JsonPrimitive value);
+ }
+
+ private class BoolValueHandler implements ValueTypeHandler {
+ public boolean isProperTypeHandler(JsonPrimitive value) {
+ return value.isBoolean();
+ }
+
+ public Criteria chainCriteriaForValue(Criteria criteria, JsonPrimitive value) {
+ return criteria.is(value.getAsString());
+ }
+
+ }
+
+ private class NumberValueHandler implements ValueTypeHandler {
+ public boolean isProperTypeHandler(JsonPrimitive value) {
+ return value.isNumber();
+ }
+
+ public Criteria chainCriteriaForValue(Criteria baseCriteria, JsonPrimitive value) {
+ return baseCriteria.is(value.getAsDouble());
+ }
+ }
+
+ private class StringValueHandler implements ValueTypeHandler {
+ public boolean isProperTypeHandler(JsonPrimitive value) {
+ return value.isString();
+ }
+
+ public Criteria chainCriteriaForValue(Criteria baseCriteria, JsonPrimitive value) {
+ return baseCriteria.regex(makeRegexCaseInsensitive(value.getAsString()));
+ }
+
+ private Pattern makeRegexCaseInsensitive(String base) {
+ String metaCharEscaped = convertToIgnoreMetaChars(base);
+ return Pattern.compile("^" + metaCharEscaped + "$", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
+ }
+
+ private String convertToIgnoreMetaChars(String valueWithMetaChars) {
+ return Pattern.quote(valueWithMetaChars);
+ }
+ }
+}
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java b/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java
new file mode 100644
index 0000000..8634052
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/FlatTemplateContent.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search.viewmodel;
+
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.pnfsimulator.db.Row;
+
+import java.util.List;
+
+@Getter
+@NoArgsConstructor
+@ToString
+public class FlatTemplateContent extends Row {
+
+ private List<KeyValuePair> keyValues;
+
+
+ public FlatTemplateContent(String name, List<KeyValuePair> keyValues) {
+ this.setId(name);
+ this.keyValues = keyValues;
+ }
+}
+
+
diff --git a/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java b/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java
new file mode 100644
index 0000000..8f24334
--- /dev/null
+++ b/src/main/java/org/onap/pnfsimulator/template/search/viewmodel/KeyValuePair.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search.viewmodel;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+@Getter
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+/**
+ * POJO for mongo structure after $objectToArray mapping where object consists of fields: k and v
+ */
+public class KeyValuePair {
+
+ private String key;
+ private String value;
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..fddcec0
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+server.port=5000
+templates.dir=/app/templates
+spring.data.mongodb.host=mongo
+spring.data.mongodb.port=27017
+spring.data.mongodb.username=pnf_simulator_user
+spring.data.mongodb.password=zXcVbN123!
+spring.data.mongodb.database=pnf_simulator
+management.endpoints.enabled-by-default=true
+management.endpoint.configprops.enabled=true
+management.endpoints.web.base-path=/
+management.endpoints.web.exposure.include=refresh,health
+
+ssl.clientCertificateEnabled=${USE_CERTIFICATE_FOR_AUTHORIZATION:true}
+ssl.strictHostnameVerification=${STRICT_HOSTNAME_VERIFICATION:false}
+ssl.clientCertificatePath=/app/store/cert.p12
+ssl.clientCertificatePasswordPath=/app/store/p12.pass
+ssl.trustStorePath=/app/store/trust.jks
+ssl.trustStorePasswordPath=/app/store/truststore.pass
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..b93fedf
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. All rights reserved.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<Configuration complete="true" compact="true">
+
+ <Property name="outputFilename" value="pnfsimulator_output"/>
+ <Property name="log-path" value="/var/log/ONAP/pnfsimulator"/>
+ <Property name="archive" value="/var/log/ONAP/pnfsimulator/archive"/>
+ <property name="maxFileSize" value="50MB"/>
+ <property name="maxHistory" value="30"/>
+ <property name="totalSizeCap" value="10GB"/>
+ <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+
+ <appender name="Console" target="SYSTEM_OUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <encoder>
+ <pattern>${FILE_LOG_PATTERN}</pattern>
+ </encoder>
+ <File>${log-path}/${outputFilename}.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <FileNamePattern>${archive}/${outputFilename}.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
+ <MaxFileSize>${maxFileSize}</MaxFileSize>
+ <MaxHistory>${maxHistory}</MaxHistory>
+ <TotalSizeCap>${totalSizeCap}</TotalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="Console"/>
+ <appender-ref ref="ROLLING-FILE"/>
+ </root>
+</Configuration>
diff --git a/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java b/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java
new file mode 100644
index 0000000..5ed51cc
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/event/EventDataServiceTest.java
@@ -0,0 +1,133 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.event;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.hamcrest.collection.IsIterableContainingInOrder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+public class EventDataServiceTest {
+
+ @Mock
+ private EventDataRepository repositoryMock;
+
+ @InjectMocks
+ private EventDataService service;
+
+ private static EventData sampleEventData(String id, String template,
+ String patched, String input, String keywords) {
+ return EventData.builder()
+ .id(id)
+ .template(template)
+ .patched(patched)
+ .input(input)
+ .keywords(keywords)
+ .build();
+ }
+
+ @BeforeEach
+ void resetMocks() {
+ initMocks(this);
+ }
+
+ @Test
+ void persistEventDataJsonObjectTest() {
+ JsonParser parser = new JsonParser();
+ JsonObject template = parser.parse("{ \"bla1\": \"bla2\"}").getAsJsonObject();
+ JsonObject patched = parser.parse("{ \"bla3\": \"bla4\"}").getAsJsonObject();
+ JsonObject input = parser.parse("{ \"bla5\": \"bla6\"}").getAsJsonObject();
+ JsonObject keywords = parser.parse("{ \"bla7\": \"bla8\"}").getAsJsonObject();
+ ArgumentCaptor<EventData> argumentCaptor = ArgumentCaptor.forClass(EventData.class);
+
+ service.persistEventData(template, patched, input, keywords);
+
+ verify(repositoryMock).save(argumentCaptor.capture());
+ EventData captured = argumentCaptor.getValue();
+
+ assertEquals(captured.getTemplate(), template.toString());
+ assertEquals(captured.getPatched(), patched.toString());
+ assertEquals(captured.getInput(), input.toString());
+ assertEquals(captured.getKeywords(), keywords.toString());
+ }
+
+ @Test
+ void getAllEventsTest() {
+
+ List<EventData> eventDataList = new ArrayList<>();
+ EventData ed1 = sampleEventData("id1", "t1", "p1", "i1", "k1");
+ EventData ed2 = sampleEventData("id2", "t2", "p2", "i2", "k2");
+ eventDataList.add(ed1);
+ eventDataList.add(ed2);
+
+ when(repositoryMock.findAll()).thenReturn(eventDataList);
+ List<EventData> actualList = service.getAllEvents();
+
+ assertEquals(eventDataList.size(), actualList.size());
+ assertThat(actualList, IsIterableContainingInOrder.contains(ed1, ed2));
+ }
+
+ @Test
+ void findByIdPresentTest() {
+ String id = "some_object";
+ EventData eventData = sampleEventData(id, "template", "patched", "input", "keywords");
+ Optional<EventData> optional = Optional.of(eventData);
+
+ when(repositoryMock.findById(id)).thenReturn(optional);
+
+ Optional<EventData> actualOptional = service.getById(id);
+ assertTrue(actualOptional.isPresent());
+ EventData actualObject = actualOptional.get();
+ assertEquals(eventData.getId(), actualObject.getId());
+ assertEquals(eventData.getTemplate(), actualObject.getTemplate());
+ assertEquals(eventData.getPatched(), actualObject.getPatched());
+ assertEquals(eventData.getInput(), actualObject.getInput());
+ assertEquals(eventData.getKeywords(), actualObject.getKeywords());
+
+ }
+
+ @Test
+ void findByIdNotPresentTest() {
+ String id = "some_object";
+ Optional<EventData> optional = Optional.empty();
+
+ when(repositoryMock.findById(id)).thenReturn(optional);
+
+ Optional<EventData> actualOptional = service.getById(id);
+ assertTrue(!actualOptional.isPresent());
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java b/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java
new file mode 100644
index 0000000..b86a0f9
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/filesystem/InMemoryTemplateStorage.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import com.google.gson.JsonObject;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.template.Template;
+
+public class InMemoryTemplateStorage implements Storage<Template> {
+
+ private List<Template> storage = new ArrayList<>();
+
+ @Override
+ public List<Template> getAll() {
+ return new ArrayList<>(storage);
+ }
+
+ @Override
+ public Optional<Template> get(String name) {
+ return storage.stream().filter(template -> template.getId().equals(name)).findFirst();
+ }
+
+ @Override
+ public void persist(Template template) {
+ if (!storage.contains(template)) {
+ storage.add(template);
+ }
+ }
+
+ @Override
+ public boolean tryPersistOrOverwrite(Template template, boolean overwrite) {
+ if (!storage.contains(template) || overwrite) {
+ storage.add(template);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void delete(String templateName) {
+ get(templateName).ifPresent(template -> storage.remove(template));
+ }
+
+ @Override
+ public List<String> getIdsByContentCriteria(JsonObject queryJson) {
+ throw new RuntimeException("Method is not implemented.");
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java b/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java
new file mode 100644
index 0000000..9dfa002
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/filesystem/WatcherEventProcessorTest.java
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.filesystem;
+
+import static junit.framework.TestCase.fail;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Optional;
+
+import org.bson.Document;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.template.Template;
+
+class WatcherEventProcessorTest {
+
+ @Mock
+ private WatchEvent watchEvent;
+ @Mock
+ private Path templatesDir;
+
+ private Storage<Template> storage;
+ private static Path jsonFilePath;
+
+ @BeforeAll
+ static void init() {
+ jsonFilePath = Paths.get("src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json");
+ }
+
+ @BeforeEach
+ void resetMocks() {
+ initMocks(this);
+ storage = new InMemoryTemplateStorage();
+ initStubs();
+ }
+
+ @Test
+ void shouldProcessCreatedEventTest() {
+ // when
+ Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_CREATE);
+ WatcherEventProcessor.process(watchEvent, storage, templatesDir);
+ // then
+ verifyPersistedValue();
+ }
+
+ @Test
+ void shouldProcessModifiedEventTest() {
+ //given
+ storage.persist(new Template("test1.json", new Document(Collections.emptyMap()), Instant.now().getNano()));
+ // when
+ Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_MODIFY);
+ WatcherEventProcessor.process(watchEvent, storage, templatesDir);
+ // then
+ verifyPersistedValue();
+ }
+
+ private void verifyPersistedValue() {
+ Assertions.assertEquals(1, storage.getAll().size());
+ Optional<Template> templateFromStorage = storage.get("test1.json");
+ if (templateFromStorage.isPresent()) {
+ Template retrievedTemplate = templateFromStorage.get();
+ Document templateContent = retrievedTemplate.getContent();
+ Document flatContent = retrievedTemplate.getFlatContent();
+ Assertions.assertEquals("value1", templateContent.getString("field1"));
+ Assertions.assertEquals(2, templateContent.getInteger("field2", 0));
+ Assertions.assertEquals(1, flatContent.getInteger(":nested:key1[0]", 0));
+ Assertions.assertEquals(2, flatContent.getInteger(":nested:key1[1]", 0));
+ Assertions.assertEquals(3, flatContent.getInteger(":nested:key1[2]", 0));
+ Assertions.assertEquals("sampleValue2", flatContent.getString(":nested:key2"));
+ } else {
+ fail();
+ }
+ }
+
+ @Test
+ void shouldProcessDeletedEventTest() {
+ //given
+ HashMap<String, Object> legacyObject = new HashMap<>();
+ legacyObject.put("field1", "value1");
+ legacyObject.put("field2", 2);
+
+ storage.persist(new Template("test1.json", new Document(legacyObject), Instant.now().getNano()));
+ // when
+ Mockito.when(watchEvent.kind()).thenReturn(StandardWatchEventKinds.ENTRY_DELETE);
+ WatcherEventProcessor.process(watchEvent, storage, templatesDir);
+ // then
+ Assertions.assertEquals(0, storage.getAll().size());
+ }
+
+ private void initStubs() {
+ Mockito.when(templatesDir.resolve(jsonFilePath)).thenReturn(jsonFilePath);
+ Mockito.when(watchEvent.context()).thenReturn(jsonFilePath);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java b/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java
new file mode 100644
index 0000000..8dba750
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/rest/SimulatorControllerTest.java
@@ -0,0 +1,329 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataService;
+import org.onap.pnfsimulator.rest.model.FullEvent;
+import org.onap.pnfsimulator.rest.model.SimulatorParams;
+import org.onap.pnfsimulator.rest.model.SimulatorRequest;
+import org.onap.pnfsimulator.simulator.SimulatorService;
+import org.onap.pnfsimulator.simulator.client.HttpResponseAdapter;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig;
+import org.quartz.SchedulerException;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+class SimulatorControllerTest {
+
+ private static final String START_ENDPOINT = "/simulator/start";
+ private static final String CONFIG_ENDPOINT = "/simulator/config";
+ private static final String EVENT_ENDPOINT = "/simulator/event";
+ private static final String CANCEL_JOB_ENDPOINT = "/simulator/cancel/";
+ private static final String ALL_EVENTS_ENDPOINT = "/simulator/all-events";
+ private static final String TEST_ENDPOINT = "/simulator/test";
+
+ private static final String JSON_MSG_EXPRESSION = "$.message";
+ private static final String EVENT_WAS_CANCELLED = "Event(s) was cancelled";
+ private static final String EVENT_WAS_NOT_CANCELLED = "Simulator was not able to cancel event(s)";
+
+ private static final String NEW_URL = "http://0.0.0.0:8090/eventListener/v7";
+ private static final String UPDATE_SIM_CONFIG_VALID_JSON = "{\"vesServerUrl\": \""
+ + NEW_URL + "\"}";
+ private static final String SAMPLE_ID = "sampleId";
+ private static final Gson GSON_OBJ = new Gson();
+ private static final String JOB_NAME = "testJobName";
+ private static final HttpResponseAdapter TEST_HTTP_ACCEPTED_RESPONSE = new HttpResponseAdapter(202,"");
+ private static String simulatorRequestBody;
+ private MockMvc mockMvc;
+ @InjectMocks
+ private SimulatorController controller;
+ @Mock
+ private EventDataService eventDataService;
+ @Mock
+ private SimulatorService simulatorService;
+
+ @BeforeAll
+ static void beforeAll() {
+ SimulatorParams simulatorParams = new SimulatorParams("http://0.0.0.0:8080", 1, 1);
+ SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams,
+ "testTemplate.json", new JsonObject(), new JsonObject());
+
+ simulatorRequestBody = GSON_OBJ.toJson(simulatorRequest);
+ }
+
+ @BeforeEach
+ void setup() throws IOException, SchedulerException, GeneralSecurityException {
+ MockitoAnnotations.initMocks(this);
+ when(simulatorService.triggerEvent(any())).thenReturn("jobName");
+ when(simulatorService.triggerOneTimeEvent(any())).thenReturn(TEST_HTTP_ACCEPTED_RESPONSE);
+ mockMvc = MockMvcBuilders
+ .standaloneSetup(controller)
+ .build();
+ }
+
+ @Test
+ void shouldStartSimulatorProperly() throws Exception {
+ startSimulator();
+ SimulatorRequest simulatorRequest = new Gson().fromJson(simulatorRequestBody, SimulatorRequest.class);
+
+ verify(simulatorService).triggerEvent(eq(simulatorRequest));
+ }
+
+ @Test
+ void testShouldGetConfigurationWhenRequested() throws Exception {
+ String newUrl = "http://localhost:8090/eventListener/v7";
+ SimulatorConfig expectedConfig = new SimulatorConfig(SAMPLE_ID, new URL(newUrl));
+ when(simulatorService.getConfiguration()).thenReturn(expectedConfig);
+
+ MvcResult getResult = mockMvc
+ .perform(get(CONFIG_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(UPDATE_SIM_CONFIG_VALID_JSON))
+ .andExpect(status().isOk())
+ .andReturn();
+
+ String expectedVesUrlJsonPart = createStringReprOfJson("vesServerUrl", newUrl);
+ assertThat(getResult.getResponse().getContentAsString()).contains(expectedVesUrlJsonPart);
+ }
+
+ @Test
+ void testShouldSuccessfullyUpdateConfigurationWithNewVesUrl() throws Exception {
+ String oldUrl = "http://localhost:8090/eventListener/v7";
+ SimulatorConfig expectedConfigBeforeUpdate = new SimulatorConfig(SAMPLE_ID, new URL(oldUrl));
+ SimulatorConfig expectedConfigAfterUpdate = new SimulatorConfig(SAMPLE_ID, new URL(NEW_URL));
+
+ when(simulatorService.getConfiguration()).thenReturn(expectedConfigBeforeUpdate);
+ when(simulatorService.updateConfiguration(any(SimulatorConfig.class))).thenReturn(expectedConfigAfterUpdate);
+
+ MvcResult postResult = mockMvc
+ .perform(put(CONFIG_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(UPDATE_SIM_CONFIG_VALID_JSON))
+ .andExpect(status().isOk())
+ .andReturn();
+
+ String expectedVesUrlJsonPart = createStringReprOfJson("vesServerUrl", expectedConfigAfterUpdate.getVesServerUrl().toString());
+ assertThat(postResult.getResponse().getContentAsString()).contains(expectedVesUrlJsonPart);
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenUpdateConfigWithIncorrectPayloadWasSent() throws Exception {
+ mockMvc
+ .perform(put(CONFIG_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"vesUrl\": \""
+ + NEW_URL + "\"}"))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenUrlInInvalidFormatIsSent() throws Exception {
+ mockMvc
+ .perform(put(CONFIG_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content("{\"vesUrl\": \"http://0.0.0.0:VES-PORT/eventListener/v7\"}"))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ void testShouldSendEventDirectly() throws Exception {
+ String contentAsString = mockMvc
+ .perform(post(EVENT_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content("{\"vesServerUrl\":\"http://0.0.0.0:8080/simulator/v7\",\n"
+ + " \"event\":{ \n"
+ + " \"commonEventHeader\":{ \n"
+ + " \"domain\":\"notification\",\n"
+ + " \"eventName\":\"vFirewallBroadcastPackets\"\n"
+ + " },\n"
+ + " \"notificationFields\":{ \n"
+ + " \"arrayOfNamedHashMap\":[ \n"
+ + " { \n"
+ + " \"name\":\"A20161221.1031-1041.bin.gz\",\n"
+ + " \"hashMap\":{ \n"
+ + " \"fileformatType\":\"org.3GPP.32.435#measCollec\"}}]}}}"))
+ .andExpect(status().isAccepted()).andReturn().getResponse().getContentAsString();
+ assertThat(contentAsString).contains("One-time direct event sent successfully");
+ }
+
+ @Test
+ void testShouldReplaceKeywordsAndSendEventDirectly() throws Exception {
+ String contentAsString = mockMvc
+ .perform(post(EVENT_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content("{\"vesServerUrl\": \"http://localhost:9999/eventListener\",\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"eventId\": \"#RandomString(20)\",\n"
+ + " \"sourceName\": \"PATCHED_sourceName\",\n"
+ + " \"version\": 3.0\n}}}"))
+ .andExpect(status().isAccepted()).andReturn().getResponse().getContentAsString();
+ assertThat(contentAsString).contains("One-time direct event sent successfully");
+
+ verify(simulatorService, Mockito.times(1)).triggerOneTimeEvent(any(FullEvent.class));
+ }
+
+ @Test
+ void shouldUseTestEndpointThenReceiveProperMessage() throws Exception {
+ String contentAsString = mockMvc
+ .perform(post(TEST_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content("{\"simulatorParams\": {\n" +
+ " \"vesServerUrl\": \"http://localhost:9999/eventListener\"\n" +
+ " },\n" +
+ " \"templateName\": \"testTemplateName\"\n" +
+ "}"))
+ .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
+ assertThat(contentAsString).contains("message1234");
+ }
+
+ @Test
+ void shouldSuccessfullyCancelJobThenReturnProperMessage() throws Exception {
+ when(simulatorService.cancelEvent(JOB_NAME)).thenReturn(true);
+
+ String contentAsString = mockMvc
+ .perform(post(CANCEL_JOB_ENDPOINT + JOB_NAME)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(""))
+ .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
+
+ assertThat(contentAsString).contains(EVENT_WAS_CANCELLED);
+ }
+
+ @Test
+ void shouldFailWhileCancelingJobThenReturnProperMessage() throws Exception {
+ when(simulatorService.cancelEvent(JOB_NAME)).thenReturn(false);
+
+ String contentAsString = mockMvc
+ .perform(post(CANCEL_JOB_ENDPOINT + JOB_NAME)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(""))
+ .andExpect(status().isNotFound()).andReturn().getResponse().getContentAsString();
+
+ assertThat(contentAsString).contains(EVENT_WAS_NOT_CANCELLED);
+ }
+
+ @Test
+ void shouldSuccessfullyCancelAllJobsThenReturnsProperMessage() throws Exception {
+ when(simulatorService.cancelAllEvents()).thenReturn(true);
+
+ String contentAsString = mockMvc
+ .perform(post(CANCEL_JOB_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(""))
+ .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
+
+ assertThat(contentAsString).contains(EVENT_WAS_CANCELLED);
+ }
+
+ @Test
+ void shouldSuccessfullyCancelJobWhenSendingJobNameWithBreakingCharactersThenReturnProperMessage() throws SchedulerException {
+ final String lineBreakingJobName = "test\tJob\nName\r";
+ when(simulatorService.cancelEvent(lineBreakingJobName)).thenReturn(true);
+
+ Object actualResponseBody = Objects.requireNonNull(controller.cancelEvent(lineBreakingJobName).getBody());
+
+ assertThat(actualResponseBody.toString()).contains(EVENT_WAS_CANCELLED);
+ }
+
+ @Test
+ void shouldReturnAllEvents() throws Exception {
+ List<EventData> events = getEventDatas();
+ String expectedMessage = events.stream()
+ .map(EventData::toString)
+ .collect(Collectors.joining("\\n"));
+
+ when(eventDataService.getAllEvents()).thenReturn(events);
+
+ String contentAsString = mockMvc
+ .perform(get(ALL_EVENTS_ENDPOINT)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(""))
+ .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
+
+ assertThat(contentAsString).contains(expectedMessage);
+ }
+
+
+ private List<EventData> getEventDatas() {
+ return Arrays.asList(
+ getEventData("id1", "keywords1", "input1", "patched1", "template1", 0),
+ getEventData("id2", "keywords2", "input2", "patched2", "template2", 1)
+ );
+ }
+
+ private EventData getEventData(String id, String keywords, String input, String patched, String template, int incrementValue) {
+ return EventData.builder()
+ .id(id)
+ .keywords(keywords)
+ .input(input)
+ .patched(patched)
+ .template(template)
+ .incrementValue(incrementValue)
+ .build();
+ }
+
+ private void startSimulator() throws Exception {
+ mockMvc
+ .perform(post(START_ENDPOINT)
+ .content(simulatorRequestBody)
+ .contentType(MediaType.APPLICATION_JSON).characterEncoding("utf-8"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath(JSON_MSG_EXPRESSION).value("Request started"));
+
+ }
+
+ private String createStringReprOfJson(String key, String value) {
+ return GSON_OBJ.toJson(ImmutableMap.of(key, value));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java b/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java
new file mode 100644
index 0000000..17be475
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/rest/TemplateControllerTest.java
@@ -0,0 +1,256 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.onap.pnfsimulator.rest.TemplateController.CANNOT_OVERRIDE_TEMPLATE_MSG;
+import static org.onap.pnfsimulator.rest.TemplateController.TEMPLATE_NOT_FOUND_MSG;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.mockito.Mockito.times;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import org.assertj.core.util.Lists;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.pnfsimulator.db.Storage;
+import org.onap.pnfsimulator.rest.model.SearchExp;
+import org.onap.pnfsimulator.template.Template;
+import org.onap.pnfsimulator.template.search.IllegalJsonValueException;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+
+class TemplateControllerTest {
+
+ private static final String LIST_URL = "/template/list";
+ private static final String GET_FORMAT_STR = "/template/get/%s";
+ private static final String SEARCH_ENDPOINT = "/template/search";
+ private static final String UPLOAD_URL_NOFORCE = "/template/upload";
+ private static final String UPLOAD_URL_FORCE = "/template/upload?override=true";
+ private static final String SAMPLE_TEMPLATE_JSON = "{\"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"measurementsForVfScaling\",\n"
+ + " \"eventName\": \"vFirewallBroadcastPackets\",\n"
+ + " }"
+ + "}}";
+
+ public static final String TEMPLATE_REQUEST = "{\n"
+ + " \"name\": \"someTemplate\",\n"
+ + " \"template\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"notification\",\n"
+ + " \"eventName\": \"vFirewallBroadcastPackets\"\n"
+ + " },\n"
+ + " \"notificationFields\": {\n"
+ + " \"arrayOfNamedHashMap\": [{\n"
+ + " \"name\": \"A20161221.1031-1041.bin.gz\",\n"
+ + "\n"
+ + " \"hashMap\": {\n"
+ + " \"fileformatType\": \"org.3GPP.32.435#measCollec\"\n"
+ + " }\n"
+ + " }]\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+ private static final Document SAMPLE_TEMPLATE_BSON = Document.parse(SAMPLE_TEMPLATE_JSON);
+ private static final List<String> SAMPLE_TEMPLATE_NAME_LIST = Lists.newArrayList("notification.json", "registration.json");
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+ private static final Gson GSON_OBJ = new GsonBuilder().create();
+ private MockMvc mockMvc;
+
+ @Mock
+ private Storage<Template> templateService;
+ @InjectMocks
+ private TemplateController controller;
+
+ @BeforeEach
+ void setup() {
+ MockitoAnnotations.initMocks(this);
+ mockMvc = MockMvcBuilders
+ .standaloneSetup(controller)
+ .build();
+ }
+
+ @Test
+ void shouldGetAllTemplates() throws Exception {
+ List<Template> templateList = createTemplatesList();
+ when(templateService.getAll()).thenReturn(templateList);
+
+ MvcResult getResult = mockMvc
+ .perform(get(LIST_URL)
+ .accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andReturn();
+
+ Type listType = new TypeToken<ArrayList<Template>>() {}.getType();
+ List<Template> resultList = GSON_OBJ.fromJson(getResult.getResponse().getContentAsString(), listType);
+ assertThat(resultList).containsExactlyInAnyOrderElementsOf(templateList);
+ }
+
+ @Test
+ void shouldListEmptyCollectionWhenNoTemplatesAvailable() throws Exception {
+ List<Template> templateList = Collections.emptyList();
+ when(templateService.getAll()).thenReturn(templateList);
+
+ MvcResult getResult = mockMvc
+ .perform(get(LIST_URL))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andReturn();
+
+ String templatesAsString = GSON_OBJ.toJson(templateList);
+ assertThat(getResult.getResponse().getContentAsString()).containsSequence(templatesAsString);
+ }
+
+ @Test
+ void shouldSuccessfullyGetExisitngTemplateByName() throws Exception {
+ String sampleTemplateName = "someTemplate";
+ String requestUrl = String.format(GET_FORMAT_STR, sampleTemplateName);
+ Template sampleTemplate = new Template(sampleTemplateName, SAMPLE_TEMPLATE_BSON, 0L);
+
+ when(templateService.get(sampleTemplateName)).thenReturn(Optional.of(sampleTemplate));
+
+ MvcResult getResult = mockMvc
+ .perform(get(requestUrl))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andReturn();
+
+ Template result = new Gson().fromJson(getResult.getResponse().getContentAsString(), Template.class);
+ assertThat(result).isEqualTo(sampleTemplate);
+ }
+
+ @Test
+ void shouldReturnNotFoundWhenGetNonExisitngTemplateByName() throws Exception {
+ String sampleTemplateName = "doesNotExist";
+ String requestUrl = String.format(GET_FORMAT_STR, sampleTemplateName);
+
+ when(templateService.get(sampleTemplateName)).thenReturn(Optional.empty());
+
+ MvcResult getResult = mockMvc
+ .perform(get(requestUrl))
+ .andExpect(status().isNotFound())
+ .andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE))
+ .andReturn();
+
+ assertThat(getResult.getResponse().getContentLength()).isEqualTo(TEMPLATE_NOT_FOUND_MSG.length());
+ }
+
+
+ @Test
+ void shouldReturnNamesOfTemplatesThatSatisfyGivenCriteria() throws Exception {
+ when(templateService.getIdsByContentCriteria(any(JsonObject.class))).thenReturn(SAMPLE_TEMPLATE_NAME_LIST);
+ SearchExp expr = new SearchExp(new JsonObject());
+
+ String responseContent = mockMvc
+ .perform(post(SEARCH_ENDPOINT).content(GSON_OBJ.toJson(expr)).contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andReturn().getResponse().getContentAsString();
+
+ List<String> actualTemplates = OBJECT_MAPPER.readValue(responseContent, new TypeReference<List<String>>() {});
+ verify(templateService, times(1)).getIdsByContentCriteria(any(JsonObject.class));
+ assertThat(actualTemplates).isEqualTo(SAMPLE_TEMPLATE_NAME_LIST);
+ }
+
+ @Test
+ void shouldRaiseBadRequestWhenNullValueProvidedInSearchJsonAsJsonValue() throws Exception {
+ when(templateService.getIdsByContentCriteria(any(JsonObject.class))).thenThrow(IllegalJsonValueException.class);
+ SearchExp expr = new SearchExp(new JsonObject());
+
+ mockMvc.perform(post(SEARCH_ENDPOINT)
+ .content(GSON_OBJ.toJson(expr))
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
+ .andExpect(status().isBadRequest());
+ }
+
+
+ @Test
+ void testTryUploadNewTemplate() throws Exception {
+ when(templateService.tryPersistOrOverwrite(any(Template.class), eq(false))).thenReturn(true);
+
+ MvcResult postResult = mockMvc
+ .perform(post(UPLOAD_URL_NOFORCE)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(TEMPLATE_REQUEST))
+ .andExpect(status().isCreated())
+ .andReturn();
+ }
+
+ @Test
+ void testTryUploadNewTemplateWithForce() throws Exception {
+ when(templateService.tryPersistOrOverwrite(any(Template.class), eq(true))).thenReturn(true);
+
+ MvcResult postResult = mockMvc
+ .perform(post(UPLOAD_URL_FORCE)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(TEMPLATE_REQUEST))
+ .andExpect(status().isCreated())
+ .andReturn();
+ }
+
+ @Test
+ void testOverrideExistingTemplateWithoutForceShouldFail() throws Exception {
+ when(templateService.tryPersistOrOverwrite(any(Template.class), eq(true))).thenReturn(false);
+
+ MvcResult postResult = mockMvc
+ .perform(post(UPLOAD_URL_FORCE)
+ .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
+ .content(TEMPLATE_REQUEST))
+ .andExpect(status().isConflict())
+ .andReturn();
+
+ assertThat(postResult.getResponse().getContentAsString()).isEqualTo(CANNOT_OVERRIDE_TEMPLATE_MSG);
+ }
+
+ private List<Template> createTemplatesList() {
+ return Arrays.asList(
+ new Template("1", SAMPLE_TEMPLATE_BSON, 0L),
+ new Template("2", SAMPLE_TEMPLATE_BSON, 0L),
+ new Template("3", SAMPLE_TEMPLATE_BSON, 0L));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java b/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java
new file mode 100644
index 0000000..1591a59
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/rest/util/DateUtilTest.java
@@ -0,0 +1,38 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.util;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import org.junit.jupiter.api.Test;
+
+class DateUtilTest {
+
+ @Test
+ void getFormattedDate() {
+ Calendar currentCalendar = Calendar.getInstance();
+ String expectedResult = String.valueOf(currentCalendar.get(Calendar.YEAR));
+
+ assertEquals(expectedResult, DateUtil.getTimestamp(new SimpleDateFormat("yyyy")));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java b/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java
new file mode 100644
index 0000000..4e8e4dc
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/rest/util/ResponseBuilderTest.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.rest.util;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+class ResponseBuilderTest {
+
+
+ private static final HttpStatus SAMPLE_STATUS = HttpStatus.OK;
+
+ @Test
+ void response_should_have_empty_body_when_built_immediately() {
+ ResponseEntity responseEntity = ResponseBuilder.status(SAMPLE_STATUS).build();
+
+ assertAll(
+ () -> assertEquals(SAMPLE_STATUS, responseEntity.getStatusCode()),
+ () -> assertNull(responseEntity.getBody())
+ );
+ }
+
+ @Test
+ void builder_should_set_response_status_and_body() {
+ String key = "key";
+ String value = "value";
+ ResponseEntity response = ResponseBuilder
+ .status(SAMPLE_STATUS)
+ .put(key, value)
+ .build();
+
+ Map<String, Object> body = (Map<String, Object>) response.getBody();
+
+ assertAll(
+ () -> assertEquals(SAMPLE_STATUS, response.getStatusCode()),
+ () -> assertEquals(value, body.get(key))
+ );
+ }
+
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/DbTemplateReaderTest.java b/src/test/java/org/onap/pnfsimulator/simulator/DbTemplateReaderTest.java
new file mode 100644
index 0000000..c3f85f5
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/DbTemplateReaderTest.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.assertj.core.api.Assertions;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.pnfsimulator.template.Template;
+import org.onap.pnfsimulator.template.TemplateService;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DbTemplateReaderTest {
+
+ public static final String SOME_TEMPLATE = "someTemplate";
+ public static final String KEY = "key";
+ public static final String VALUE = "value";
+ public static final long LMOD = 10L;
+ private TemplateService service;
+ private DbTemplateReader dbTemplateReader;
+
+ @BeforeEach
+ void setUp() {
+ this.service = mock(TemplateService.class);
+ this.dbTemplateReader = new DbTemplateReader(this.service, new Gson());
+ }
+
+ @Test
+ public void shouldReportErrorWhenTemplateDoesNotExistInTemplateService() {
+ // given
+ when(this.service.get(SOME_TEMPLATE)).thenReturn(Optional.empty());
+
+ // when/then
+ assertThrows(IOException.class,
+ () -> this.dbTemplateReader.readTemplate(SOME_TEMPLATE)
+ );
+ }
+
+ @Test
+ public void shouldReturnTemplateFromService() throws IOException {
+ // given
+ Template template = givenTemplate(SOME_TEMPLATE);
+ when(this.service.get(SOME_TEMPLATE)).thenReturn(Optional.of(template));
+
+ // when
+ final JsonObject someTemplate = this.dbTemplateReader.readTemplate(SOME_TEMPLATE);
+
+ // then
+ Assertions.assertThat(someTemplate).isNotNull();
+ Assertions.assertThat(someTemplate.get(KEY).getAsString()).isEqualTo(VALUE);
+ }
+
+ private Template givenTemplate(String templateName) {
+ return new Template(templateName, new Document(KEY, VALUE), LMOD);
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java b/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java
new file mode 100644
index 0000000..b5304a7
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/IncrementProviderImplTest.java
@@ -0,0 +1,79 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataRepository;
+
+public class IncrementProviderImplTest {
+ private IncrementProvider incrementProvider;
+
+ @Mock
+ private EventDataRepository eventDataRepositoryMock;
+
+ @BeforeEach
+ void setUp() {
+ eventDataRepositoryMock = mock(EventDataRepository.class);
+ incrementProvider = new IncrementProviderImpl(eventDataRepositoryMock);
+ }
+
+ @Test
+ public void getAndIncrementTest() {
+ ArgumentCaptor<EventData> eventDataArgumentCaptor = ArgumentCaptor.forClass(EventData.class);
+ String eventId = "1";
+ int initialIncrementValue = 0;
+ int expectedValue = initialIncrementValue + 1;
+ EventData eventData = EventData.builder().id(eventId).incrementValue(initialIncrementValue).build();
+ Optional<EventData> optional = Optional.of(eventData);
+
+ when(eventDataRepositoryMock.findById(eventId)).thenReturn(optional);
+
+ int value = incrementProvider.getAndIncrement(eventId);
+
+ verify(eventDataRepositoryMock).save(eventDataArgumentCaptor.capture());
+
+ assertThat(value).isEqualTo(expectedValue);
+ assertThat(eventDataArgumentCaptor.getValue().getIncrementValue()).isEqualTo(expectedValue);
+
+ }
+
+ @Test
+ public void shouldThrowOnNonExistingEvent() {
+ Optional<EventData> emptyOptional = Optional.empty();
+ String nonExistingEventId = "THIS_DOES_NOT_EXIST";
+ when(eventDataRepositoryMock.findById(nonExistingEventId)).thenReturn(emptyOptional);
+
+ assertThrows(EventNotFoundException.class,
+ () -> incrementProvider.getAndIncrement(nonExistingEventId));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java
new file mode 100644
index 0000000..8198e95
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomIntegerTest.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorInvalidRandomIntegerTest {
+
+ private final String keyword;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection INVALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#RandoInteger"},
+ {"#Randominteger(23,11)"},
+ {"#randomInteger(11,34)"},
+ {"#Random_Integer(11,13)"},
+ {"#RandomInteger(11)"},
+ {"RandomInteger(11)"},
+ {"RandomInteger"}
+ });
+
+ public KeywordsExtractorInvalidRandomIntegerTest(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return INVALID_INTEGER_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.keyword);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java
new file mode 100644
index 0000000..6834c0d
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidRandomStringTest.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorInvalidRandomStringTest {
+
+ private final String keyword;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection INVALID_STRING_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#RandoString"},
+ {"#Randomstring(23)"},
+ {"#randomString(11)"},
+ {"#Random_String(11)"},
+ {"#RandomString(11,10)"},
+ {"RandomString(11)"},
+ {"RandomString"}
+ });
+
+ public KeywordsExtractorInvalidRandomStringTest(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return INVALID_STRING_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1).length(), this.keyword.length());
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java
new file mode 100644
index 0000000..eda4070
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorInvalidTimestampTest.java
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorInvalidTimestampTest {
+
+ private final String keyword;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection INVALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#Timesamp"},
+ {"#Timestamp(10)"},
+ {"#timestamp"},
+ {"#Timestamp(11,13)"},
+ {"Timestamp"}
+ });
+
+ public KeywordsExtractorInvalidTimestampTest(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return INVALID_TIMESTAMP_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.keyword);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java
new file mode 100644
index 0000000..be79488
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomIntegerTest.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorValidRandomIntegerTest {
+
+ private final String keyword;
+ private final String shouldParseTo;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection VALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#RandomInteger(23,23)", "23"},
+ {"#RandomInteger(6, 6)12", "612"},
+ {"1#RandomInteger(11,11)", "111"},
+ {"1#RandomInteger(11,11)2", "1112"}
+ });
+
+ public KeywordsExtractorValidRandomIntegerTest(String keyword, String shouldParseTo) {
+ this.keyword = keyword;
+ this.shouldParseTo = shouldParseTo;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return VALID_INTEGER_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1), this.shouldParseTo);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java
new file mode 100644
index 0000000..0843ad1
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomPrimitiveIntegerTest.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorValidRandomPrimitiveIntegerTest {
+
+ private final String keyword;
+ private final Integer shouldParseTo;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection VALID_INTEGER_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#RandomPrimitiveInteger(23,23)", 23},
+ {"#RandomPrimitiveInteger(6, 6)12", 6},
+ {"1#RandomPrimitiveInteger(11,11)", 11},
+ {"1#RandomPrimitiveInteger(11,11)2", 11}
+ });
+
+ public KeywordsExtractorValidRandomPrimitiveIntegerTest(String keyword, Integer shouldParseTo) {
+ this.keyword = keyword;
+ this.shouldParseTo = shouldParseTo;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return VALID_INTEGER_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substitutePrimitiveKeyword(this.keyword), Long.valueOf(this.shouldParseTo));
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java
new file mode 100644
index 0000000..f0fdc0f
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidRandomStringTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorValidRandomStringTest {
+
+ private final String keyword;
+ private final int length;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection VALID_STRING_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#RandomString", DEFAULT_STRING_LENGTH},
+ {"1#RandomString2", 1 + DEFAULT_STRING_LENGTH + 1},
+ {"#RandomString(23)", 23},
+ {"#RandomString(11)12", 11 + 2},
+ {"1#RandomString(11)", 1 + 11},
+ {"1#RandomString(11)2", 1 + 11 + 1}
+ });
+
+ public KeywordsExtractorValidRandomStringTest(String keyword, int length) {
+ this.keyword = keyword;
+ this.length = length;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return VALID_STRING_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ assertEquals(keywordsExtractor.substituteStringKeyword(this.keyword, 1).length(), this.length);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java
new file mode 100644
index 0000000..7743e55
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampPrimitiveTest.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorValidTimestampPrimitiveTest {
+ private final String keyword;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection VALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#TimestampPrimitive"}
+ });
+
+ public KeywordsExtractorValidTimestampPrimitiveTest(String keyword) {
+ this.keyword = keyword;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return VALID_TIMESTAMP_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ long currentTimestamp = Instant.now().getEpochSecond();
+ Long timestamp = keywordsExtractor.substitutePrimitiveKeyword(this.keyword);
+ long afterExecution = Instant.now().getEpochSecond();
+
+ assertThat(timestamp).isBetween(currentTimestamp, afterExecution);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java
new file mode 100644
index 0000000..bf6f290
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsExtractorValidTimestampTest.java
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class KeywordsExtractorValidTimestampTest {
+
+ private final String keyword;
+ private final int length;
+ private KeywordsExtractor keywordsExtractor;
+
+ private static final Collection VALID_TIMESTAMP_KEYWORDS = Arrays.asList(new Object[][]{
+ {"#Timestamp", 10},
+ {"#Timestamp12", 10 + 2},
+ {"1#Timestamp", 1 + 10},
+ {"1#Timestamp2", 1 + 10 + 1}
+ });
+
+ public KeywordsExtractorValidTimestampTest(String keyword, Integer length) {
+ this.keyword = keyword;
+ this.length = length;
+ }
+
+ @Before
+ public void setUp() {
+ this.keywordsExtractor = new KeywordsExtractor();
+ }
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return VALID_TIMESTAMP_KEYWORDS;
+ }
+
+ @Test
+ public void checkValidRandomStringKeyword() {
+ String substitution = keywordsExtractor.substituteStringKeyword(this.keyword, 1);
+ assertEquals(substitution.length(), this.length);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java
new file mode 100644
index 0000000..e36bb28
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsHandlerTest.java
@@ -0,0 +1,306 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.junit.jupiter.api.Test;
+
+class KeywordsHandlerTest {
+
+ private static final String TEMPLATE_JSON = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"#RandomString\"\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n"
+ + " \"additionalMeasurements\": {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"extraFields\": {\n"
+ + " \"name\": \"#RandomString(4)\",\n"
+ + " \"value\": \"1\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private static final String TEMPLATE_JSON_WITH_MANY_KEYWORDS_INSIDE_SINGLE_VALUE = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain1\": \"#RandomString(1) #RandomString(2) #RandomString(3)\",\n"
+ + " \"domain2\": \"1 #RandomString(1) 2\"\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n"
+ + " \"additionalMeasurements\": {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"extraFields\": {\n"
+ + " \"value\": \"1\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private static final String TEMPLATE_JSON_WITH_ARRAY = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"#RandomString(1)\",\n"
+ + " \"version\": 2.0\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"additionalMeasurements\": [\n"
+ + " {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"arrayOfFields\": [\n"
+ + " {\n"
+ + " \"name\": \"G711AudioPort\",\n"
+ + " \"value\": \"1\"\n"
+ + " },\n"
+ + " {\n"
+ + " \"name\": [\"1\",\"2\"],\n"
+ + " \"value\": \"#RandomString(2)\"\n"
+ + " },\n"
+ + " {\n"
+ + " \"name\": \"G722AudioPort\",\n"
+ + " \"value\": \"1\"\n"
+ + " }\n"
+ + " ]\n"
+ + " }\n"
+ + " ]\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private static final String TEMPLATE_ONE_INCREMENT_JSON = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"#RandomString\"\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n"
+ + " \"additionalMeasurements\": {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"extraFields\": {\n"
+ + " \"name\": \"#RandomString(4)\",\n"
+ + " \"value\": \"#Increment\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private static final String TEMPLATE_WITH_SIMPLE_VALUE = "\"#RandomString(4)\"";
+
+ private static final String TEMPLATE_WITH_ARRAY_OF_PRIMITIVES = "[ 1, \"#RandomString(5)\", 3]";
+
+ private static final String TEMPLATE_TWO_INCREMENT_JSON = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"#RandomString\"\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n"
+ + " \"additionalMeasurements\": {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"extraFields\": {\n"
+ + " \"name\": \"#RandomString(4)\",\n"
+ + " \"value\": \"#Increment\",\n"
+ + " \"otherValue\": \"#Increment\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private Gson gson = new Gson();
+
+ @Test
+ void shouldReplaceRandomStringKeyword() {
+ // given
+ JsonObject templateJson = gson.fromJson(TEMPLATE_JSON, JsonObject.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1);
+
+ // when
+ JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject();
+
+ // then
+ String extraFields = resultJson
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonObject()
+ .get("extraFields").getAsJsonObject()
+ .get("name").getAsString();
+ String newDomain = resultJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain").getAsString();
+
+ assertThat(extraFields.length()).isEqualTo(4);
+ assertThat(newDomain.length()).isEqualTo(DEFAULT_STRING_LENGTH);
+ }
+
+ @Test
+ void shouldReplaceRandomStringKeywordsInsideSingleValue() {
+ // given
+ JsonObject templateJson = gson.fromJson(TEMPLATE_JSON_WITH_MANY_KEYWORDS_INSIDE_SINGLE_VALUE, JsonObject.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1);
+
+ // when
+ JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject();
+
+ // then
+ String newDomain1 = resultJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain1").getAsString();
+ String newDomain2 = resultJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain2").getAsString();
+
+ assertThat(newDomain1.length()).isEqualTo(1 + 1 + 2 + 1 + 3);
+ assertThat(newDomain2.length()).isEqualTo(1 + 1 + 1 + 1 + 1);
+ }
+
+ @Test
+ void shouldReplaceRandomStringKeywordInTeplateAsArrayWithPrimitves() {
+ // given
+ JsonElement templateJson = gson.fromJson(TEMPLATE_WITH_ARRAY_OF_PRIMITIVES, JsonElement.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1);
+
+ // when
+ JsonElement resultJson = keywordsHandler.substituteKeywords(templateJson, "");
+ assertThat(resultJson.getAsJsonArray().get(1).getAsString().length()).isEqualTo(5);
+ }
+
+ @Test
+ void shouldReplaceRandomStringKeywordInTeplateAsSimpleValue() {
+ // given
+ JsonElement templateJson = gson.fromJson(TEMPLATE_WITH_SIMPLE_VALUE, JsonElement.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1);
+
+ // when
+ JsonElement resultJson = keywordsHandler.substituteKeywords(templateJson, "");
+
+ // then
+ assertThat(resultJson.getAsString().length()).isEqualTo(4);
+ }
+
+ @Test
+ void shouldReplaceRandomStringKeywordInTeplateWithJsonArray() {
+ // given
+ JsonElement templateJson = gson.fromJson(TEMPLATE_JSON_WITH_ARRAY, JsonElement.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> 1);
+
+ // when
+ JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "").getAsJsonObject();
+
+ // then
+ String actualValue = resultJson
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonArray()
+ .get(0).getAsJsonObject()
+ .get("arrayOfFields").getAsJsonArray()
+ .get(1).getAsJsonObject()
+ .get("value").getAsString();
+ String otherActualValue = resultJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain").getAsString();
+
+ assertThat(otherActualValue.length()).isEqualTo(1);
+ assertThat(actualValue.length()).isEqualTo(2);
+ }
+
+ @Test
+ void shouldReplaceOneIncrementKeyword() {
+ // given
+ final Integer newIncrementedValue = 2;
+ JsonObject templateJson = gson.fromJson(TEMPLATE_ONE_INCREMENT_JSON, JsonObject.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), (id) -> newIncrementedValue);
+
+ // when
+ JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject();
+
+ // then
+ String actualValue = resultJson
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonObject()
+ .get("extraFields").getAsJsonObject()
+ .get("value").getAsString();
+
+ assertThat(actualValue).isEqualTo(newIncrementedValue.toString());
+ }
+
+ @Test
+ void shouldReplaceTwoIncrementKeyword() {
+ // given
+ final Integer firstIncrementValue = 2;
+ final Integer secondIncrementValue = 3;
+ JsonObject templateJson = gson.fromJson(TEMPLATE_TWO_INCREMENT_JSON, JsonObject.class);
+ KeywordsHandler keywordsHandler = new KeywordsHandler(new KeywordsExtractor(), new IncrementProvider() {
+ Queue<Integer> sequenceOfValues = new LinkedList<>(
+ Arrays.asList(firstIncrementValue, secondIncrementValue));
+
+ @Override
+ public int getAndIncrement(String id) {
+ return sequenceOfValues.poll();
+ }
+ });
+
+ // when
+ JsonObject resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject();
+ resultJson = keywordsHandler.substituteKeywords(templateJson, "some random id").getAsJsonObject();
+
+ // then
+ String actualValue = resultJson
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonObject()
+ .get("extraFields").getAsJsonObject()
+ .get("value").getAsString();
+
+ String actualOtherValue = resultJson
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonObject()
+ .get("extraFields").getAsJsonObject()
+ .get("otherValue").getAsString();
+
+ assertThat(actualValue).isEqualTo(secondIncrementValue.toString());
+ assertThat(actualOtherValue).isEqualTo(secondIncrementValue.toString());
+
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java
new file mode 100644
index 0000000..ac54237
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/KeywordsValueProviderTest.java
@@ -0,0 +1,82 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.onap.pnfsimulator.simulator.KeywordsValueProvider.DEFAULT_STRING_LENGTH;
+
+import java.util.Random;
+
+import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.api.Test;
+
+class KeywordsValueProviderTest {
+
+ @RepeatedTest(10)
+ void randomLimitedStringTest() {
+ String supplierResult = KeywordsValueProvider.getRandomLimitedString().apply();
+ assertEquals(DEFAULT_STRING_LENGTH, supplierResult.length());
+ }
+
+ @RepeatedTest(10)
+ void randomStringTest() {
+ int length = new Random().nextInt(15) + 1;
+ String supplierResult = KeywordsValueProvider.getRandomString().apply(length);
+ assertEquals(length, supplierResult.length());
+ }
+
+ @RepeatedTest(10)
+ void randomIntegerTest() {
+ int min = new Random().nextInt(10) + 1;
+ int max = new Random().nextInt(1000) + 20;
+ String supplierResult = KeywordsValueProvider.getRandomInteger().apply(min, max);
+ assertTrue(Integer.parseInt(supplierResult) >= min);
+ assertTrue(Integer.parseInt(supplierResult) <= max);
+ }
+
+ @Test
+ void randomIntegerContainsMaximalAndMinimalValuesTest() {
+ int anyNumber = new Random().nextInt(10) + 1;
+ String supplierResult = KeywordsValueProvider.getRandomInteger().apply(anyNumber, anyNumber);
+ assertEquals(Integer.parseInt(supplierResult), anyNumber);
+ }
+
+ @Test
+ void randomIntegerFromNegativeRangeTest() {
+ String supplierResult = KeywordsValueProvider.getRandomInteger().apply(-20, -20);
+ assertEquals(Integer.parseInt(supplierResult), -20);
+ }
+
+ @RepeatedTest(10)
+ void randomIntegerFromParametersWithDifferentOrdersTest() {
+ String supplierResult = KeywordsValueProvider.getRandomInteger().apply(-20, -10);
+ assertTrue(Integer.parseInt(supplierResult) >= -20);
+ assertTrue(Integer.parseInt(supplierResult) <= -10);
+ }
+
+ @RepeatedTest(10)
+ void epochSecondGeneratedInCorrectFormatTest() {
+ String supplierResult = KeywordsValueProvider.getEpochSecond().apply();
+ assertEquals(10, supplierResult.length());
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java b/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java
new file mode 100644
index 0000000..d5426ec
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/SimulatorServiceTest.java
@@ -0,0 +1,308 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.pnfsimulator.event.EventData;
+import org.onap.pnfsimulator.event.EventDataService;
+import org.onap.pnfsimulator.rest.model.FullEvent;
+import org.onap.pnfsimulator.rest.model.SimulatorParams;
+import org.onap.pnfsimulator.rest.model.SimulatorRequest;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapter;
+import org.onap.pnfsimulator.simulator.client.HttpResponseAdapter;
+import org.onap.pnfsimulator.simulator.client.HttpTestUtils;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.onap.pnfsimulator.simulator.scheduler.EventScheduler;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfig;
+import org.onap.pnfsimulator.simulatorconfig.SimulatorConfigService;
+import org.quartz.SchedulerException;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
+class SimulatorServiceTest {
+
+ private static final String VES_URL = "http://0.0.0.0:8080";
+ private static final String IN_DB_VES_URL = "http://0.0.0.0:8080/eventListener/v6";
+ private static final Gson GSON = new Gson();
+ private static final JsonObject VALID_PATCH = GSON.fromJson("{\"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"sourceName\": \"SomeCustomSource\"}}}\n", JsonObject.class);
+ private static final JsonObject VALID_FULL_EVENT = GSON.fromJson("{\"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"notification\",\n"
+ + " \"eventName\": \"vFirewallBroadcastPackets\"\n"
+ + " },\n"
+ + " \"notificationFields\": {\n"
+ + " \"arrayOfNamedHashMap\": [{\n"
+ + " \"name\": \"A20161221.1031-1041.bin.gz\",\n"
+ + " \"hashMap\": {\n"
+ + " \"fileformatType\": \"org.3GPP.32.435#measCollec\"}}]}}}", JsonObject.class);
+ private static final JsonObject FULL_EVENT_WITH_KEYWORDS = GSON.fromJson("{\"event\":{ \n"
+ + " \"commonEventHeader\":{ \n"
+ + " \"domain\":\"notification\",\n"
+ + " \"eventName\":\"#RandomString(20)\",\n"
+ + " \"eventOrderNo\":\"#Increment\"}}}", JsonObject.class);
+ private static final JsonObject VALID_VARIABLES = GSON.fromJson("{\"dn\": \"TestDN-1\", \"measurement\":{\n"
+ + " \"name\": \"AdditionalM\",\n"
+ + " \"value\": \"1.5\"\n"
+ + " }}", JsonObject.class);
+ private static final String SOME_CUSTOM_SOURCE = "SomeCustomSource";
+ private static final String CLOSED_LOOP_VNF = "ClosedLoopVNF";
+ private static final String SAMPLE_ID = "sampleId";
+ private static final EventData SAMPLE_EVENT = EventData.builder().id("1").build();
+ private static URL inDbVesUrl;
+ private final ArgumentCaptor<JsonObject> bodyCaptor = ArgumentCaptor.forClass(JsonObject.class);
+ private final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class);
+ private final ArgumentCaptor<Integer> repeatCountCaptor = ArgumentCaptor
+ .forClass(Integer.class);
+ private final ArgumentCaptor<String> templateNameCaptor = ArgumentCaptor.forClass(String.class);
+ private final ArgumentCaptor<String> eventIdCaptor = ArgumentCaptor.forClass(String.class);
+ private final ArgumentCaptor<String> vesUrlCaptor = ArgumentCaptor.forClass(String.class);
+ private final ArgumentCaptor<String> eventContentCaptor = ArgumentCaptor.forClass(String.class);
+ private final SslAuthenticationHelper sslAuthenticationHelper = new SslAuthenticationHelper();
+ private final TemplatePatcher templatePatcher = new TemplatePatcher();
+ private final TemplateReader templateReader = new FilesystemTemplateReader(
+ "src/test/resources/org/onap/pnfsimulator/simulator/", GSON);
+
+ private SimulatorService simulatorService;
+ private EventDataService eventDataService;
+ private EventScheduler eventScheduler;
+ private SimulatorConfigService simulatorConfigService;
+
+ @BeforeEach
+ void setUp() throws MalformedURLException {
+ inDbVesUrl = new URL(IN_DB_VES_URL);
+ eventDataService = mock(EventDataService.class);
+ eventScheduler = mock(EventScheduler.class);
+ simulatorConfigService = mock(SimulatorConfigService.class);
+
+ simulatorService = new SimulatorService(templatePatcher, templateReader,
+ eventScheduler, eventDataService, simulatorConfigService,
+ new TemplateVariablesReplacer(),new SslAuthenticationHelper());
+ }
+
+ @Test
+ void shouldTriggerEventWithGivenParams() throws IOException, SchedulerException, GeneralSecurityException {
+ String templateName = "validExampleMeasurementEvent.json";
+ SimulatorParams simulatorParams = new SimulatorParams(VES_URL, 1, 1);
+ SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams,
+ templateName, VALID_PATCH, VALID_VARIABLES);
+
+ doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class));
+
+ simulatorService.triggerEvent(simulatorRequest);
+
+ assertEventHasExpectedStructure(VES_URL, templateName, SOME_CUSTOM_SOURCE);
+ assertEventHasReplacedVariables();
+ }
+
+ @Test
+ void shouldTriggerEventWithDefaultVesUrlWhenNotProvidedInRequest() throws IOException, SchedulerException, GeneralSecurityException {
+ String templateName = "validExampleMeasurementEvent.json";
+ SimulatorRequest simulatorRequest = new SimulatorRequest(
+ new SimulatorParams("", 1, 1),
+ templateName, VALID_PATCH, new JsonObject());
+
+ doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class));
+ when(simulatorConfigService.getConfiguration()).thenReturn(new SimulatorConfig(SAMPLE_ID, inDbVesUrl));
+
+ simulatorService.triggerEvent(simulatorRequest);
+
+ assertEventHasExpectedStructure(inDbVesUrl.toString(), templateName, SOME_CUSTOM_SOURCE);
+ }
+
+ @Test
+ void shouldThrowJsonSyntaxWhenInvalidJson() {
+ //given
+ JsonObject patch = GSON.fromJson("{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"sourceName\": \""
+ + SOME_CUSTOM_SOURCE + "\"\n"
+ + " }\n"
+ + " }\n"
+ + "}\n", JsonObject.class);
+ EventData eventData = EventData.builder().id("1").build();
+
+ SimulatorParams simulatorParams = new SimulatorParams(VES_URL, 1, 1);
+ SimulatorRequest simulatorRequest = new SimulatorRequest(simulatorParams,
+ "invalidJsonStructureEvent.json", patch, new JsonObject());
+ doReturn(eventData).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class));
+
+ //when
+ assertThrows(JsonSyntaxException.class,
+ () -> simulatorService.triggerEvent(simulatorRequest));
+ }
+
+ @Test
+ void shouldHandleNonExistingPatchSection() throws IOException, SchedulerException, GeneralSecurityException {
+ String templateName = "validExampleMeasurementEvent.json";
+ SimulatorRequest simulatorRequest = new SimulatorRequest(
+ new SimulatorParams("", 1, 1),
+ templateName, null, new JsonObject());
+
+ doReturn(SAMPLE_EVENT).when(eventDataService).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class));
+ doReturn(new SimulatorConfig(SAMPLE_ID, inDbVesUrl)).when(simulatorConfigService).getConfiguration();
+
+ simulatorService.triggerEvent(simulatorRequest);
+
+ assertEventHasExpectedStructure(inDbVesUrl.toString(), templateName, CLOSED_LOOP_VNF);
+ }
+
+ @Test
+ void shouldSuccessfullySendOneTimeEventWithVesUrlWhenPassed() throws IOException, GeneralSecurityException {
+ SimulatorService spiedTestedService = spy(new SimulatorService(
+ templatePatcher, templateReader, eventScheduler,
+ eventDataService, simulatorConfigService,
+ new TemplateVariablesReplacer(),
+ new SslAuthenticationHelper()));
+
+ HttpClientAdapter adapterMock = mock(HttpClientAdapter.class);
+ prepareMocksWithAcceptedResponse(spiedTestedService, adapterMock);
+ FullEvent event = new FullEvent(VES_URL, VALID_FULL_EVENT);
+
+ spiedTestedService.triggerOneTimeEvent(event);
+
+ assertThat(eventContentCaptor.getValue()).isEqualTo(VALID_FULL_EVENT.toString());
+ verify(eventDataService, times(1)).persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class), any(JsonObject.class));
+ verify(adapterMock, times(1)).send(VALID_FULL_EVENT.toString());
+ }
+
+ @Test
+ void shouldSubstituteKeywordsAndSuccessfullySendOneTimeEvent() throws IOException, GeneralSecurityException {
+ SimulatorService spiedTestedService = spy(new SimulatorService(
+ templatePatcher, templateReader, eventScheduler,
+ eventDataService, simulatorConfigService,
+ new TemplateVariablesReplacer(),
+ new SslAuthenticationHelper())
+ );
+
+ HttpClientAdapter adapterMock = mock(HttpClientAdapter.class);
+ prepareMocksWithAcceptedResponse(spiedTestedService, adapterMock);
+ FullEvent event = new FullEvent(VES_URL, FULL_EVENT_WITH_KEYWORDS);
+
+ spiedTestedService.triggerOneTimeEvent(event);
+
+ JsonObject sentContent = GSON.fromJson(eventContentCaptor.getValue(), JsonElement.class).getAsJsonObject();
+ assertThat(sentContent.getAsJsonObject("event").getAsJsonObject("commonEventHeader").get("eventOrderNo").getAsString()).isEqualTo("1");
+ assertThat(sentContent.getAsJsonObject("event").getAsJsonObject("commonEventHeader").get("eventName").getAsString()).hasSize(20);
+ }
+
+ @Test
+ void shouldGetSimulatorConfiguration() {
+ SimulatorConfig simulatorConfig = getSimulatorConfig();
+
+ when(simulatorConfigService.getConfiguration()).thenReturn(simulatorConfig);
+
+ assertEquals(simulatorService.getConfiguration(), simulatorConfig);
+ }
+
+ @Test
+ void shouldUpdateSimulatorConfiguration() {
+ SimulatorConfig simulatorConfig = getSimulatorConfig();
+
+ when(simulatorConfigService.updateConfiguration(simulatorConfig)).thenReturn(simulatorConfig);
+
+ assertEquals(simulatorService.updateConfiguration(simulatorConfig), simulatorConfig);
+ }
+
+ @Test
+ void shouldCancelAllEvents() throws SchedulerException {
+ when(eventScheduler.cancelAllEvents()).thenReturn(true);
+
+ assertTrue(simulatorService.cancelAllEvents());
+ }
+
+ @Test
+ void shouldCancelSingleEvent() throws SchedulerException {
+ final String jobName = "testJobName";
+ when(eventScheduler.cancelEvent(jobName)).thenReturn(true);
+
+ assertTrue(simulatorService.cancelEvent(jobName));
+ }
+
+ private void prepareMocksWithAcceptedResponse(SimulatorService spiedTestedService, HttpClientAdapter adapterMock) throws IOException, GeneralSecurityException {
+ HttpResponseAdapter response = new HttpResponseAdapter(HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER);
+ doReturn(response).when(adapterMock).send(eventContentCaptor.capture());
+ doReturn(adapterMock).when(spiedTestedService).createHttpClientAdapter(any(String.class));
+ }
+
+ private void assertEventHasExpectedStructure(String expectedVesUrl, String templateName, String sourceNameString) throws SchedulerException, IOException, GeneralSecurityException {
+ verify(eventScheduler, times(1)).scheduleEvent(vesUrlCaptor.capture(), intervalCaptor.capture(),
+ repeatCountCaptor.capture(), templateNameCaptor.capture(), eventIdCaptor.capture(), bodyCaptor.capture());
+ assertThat(vesUrlCaptor.getValue()).isEqualTo(expectedVesUrl);
+ assertThat(intervalCaptor.getValue()).isEqualTo(1);
+ assertThat(repeatCountCaptor.getValue()).isEqualTo(1);
+ assertThat(templateNameCaptor.getValue()).isEqualTo(templateName);
+ String actualSourceName = GSON.fromJson(bodyCaptor.getValue(), JsonObject.class)
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("sourceName").getAsString();
+ assertThat(actualSourceName).isEqualTo(sourceNameString);
+ verify(eventDataService)
+ .persistEventData(any(JsonObject.class), any(JsonObject.class), any(JsonObject.class),
+ any(JsonObject.class));
+ }
+
+ private SimulatorConfig getSimulatorConfig() {
+ return new SimulatorConfig(SAMPLE_ID, inDbVesUrl);
+ }
+
+ private void assertEventHasReplacedVariables() {
+ String measurementName = GSON.fromJson(bodyCaptor.getValue(), JsonObject.class)
+ .get("event").getAsJsonObject()
+ .get("measurementsForVfScalingFields").getAsJsonObject()
+ .get("additionalMeasurements").getAsJsonArray().get(0).getAsJsonObject()
+ .get("arrayOfFields").getAsJsonArray().get(0).getAsJsonObject()
+ .get("name").getAsString();
+
+ String reportingEntityName = GSON.fromJson(bodyCaptor.getValue(), JsonObject.class)
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("reportingEntityName").getAsString();
+
+ assertThat(measurementName).isEqualTo("AdditionalM");
+ assertThat(reportingEntityName).isEqualTo("TestDN-1");
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java b/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java
new file mode 100644
index 0000000..818c8be
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/TemplatePatcherTest.java
@@ -0,0 +1,164 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.assertj.core.api.AssertionsForInterfaceTypes;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+class TemplatePatcherTest {
+
+ private static final String TEMPLATE_JSON = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"measurementsForVfScaling\"\n"
+ + " },\n"
+ + " \"measurementsForVfScalingFields\": {\n"
+ + " \"measurementsForVfSclaingFieldsVersion\": 2.0,\n"
+ + " \"additionalMeasurements\": {\n"
+ + " \"name\": \"licenseUsage\",\n"
+ + " \"extraFields\": {\n"
+ + " \"name\": \"G711AudioPort\",\n"
+ + " \"value\": \"1\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+
+ private TemplatePatcher templatePatcher;
+ private Gson gson = new Gson();
+ private JsonObject templateJson;
+
+ @BeforeEach
+ void setUp() {
+ templatePatcher = new TemplatePatcher();
+ templateJson = gson.fromJson(TEMPLATE_JSON, JsonObject.class);
+ }
+
+ @Test
+ void shouldReplaceJsonElementsInTemplate() {
+ //given
+ String patchJsonString = "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"newDomain\"\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+ JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class);
+
+ //when
+ JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson);
+
+ //then
+ String newDomain = requestJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain").getAsString();
+ assertThat(newDomain).isEqualTo("newDomain");
+ }
+
+ @Test
+ void shouldAddWholeJsonObjectToTemplateWhenItFinished() {
+ //given
+ String patchJsonString =
+ "{\n"
+ + " \"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": {\n"
+ + " \"extraFields\": {\n"
+ + " \"name\": \"G711AudioPort\",\n"
+ + " \"value\": \"1\"\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}";
+ JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class);
+
+ //when
+ JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson);
+
+ //then
+ JsonElement newDomain = requestJson
+ .get("event").getAsJsonObject()
+ .get("commonEventHeader").getAsJsonObject()
+ .get("domain");
+ assertThat(newDomain.isJsonObject()).isTrue();
+ JsonObject newDomainJsonObject = newDomain.getAsJsonObject();
+ AssertionsForInterfaceTypes.assertThat(newDomainJsonObject.keySet()).containsExactly("extraFields");
+ JsonObject newDomainExtraFields = newDomainJsonObject.get("extraFields").getAsJsonObject();
+ AssertionsForInterfaceTypes.assertThat(newDomainExtraFields.keySet()).containsExactly("name", "value");
+ }
+
+ @Test
+ void shouldReplaceJsonObjectWithJsonElementFromPatch() {
+ //given
+ String patchJsonString = "{ \"event\": \"test\" }";
+ JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class);
+
+ //when
+ JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson);
+
+ //then
+ assertThat(requestJson.get("event").isJsonObject()).isFalse();
+ assertThat(requestJson.get("event").getAsString()).isEqualTo("test");
+ }
+
+ @Test
+ void shouldAddNewKeyIfPatchHasItAndTempleteDoesnt() {
+ //given
+ String patchJsonString = "{ \"newTestKey\": { \"newTestKeyChild\":\"newTestValue\" }}";
+ JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class);
+
+ //when
+ JsonObject requestJson = templatePatcher.mergeTemplateWithPatch(templateJson, patchJson);
+
+ //then
+ assertThat(requestJson.get("event").isJsonObject()).isTrue();
+ assertThat(requestJson.get("newTestKey").isJsonObject()).isTrue();
+ JsonObject newTestKey = requestJson.get("newTestKey").getAsJsonObject();
+ AssertionsForInterfaceTypes.assertThat(newTestKey.keySet()).containsExactly("newTestKeyChild");
+ assertThat(newTestKey.get("newTestKeyChild").getAsString()).isEqualTo("newTestValue");
+
+ }
+
+
+ @Test
+ void shouldNotChangeInputTemplateParam() {
+ //given
+ String patchJsonString = "{ \"newTestKey\": { \"newTestKeyChild\":\"newTestValue\" }}";
+ JsonObject patchJson = gson.fromJson(patchJsonString, JsonObject.class);
+
+ //when
+ templatePatcher.mergeTemplateWithPatch(templateJson, patchJson);
+
+ //then
+ assertThat(templateJson).isEqualTo(gson.fromJson(TEMPLATE_JSON, JsonObject.class));
+
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java b/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java
new file mode 100644
index 0000000..f029fce
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/TemplateReaderTest.java
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.context.TestPropertySource;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+@TestPropertySource
+class TemplateReaderTest {
+
+ private FilesystemTemplateReader templateReader = new FilesystemTemplateReader("src/test/resources/org/onap/pnfsimulator/simulator/", new Gson());
+
+ @Test
+ void testShouldReadJsonFromFile() throws IOException {
+ JsonObject readJson = templateReader.readTemplate("validExampleMeasurementEvent.json");
+ assertThat(readJson.keySet()).containsOnly("event");
+ assertThat(readJson.get("event").getAsJsonObject().keySet()).containsExactlyInAnyOrder("commonEventHeader", "measurementsForVfScalingFields");
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenInvalidJsonIsRead() {
+ Assertions.assertThrows(JsonSyntaxException.class, () -> templateReader.readTemplate("invalidJsonStructureEvent.json"));
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacerTest.java
new file mode 100644
index 0000000..5b7e4f4
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/TemplateVariablesReplacerTest.java
@@ -0,0 +1,174 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator;
+
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import lombok.val;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+@TestInstance(Lifecycle.PER_CLASS)
+class TemplateVariablesReplacerTest {
+
+ private static final Gson GSON = new Gson();
+
+ private TemplateVariablesReplacer replacer;
+
+ @BeforeAll
+ void setUp() {
+ replacer = new TemplateVariablesReplacer();
+ }
+
+ @Test
+ void shouldReplaceStringVariable() {
+ val sourceAsString = "{\"test1\":\"#variable1\", \"variable1\":\"value2 #variable1\"}";
+ val expectedAsString = "{\"test1\":\"valueOfVariable1\", \"variable1\":\"value2 #variable1\"}";
+ val variablesAsString = "{\"variable1\":\"valueOfVariable1\"}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceStringAndNumberVariable() {
+ val sourceAsString = "{\"test1\":\"#variable1\", \"test2\":\"#variable2\"}";
+ val expectedAsString = "{\"test1\":\"valueOfVariable1=1\", \"test2\":2}";
+ val variablesAsString = "{\"variable1\":\"valueOfVariable1=1\", \"variable2\":2}";
+
+ val source = new Gson().fromJson(sourceAsString, JsonObject.class);
+ val variables = new Gson().fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceSimpleStringVariable() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\":\"valueOfVariable1\"}";
+ val variablesAsString = "{\"variable1\":\"valueOfVariable1\"}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceObjectVariable() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\":{\"replaced1\":\"valueOfVariable1\"}}";
+ val variablesAsString = "{\"variable1\":{\"replaced1\":\"valueOfVariable1\"}}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceIntegerVariable() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\": 1}";
+ val variablesAsString = "{\"variable1\": 1}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceBoolVariable() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\": true}";
+ val variablesAsString = "{\"variable1\": true}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceDifferentVariables() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable\", \"variable2\":\"text #variable\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\":{\"replaced1\":\"valueOfVariable1\"}, \"variable2\":\"text #variable\"}";
+ val variablesAsString = "{\"variable\":{\"replaced1\":\"valueOfVariable1\"}}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceArrayVariables() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\":[1,2,3]}";
+ val variablesAsString = "{\"variable1\":[1,2,3]}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceArrayWithStringVariables() {
+ val sourceAsString = "{\"test1\":\"value1\", \"variable1\":\"#variable1\"}";
+ val expectedAsString = "{\"test1\":\"value1\", \"variable1\":[\"1\",\"2\",\"3\"]}";
+ val variablesAsString = "{\"variable1\":[\"1\",\"2\",\"3\"]}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+ @Test
+ void shouldReplaceArrayAsStringVariables() {
+ val sourceAsString = "{\"test1\":\"#variable1\", \"variable1\":\"Text #variable1\"}";
+ val expectedAsString = "{\"test1\":[1,2,3], \"variable1\": \"Text #variable1\"}";
+ val variablesAsString = "{\"variable1\":[1,2,3]}";
+
+ val source = GSON.fromJson(sourceAsString, JsonObject.class);
+ val variables = GSON.fromJson(variablesAsString, JsonObject.class);
+
+ JsonObject result = replacer.substituteVariables(source, variables);
+ JSONAssert.assertEquals(expectedAsString, result.toString(), true);
+ }
+
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactoryTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactoryTest.java
new file mode 100644
index 0000000..2f8c6b3
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpApacheResponseAdapterFactoryTest.java
@@ -0,0 +1,98 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.onap.pnfsimulator.simulator.client.HttpTestUtils.createMockedHttpEntity;
+import static org.onap.pnfsimulator.simulator.client.HttpTestUtils.createStatusLine;
+
+class HttpApacheResponseAdapterFactoryTest {
+
+ private HttpResponse httpResponse;
+
+ @BeforeEach
+ void setup() {
+ httpResponse = mock(HttpResponse.class);
+ }
+
+ @Test
+ void shouldCreateCorrectHttpResponseAdapterFromApacheHttpAcceptedResponse() throws IOException {
+ // given
+ final int responseCode = HttpStatus.SC_ACCEPTED;
+ final String responseBody = HttpTestUtils.HTTP_MESSAGE_ACCEPTER;
+ prepareHttpResponseMock(responseCode, createMockedHttpEntity(responseBody));
+
+ // when
+ HttpResponseAdapter httpResponseAdapter = new HttpApacheResponseAdapterFactory().create(httpResponse);
+
+ // then
+ assertHttpResponseIsCorrect(responseCode, responseBody, httpResponseAdapter);
+ }
+
+
+ @Test
+ void shouldCreateCorrectHttpResponseAdapterFromApacheHttpForbiddenResponse() throws IOException {
+ // given
+ final int responseCode = HttpStatus.SC_FORBIDDEN;
+ final String responseBody = HttpTestUtils.HTTP_MESSAGE_FORBIDDEN;
+ prepareHttpResponseMock(responseCode, createMockedHttpEntity(responseBody));
+
+ // when
+ HttpResponseAdapter httpResponseAdapter = new HttpApacheResponseAdapterFactory().create(httpResponse);
+
+ // then
+ assertHttpResponseIsCorrect(responseCode, responseBody, httpResponseAdapter);
+ }
+
+ @Test
+ void shouldCreateCorrectHttpResponseAdapterFromApacheHttpResponseWithEmptyEntity() {
+ // given
+ final int responseCode = HttpStatus.SC_INTERNAL_SERVER_ERROR;
+ prepareHttpResponseMock(responseCode, null);
+
+ // when
+ HttpResponseAdapter httpResponseAdapter = new HttpApacheResponseAdapterFactory().create(httpResponse);
+
+
+ assertHttpResponseIsCorrect(responseCode, "", httpResponseAdapter);
+ }
+
+ private void prepareHttpResponseMock(int responseCode, HttpEntity httpEntity) {
+ doReturn(createStatusLine(responseCode)).when(httpResponse).getStatusLine();
+ doReturn(httpEntity).when(httpResponse).getEntity();
+ }
+
+ private void assertHttpResponseIsCorrect(int responseCode, String responseBody, HttpResponseAdapter httpResponseAdapter) {
+ assertEquals(responseCode, httpResponseAdapter.getCode());
+ assertEquals(responseBody, httpResponseAdapter.getMessage());
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java
new file mode 100644
index 0000000..cfbc8c1
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpClientAdapterImplTest.java
@@ -0,0 +1,157 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.message.BasicHeader;
+import org.apache.tomcat.util.codec.binary.Base64;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.onap.pnfsimulator.simulator.client.HttpTestUtils.createMockedHttpEntity;
+import static org.onap.pnfsimulator.simulator.client.HttpTestUtils.createStatusLine;
+
+class HttpClientAdapterImplTest {
+
+ private static final String HTTPS_URL = "https://0.0.0.0:8443/";
+ private static final String HTTP_URL = "http://0.0.0.0:8000/";
+
+ private HttpClient httpClient;
+ private HttpResponse httpResponse;
+
+ @BeforeEach
+ void setup() {
+ httpClient = mock(HttpClient.class);
+ httpResponse = mock(HttpResponse.class);
+ }
+
+ @Test
+ void sendShouldSuccessfullySendRequestGivenValidUrl() throws IOException {
+ assertAdapterSentRequest("http://valid-url:8080",
+ HttpStatus.SC_FORBIDDEN, HttpTestUtils.HTTP_MESSAGE_FORBIDDEN);
+ }
+
+ @Test
+ void sendShouldSuccessfullySendRequestGivenValidUrlUsingHttps() throws IOException {
+ assertAdapterSentRequest("https://valid-url:8443",
+ HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER);
+ }
+
+ @Test
+ void sendShouldSuccessfullySendRequestUsingBasicAuth() throws IOException {
+ String testUserInfo = "user1:pass1";
+ Header authorizationHeader = createAuthorizationHeader(testUserInfo);
+ assertAdapterSentRequest("https://" + testUserInfo + "@valid-url:8443",
+ HttpStatus.SC_ACCEPTED, HttpTestUtils.HTTP_MESSAGE_ACCEPTER,
+ List.of(authorizationHeader));
+ }
+
+ @Test
+ void sendShouldFailToSendRequestGivenInvalidUrlUsingAdnShouldInformUser() throws IOException {
+ assertAdapterInformsUserWhenServiceIsUnavailable("https://invalid-url:8080");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMalformedVesUrlPassed() {
+ assertThrows(MalformedURLException.class, () -> new HttpClientAdapterImpl("http://blablabla:VES-PORT", new SslAuthenticationHelper()));
+ }
+
+ @Test
+ void shouldCreateAdapterWithClientNotSupportingSslConnection() throws IOException, GeneralSecurityException {
+ HttpClientAdapter adapterWithHttps = new HttpClientAdapterImpl(HTTPS_URL, new SslAuthenticationHelper());
+ try {
+ adapterWithHttps.send("sample");
+ } catch (Exception actualException) {
+ assertThat(actualException).hasStackTraceContaining(SSLConnectionSocketFactory.class.toString());
+ }
+ }
+
+ @Test
+ void shouldCreateAdapterWithClientSupportingPlainConnectionOnly() throws IOException, GeneralSecurityException {
+ HttpClientAdapter adapterWithHttps = new HttpClientAdapterImpl(HTTP_URL, new SslAuthenticationHelper());
+ try {
+ adapterWithHttps.send("sample");
+ } catch (Exception actualException) {
+ assertThat(actualException).hasStackTraceContaining(PlainConnectionSocketFactory.class.toString());
+ }
+ }
+
+ private Header createAuthorizationHeader(String testUserInfo) {
+ String encodedUserInfo = new String(Base64.encodeBase64(testUserInfo.getBytes(StandardCharsets.UTF_8)));
+ return new BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedUserInfo);
+ }
+
+ private void assertAdapterSentRequest(String targetUrl, int responseCode, String responseMessage) throws IOException {
+ assertAdapterSentRequest(targetUrl, responseCode, responseMessage, List.of());
+ }
+
+ private void assertAdapterSentRequest(String targetUrl, int responseCode, String responseMessage, List<Header> expectedHeaders) throws IOException {
+ HttpClientAdapter adapter = new HttpClientAdapterImpl(httpClient, targetUrl);
+ doReturn(httpResponse).when(httpClient).execute(any());
+ doReturn(createStatusLine(responseCode)).when(httpResponse).getStatusLine();
+ doReturn(createMockedHttpEntity(responseMessage)).when(httpResponse).getEntity();
+
+ HttpResponseAdapter response = adapter.send("test-msg");
+
+ ArgumentCaptor<HttpPost> httpPostCaptor = ArgumentCaptor.forClass(HttpPost.class);
+ verify(httpClient).execute(httpPostCaptor.capture());
+ Header[] headers = httpPostCaptor.getValue().getAllHeaders();
+ assertEquals(responseCode, response.getCode());
+ assertEquals(responseMessage, response.getMessage());
+ assertThat(headers).usingFieldByFieldElementComparator().containsAll(expectedHeaders);
+ }
+
+ private void assertAdapterInformsUserWhenServiceIsUnavailable(String targetUrl) throws IOException {
+ HttpClientAdapter adapter = new HttpClientAdapterImpl(httpClient, targetUrl);
+ String exceptionMessage = "test message";
+ doThrow(new IOException(exceptionMessage)).when(httpClient).execute(any());
+
+ HttpResponseAdapter response = adapter.send("test-msg");
+
+ verify(httpClient).execute(any());
+ assertEquals(421, response.getCode());
+ assertEquals(String.format("Fail to connect with ves: %s", exceptionMessage), response.getMessage());
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/HttpTestUtils.java b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpTestUtils.java
new file mode 100644
index 0000000..02ff531
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/HttpTestUtils.java
@@ -0,0 +1,55 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.message.BasicStatusLine;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class HttpTestUtils {
+
+ private HttpTestUtils() {
+ }
+
+ public static final String HTTP_MESSAGE_ACCEPTER = "Accepted";
+ public static final String HTTP_MESSAGE_FORBIDDEN = "Forbidden";
+
+ static HttpEntity createMockedHttpEntity(String responseBody) throws IOException {
+ HttpEntity httpEntity = mock(HttpEntity.class);
+ doReturn(new ByteArrayInputStream(responseBody.getBytes())).when(httpEntity).getContent();
+ return httpEntity;
+ }
+
+ static BasicStatusLine createStatusLine(int responseCode) {
+ return new BasicStatusLine(
+ new ProtocolVersion("1.0.0", 1, 0),
+ responseCode,
+ ""
+ );
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactoryTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactoryTest.java
new file mode 100644
index 0000000..c64ddd7
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertAuthSslContextFactoryTest.java
@@ -0,0 +1,141 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import java.security.GeneralSecurityException;
+import javax.net.ssl.SSLContext;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class CertAuthSslContextFactoryTest {
+
+ private static final String CERTIFICATES_DIRECTORY = "src/test/resources/certificates/";
+
+ private static final String KEYSTORE_FILENAME = "client.p12";
+ private static final String VALID_KEYSTORE_PASSWORD_FILENAME = "client.pass";
+ private static final String INVALID_KEYSTORE_PASSWORD_FILENAME = "client_invalid.pass";
+
+ private static final String TRUSTSTORE_FILENAME = "truststore";
+ private static final String VALID_TRUSTSTORE_PASSWORD_FILENAME = "truststore.pass";
+ private static final String INVALID_TRUSTSTORE_PASSWORD_FILENAME = "truststore_invalid.pass";
+
+ private static final String NON_EXISTING_PASSWORD_FILENAME = "non_existing.pass";
+ private static final String PASSWORD_INCORRECT = "password was incorrect";
+
+ private CertAuthSslContextFactory certAuthSslContextFactory;
+
+ @Before
+ public void setup() {
+ this.certAuthSslContextFactory = new CertAuthSslContextFactory(new CertificateReader());
+ }
+
+ @Test
+ public void shouldCreateSslContextSuccessfully_whenValidPasswordsUsed()
+ throws GeneralSecurityException, IOException {
+ // Given
+ final SslAuthenticationHelper sslAuthenticationHelper = mockSslAuthenticationHelperWithFiles(
+ VALID_KEYSTORE_PASSWORD_FILENAME, VALID_TRUSTSTORE_PASSWORD_FILENAME);
+
+ // When
+ final SSLContext sslContext = certAuthSslContextFactory.createSslContext(sslAuthenticationHelper);
+
+ // Then
+ assertNotNull(sslContext);
+ }
+
+ @Test
+ public void shouldThrowIOException_whenInvalidKeystorePasswordUsed() {
+ // Given
+ final SslAuthenticationHelper sslAuthenticationHelper = mockSslAuthenticationHelperWithFiles(
+ INVALID_KEYSTORE_PASSWORD_FILENAME, VALID_TRUSTSTORE_PASSWORD_FILENAME);
+
+ // When
+ final IOException exception = assertThrows(IOException.class,
+ () -> certAuthSslContextFactory.createSslContext(sslAuthenticationHelper));
+
+ // Then
+ assertThat(exception.getMessage(), CoreMatchers.containsString(PASSWORD_INCORRECT));
+ }
+
+ @Test
+ public void shouldThrowIOException_whenInvalidTruststorePasswordUsed() {
+ // Given
+ final SslAuthenticationHelper sslAuthenticationHelper = mockSslAuthenticationHelperWithFiles(
+ VALID_KEYSTORE_PASSWORD_FILENAME, INVALID_TRUSTSTORE_PASSWORD_FILENAME);
+
+ // When
+ final IOException exception = assertThrows(IOException.class,
+ () -> certAuthSslContextFactory.createSslContext(sslAuthenticationHelper));
+
+ // Then
+ assertThat(exception.getMessage(), CoreMatchers.containsString(PASSWORD_INCORRECT));
+ }
+
+ @Test
+ public void shouldThrowNoSuchFileException_whenInvalidKeystoreFilePath() {
+ final SslAuthenticationHelper sslAuthenticationHelper = mockSslAuthenticationHelperWithFiles(
+ NON_EXISTING_PASSWORD_FILENAME, INVALID_TRUSTSTORE_PASSWORD_FILENAME);
+
+ // When, Then
+ assertThrows(NoSuchFileException.class,
+ () -> certAuthSslContextFactory.createSslContext(sslAuthenticationHelper));
+ }
+
+ @Test
+ public void shouldThrowNoSuchFileException_whenInvalidTruststoreFilePath() {
+ // Given
+ final SslAuthenticationHelper sslAuthenticationHelper = mockSslAuthenticationHelperWithFiles(
+ VALID_KEYSTORE_PASSWORD_FILENAME, NON_EXISTING_PASSWORD_FILENAME);
+
+ // When, Then
+ assertThrows(NoSuchFileException.class,
+ () -> certAuthSslContextFactory.createSslContext(sslAuthenticationHelper));
+ }
+
+ private SslAuthenticationHelper mockSslAuthenticationHelperWithFiles(String keystorePasswordFilename,
+ String truststorePasswordFilename) {
+ final SslAuthenticationHelper sslAuthenticationHelper = Mockito.mock(SslAuthenticationHelper.class);
+
+ when(sslAuthenticationHelper.getClientCertificatePath())
+ .thenReturn(getPath(KEYSTORE_FILENAME));
+ when(sslAuthenticationHelper.getClientCertificatePasswordPath())
+ .thenReturn(getPath(keystorePasswordFilename));
+ when(sslAuthenticationHelper.getTrustStorePath())
+ .thenReturn(getPath(TRUSTSTORE_FILENAME));
+ when(sslAuthenticationHelper.getTrustStorePasswordPath())
+ .thenReturn(getPath(truststorePasswordFilename));
+
+ return sslAuthenticationHelper;
+ }
+
+ private String getPath(String fileName) {
+ return CERTIFICATES_DIRECTORY + fileName;
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacadeTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacadeTest.java
new file mode 100644
index 0000000..e6d3d03
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacadeTest.java
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import static org.junit.Assert.assertNotNull;
+
+class HttpClientFactoryFacadeTest {
+ @Test
+ void shouldSuccessfullyCreateHttpClient() throws GeneralSecurityException, IOException {
+ assertNotNull(HttpClientFactoryFacade.create("http://example.com", new SslAuthenticationHelper()));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryTest.java
new file mode 100644
index 0000000..c213982
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryTest.java
@@ -0,0 +1,143 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStoreException;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class HttpClientFactoryTest {
+ private static final String HTTPS_URL = "https://example.com";
+ private static final String HTTP_URL = "http://example.com";
+
+ private SSLContextFactory sslContextFactoryMock;
+ private HttpClientFactory httpClientFactory;
+ private SslAuthenticationHelper sslAuthenticationHelper;
+
+ @BeforeEach
+ public void setup() {
+ sslContextFactoryMock = mock(SSLContextFactory.class);
+ httpClientFactory = new HttpClientFactory(sslContextFactoryMock);
+ sslAuthenticationHelper = new SslAuthenticationHelper();
+ }
+
+ @Test
+ void shouldCreateHttpsClient_whenClientCertificationDisabled() throws GeneralSecurityException, IOException {
+ // given
+ sslAuthenticationHelper.setClientCertificateEnabled(false);
+
+ // when
+ final var httpClient = httpClientFactory.create(HTTPS_URL, sslAuthenticationHelper);
+
+ // then
+ assertNotNull(httpClient);
+ verifySslContextFactoryMockCalls(0, 1);
+ }
+
+ @Test
+ void shouldCreateHttpsClient_whenClientCertificationDisabled_AndCannotCreateTrustAlwaysSslContext() throws GeneralSecurityException, IOException {
+ // given
+ sslAuthenticationHelper.setClientCertificateEnabled(false);
+ when(sslContextFactoryMock.createTrustAlways()).thenThrow(KeyStoreException.class);
+
+ // when
+ final var httpClient = httpClientFactory.create(HTTPS_URL, sslAuthenticationHelper);
+
+ // then
+ assertNotNull(httpClient);
+ verifySslContextFactoryMockCalls(0, 1);
+ }
+
+ @Test
+ void shouldCreateHttpClient_whenClientCertificationDisabled() throws GeneralSecurityException, IOException {
+ // given
+ sslAuthenticationHelper.setClientCertificateEnabled(false);
+
+ // when
+ final var httpClient = httpClientFactory.create(HTTP_URL, sslAuthenticationHelper);
+
+ // then
+ assertNotNull(httpClient);
+ verifySslContextFactoryMockCalls(0, 0);
+ }
+
+
+ @Test
+ void shouldCreateHttpClient_whenClientCertificationAndStrictHostnameVerificationAreEnabled() throws GeneralSecurityException, IOException {
+ // given
+ sslAuthenticationHelper.setClientCertificateEnabled(true);
+ sslAuthenticationHelper.setStrictHostnameVerification(true);
+
+ // when
+ final var httpClient = httpClientFactory.create(HTTP_URL, sslAuthenticationHelper);
+
+ // then
+ assertNotNull(httpClient);
+ verifySslContextFactoryMockCalls(1, 0);
+ }
+
+ @Test
+ void shouldCreateHttpClient_whenClientCertificationEnabledAndStrictHostnameVerificationDisabled() throws GeneralSecurityException, IOException {
+ // given
+ sslAuthenticationHelper.setClientCertificateEnabled(true);
+ sslAuthenticationHelper.setStrictHostnameVerification(false);
+
+ // when
+ final var httpClient = httpClientFactory.create(HTTP_URL, sslAuthenticationHelper);
+
+ // then
+ assertNotNull(httpClient);
+ verifySslContextFactoryMockCalls(1, 0);
+ }
+
+ @Test
+ void shouldThrowMalformedURLException_whenInvalidUrl() throws GeneralSecurityException, IOException {
+ // given
+ var invalidUrl = "invalid";
+
+ // when
+ final var exception = assertThrows(MalformedURLException.class,
+ () -> httpClientFactory.create(invalidUrl, sslAuthenticationHelper));
+
+ // then
+ assertThat(exception.getMessage(), CoreMatchers.containsString("invalid"));
+ }
+
+ private void verifySslContextFactoryMockCalls(int createCalls, int createTrustAlwaysCalls) throws GeneralSecurityException, IOException {
+ verify(sslContextFactoryMock, times(createCalls)).create(any());
+ verify(sslContextFactoryMock, times(createTrustAlwaysCalls)).createTrustAlways();
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverterTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverterTest.java
new file mode 100644
index 0000000..fddfc5f
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverterTest.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class PasswordConverterTest {
+
+ @Test
+ void shouldSuccessfullyConvert() {
+ // given, when
+ final char[] result = PasswordConverter.convert("sw ./#%");
+
+ // then
+ assertArrayEquals(new char[]{'s', 'w', ' ', '.', '/', '#', '%'}, result);
+ }
+
+ @Test
+ void shouldReturnNull_whenNullPasswordUsed() {
+ // given, when, then
+ assertNull(PasswordConverter.convert(null));
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactoryTest.java b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactoryTest.java
new file mode 100644
index 0000000..85e40e5
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactoryTest.java
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.client.utils.ssl;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class SSLContextFactoryTest {
+ private CertificateReader certificateReaderMock;
+ private CertAuthSslContextFactory certAuthSslContextFactory;
+ private SSLContextFactory sslContextFactory;
+
+ @BeforeEach
+ void setup() {
+ certificateReaderMock = mock(CertificateReader.class);
+ certAuthSslContextFactory = new CertAuthSslContextFactory(certificateReaderMock);
+ sslContextFactory = new SSLContextFactory(certAuthSslContextFactory);
+ }
+
+ @Test
+ void shouldSuccessfullyCreateTrustAlwaysSSLContext() throws GeneralSecurityException, IOException {
+ // given, when, then
+ assertNotNull(sslContextFactory.createTrustAlways());
+ verify(certificateReaderMock, times(0)).read(any(), any(), any());
+ }
+
+ @Test
+ void shouldSuccessfullyCreateSSLContext() throws GeneralSecurityException, IOException {
+ // given, when, then
+ assertNotNull(sslContextFactory.create(new SslAuthenticationHelper()));
+ verify(certificateReaderMock, times(2)).read(any(), any(), any());
+ }
+
+}
+
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeywordTest.java b/src/test/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeywordTest.java
new file mode 100644
index 0000000..6477fbf
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/keywords/TwoParameterKeywordTest.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.keywords;
+
+
+import io.vavr.Tuple1;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.Assert.assertEquals;
+
+class TwoParameterKeywordTest {
+ @Test
+ public void whenGivenKeywordShouldReturnTwoParameterKeywordObjectWithParsedValues() {
+ //given
+ final String expectedName = "TEST";
+ final Integer expectedParam1 = 123;
+ final Integer expectedParam2 = 456;
+
+ String keyword = "#" + expectedName + "(" + expectedParam1 + "," + expectedParam2 + ")";
+
+ //when
+ Tuple1<TwoParameterKeyword> keywordTuple = TwoParameterKeyword.twoParameterKeyword(keyword);
+ TwoParameterKeyword twoParameterKeyword = keywordTuple._1();
+
+ //then
+ assertEquals(twoParameterKeyword.getName(), expectedName);
+ assertEquals(twoParameterKeyword.getAdditionalParameter1(), expectedParam1);
+ assertEquals(twoParameterKeyword.getAdditionalParameter2(), expectedParam2);
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java b/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java
new file mode 100644
index 0000000..fed6bb6
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventJobTest.java
@@ -0,0 +1,90 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.scheduler;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.BODY;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.CLIENT_ADAPTER;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.EVENT_ID;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.KEYWORDS_HANDLER;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.TEMPLATE_NAME;
+import static org.onap.pnfsimulator.simulator.scheduler.EventJob.VES_URL;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.pnfsimulator.simulator.KeywordsExtractor;
+import org.onap.pnfsimulator.simulator.KeywordsHandler;
+import org.onap.pnfsimulator.simulator.client.HttpClientAdapter;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+
+class EventJobTest {
+
+ @Test
+ void shouldSendEventWhenExecuteCalled() {
+ //given
+ EventJob eventJob = new EventJob();
+ String templateName = "template name";
+ String vesUrl = "http://someurl:80/";
+ String eventId = "1";
+ JsonParser parser = new JsonParser();
+ JsonObject body = parser.parse("{\"a\": \"A\"}").getAsJsonObject();
+ HttpClientAdapter clientAdapter = mock(HttpClientAdapter.class);
+ JobExecutionContext jobExecutionContext =
+ createMockJobExecutionContext(templateName, eventId, vesUrl, body, clientAdapter);
+
+ ArgumentCaptor<String> vesUrlCaptor = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<String> bodyCaptor = ArgumentCaptor.forClass(String.class);
+
+ //when
+ eventJob.execute(jobExecutionContext);
+
+ //then
+ verify(clientAdapter).send(bodyCaptor.capture());
+ assertThat(bodyCaptor.getValue()).isEqualTo(body.toString());
+ }
+
+ private JobExecutionContext createMockJobExecutionContext(String templateName, String eventId, String vesUrl,
+ JsonObject body, HttpClientAdapter clientAdapter) {
+
+ JobDataMap jobDataMap = new JobDataMap();
+ jobDataMap.put(TEMPLATE_NAME, templateName);
+ jobDataMap.put(KEYWORDS_HANDLER, new KeywordsHandler(new KeywordsExtractor(), (id) -> 1));
+ jobDataMap.put(EVENT_ID, eventId);
+ jobDataMap.put(VES_URL, vesUrl);
+ jobDataMap.put(BODY, body);
+ jobDataMap.put(CLIENT_ADAPTER, clientAdapter);
+
+ JobExecutionContext jobExecutionContext = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ when(jobExecutionContext.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getJobDataMap()).thenReturn(jobDataMap);
+ when(jobDetail.getKey()).thenReturn(new JobKey("jobId", "group"));
+ return jobExecutionContext;
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java b/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java
new file mode 100644
index 0000000..d7cabb7
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulator/scheduler/EventSchedulerTest.java
@@ -0,0 +1,148 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulator.scheduler;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.pnfsimulator.simulator.client.utils.ssl.SslAuthenticationHelper;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.SimpleTrigger;
+
+class EventSchedulerTest {
+
+ @InjectMocks
+ EventScheduler eventScheduler;
+
+ @Mock
+ Scheduler quartzScheduler;
+
+ @Mock
+ SslAuthenticationHelper sslAuthenticationHelper;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ void shouldTriggerEventWithGivenConfiguration() throws SchedulerException, IOException, GeneralSecurityException {
+ //given
+ ArgumentCaptor<JobDetail> jobDetailCaptor = ArgumentCaptor.forClass(JobDetail.class);
+ ArgumentCaptor<SimpleTrigger> triggerCaptor = ArgumentCaptor.forClass(SimpleTrigger.class);
+
+ String vesUrl = "http://some:80/";
+ int repeatInterval = 1;
+ int repeatCount = 4;
+ String testName = "testName";
+ String eventId = "1";
+ JsonObject body = new JsonObject();
+
+ //when
+ eventScheduler.scheduleEvent(vesUrl, repeatInterval, repeatCount, testName, eventId, body);
+
+ //then
+ verify(quartzScheduler).scheduleJob(jobDetailCaptor.capture(), triggerCaptor.capture());
+ JobDataMap actualJobDataMap = jobDetailCaptor.getValue().getJobDataMap();
+ assertThat(actualJobDataMap.get(EventJob.BODY)).isEqualTo(body);
+ assertThat(actualJobDataMap.get(EventJob.TEMPLATE_NAME)).isEqualTo(testName);
+ assertThat(actualJobDataMap.get(EventJob.VES_URL)).isEqualTo(vesUrl);
+
+ SimpleTrigger actualTrigger = triggerCaptor.getValue();
+ // repeat count adds 1 to given value
+ assertThat(actualTrigger.getRepeatCount()).isEqualTo(repeatCount - 1);
+
+ //getRepeatInterval returns interval in ms
+ assertThat(actualTrigger.getRepeatInterval()).isEqualTo(repeatInterval * 1000);
+ }
+
+ @Test
+ void shouldCancelAllEvents() throws SchedulerException {
+ //given
+ List<JobKey> jobsKeys = Arrays.asList(new JobKey("jobName1"), new JobKey("jobName2"),
+ new JobKey("jobName3"), new JobKey("jobName4"));
+ List<JobExecutionContext> jobExecutionContexts = createExecutionContextWithKeys(jobsKeys);
+ when(quartzScheduler.getCurrentlyExecutingJobs()).thenReturn(jobExecutionContexts);
+ when(quartzScheduler.deleteJobs(jobsKeys)).thenReturn(true);
+
+ //when
+ boolean isCancelled = eventScheduler.cancelAllEvents();
+
+ //then
+ assertThat(isCancelled).isTrue();
+ }
+
+ @Test
+ void shouldCancelSingleEvent() throws SchedulerException {
+ //given
+ JobKey jobToRemove = new JobKey("jobName3");
+ List<JobKey> jobsKeys = Arrays.asList(new JobKey("jobName1"), new JobKey("jobName2"),
+ jobToRemove, new JobKey("jobName4"));
+ List<JobExecutionContext> jobExecutionContexts = createExecutionContextWithKeys(jobsKeys);
+
+ when(quartzScheduler.getCurrentlyExecutingJobs()).thenReturn(jobExecutionContexts);
+ when(quartzScheduler.deleteJob(jobToRemove)).thenReturn(true);
+
+ //when
+ boolean isCancelled = eventScheduler.cancelEvent("jobName3");
+
+ //then
+ assertThat(isCancelled).isTrue();
+ }
+
+ private List<JobExecutionContext> createExecutionContextWithKeys(List<JobKey> jobsKeys) {
+ List<JobExecutionContext> contexts = new ArrayList<>();
+ for (JobKey key : jobsKeys) {
+ contexts.add(createExecutionContextFromKey(key));
+ }
+ return contexts;
+ }
+
+ private JobExecutionContext createExecutionContextFromKey(JobKey key) {
+ JobExecutionContext context = mock(JobExecutionContext.class);
+ JobDetail jobDetail = mock(JobDetail.class);
+ when(context.getJobDetail()).thenReturn(jobDetail);
+ when(jobDetail.getKey()).thenReturn(key);
+ return context;
+ }
+
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java b/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java
new file mode 100644
index 0000000..4ed0972
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/simulatorconfig/SimulatorConfigServiceTest.java
@@ -0,0 +1,104 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.simulatorconfig;
+
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.assertj.core.api.Java6Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+class SimulatorConfigServiceTest {
+
+ private static final String SAMPLE_ID = "sampleId";
+ private static final String SAMPLE_NEW_VES_URL = "http://localhost:8090/eventListener/v7";
+ @Mock
+ private SimulatorConfigRepository repository;
+
+ @InjectMocks
+ private SimulatorConfigService service;
+
+ @BeforeEach
+ void resetMocks() {
+ initMocks(this);
+ }
+
+ @Test
+ void testShouldReturnConfiguration() throws MalformedURLException {
+ List<SimulatorConfig> expectedConfig = getExpectedConfig();
+ when(repository.findAll()).thenReturn(expectedConfig);
+
+ SimulatorConfig configs = service.getConfiguration();
+
+ assertThat(configs).isNotNull();
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenNoConfigurationPresent() {
+ when(repository.findAll()).thenReturn(Lists.emptyList());
+
+ assertThatThrownBy(() -> service.getConfiguration())
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessageContaining("No configuration found in db");
+ }
+
+ @Test
+ void testShouldUpdateConfigurationWithVesUrl() throws MalformedURLException {
+ URL updatedUrl = new URL("http://localhost:8090/listener/v8");
+ SimulatorConfig configWithUpdates = new SimulatorConfig("sampleId", updatedUrl);
+ List<SimulatorConfig> expectedConfig = getExpectedConfig();
+
+ when(repository.findAll()).thenReturn(expectedConfig);
+ when(repository.save(any(SimulatorConfig.class))).thenReturn(configWithUpdates);
+
+ SimulatorConfig updatedConfig = service.updateConfiguration(configWithUpdates);
+
+ assertThat(updatedConfig).isEqualToComparingFieldByField(configWithUpdates);
+ }
+
+ @Test
+ void testShouldRaiseExceptionWhenNoConfigInDbPresentOnUpdate() throws MalformedURLException {
+ when(repository.findAll()).thenReturn(Lists.emptyList());
+
+ SimulatorConfig configWithUpdates = new SimulatorConfig(SAMPLE_ID, new URL(SAMPLE_NEW_VES_URL));
+
+ assertThatThrownBy(() -> service.updateConfiguration(configWithUpdates))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessageContaining("No configuration found in db");
+ }
+
+ private List<SimulatorConfig> getExpectedConfig() throws MalformedURLException {
+ URL sampleVesUrl = new URL("http://localhost:8080/eventListener/v7");
+ SimulatorConfig config = new SimulatorConfig(SAMPLE_ID, sampleVesUrl);
+ return Lists.newArrayList(config);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizerTest.java b/src/test/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizerTest.java
new file mode 100644
index 0000000..2d65097
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/template/FsToDbTemplateSynchronizerTest.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
+import org.junit.jupiter.api.Test;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class FsToDbTemplateSynchronizerTest {
+
+
+ @Test
+ public void shouldReturnErrorSynchronizedMessage() {
+ //given
+ FsToDbTemplateSynchronizer fsToDbTemplateSynchronizer = new FsToDbTemplateSynchronizer("someInvalidValue", null);
+ Logger logger = (Logger) LoggerFactory.getLogger(FsToDbTemplateSynchronizer.class);
+ ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
+ listAppender.start();
+ logger.addAppender(listAppender);
+ //when
+ fsToDbTemplateSynchronizer.synchronize();
+ List<ILoggingEvent> logsList = listAppender.list;
+ //then
+ assertEquals("Cannot synchronize templates. Check whether the proper folder exists.", logsList.get(0)
+ .getMessage());
+ assertEquals(Level.ERROR, logsList.get(0)
+ .getLevel());
+ }
+} \ No newline at end of file
diff --git a/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java b/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java
new file mode 100644
index 0000000..fd41045
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/template/TemplateServiceTest.java
@@ -0,0 +1,152 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.assertj.core.util.Lists;
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent;
+import org.onap.pnfsimulator.template.search.TemplateSearchHelper;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+class TemplateServiceTest {
+ private static final Gson GSON = new Gson();
+ private static final Template SAMPLE_TEMPLATE = new Template("sample name", new Document(), Instant.now().getNano());
+ private static final List<Template> SAMPLE_TEMPLATE_LIST = Collections.singletonList(SAMPLE_TEMPLATE);
+
+ @Mock
+ private TemplateRepository templateRepositoryMock;
+
+ @Mock
+ private MongoTemplate mongoTemplate;
+
+ @InjectMocks
+ private TemplateService service;
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ TemplateSearchHelper searchHelper = new TemplateSearchHelper(mongoTemplate);
+ service = new TemplateService(templateRepositoryMock, searchHelper);
+ }
+
+ @Test
+ void testShouldReturnAllTemplates() {
+ when(templateRepositoryMock.findAll()).thenReturn(SAMPLE_TEMPLATE_LIST);
+
+ List<Template> actual = service.getAll();
+ assertThat(actual).containsExactly(SAMPLE_TEMPLATE_LIST.get(0));
+ }
+
+
+ @Test
+ void testShouldGetTemplateBySpecifiedName() {
+ when(templateRepositoryMock.findById("sample name")).thenReturn(Optional.of(SAMPLE_TEMPLATE));
+
+ Optional<Template> actualTemplate = service.get("sample name");
+ assertThat(actualTemplate).isPresent();
+ assertThat(actualTemplate.get()).isEqualTo(SAMPLE_TEMPLATE);
+ }
+
+ @Test
+ void testShouldSaveTemplate() {
+ service.persist(SAMPLE_TEMPLATE);
+
+ verify(templateRepositoryMock, times(1)).save(SAMPLE_TEMPLATE);
+ }
+
+ @Test
+ void testShouldDeleteTemplateByName() {
+ service.delete("sample name");
+
+ verify(templateRepositoryMock, times(1)).deleteById("sample name");
+ }
+
+
+ @Test
+ void testShouldReturnTemplatesAccordingToGivenSearchCriteria() {
+ doReturn(Lists.emptyList()).when(mongoTemplate).find(any(Query.class), anyObject(), any(String.class));
+
+ List<String> idsByContentCriteria = service.getIdsByContentCriteria(GSON.fromJson("{\"domain\": \"notification.json\"}", JsonObject.class));
+
+ assertThat(idsByContentCriteria).isEmpty();
+ }
+
+ @Test
+ void shouldReturnNamesForGivenComposedSearchCriteria() {
+ JsonObject composedCriteriaObject = GSON.fromJson("{\"eventName\": \"pnfRegistration_Nokia_5gDu\", \"sequence\": 1}", JsonObject.class);
+ List<FlatTemplateContent> arr = Lists.newArrayList(new FlatTemplateContent("sampleId", null));
+
+ doReturn(arr).when(mongoTemplate).find(any(Query.class), anyObject(), any(String.class));
+
+ List<String> idsByContentCriteria = service.getIdsByContentCriteria(composedCriteriaObject);
+ assertThat(idsByContentCriteria).containsOnly("sampleId");
+ }
+
+ @Test
+ void shouldReturnFalseWhenOverwritingWithoutForce() {
+ String id = "someTemplate";
+ Template template = new Template(id, new Document(), Instant.now().getNano());
+ when(templateRepositoryMock.existsById(id)).thenReturn(true);
+ boolean actual = service.tryPersistOrOverwrite(template, false);
+ Assert.assertFalse(actual);
+ }
+
+ @Test
+ void shouldReturnTrueWhenOverwritingWithForce() {
+ String id = "someTemplate";
+ Template template = new Template(id, new Document(), Instant.now().getNano());
+ when(templateRepositoryMock.existsById(id)).thenReturn(true);
+ boolean actual = service.tryPersistOrOverwrite(template, true);
+ Assert.assertTrue(actual);
+ }
+
+ @Test
+ void shouldReturnTrueWhenSavingNonExistingTemplate() {
+ String id = "someTemplate";
+ Template template = new Template(id, new Document(), Instant.now().getNano());
+ when(templateRepositoryMock.existsById(id)).thenReturn(false);
+ boolean actual = service.tryPersistOrOverwrite(template, false);
+ Assert.assertTrue(actual);
+ }
+
+}
diff --git a/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java b/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java
new file mode 100644
index 0000000..aac15a6
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/template/search/JsonUtilsTest.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+class JsonUtilsTest {
+
+ private static final Gson GSON_HELPER = new Gson();
+ private JsonUtils utils;
+
+ @BeforeEach
+ void setUp() {
+ utils = new JsonUtils();
+ }
+
+ private static final String NOTIFICATION_JSON = "{\n\"event\": {\n"
+ + " \"commonEventHeader\": {\n"
+ + " \"domain\": \"notification\",\n"
+ + " \"eventName\": \"vFirewallBroadcastPackets\"\n"
+ + " },\n"
+ + " \"notificationFields\": {\n"
+ + " \"changeIdentifier\": \"PM_MEAS_FILES\",\n"
+ + " \"arrayOfNamedHashMap\": [{\n"
+ + " \"name\": \"A20161221.1031-1041.bin.gz\",\n"
+ + " \"hashMap\": {\n"
+ + " \"fileformatType\": \"org.3GPP.32.435#measCollec\",\n"
+ + " \"fileFormatVersion\": \"V10\"\n"
+ + " }\n"
+ + " }, {\n"
+ + " \"name\": \"A20161222.1042-1102.bin.gz\",\n"
+ + " \"hashMap\": {\n"
+ + " \"fileFormatType\": \"org.3GPP.32.435#measCollec\",\n"
+ + " \"fileFormatVersion\": \"1.0.0\"\n"
+ + " }\n"
+ + " }],\n"
+ + " \"notificationFieldsVersion\": \"2.0\"\n}\n\n}}";
+ private static final String EXPECTED_FLATTENED_NOTIFICATION = "{"
+ + " \":event:commonEventHeader:domain\" : \"notification\","
+ + " \":event:commonEventHeader:eventName\" : \"vFirewallBroadcastPackets\","
+ + " \":event:notificationFields:changeIdentifier\" : \"PM_MEAS_FILES\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[0]:name\" : \"A20161221.1031-1041.bin.gz\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[0]:hashMap:fileformatType\" : \"org.3GPP.32.435#measCollec\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[0]:hashMap:fileFormatVersion\" : \"V10\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[1]:name\" : \"A20161222.1042-1102.bin.gz\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[1]:hashMap:fileFormatType\" : \"org.3GPP.32.435#measCollec\","
+ + " \":event:notificationFields:arrayOfNamedHashMap[1]:hashMap:fileFormatVersion\" : \"1.0.0\","
+ + " \":event:notificationFields:notificationFieldsVersion\" : \"2.0\" }";
+
+ @Test
+ void shouldFlattenNestedJsonAndSeparateKeysWithDoubleHash() {
+ JsonObject templateJson = GSON_HELPER.fromJson(NOTIFICATION_JSON, JsonObject.class);
+
+ JsonObject result = utils.flatten(templateJson);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(EXPECTED_FLATTENED_NOTIFICATION, JsonObject.class));
+ }
+
+ @Test
+ void shouldWorkOnEmptyJsonObject() {
+ JsonObject result = utils.flatten(new JsonObject());
+
+ assertThat(result.toString()).isEqualTo("{}");
+ }
+
+ @Test
+ void shouldFlattenObjectWithArrayValue() {
+ String expectedFlattenedObjectWithArray = "{"
+ + " \":sample[0]\": 1,"
+ + " \":sample[1]\": 2,"
+ + " \":sample[2]\": 3}";
+ JsonObject jsonWithPrimitivesArray = GSON_HELPER.fromJson("{\"sample\": [1, 2, 3]}", JsonObject.class);
+
+ JsonObject result = utils.flatten(jsonWithPrimitivesArray);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedObjectWithArray, JsonObject.class));
+ }
+
+ @Test
+ void shouldFlattenObjectWithEmptyArrayValue() {
+ String expectedFlattenedObjectWithEmptyArray = "{\":sample\": []}";
+ JsonObject jsonWithEmptyArrayValue = GSON_HELPER.fromJson("{\"sample\": []}", JsonObject.class);
+
+ JsonObject result = utils.flatten(jsonWithEmptyArrayValue);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedObjectWithEmptyArray, JsonObject.class));
+ }
+
+ @Test
+ void shouldFlattenNestedObjectWithEmptyObjectValue() {
+ String expectedFlattenedNestedObjectWithEmptyObject = "{\":sample:key\": {}}";
+ JsonObject nestedJsonWithEmptyObject = GSON_HELPER.fromJson("{\"sample\": {\"key\":{}}}", JsonObject.class);
+
+ JsonObject result = utils.flatten(nestedJsonWithEmptyObject);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedFlattenedNestedObjectWithEmptyObject, JsonObject.class));
+ }
+
+ @Test
+ void shouldFlattenObjectWithDifferentDataTypes() {
+ String jsonWithDifferentDataTypes = "{ \"topLevelKey\": {\"sampleInt\": 1, \"sampleBool\": false, \"sampleDouble\": 10.0, \"sampleString\": \"str\"}}";
+ String expectedResult = "{\":topLevelKey:sampleInt\": 1,"
+ + " \":topLevelKey:sampleBool\": \"false\","
+ + " \":topLevelKey:sampleDouble\": 10.0,"
+ + " \":topLevelKey:sampleString\": \"str\"}";
+ JsonObject templateJson = GSON_HELPER.fromJson(jsonWithDifferentDataTypes, JsonObject.class);
+
+ JsonObject result = utils.flatten(templateJson);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedResult, JsonObject.class));
+ }
+
+ @Test
+ void shouldHandleNullValues() {
+ String jsonWithNullValue = "{ \"topLevelKey\": {\"sampleNull\": null, \"sampleString\": \"str\"}}";
+ String expectedResult = "{\":topLevelKey:sampleNull\": null,"
+ + " \":topLevelKey:sampleString\": \"str\"}";
+ JsonObject templateJson = GSON_HELPER.fromJson(jsonWithNullValue, JsonObject.class);
+
+ JsonObject result = utils.flatten(templateJson);
+
+ assertThat(result).isEqualTo(GSON_HELPER.fromJson(expectedResult, JsonObject.class));
+ }
+
+ @Test
+ void shouldFlattenBsonDocument() {
+ Document documentInput = Document.parse(NOTIFICATION_JSON);
+
+ Document result = utils.flatten(documentInput);
+
+ assertThat(result.toJson()).isEqualTo(EXPECTED_FLATTENED_NOTIFICATION);
+ }
+
+ @Test
+ void shouldNotChangeEmptyBsonDocument() {
+ Document input = Document.parse("{}");
+
+ Document result = utils.flatten(input);
+
+ assertThat(result.toJson()).isEqualTo("{ }");
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java b/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java
new file mode 100644
index 0000000..13ea7c6
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/template/search/TemplateSearchHelperTest.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.mongodb.BasicDBList;
+import org.assertj.core.util.Lists;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.onap.pnfsimulator.template.search.viewmodel.FlatTemplateContent;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.BasicQuery;
+import org.springframework.data.mongodb.core.query.Query;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+
+class TemplateSearchHelperTest {
+
+ private static final Gson GSON = new Gson();
+ private static final String FLATTENED_TEMPLATES_VIEW = "flatTemplatesView";
+
+ @Mock
+ private MongoTemplate mongoTemplate;
+
+ @InjectMocks
+ private TemplateSearchHelper helper;
+
+ private static final ArgumentCaptor<Query> QUERY_CAPTOR = ArgumentCaptor.forClass(Query.class);
+ private static final ArgumentCaptor<String> COLLECTION_NAME_CAPTOR = ArgumentCaptor.forClass(String.class);
+ private static final ArgumentCaptor<Class<FlatTemplateContent>> CLASS_TYPE_CAPTOR = ArgumentCaptor.forClass((Class) FlatTemplateContent.class);
+
+
+ @BeforeEach
+ void setUp() {
+ initMocks(this);
+ }
+
+ @Test
+ void shouldReturnNamesForGivenComposedSearchCriteria() {
+ String expectedComposedQueryString = "{\"$and\":[{\"keyValues\":{\"$elemMatch\":{\"k\":{\"$regex\":\":eventName(?:(\\\\[[\\\\d]+\\\\]))?$\",\"$options\":\"iu\"},\"v\":{\"$regex\":\"^\\\\QpnfRegistration_Nokia_5gDu\\\\E$\",\"$options\":\"iu\"}}}},{\"keyValues\":{\"$elemMatch\":{\"k\":{\"$regex\":\":sequence(?:(\\\\[[\\\\d]+\\\\]))?$\",\"$options\":\"iu\"},\"v\":1.0}}}]}";
+ Query expectedQuery = new BasicQuery(expectedComposedQueryString);
+
+ String composedCriteriaInputJson = "{\"eventName\": \"pnfRegistration_Nokia_5gDu\", \"sequence\": 1}";
+ JsonObject composedCriteriaObject = GSON.fromJson(composedCriteriaInputJson, JsonObject.class);
+
+ when(mongoTemplate.find(any(Query.class), anyObject(), any(String.class))).thenReturn(Lists.newArrayList(new FlatTemplateContent("sampleId1", null), new FlatTemplateContent("sampleId2", null)));
+
+ List<String> idsOfDocumentMatchingCriteria = helper.getIdsOfDocumentMatchingCriteria(composedCriteriaObject);
+
+ assertThat(idsOfDocumentMatchingCriteria).containsOnly("sampleId1", "sampleId2");
+ verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture());
+ assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQuery.toString());
+ assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW);
+ assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class);
+ }
+
+ @Test
+ void shouldReturnTemplatesAccordingToGivenSearchCriteria() {
+ Query expectedQueryStructure = new BasicQuery("{\"$and\":[{\"keyValues\": { \"$elemMatch\" : { \"k\" : { \"$regex\" : \":domain(?:(\\\\[[\\\\d]+\\\\]))?$\", \"$options\" : \"iu\" }, \"v\" : { \"$regex\" : \"^\\\\Qnotification\\\\E$\", \"$options\" : \"iu\" }}}}]}");
+
+ helper.getIdsOfDocumentMatchingCriteria(GSON.fromJson("{\"domain\": \"notification\"}", JsonObject.class));
+
+
+ verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture());
+
+ assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQueryStructure.toString());
+ assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW);
+ assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class);
+ }
+
+ @Test
+ void shouldGetQueryForEmptyJson() {
+ JsonObject jsonObject = GSON.fromJson("{}", JsonObject.class);
+
+ String expectedComposedQueryString = "{}";
+ Query expectedQuery = new BasicQuery(expectedComposedQueryString);
+
+ helper.getIdsOfDocumentMatchingCriteria(jsonObject);
+
+ verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture());
+ Query queryBasedOnCriteria = QUERY_CAPTOR.getValue();
+
+ assertThat(QUERY_CAPTOR.getValue().toString()).isEqualTo(expectedQuery.toString());
+ assertThat(COLLECTION_NAME_CAPTOR.getValue()).isEqualTo(FLATTENED_TEMPLATES_VIEW);
+ assertThat(CLASS_TYPE_CAPTOR.getValue()).isEqualTo(FlatTemplateContent.class);
+ }
+
+
+ @Test
+ void shouldGetQueryWithAllTypeValues() {
+ JsonObject jsonObject = GSON.fromJson("{\"stringKey\": \"stringValue\", \"numberKey\": 16.00, \"boolKey\": false}", JsonObject.class);
+
+ helper.getIdsOfDocumentMatchingCriteria(jsonObject);
+
+ verify(mongoTemplate, times(1)).find(QUERY_CAPTOR.capture(), CLASS_TYPE_CAPTOR.capture(), COLLECTION_NAME_CAPTOR.capture());
+ Query queryBasedOnCriteria = QUERY_CAPTOR.getValue();
+
+ assertThat(queryBasedOnCriteria.getQueryObject().get("$and")).isInstanceOf(List.class);
+ List<Document> conditionDocuments = new ArrayList<>((List<Document>) queryBasedOnCriteria.getQueryObject().get("$and"));
+ List<Document> conditions = conditionDocuments.stream().map(el -> (Document) el.get("keyValues")).map(el -> (Document) el.get("$elemMatch")).collect(Collectors.toList());
+
+ assertThat(conditionDocuments).hasSize(3);
+ assertJsonPreparedKeyHasCorrectStructure(conditions.get(0), "stringKey");
+ assertThat(conditions.get(0).get("v").toString()).isEqualTo(TemplateSearchHelper.getCaseInsensitive("^\\QstringValue\\E$").toString());
+
+ assertJsonPreparedKeyHasCorrectStructure(conditions.get(1), "numberKey");
+ assertThat(conditions.get(1).get("v")).isEqualTo(16.0);
+
+ assertJsonPreparedKeyHasCorrectStructure(conditions.get(2), "boolKey");
+ assertThat(conditions.get(2).get("v")).isEqualTo("false");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenNullIsPresentAsCriteriaValue() {
+ JsonObject jsonObject = GSON.fromJson("{\"stringKey\": \"stringValue\", \"nullKey\": null}", JsonObject.class);
+
+ assertThrows(IllegalJsonValueException.class, () -> helper.getIdsOfDocumentMatchingCriteria(jsonObject));
+ }
+
+ private void assertJsonPreparedKeyHasCorrectStructure(Document actual, String expectedPattern) {
+ assertThat(actual.get("k").toString()).isEqualTo(Pattern.compile(String.format(":%s(?:(\\[[\\d]+\\]))?$", expectedPattern)).toString());
+
+ }
+}
diff --git a/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java b/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java
new file mode 100644
index 0000000..6de86e0
--- /dev/null
+++ b/src/test/java/org/onap/pnfsimulator/template/search/handler/PrimitiveValueCriteriaBuilderTest.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Simulator
+ * ================================================================================
+ * Copyright (C) 2019 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.pnfsimulator.template.search.handler;
+
+import com.google.gson.JsonPrimitive;
+import org.junit.jupiter.api.Test;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+class PrimitiveValueCriteriaBuilderTest {
+
+ private PrimitiveValueCriteriaBuilder builder = new PrimitiveValueCriteriaBuilder();
+
+ @Test
+ void testShouldAddRegexLikeCriteriaForStringType() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive("sample"));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : { \"$regex\" : \"^\\\\Qsample\\\\E$\", \"$options\" : \"iu\" } }");
+ }
+
+ @Test
+ void testShouldAddRegexLikeAndEscapeStringWithMetaChars() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive("[1,2,3,4,5]"));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : { \"$regex\" : \"^\\\\Q[1,2,3,4,5]\\\\E$\", \"$options\" : \"iu\" } }");
+ }
+
+ @Test
+ void testShouldAddRegexLikeCriteriaForIntType() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(1));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 1.0 }");
+ }
+
+ @Test
+ void testShouldAddRegexLikeCriteriaForLongType() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(Long.MAX_VALUE));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 9.223372036854776E18 }");
+ }
+
+ @Test
+ void testShouldAddRegexLikeCriteriaForDoubleType() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(2.5));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : 2.5 }");
+ }
+
+ @Test
+ void testShouldAddRegexLikeCriteriaForBooleanType() {
+ Criteria criteria = builder.applyValueCriteriaBasedOnPrimitiveType(Criteria.where("k").is("10").and("v"), new JsonPrimitive(true));
+
+ assertThat(criteria.getCriteriaObject().toJson()).isEqualTo("{ \"k\" : \"10\", \"v\" : \"true\" }");
+ }
+
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644
index 0000000..6815680
--- /dev/null
+++ b/src/test/resources/application.properties
@@ -0,0 +1,2 @@
+templates.dir=src/test/resources/org/onap/pnfsimulator/simulator
+ssl.clientCertificateEnabled=false
diff --git a/src/test/resources/certificates/client.p12 b/src/test/resources/certificates/client.p12
new file mode 100644
index 0000000..0bbec38
--- /dev/null
+++ b/src/test/resources/certificates/client.p12
Binary files differ
diff --git a/src/test/resources/certificates/client.pass b/src/test/resources/certificates/client.pass
new file mode 100644
index 0000000..25acfbf
--- /dev/null
+++ b/src/test/resources/certificates/client.pass
@@ -0,0 +1 @@
+collector \ No newline at end of file
diff --git a/src/test/resources/certificates/client_invalid.pass b/src/test/resources/certificates/client_invalid.pass
new file mode 100644
index 0000000..0b54957
--- /dev/null
+++ b/src/test/resources/certificates/client_invalid.pass
@@ -0,0 +1 @@
+invalidpassword \ No newline at end of file
diff --git a/src/test/resources/certificates/truststore b/src/test/resources/certificates/truststore
new file mode 100644
index 0000000..e90b710
--- /dev/null
+++ b/src/test/resources/certificates/truststore
Binary files differ
diff --git a/src/test/resources/certificates/truststore.pass b/src/test/resources/certificates/truststore.pass
new file mode 100644
index 0000000..25acfbf
--- /dev/null
+++ b/src/test/resources/certificates/truststore.pass
@@ -0,0 +1 @@
+collector \ No newline at end of file
diff --git a/src/test/resources/certificates/truststore_invalid.pass b/src/test/resources/certificates/truststore_invalid.pass
new file mode 100644
index 0000000..0b54957
--- /dev/null
+++ b/src/test/resources/certificates/truststore_invalid.pass
@@ -0,0 +1 @@
+invalidpassword \ No newline at end of file
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..0dedeba
--- /dev/null
+++ b/src/test/resources/logback-test.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ Simulator
+ ================================================================================
+ Copyright (C) 2019 Nokia. All rights reserved.
+ ================================================================================
+ 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=========================================================
+ -->
+
+<Configuration complete="true" compact="true">
+
+ <Property name="outputFilename" value="pnfsimulator_output"/>
+ <Property name="log-path" value="${java.io.tmpdir}"/>
+ <property name="maxFileSize" value="50MB"/>
+ <property name="maxHistory" value="30"/>
+ <property name="totalSizeCap" value="10GB"/>
+ <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+
+
+ <appender name="Console" target="SYSTEM_OUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+ </encoder>
+ </appender>
+
+ <appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <encoder>
+ <pattern>${FILE_LOG_PATTERN}</pattern>
+ </encoder>
+ <File>${log-path}/${outputFilename}.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <FileNamePattern>${log-path}/${outputFilename}.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
+ <MaxFileSize>${maxFileSize}</MaxFileSize>
+ <MaxHistory>${maxHistory}</MaxHistory>
+ <TotalSizeCap>${totalSizeCap}</TotalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="Console" />
+ <appender-ref ref="ROLLING-FILE" />
+ </root>
+</Configuration>
diff --git a/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json b/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json
new file mode 100644
index 0000000..89e4a76
--- /dev/null
+++ b/src/test/resources/org/onap/pnfsimulator/simulator/filesystem/test1.json
@@ -0,0 +1,12 @@
+{
+ "field1": "value1",
+ "field2": 2,
+ "nested": {
+ "key1": [
+ 1,
+ 2,
+ 3
+ ],
+ "key2": "sampleValue2"
+ }
+}
diff --git a/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json b/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json
new file mode 100644
index 0000000..4d6ef7d
--- /dev/null
+++ b/src/test/resources/org/onap/pnfsimulator/simulator/invalidJsonStructureEvent.json
@@ -0,0 +1 @@
+{"sampleKey1": [{"sampleKey2": "1"}, {"sampleKey2": "2"}]
diff --git a/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json b/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json
new file mode 100644
index 0000000..a240b93
--- /dev/null
+++ b/src/test/resources/org/onap/pnfsimulator/simulator/validExampleMeasurementEvent.json
@@ -0,0 +1,86 @@
+{
+ "event": {
+ "commonEventHeader": {
+ "domain": "measurementsForVfScaling",
+ "eventName": "vFirewallBroadcastPackets",
+ "eventId": "4cfc-91cf-31a46",
+ "nfType": "mrfx",
+ "priority": "Normal",
+ "reportingEntityName": "#dn",
+ "sequence": 1,
+ "sourceName": "ClosedLoopVNF",
+ "startEpochMicrosec": 1531616794,
+ "lastEpochMicrosec": 1531719042,
+ "version": 2.0
+ },
+ "measurementsForVfScalingFields": {
+ "measurementsForVfSclaingFieldsVersion": 2.0,
+ "measurementsForVfScalingVersion": 2.0,
+ "measurementInterval": 180,
+ "concurrentSessions": 2,
+ "cpuUsageArray": [
+ {
+ "cpuIdentifier": "INTEL_CORE_I7_1",
+ "percentUsage": 50
+ },
+ {
+ "cpuIdentifier": "INTEL_CORE_I7_2",
+ "percentUsage": 70
+ }
+ ],
+ "memoryUsageArray": [
+ {
+ "vmIdentifier": "vmIdentifier",
+ "memoryFree": 50,
+ "memoryUsed": 10
+ }
+ ],
+ "vNicUsageArray": [
+ {
+ "receivedTotalPacketsDelta": 30
+ }
+ ],
+ "numberOfMediaPortsInUse": 100,
+ "additionalMeasurements": [
+ {
+ "name": "licenseUsage",
+ "arrayOfFields": [
+ "#measurement",
+ {
+ "name": "G729AudioPort",
+ "value": "1"
+ },
+ {
+ "name": "G722AudioPort",
+ "value": "1"
+ },
+ {
+ "name": "AMRAudioPort",
+ "value": "4"
+ },
+ {
+ "name": "AMRWBAudioPort",
+ "value": "5"
+ },
+ {
+ "name": "OpusAudioPort",
+ "value": "6"
+ },
+ {
+ "name": "H263VideoPort",
+ "value": "7"
+ },
+ {
+ "name": "H264NonHCVideoPort",
+ "value": "8"
+ },
+ {
+ "name": "H264HCVideoPort",
+ "value": "9"
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/store/cert.p12 b/store/cert.p12
new file mode 100644
index 0000000..0bbec38
--- /dev/null
+++ b/store/cert.p12
Binary files differ
diff --git a/store/p12.pass b/store/p12.pass
new file mode 100644
index 0000000..25acfbf
--- /dev/null
+++ b/store/p12.pass
@@ -0,0 +1 @@
+collector \ No newline at end of file
diff --git a/store/trust.jks b/store/trust.jks
new file mode 100644
index 0000000..e90b710
--- /dev/null
+++ b/store/trust.jks
Binary files differ
diff --git a/store/truststore.pass b/store/truststore.pass
new file mode 100644
index 0000000..25acfbf
--- /dev/null
+++ b/store/truststore.pass
@@ -0,0 +1 @@
+collector \ No newline at end of file
diff --git a/templates/cmNotification.json b/templates/cmNotification.json
new file mode 100644
index 0000000..750ce30
--- /dev/null
+++ b/templates/cmNotification.json
@@ -0,0 +1,32 @@
+{
+ "event": {
+ "otherFields": {
+ "otherFieldsVersion": "3.0",
+ "jsonObjects": [
+ {
+ "objectName": "CustomNotification",
+ "objectInstances": [
+ {
+ "objectInstance": {
+ "cm3gppNotifyFields": {
+ "dN": "#dN",
+ "notificationType": "notifyMOIAttributeValueChange",
+ "notificationId": "notificationID123121312323",
+ "sourceIndicator": "sONOperation",
+ "eventTime": "#Timestamp",
+ "systemDN": "NRNB=5",
+ "attributeList": "#attributeList",
+ "correlatedNotifications": {
+ "notificationID-notifyMOIAttributeValueChange": "sONOperation"
+ },
+ "additionalText": "sometext",
+ "cm3gppNotifyFieldsVersion": "1.0"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
diff --git a/templates/measurement.json b/templates/measurement.json
new file mode 100644
index 0000000..a29b063
--- /dev/null
+++ b/templates/measurement.json
@@ -0,0 +1,44 @@
+{
+ "event": {
+ "commonEventHeader": {
+ "domain": "measurementsForVfScaling",
+ "eventName": "vFirewallBroadcastPackets",
+ "eventId": "eventID123121312323",
+ "nfType": "mrfx",
+ "priority": "Normal",
+ "reportingEntityName": "vnf",
+ "sequence": 1,
+ "sourceName": "sample-vnf-#RandomInteger(1,10)",
+ "startEpochMicrosec": "#TimestampPrimitive",
+ "lastEpochMicrosec": "#TimestampPrimitive",
+ "version": 1.0
+ },
+ "measurementsForVfScalingFields": {
+ "measurementsForVfScalingFieldsVersion": 2.0,
+ "measurementsForVfScalingVersion": 2.0,
+ "measurementInterval": 180,
+ "concurrentSessions": 2,
+ "requestRate": "#RandomPrimitiveInteger(50,100)",
+ "meanRequestLatency": "#RandomPrimitiveInteger(1,1000)",
+ "cpuUsageArray": [
+ {
+ "cpuIdentifier": "INTEL_CORE_I7_1",
+ "percentUsage": "#RandomPrimitiveInteger(1,100)"
+ },
+ {
+ "cpuIdentifier": "INTEL_CORE_I7_2",
+ "percentUsage": "#RandomPrimitiveInteger(1,100)"
+ }
+ ],
+ "memoryUsageArray": [
+ {
+ "vmIdentifier": "vmIdentifier",
+ "memoryFree": 50,
+ "memoryUsed": 10
+ }
+ ],
+ "numberOfMediaPortsInUse": 100,
+ "additionalMeasurements": []
+ }
+ }
+}
diff --git a/templates/notification.json b/templates/notification.json
new file mode 100644
index 0000000..74888fb
--- /dev/null
+++ b/templates/notification.json
@@ -0,0 +1,42 @@
+{
+ "event": {
+ "commonEventHeader": {
+ "domain": "notification",
+ "eventName": "vFirewallBroadcastPackets",
+ "eventId": "4cfc-91cf-31a46",
+ "priority": "Normal",
+ "reportingEntityName": "myVNF",
+ "sequence": 1,
+ "sourceName": "ClosedLoopVNF",
+ "startEpochMicrosec": 1531616794,
+ "lastEpochMicrosec": 1531719042,
+ "vesEventListenerVersion": "7.0.1",
+ "version": "4.0.1"
+ },
+ "notificationFields": {
+ "changeIdentifier": "PM_MEAS_FILES",
+ "changeType": "FileReady",
+ "arrayOfNamedHashMap": [
+ {
+ "name": "A20161221.1031-1041.bin.gz",
+ "hashMap": {
+ "fileformatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10",
+ "location": "ftpes://192.169.0.1:22/ftp/rop/A20161224.1030-1045.bin.gz",
+ "compression": "gzip"
+ }
+ },
+ {
+ "name": "A20161222.1042-1102.bin.gz",
+ "hashMap": {
+ "fileFormatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10",
+ "location": "ftpes://192.168.0.102:22/ftp/rop/A20161224.1045-1100.bin.gz",
+ "compression": "gzip"
+ }
+ }
+ ],
+ "notificationFieldsVersion": "2.0"
+ }
+ }
+}
diff --git a/templates/notificationHttpServer.json b/templates/notificationHttpServer.json
new file mode 100644
index 0000000..f4fcc76
--- /dev/null
+++ b/templates/notificationHttpServer.json
@@ -0,0 +1,52 @@
+{
+ "event": {
+ "commonEventHeader": {
+ "version": "4.0.1",
+ "vesEventListenerVersion": "7.0.1",
+ "domain": "notification",
+ "eventName": "Notification_gnb-Nokia_FileReady",
+ "eventId": "FileReady_1797490e-10ae-4d48-9ea7-3d7d790b25e1",
+ "lastEpochMicrosec": 8745745764578,
+ "priority": "Normal",
+ "reportingEntityName": "NOK6061ZW3",
+ "sequence": 0,
+ "sourceName": "NOK6061ZW3",
+ "startEpochMicrosec": 8745745764578,
+ "timeZoneOffset": "UTC+05.30"
+ },
+ "notificationFields": {
+ "changeIdentifier": "PM_MEAS_FILES",
+ "changeType": "FileReady",
+ "notificationFieldsVersion": "2.0",
+ "arrayOfNamedHashMap": [
+ {
+ "name": "C_28532_measData_pm_98.xml",
+ "hashMap": {
+ "location": "http://demo:demo123456!@localhost:32080/E_VES_bulkPM_IF_3GPP_3_example_1.xml.gz",
+ "compression": "gzip",
+ "fileFormatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10"
+ }
+ },
+ {
+ "name": "C_28532_measData_pm_99.xml",
+ "hashMap": {
+ "location": "http://demo:demo123456!@localhost:32080/E_VES_bulkPM_IF_3GPP_3_example_1.xml.gz",
+ "compression": "gzip",
+ "fileFormatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10"
+ }
+ },
+ {
+ "name": "C_28532_measData_pm_100.xml",
+ "hashMap": {
+ "location": "http://demo:demo123456!@localhost:32080/E_VES_bulkPM_IF_3GPP_3_example_1.xml.gz",
+ "compression": "gzip",
+ "fileFormatType": "org.3GPP.32.435#measCollec",
+ "fileFormatVersion": "V10"
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/templates/registration.json b/templates/registration.json
new file mode 100644
index 0000000..5c4dea5
--- /dev/null
+++ b/templates/registration.json
@@ -0,0 +1,33 @@
+{
+ "event": {
+ "commonEventHeader": {
+ "eventId": "registration_39239592",
+ "eventType": "pnfRegistration",
+ "reportingEntityName": "NOK6061ZW3",
+ "domain": "pnfRegistration",
+ "nfcNamingCode": "oam",
+ "sequence": 0,
+ "sourceId": "val13",
+ "internalHeaderFields": {},
+ "priority": "Normal",
+ "sourceName": "NOK6061ZW3",
+ "eventName": "pnfRegistration_Nokia_5gDu",
+ "version": "4.0.1",
+ "nfNamingCode": "gNB",
+ "startEpochMicrosec": 1539239592379,
+ "vesEventListenerVersion": "7.0.1",
+ "lastEpochMicrosec": 1539239592379
+ },
+ "pnfRegistrationFields": {
+ "pnfRegistrationFieldsVersion": "2.0",
+ "serialNumber": "6061ZW3",
+ "vendorName": "Nokia",
+ "oamV4IpAddress": "val3",
+ "oamV6IpAddress": "val4",
+ "unitFamily": "BBU",
+ "modelNumber": "val6",
+ "softwareVersion": "val7",
+ "unitType": "val8"
+ }
+ }
+}
diff --git a/version.properties b/version.properties
new file mode 100644
index 0000000..bf3f0bf
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,13 @@
+###########################################################
+# Versioning variables
+# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... )
+# because they are used in Jenkins, whose plug-in doesn't support
+
+major=1
+minor=0
+patch=0
+
+base_version=${major}.${minor}.${patch}
+
+release_version=${base_version}
+snapshot_version=${base_version}-SNAPSHOT