From 4b54b7ed29e736b2f80878bab90acaedb4e7117e Mon Sep 17 00:00:00 2001 From: "aravind.est" Date: Tue, 20 Feb 2024 11:46:23 +0000 Subject: [PATCH] rApp package validation code refactor rApp package validation refactored. Each validation condition should implement the interface RappValidator. It should throw respective error incase of the validation(RappValidationException) failure. Order should be defined for each validator. The validator gets evaluated based on the ascending order. Issue-ID: NONRTRIC-984 Change-Id: I3309e714f26a1fdb5aa10b32c5a7113411dcdf4d Signed-off-by: aravind.est --- .../oransc/rappmanager/rest/RappController.java | 6 +- .../models/csar/RappCsarConfigurationHandler.java | 142 ++++++--------------- .../models/csar/RappCsarPathProvider.java | 41 ++++++ .../validator/ArtifactDefinitionValidator.java | 72 +++++++++++ .../csar/validator/FileExistenceValidator.java | 47 +++++++ .../models/csar/validator/NamingValidator.java | 45 +++++++ .../csar/validator/RappValidationHandler.java | 40 ++++++ .../models/csar/validator/RappValidationUtils.java | 68 ++++++++++ .../models/csar/validator/RappValidator.java | 30 +++++ .../exception/ExceptionControllerHandler.java | 9 +- .../models/exception/RappHandlerException.java | 4 +- .../models/exception/RappValidationException.java | 35 +++++ .../csar/RappCsarConfigurationHandlerTest.java | 128 ------------------- .../validator/ArtifactDefinitionValidatorTest.java | 132 +++++++++++++++++++ .../csar/validator/FileExistenceValidatorTest.java | 87 +++++++++++++ .../models/csar/validator/NamingValidatorTest.java | 78 +++++++++++ .../csar/validator/RappValidationHandlerTest.java | 114 +++++++++++++++++ .../csar/validator/RappValidationUtilsTest.java | 110 ++++++++++++++++ 18 files changed, 950 insertions(+), 238 deletions(-) create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java create mode 100755 rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java create mode 100755 rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java create mode 100755 rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java create mode 100755 rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java create mode 100755 rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java create mode 100755 rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java index 287e297..85e1a44 100755 --- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. All rights reserved. + * Copyright (C) 2023-2024 Nordix Foundation. 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. @@ -21,6 +21,7 @@ package com.oransc.rappmanager.rest; import com.oransc.rappmanager.configuration.RappManagerConfiguration; import com.oransc.rappmanager.models.cache.RappCacheService; import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.csar.validator.RappValidationHandler; import com.oransc.rappmanager.models.exception.RappHandlerException; import com.oransc.rappmanager.models.rapp.PrimeOrder; import com.oransc.rappmanager.models.rapp.Rapp; @@ -56,6 +57,7 @@ public class RappController { Logger logger = LoggerFactory.getLogger(RappController.class); private final RappCsarConfigurationHandler rappCsarConfigurationHandler; + private final RappValidationHandler rappValidationHandler; private final RappManagerConfiguration rappManagerConfiguration; private final RappCacheService rappCacheService; private final RappService rappService; @@ -75,7 +77,7 @@ public class RappController { @PostMapping("{rapp_id}") public ResponseEntity createRapp(@PathVariable("rapp_id") String rappId, @RequestPart("file") MultipartFile csarFilePart) throws IOException { - if (rappCsarConfigurationHandler.isValidRappPackage(csarFilePart)) { + if (rappValidationHandler.isValidRappPackage(csarFilePart)) { File csarFile = new File( rappCsarConfigurationHandler.getRappPackageLocation(rappManagerConfiguration.getCsarLocation(), rappId, csarFilePart.getOriginalFilename()).toUri()); diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java index 9e2f953..41c0eaf 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java @@ -26,7 +26,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; -import com.oransc.rappmanager.models.exception.RappHandlerException; import com.oransc.rappmanager.models.rapp.Rapp; import com.oransc.rappmanager.models.rapp.RappResources; import com.oransc.rappmanager.models.rappinstance.RappACMInstance; @@ -50,9 +49,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ByteArrayResource; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; import org.yaml.snakeyaml.Yaml; @Service @@ -62,53 +59,14 @@ public class RappCsarConfigurationHandler { Logger logger = LoggerFactory.getLogger(RappCsarConfigurationHandler.class); private final ObjectMapper objectMapper; - private static final String TOSCA_METADATA_LOCATION = "TOSCA-Metadata/TOSCA.meta"; - private static final String ENTRY_DEFINITIONS_INDEX = "Entry-Definitions"; - private static final String ACM_COMPOSITION_JSON_LOCATION = "Files/Acm/definition/compositions.json"; - private static final String ACM_DEFINITION_LOCATION = "Files/Acm/definition"; - private static final String ACM_INSTANCES_LOCATION = "Files/Acm/instances"; - private static final String SME_PROVIDER_FUNCS_LOCATION = "Files/Sme/providers"; - private static final String SME_SERVICE_APIS_LOCATION = "Files/Sme/serviceapis"; - private static final String SME_INVOKERS_LOCATION = "Files/Sme/invokers"; - private static final String DME_PRODUCER_INFO_TYPES_LOCATION = "Files/Dme/producerinfotypes"; - private static final String DME_CONSUMER_INFO_TYPES_LOCATION = "Files/Dme/consumerinfotypes"; - private static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers"; - private static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers"; - private static final String ARTIFACTS_LOCATION_JSON_POINTER = - "/topology_template/node_templates/applicationServiceDescriptor/artifacts"; - - - public boolean isValidRappPackage(MultipartFile multipartFile) { - String originalFilename = multipartFile.getOriginalFilename(); - if (originalFilename != null) { - return originalFilename.endsWith(".csar") && isFileExistsInCsar(multipartFile, - ACM_COMPOSITION_JSON_LOCATION) && isFileExistsInCsar(multipartFile, TOSCA_METADATA_LOCATION) - && containsValidArtifactDefinition(multipartFile); - } - return false; - } - - boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) { - try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) { - ArchiveEntry zipEntry; - while ((zipEntry = zipArchiveInputStream.getNextEntry()) != null) { - if (zipEntry.getName().matches(fileLocation)) { - return Boolean.TRUE; - } - } - throw new RappHandlerException(HttpStatus.BAD_REQUEST, "rApp package missing a file " + fileLocation); - } catch (IOException e) { - logger.error("Unable to find the CSAR file", e); - throw new RappHandlerException(HttpStatus.BAD_REQUEST, "rApp package missing a file " + fileLocation); - } - } public Path getRappPackageLocation(String csarLocation, String rappId, String fileName) { return Path.of(csarLocation, rappId, fileName); } public String getInstantiationPayload(Rapp rapp, RappACMInstance rappACMInstance, UUID compositionId) { - return getPayload(rapp, getResourceUri(ACM_INSTANCES_LOCATION, rappACMInstance.getInstance())).replaceAll( + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.ACM_INSTANCES_LOCATION, rappACMInstance.getInstance())).replaceAll( "COMPOSITIONID", String.valueOf(compositionId)); } @@ -131,16 +89,6 @@ public class RappCsarConfigurationHandler { getRappPackageLocation(rapp.getPackageLocation(), rapp.getName(), rapp.getPackageName()).toUri()); } - ByteArrayOutputStream getFileFromCsar(MultipartFile multipartFile, String fileLocation) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) { - byteArrayOutputStream = getFileFromCsar(zipArchiveInputStream, fileLocation); - } catch (IOException e) { - logger.info("Unable to get file {} from the multipart CSAR file", fileLocation, e); - } - return byteArrayOutputStream; - } - ByteArrayOutputStream getFileFromCsar(File csarFile, String fileLocation) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try (FileInputStream fileInputStream = new FileInputStream(csarFile); @@ -152,7 +100,7 @@ public class RappCsarConfigurationHandler { return byteArrayOutputStream; } - ByteArrayOutputStream getFileFromCsar(ZipArchiveInputStream zipArchiveInputStream, String fileLocation) { + public ByteArrayOutputStream getFileFromCsar(ZipArchiveInputStream zipArchiveInputStream, String fileLocation) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try { ArchiveEntry entry; @@ -171,44 +119,21 @@ public class RappCsarConfigurationHandler { return byteArrayOutputStream; } - boolean containsValidArtifactDefinition(MultipartFile multipartFile) { - String asdLocation = getAsdDefinitionLocation(multipartFile); - if (asdLocation != null && !asdLocation.isEmpty() && isFileExistsInCsar(multipartFile, asdLocation)) { - try { - String asdContent = getFileFromCsar(multipartFile, asdLocation).toString(); - JsonNode jsonNode = getAsdContentNode(asdContent); - List artifactFileList = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file"); - return artifactFileList.stream() - .allMatch(artifactFile -> isFileExistsInCsar(multipartFile, artifactFile)); - } catch (RappHandlerException e) { - throw e; - } catch (Exception e) { - logger.warn("Unable to validate artifact definition", e); - throw new RappHandlerException(HttpStatus.BAD_REQUEST, "ASD definition in rApp package is invalid."); - } - } - throw new RappHandlerException(HttpStatus.BAD_REQUEST, "ASD definition in rApp package is invalid."); - } - - JsonNode getAsdContentNode(String asdContent) throws JsonProcessingException { + public JsonNode getAsdContentNode(String asdContent) throws JsonProcessingException { return objectMapper.readTree(new Gson().toJsonTree(new Yaml().load(asdContent)).toString()); } String getAsdDefinitionLocation(final File csarFile) { - return getAsdDefinitionLocation(getFileFromCsar(csarFile, TOSCA_METADATA_LOCATION).toString()); + return getAsdDefinitionLocation( + getFileFromCsar(csarFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION).toString()); } - String getAsdDefinitionLocation(final MultipartFile multipartFile) { - return getAsdDefinitionLocation(getFileFromCsar(multipartFile, TOSCA_METADATA_LOCATION).toString()); - } - - String getAsdDefinitionLocation(final String toscaMetadata) { + public String getAsdDefinitionLocation(final String toscaMetadata) { String asdLocation = ""; if (toscaMetadata != null && !toscaMetadata.isEmpty()) { - final String entry = - filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_INDEX)).iterator() - .next(); - asdLocation = entry.replace(ENTRY_DEFINITIONS_INDEX + ":", "").trim(); + final String entry = filter(on("\n").split(toscaMetadata), + line -> line.contains(RappCsarPathProvider.ENTRY_DEFINITIONS_INDEX)).iterator().next(); + asdLocation = entry.replace(RappCsarPathProvider.ENTRY_DEFINITIONS_INDEX + ":", "").trim(); } return asdLocation; } @@ -221,7 +146,7 @@ public class RappCsarConfigurationHandler { try { String asdContent = getFileFromCsar(csarFile, asdDefinitionLocation).toString(); JsonNode jsonNode = getAsdContentNode(asdContent); - JsonNode artifactsJsonNode = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER); + JsonNode artifactsJsonNode = jsonNode.at(RappCsarPathProvider.ARTIFACTS_LOCATION_JSON_POINTER); artifactsJsonNode.forEach(artifactJsonNode -> { DeploymentItem deploymentItem = objectMapper.convertValue(artifactJsonNode.at("/properties"), DeploymentItem.class); @@ -237,36 +162,42 @@ public class RappCsarConfigurationHandler { public String getSmeProviderDomainPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { - return getPayload(rapp, getResourceUri(SME_PROVIDER_FUNCS_LOCATION, rappSMEInstance.getProviderFunction())); + return getPayload(rapp, getResourceUri(RappCsarPathProvider.SME_PROVIDER_FUNCS_LOCATION, + rappSMEInstance.getProviderFunction())); } public String getSmeProviderApiPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { - return getPayload(rapp, getResourceUri(SME_SERVICE_APIS_LOCATION, rappSMEInstance.getServiceApis())); + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.SME_SERVICE_APIS_LOCATION, rappSMEInstance.getServiceApis())); } public String getSmeInvokerPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { - return getPayload(rapp, getResourceUri(SME_INVOKERS_LOCATION, rappSMEInstance.getInvokers())); + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.SME_INVOKERS_LOCATION, rappSMEInstance.getInvokers())); } public String getAcmCompositionPayload(Rapp rapp) { - return getPayload(rapp, - getResourceUri(ACM_DEFINITION_LOCATION, rapp.getRappResources().getAcm().getCompositionDefinitions())); + return getPayload(rapp, getResourceUri(RappCsarPathProvider.ACM_DEFINITION_LOCATION, + rapp.getRappResources().getAcm().getCompositionDefinitions())); } public String getDmeInfoProducerPayload(Rapp rapp, String producerIdentifier) { - return getPayload(rapp, getResourceUri(DME_INFO_PRODUCERS_LOCATION, producerIdentifier)); + return getPayload(rapp, getResourceUri(RappCsarPathProvider.DME_INFO_PRODUCERS_LOCATION, producerIdentifier)); } public String getDmeProducerInfoTypePayload(Rapp rapp, String infoTypeIdentifier) { - return getPayload(rapp, getResourceUri(DME_PRODUCER_INFO_TYPES_LOCATION, infoTypeIdentifier)); + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.DME_PRODUCER_INFO_TYPES_LOCATION, infoTypeIdentifier)); } public String getDmeConsumerInfoTypePayload(Rapp rapp, String infoTypeIdentifier) { - return getPayload(rapp, getResourceUri(DME_CONSUMER_INFO_TYPES_LOCATION, infoTypeIdentifier)); + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.DME_CONSUMER_INFO_TYPES_LOCATION, infoTypeIdentifier)); } public String getDmeInfoConsumerPayload(Rapp rapp, String infoConsumerIdentifier) { - return getPayload(rapp, getResourceUri(DME_INFO_CONSUMERS_LOCATION, infoConsumerIdentifier)); + return getPayload(rapp, + getResourceUri(RappCsarPathProvider.DME_INFO_CONSUMERS_LOCATION, infoConsumerIdentifier)); } String getResourceUri(String resourceLocation, String resource) { @@ -279,17 +210,20 @@ public class RappCsarConfigurationHandler { File csarFile = getCsarFile(rapp); if (csarFile.exists()) { rappResources.setAcm(RappResources.ACMResources.builder().compositionDefinitions( - getFileListFromCsar(csarFile, ACM_DEFINITION_LOCATION).iterator().next()).compositionInstances( - getFileListFromCsar(csarFile, ACM_INSTANCES_LOCATION)).build()); + getFileListFromCsar(csarFile, RappCsarPathProvider.ACM_DEFINITION_LOCATION).iterator().next()) + .compositionInstances(getFileListFromCsar(csarFile, + RappCsarPathProvider.ACM_INSTANCES_LOCATION)).build()); rappResources.setSme(RappResources.SMEResources.builder().providerFunctions( - getFileListFromCsar(csarFile, SME_PROVIDER_FUNCS_LOCATION)) - .serviceApis(getFileListFromCsar(csarFile, SME_SERVICE_APIS_LOCATION)) - .invokers(getFileListFromCsar(csarFile, SME_INVOKERS_LOCATION)).build()); + getFileListFromCsar(csarFile, RappCsarPathProvider.SME_PROVIDER_FUNCS_LOCATION)).serviceApis( + getFileListFromCsar(csarFile, RappCsarPathProvider.SME_SERVICE_APIS_LOCATION)).invokers( + getFileListFromCsar(csarFile, RappCsarPathProvider.SME_INVOKERS_LOCATION)).build()); rappResources.setDme(RappResources.DMEResources.builder().producerInfoTypes( - getFileListFromCsar(csarFile, DME_PRODUCER_INFO_TYPES_LOCATION)).consumerInfoTypes( - getFileListFromCsar(csarFile, DME_CONSUMER_INFO_TYPES_LOCATION)) - .infoProducers(getFileListFromCsar(csarFile, DME_INFO_PRODUCERS_LOCATION)) - .infoConsumers(getFileListFromCsar(csarFile, DME_INFO_CONSUMERS_LOCATION)) + getFileListFromCsar(csarFile, RappCsarPathProvider.DME_PRODUCER_INFO_TYPES_LOCATION)) + .consumerInfoTypes(getFileListFromCsar(csarFile, + RappCsarPathProvider.DME_CONSUMER_INFO_TYPES_LOCATION)) + .infoProducers(getFileListFromCsar(csarFile, + RappCsarPathProvider.DME_INFO_PRODUCERS_LOCATION)).infoConsumers( + getFileListFromCsar(csarFile, RappCsarPathProvider.DME_INFO_CONSUMERS_LOCATION)) .build()); } } catch (Exception e) { diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java new file mode 100755 index 0000000..745ae14 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class RappCsarPathProvider { + + public static final String TOSCA_METADATA_LOCATION = "TOSCA-Metadata/TOSCA.meta"; + public static final String ENTRY_DEFINITIONS_INDEX = "Entry-Definitions"; + public static final String ACM_COMPOSITION_JSON_LOCATION = "Files/Acm/definition/compositions.json"; + public static final String ACM_DEFINITION_LOCATION = "Files/Acm/definition"; + public static final String ACM_INSTANCES_LOCATION = "Files/Acm/instances"; + public static final String SME_PROVIDER_FUNCS_LOCATION = "Files/Sme/providers"; + public static final String SME_SERVICE_APIS_LOCATION = "Files/Sme/serviceapis"; + public static final String SME_INVOKERS_LOCATION = "Files/Sme/invokers"; + public static final String DME_PRODUCER_INFO_TYPES_LOCATION = "Files/Dme/producerinfotypes"; + public static final String DME_CONSUMER_INFO_TYPES_LOCATION = "Files/Dme/consumerinfotypes"; + public static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers"; + public static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers"; + public static final String ARTIFACTS_LOCATION_JSON_POINTER = + "/topology_template/node_templates/applicationServiceDescriptor/artifacts"; +} \ No newline at end of file diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java new file mode 100755 index 0000000..ac00e95 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import com.fasterxml.jackson.databind.JsonNode; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.csar.RappCsarPathProvider; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.web.multipart.MultipartFile; + +@Component +@RequiredArgsConstructor +public class ArtifactDefinitionValidator implements RappValidator { + + private final RappCsarConfigurationHandler rappCsarConfigurationHandler; + private final RappValidationUtils rappValidationUtils; + String invalidAsdErrorMsg = "ASD definition in rApp package is invalid."; + private static final int VALIDATION_ORDER = 10; + + @Override + public int getOrder() { + return VALIDATION_ORDER; + } + + @Override + public void validate(Object target, Errors errors) { + MultipartFile multipartFile = (MultipartFile) target; + String asdLocation = rappValidationUtils.getAsdDefinitionLocation(multipartFile); + if (asdLocation != null && !asdLocation.isEmpty() && rappValidationUtils.isFileExistsInCsar(multipartFile, + asdLocation)) { + try { + String asdContent = rappValidationUtils.getFileFromCsar(multipartFile, asdLocation).toString(); + if(asdContent != null && !asdContent.isEmpty()) { + JsonNode jsonNode = rappCsarConfigurationHandler.getAsdContentNode(asdContent); + List artifactFileList = + jsonNode.at(RappCsarPathProvider.ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file"); + artifactFileList.forEach( + artifactFile -> rappValidationUtils.isFileExistsInCsar(multipartFile, artifactFile)); + } else { + throw new RappValidationException(invalidAsdErrorMsg); + } + } catch (RappValidationException e) { + throw new RappValidationException(e.getMessage()); + } catch (Exception e) { + throw new RappValidationException(invalidAsdErrorMsg); + } + } else { + throw new RappValidationException(invalidAsdErrorMsg); + } + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java new file mode 100755 index 0000000..3ed6124 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import com.oransc.rappmanager.models.csar.RappCsarPathProvider; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.web.multipart.MultipartFile; + +@Component +@RequiredArgsConstructor +public class FileExistenceValidator implements RappValidator { + + private final RappValidationUtils rappValidationUtils; + private final List requiredFiles = + List.of(RappCsarPathProvider.ACM_COMPOSITION_JSON_LOCATION, RappCsarPathProvider.TOSCA_METADATA_LOCATION); + private static final int VALIDATION_ORDER = 5; + + @Override + public int getOrder() { + return VALIDATION_ORDER; + } + + @Override + public void validate(Object target, Errors errors) { + MultipartFile multipartFile = (MultipartFile) target; + requiredFiles.forEach(requiredFile -> rappValidationUtils.isFileExistsInCsar(multipartFile, requiredFile)); + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java new file mode 100755 index 0000000..00348af --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import com.oransc.rappmanager.models.exception.RappValidationException; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.web.multipart.MultipartFile; + +@Component +public class NamingValidator implements RappValidator { + + private static final int VALIDATION_ORDER = 1; + + @Override + public int getOrder() { + return VALIDATION_ORDER; + } + + @Override + public void validate(Object target, Errors errors) { + MultipartFile multipartFile = (MultipartFile) target; + String originalFilename = multipartFile.getOriginalFilename(); + if (originalFilename == null || !originalFilename.endsWith(".csar")) { + throw new RappValidationException("rApp package name should end with .csar"); + } + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java new file mode 100755 index 0000000..8df2154 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component +@RequiredArgsConstructor +public class RappValidationHandler { + + private final List rappValidators; + + public boolean isValidRappPackage(MultipartFile multipartFile) { + List validatorList = + rappValidators.stream().sorted(Comparator.comparing(RappValidator::getOrder)).toList(); + validatorList.forEach(rappValidator -> rappValidator.validate(multipartFile, null)); + return true; + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java new file mode 100755 index 0000000..29be2d3 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.csar.RappCsarPathProvider; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component +@RequiredArgsConstructor +public class RappValidationUtils { + + private final RappCsarConfigurationHandler rappCsarConfigurationHandler; + + boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) { + try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) { + ArchiveEntry zipEntry; + while ((zipEntry = zipArchiveInputStream.getNextEntry()) != null) { + if (zipEntry.getName().matches(fileLocation)) { + return Boolean.TRUE; + } + } + throw new RappValidationException("rApp package missing a file " + fileLocation); + } catch (IOException e) { + throw new RappValidationException("rApp package missing a file " + fileLocation); + } + } + + public String getAsdDefinitionLocation(final MultipartFile multipartFile) { + return rappCsarConfigurationHandler.getAsdDefinitionLocation( + getFileFromCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION).toString()); + } + + ByteArrayOutputStream getFileFromCsar(MultipartFile multipartFile, String fileLocation) { + ByteArrayOutputStream byteArrayOutputStream; + try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) { + byteArrayOutputStream = rappCsarConfigurationHandler.getFileFromCsar(zipArchiveInputStream, fileLocation); + } catch (IOException e) { + throw new RappValidationException( + String.format("Unable to get file %s from the multipart CSAR file", fileLocation)); + } + return byteArrayOutputStream; + } +} \ No newline at end of file diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java new file mode 100755 index 0000000..a1f3930 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java @@ -0,0 +1,30 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import org.springframework.validation.Validator; +import org.springframework.web.multipart.MultipartFile; + +public interface RappValidator extends Validator { + int getOrder(); + @Override + default boolean supports(Class cls) { + return MultipartFile.class.isAssignableFrom(cls); + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/ExceptionControllerHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/ExceptionControllerHandler.java index 40af0d3..ae26a5e 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/ExceptionControllerHandler.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/ExceptionControllerHandler.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START====================================================================== - * Copyright (C) 2023 OpenInfra Foundation Europe. All rights reserved. + * Copyright (C) 2023-2024 OpenInfra Foundation Europe. 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. @@ -30,4 +30,11 @@ public class ExceptionControllerHandler { return ResponseEntity.status(rappHandlerException.getStatusCode()) .body(new ErrorResponse(rappHandlerException.getMessage())); } + + @ExceptionHandler(RappValidationException.class) + public ResponseEntity handleRappValidationException( + RappValidationException rappValidationException) { + return ResponseEntity.status(rappValidationException.getStatusCode()) + .body(new ErrorResponse(rappValidationException.getMessage())); + } } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappHandlerException.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappHandlerException.java index 8ea89be..48b5067 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappHandlerException.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappHandlerException.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START====================================================================== - * Copyright (C) 2023 OpenInfra Foundation Europe. All rights reserved. + * Copyright (C) 2023-2024 OpenInfra Foundation Europe. 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. @@ -29,7 +29,5 @@ public class RappHandlerException extends RuntimeException { public RappHandlerException(HttpStatusCode statusCode, String message) { super(message); this.statusCode = statusCode; - } - } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java new file mode 100755 index 0000000..f8c291c --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java @@ -0,0 +1,35 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; + +@Getter +public class RappValidationException extends RuntimeException { + + private final HttpStatusCode statusCode; + + public RappValidationException(String message) { + super(message); + this.statusCode = HttpStatus.BAD_REQUEST; + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java index e769b12..2325789 100755 --- a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java @@ -23,18 +23,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -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.doCallRealMethod; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonSyntaxException; -import com.oransc.rappmanager.models.exception.RappHandlerException; import com.oransc.rappmanager.models.rapp.Rapp; import com.oransc.rappmanager.models.rapp.RappResources; import com.oransc.rappmanager.models.rappinstance.RappACMInstance; @@ -42,26 +36,17 @@ import com.oransc.rappmanager.models.rappinstance.RappDMEInstance; import com.oransc.rappmanager.models.rappinstance.RappSMEInstance; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; import java.util.List; import java.util.Set; import java.util.UUID; -import java.util.stream.Stream; -import org.apache.http.entity.ContentType; import org.json.JSONException; import org.json.JSONObject; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.http.HttpStatus; -import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ContextConfiguration; -import org.springframework.web.multipart.MultipartFile; @SpringBootTest @ContextConfiguration(classes = {ObjectMapper.class, RappCsarConfigurationHandler.class}) @@ -74,123 +59,10 @@ class RappCsarConfigurationHandlerTest { private final String validRappFile = "valid-rapp-package.csar"; - private final String invalidRappFile = "invalid-rapp-package.csar"; - private final String invalidRappNoAsdFile = "invalid-rapp-package-no-asd-yaml.csar"; private final String invalidRappEmptyAsdFile = "invalid-rapp-package-empty-asd-yaml.csar"; - @Test - void testCsarPackageValidationSuccess() throws IOException { - String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - assertEquals(Boolean.TRUE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); - } - - @ParameterizedTest - @MethodSource("getInvalidCsarPackage") - void testCsarPackageValidationFailure(MultipartFile multipartFile) { - RappHandlerException exception = assertThrows(RappHandlerException.class, - () -> rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); - assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); - } - - - private static Stream getInvalidCsarPackage() throws IOException { - String validCsarFileLocation = "src/test/resources"; - String rappCsarPath = validCsarFileLocation + File.separator + "invalid-rapp-package.csar"; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - String rappCsarPathNoTosca = validCsarFileLocation + File.separator + "invalid-rapp-package-no-tosca.csar"; - MultipartFile multipartFileNoTosca = new MockMultipartFile(rappCsarPathNoTosca, rappCsarPathNoTosca, - ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoTosca)); - String rappCsarPathNoAsdYaml = validCsarFileLocation + File.separator + "invalid-rapp-package-no-asd-yaml.csar"; - MultipartFile multipartFileNoAsdYaml = new MockMultipartFile(rappCsarPathNoAsdYaml, rappCsarPathNoAsdYaml, - ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoAsdYaml)); - String rappCsarPathMissingArtifact = - validCsarFileLocation + File.separator + "invalid-rapp-package-missing-artifact.csar"; - MultipartFile multipartFileMissingArtifact = - new MockMultipartFile(rappCsarPathMissingArtifact, rappCsarPathMissingArtifact, - ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPathMissingArtifact)); - String rappCsarPathNoComposition = - validCsarFileLocation + File.separator + "invalid-rapp-package-no-acm-composition.csar"; - MultipartFile multipartFileNoComposition = - new MockMultipartFile(rappCsarPathNoComposition, rappCsarPathNoComposition, - ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoComposition)); - return Stream.of(Arguments.of(multipartFile), Arguments.of(multipartFileNoTosca), - Arguments.of(multipartFileNoAsdYaml), Arguments.of(multipartFileMissingArtifact), - Arguments.of(multipartFileNoComposition)); - } - - @Test - void testCsarPackageValidationFailureWithoutOrginalName() { - MultipartFile multipartFile = mock(MultipartFile.class); - assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); - } - - @Test - void testInvalidCsarFileExist() { - MultipartFile multipartFile = mock(MultipartFile.class); - RappHandlerException exception = assertThrows(RappHandlerException.class, - () -> rappCsarConfigurationHandler.isFileExistsInCsar(multipartFile, "INVALID_LOCATION")); - assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); - } - - @Test - void testCsarContainsValidAsdFile() throws IOException { - String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - assertTrue(rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile)); - } - - @Test - void testCsarContainsValidAsdFileFailure() throws IOException { - String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - RappHandlerException exception = assertThrows(RappHandlerException.class, - () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile)); - assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); - } - - @Test - void testCsarNoAsdFailure() { - MultipartFile multipartFile = mock(MultipartFile.class); - RappHandlerException exception = assertThrows(RappHandlerException.class, - () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile)); - assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); - } - - @Test - void testCsarAsdContentInvalidFailure() throws IOException { - String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - String invalidJson = "{asasdasd"; - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - byteArrayOutputStream.write(invalidJson.getBytes(), 0, invalidJson.getBytes().length); - doCallRealMethod().doReturn(byteArrayOutputStream).when(rappCsarConfigurationHandler) - .getFileFromCsar(any(MultipartFile.class), any()); - RappHandlerException exception = assertThrows(RappHandlerException.class, - () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile)); - assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); - } - - @Test - void testgetFileFromCsarFailure() throws IOException { - MultipartFile multipartFile = mock(MultipartFile.class); - when(multipartFile.getInputStream()).thenThrow(new IOException()); - assertThat(rappCsarConfigurationHandler.getFileFromCsar(multipartFile, null).size()).isZero(); - } - @Test void testCsarInstantiationPayload() throws JSONException { Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build(); diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java new file mode 100755 index 0000000..7348116 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +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.doCallRealMethod; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = {ArtifactDefinitionValidator.class, RappValidationUtils.class, ObjectMapper.class, + RappCsarConfigurationHandler.class}) +class ArtifactDefinitionValidatorTest { + + @Autowired + ArtifactDefinitionValidator artifactDefinitionValidator; + @SpyBean + RappValidationUtils rappValidationUtils; + String validCsarFileLocation = "src/test/resources/"; + String validRappFile = "valid-rapp-package.csar"; + String invalidRappFile = "invalid-rapp-package.csar"; + String invalidRappAsdEmptyFile = "invalid-rapp-package-empty-asd-yaml.csar"; + + @Test + void testCsarContainsValidAsdFile() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertDoesNotThrow(() -> artifactDefinitionValidator.validate(multipartFile, null)); + } + + @Test + void testCsarContainsValidAsdFileFailure() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> artifactDefinitionValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertTrue(exception.getMessage().startsWith("rApp package missing a file")); + } + + @Test + void testCsarNoAsdFailure() { + MultipartFile multipartFile = mock(MultipartFile.class); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> artifactDefinitionValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals("ASD definition in rApp package is invalid.", exception.getMessage()); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {""}) + void testCsarAsdLocationNullFailure(String asdLocation) throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappAsdEmptyFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + doReturn(asdLocation).when(rappValidationUtils).getAsdDefinitionLocation(any()); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> artifactDefinitionValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals("ASD definition in rApp package is invalid.", exception.getMessage()); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "{asasdasd"}) + void testCsarAsdContentInvalidFailure(String asdContent) throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + if (asdContent != null) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byteArrayOutputStream.write(asdContent.getBytes(), 0, asdContent.getBytes().length); + doCallRealMethod().doReturn(byteArrayOutputStream).when(rappValidationUtils) + .getFileFromCsar(any(MultipartFile.class), any()); + } else { + doCallRealMethod().doReturn(asdContent).when(rappValidationUtils) + .getFileFromCsar(any(MultipartFile.class), any()); + } + RappValidationException exception = assertThrows(RappValidationException.class, + () -> artifactDefinitionValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals("ASD definition in rApp package is invalid.", exception.getMessage()); + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java new file mode 100755 index 0000000..2b6e369 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = {FileExistenceValidator.class, RappValidationUtils.class, ObjectMapper.class, + RappCsarConfigurationHandler.class}) +class FileExistenceValidatorTest { + + @Autowired + FileExistenceValidator fileExistenceValidator; + String validCsarFileLocation = "src/test/resources/"; + String validRappFile = "valid-rapp-package.csar"; + String invalidRappFile = "invalid-rapp-package.csar"; + String invalidRappFileNoTosca = "invalid-rapp-package-no-tosca.csar"; + + @Test + void testFileExistenceValidationSuccess() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertDoesNotThrow(() -> fileExistenceValidator.validate(multipartFile, null)); + } + + @Test + void testFileExistenceNoCompositionValidation() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + RappValidationException rappValidationException = + assertThrows(RappValidationException.class, () -> fileExistenceValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode()); + assertEquals("rApp package missing a file Files/Acm/definition/compositions.json", + rappValidationException.getMessage()); + } + + @Test + void testFileExistenceNoToscaValidation() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFileNoTosca; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + RappValidationException rappValidationException = + assertThrows(RappValidationException.class, () -> fileExistenceValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode()); + assertEquals("rApp package missing a file TOSCA-Metadata/TOSCA.meta", rappValidationException.getMessage()); + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java new file mode 100755 index 0000000..e059cf3 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = {NamingValidator.class}) +class NamingValidatorTest { + + @Autowired + NamingValidator namingValidator; + String validCsarFileLocation = "src/test/resources/"; + String validRappFile = "valid-rapp-package.csar"; + String expectedErrorMessage = "rApp package name should end with .csar"; + + @Test + void testNamingValidationSuccess() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertDoesNotThrow(() -> namingValidator.validate(multipartFile, null)); + } + + @Test + void testNamingValidationFailureWithNull() { + MultipartFile multipartFile = mock(MultipartFile.class); + RappValidationException rappValidationException = + assertThrows(RappValidationException.class, () -> namingValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode()); + assertEquals(expectedErrorMessage, rappValidationException.getMessage()); + } + + @Test + void testNamingValidationFailureWithEmptyName() { + MultipartFile multipartFile = mock(MultipartFile.class); + when(multipartFile.getOriginalFilename()).thenReturn(""); + RappValidationException rappValidationException = + assertThrows(RappValidationException.class, () -> namingValidator.validate(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode()); + assertEquals(expectedErrorMessage, rappValidationException.getMessage()); + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java new file mode 100755 index 0000000..9edfe34 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java @@ -0,0 +1,114 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.stream.Stream; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = {RappValidationHandler.class, NamingValidator.class, FileExistenceValidator.class, + ArtifactDefinitionValidator.class, RappValidationUtils.class, RappCsarConfigurationHandler.class, + ObjectMapper.class}) +class RappValidationHandlerTest { + + @Autowired + RappValidationHandler rappValidationHandler; + String validCsarFileLocation = "src/test/resources/"; + private final String validRappFile = "valid-rapp-package.csar"; + + @Test + void testCsarPackageValidationSuccess() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertEquals(Boolean.TRUE, rappValidationHandler.isValidRappPackage(multipartFile)); + } + + @ParameterizedTest + @MethodSource("getInvalidCsarPackage") + void testCsarPackageValidationFailure(MultipartFile multipartFile, String errorMessage) { + RappValidationException exception = assertThrows(RappValidationException.class, + () -> rappValidationHandler.isValidRappPackage(multipartFile)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals(errorMessage, exception.getMessage()); + } + + private static Stream getInvalidCsarPackage() throws IOException { + String validCsarFileLocation = "src/test/resources"; + String errorMsgMissingAcmComposition = "rApp package missing a file Files/Acm/definition/compositions.json"; + String rappCsarPath = validCsarFileLocation + File.separator + "invalid-rapp-package.csar"; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + String rappCsarPathNoTosca = validCsarFileLocation + File.separator + "invalid-rapp-package-no-tosca.csar"; + MultipartFile multipartFileNoTosca = new MockMultipartFile(rappCsarPathNoTosca, rappCsarPathNoTosca, + ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoTosca)); + String rappCsarPathNoAsdYaml = validCsarFileLocation + File.separator + "invalid-rapp-package-no-asd-yaml.csar"; + MultipartFile multipartFileNoAsdYaml = new MockMultipartFile(rappCsarPathNoAsdYaml, rappCsarPathNoAsdYaml, + ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoAsdYaml)); + String rappCsarPathMissingArtifact = + validCsarFileLocation + File.separator + "invalid-rapp-package-missing-artifact.csar"; + MultipartFile multipartFileMissingArtifact = + new MockMultipartFile(rappCsarPathMissingArtifact, rappCsarPathMissingArtifact, + ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPathMissingArtifact)); + String rappCsarPathNoComposition = + validCsarFileLocation + File.separator + "invalid-rapp-package-no-acm-composition.csar"; + MultipartFile multipartFileNoComposition = + new MockMultipartFile(rappCsarPathNoComposition, rappCsarPathNoComposition, + ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoComposition)); + return Stream.of(Arguments.of(multipartFile, errorMsgMissingAcmComposition), + Arguments.of(multipartFileNoTosca, "rApp package missing a file TOSCA-Metadata/TOSCA.meta"), + Arguments.of(multipartFileNoAsdYaml, "rApp package missing a file Definitions/asd.yaml"), + Arguments.of(multipartFileMissingArtifact, + "rApp package missing a file Artifacts/Deployment/HELM/orufhrecovery-1.0.0.tgz"), + Arguments.of(multipartFileNoComposition, errorMsgMissingAcmComposition)); + } + + @Test + void testCsarPackageValidationFailureWithoutOrginalName() { + MultipartFile multipartFile = mock(MultipartFile.class); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> rappValidationHandler.isValidRappPackage(multipartFile)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals("rApp package name should end with .csar", exception.getMessage()); + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java new file mode 100755 index 0000000..7f1d8de --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java @@ -0,0 +1,110 @@ +/* + * ============LICENSE_START====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.csar.RappCsarPathProvider; +import com.oransc.rappmanager.models.exception.RappValidationException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = {RappValidationUtils.class, ObjectMapper.class, RappCsarConfigurationHandler.class}) +class RappValidationUtilsTest { + + String validCsarFileLocation = "src/test/resources/"; + private final String validRappFile = "valid-rapp-package.csar"; + private final String invalidRappNoToscaFile = "invalid-rapp-package-no-tosca.csar"; + @Autowired + RappValidationUtils rappValidationUtils; + + @Test + void testCsarFileExist() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertTrue(rappValidationUtils.isFileExistsInCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION)); + + } + + @Test + void testInvalidCsarFileExist() { + MultipartFile multipartFile = mock(MultipartFile.class); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> rappValidationUtils.isFileExistsInCsar(multipartFile, "INVALID_LOCATION")); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals("rApp package missing a file INVALID_LOCATION", exception.getMessage()); + } + + @Test + void testGetFileFromCsar() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertNotNull(rappValidationUtils.getFileFromCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION)); + } + + @Test + void testGetFileFromCsarFailure() throws IOException { + MultipartFile multipartFile = mock(MultipartFile.class); + when(multipartFile.getInputStream()).thenThrow(new IOException()); + RappValidationException exception = assertThrows(RappValidationException.class, + () -> rappValidationUtils.getFileFromCsar(multipartFile, null)); + assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); + assertEquals(String.format("Unable to get file %s from the multipart CSAR file", null), exception.getMessage()); + } + + @Test + void testGetAsdLocationCsar() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertEquals("Definitions/asd.yaml", rappValidationUtils.getAsdDefinitionLocation(multipartFile)); + } + + @Test + void testGetAsdLocationCsarFailure() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappNoToscaFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertEquals("", rappValidationUtils.getAsdDefinitionLocation(multipartFile)); + } +} -- 2.16.6