diff options
author | Bogumil Zebek <bogumil.zebek@nokia.com> | 2021-03-09 12:54:38 +0100 |
---|---|---|
committer | Zebek Bogumil <bogumil.zebek@nokia.com> | 2021-03-10 09:31:58 +0100 |
commit | 4af5241ab25b0103d8ea680789aaf9a8696dfc75 (patch) | |
tree | 36ccae11ebf094aa1ddd65df309b7531ce0db1ff /integration | |
parent | c9975cb96ba4e0208e72399ed80f909beb95d9d9 (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
Diffstat (limited to 'integration')
28 files changed, 1776 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 0000000..26a16f7 --- /dev/null +++ b/integration/src/main/resources/keystore 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¶m2=*\" }}") + .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¶m2=*" + } + } +} 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" + } +} |