summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md106
-rw-r--r--csarvalidation/pom.xml110
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/CSARArchive.java93
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java121
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/VTPValidateCSARBase.java4
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR02454.java5
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR35851.java2
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123.java111
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java266
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745.java140
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java43
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestLine.java4
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java2
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/parser/NonManoArtifactsParser.java11
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CertificateLoadingException.java25
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureData.java75
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java91
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureLoadingException.java29
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java77
-rw-r--r--csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java1
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/CsarUtil.java254
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/CsarValidator.java144
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/FileUtil.java36
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/VTPValidateCSAR.java2
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/ValidationException.java5
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/csar/ValidatorSchemaLoader.java33
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/YamlFileValidator.java72
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java61
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java40
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java36
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java42
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java33
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java56
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java52
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java42
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java34
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java111
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java45
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java37
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java59
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java80
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java50
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java66
-rw-r--r--csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java84
-rw-r--r--csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand1
-rw-r--r--csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r01123.yaml21
-rw-r--r--csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r816745.yaml66
-rw-r--r--csarvalidation/src/main/resources/vnfreqs.properties6
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/CSARArchiveTest.java4
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/CsarValidatorTest.java68
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/PnfCSARArchiveTest.java40
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/PnfManifestParserTest.java49
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/PnfMetadataParserTest.java2
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/PnfNonManoArtifactsParserTest.java4
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/VnfManifestParserTest.java6
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/IntegrationTestUtils.java4
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123IntegrationTest.java176
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR10087IntegrationTest.java13
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java385
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java39
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR293901IntegrationTest.java2
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR57019IntegrationTest.java2
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965IntegrationTest.java4
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745IntegrationTest.java229
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java64
-rw-r--r--csarvalidation/src/test/java/org/onap/cvc/csar/security/ShaHashCodeGeneratorTest.java10
-rw-r--r--csarvalidation/src/test/java/org/onap/functional/CsarValidationUtility.java65
-rw-r--r--csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java132
-rw-r--r--csarvalidation/src/test/java/org/onap/functional/VnfValidationFunctionalTest.java75
-rw-r--r--csarvalidation/src/test/java/org/onap/functional/cli/OnapCliValidationResponseWrapper.java84
-rw-r--r--csarvalidation/src/test/java/org/onap/functional/cli/OnapCliWrapper.java42
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/csar/CsarValidatorTest.java (renamed from csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/CsarValidatorTest.java)101
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/csar/ValidationExceptionTest.java (renamed from csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/ValidationExceptionTest.java)11
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/YamlFileValidatorTest.java117
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java99
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java94
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java123
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java154
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java81
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java101
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java122
-rw-r--r--csarvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java153
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-missing-files.csarbin0 -> 7189 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noFileInManifest.csar (renamed from csarvalidation/src/test/resources/pnf/r130206/csar-option1-invalid.csar)bin5743 -> 5751 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor-noFileInManifest.csarbin0 -> 7128 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor.csarbin0 -> 7141 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option1-valid.csarbin0 -> 7182 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option2-invalid-with-cms.zipbin0 -> 4673 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r01123/csar-option2-valid-with-cms.zipbin0 -> 4691 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/cert-in-cms-and-root-and-tosca-incorrect-hash.csarbin0 -> 21667 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca-incorrect-hash.csarbin0 -> 8320 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca.csarbin0 -> 8317 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-incorrect-hash.csarbin0 -> 7275 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root.csarbin0 -> 7271 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca-incorrect-hash.csarbin0 -> 7318 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca.csarbin0 -> 7290 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-incorrect-hash.csarbin0 -> 6247 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid.csarbin0 -> 25585 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms.csarbin0 -> 6244 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca-incorrect-hash.csarbin0 -> 7563 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca.csarbin0 -> 7564 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-incorrect-hash.csarbin0 -> 6521 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-pointed-by-tosca.csarbin0 -> 6529 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root.csarbin0 -> 7473 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-incorrect-hash.csarbin0 -> 6564 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-no-cms.csarbin0 -> 5865 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-valid.csarbin0 -> 25927 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca.csarbin0 -> 6561 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-no-cert-no-tosca-dir.csarbin0 -> 6276 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-no-cms-no-cert-with-hash.csarbin0 -> 4795 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-not-secure-warning.csarbin0 -> 4576 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-option1-valid.csarbin7530 -> 0 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-option1-validSection.csarbin6170 -> 0 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-cert-pointing-non-existing-cert.csarbin0 -> 114649 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-no-cert-entry.csarbin0 -> 5491 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r146092/validFile.csarbin0 -> 118242 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-empty-pm-dictionary.csarbin0 -> 7156 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-invalid-mapping.csarbin0 -> 8590 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-unknown-escape-character.csarbin0 -> 8595 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary.csarbin0 -> 8796 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-missing-source-value-for-pm-dictionary-in-manifest.csarbin0 -> 8793 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-no-pm-dictionary.csarbin0 -> 6717 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/csar-with-valid-pm-dictionary.csarbin0 -> 8792 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/zip-with-invalid-pm-dictionary.zipbin0 -> 6425 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r816745/zip-with-valid-pm-dictionary.zipbin0 -> 6419 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r972082/fileExtensionOfArtifactIsNotYaml.csarbin0 -> 18061 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r972082/invalidYamlStructure.csarbin0 -> 18075 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r972082/missingOnapPnfSwInformationArtifactSetEntry.csarbin0 -> 116517 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/r972082/missingSourceElementUnderAttributeError.csarbin0 -> 18064 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/toscaMetaFile.csarbin0 -> 5906 bytes
-rw-r--r--csarvalidation/src/test/resources/pnf/validFile.csarbin0 -> 18069 bytes
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml86
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml228
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml239
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml149
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml39
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml39
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml149
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml39
-rw-r--r--csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml23
-rw-r--r--deployment/pom.xml10
-rw-r--r--pom.xml15
-rw-r--r--releases/1.2.10-maven.yaml5
-rw-r--r--releases/1.2.11-maven.yaml5
-rw-r--r--releases/1.2.12-maven.yaml5
-rw-r--r--releases/1.2.13-maven.yaml5
-rw-r--r--releases/1.2.14-maven.yaml5
-rw-r--r--releases/1.2.5-maven.yaml5
-rw-r--r--releases/1.2.6-maven.yaml5
-rw-r--r--releases/1.2.7-maven.yaml5
-rw-r--r--releases/1.2.8-maven.yaml5
-rw-r--r--releases/1.2.9-maven.yaml5
-rw-r--r--version.properties2
153 files changed, 5913 insertions, 694 deletions
diff --git a/Changelog.md b/Changelog.md
new file mode 100644
index 0000000..8bf5b52
--- /dev/null
+++ b/Changelog.md
@@ -0,0 +1,106 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+
+## [1.2.5]
+
+### Added
+- Added rule R972082 to enabled PNF requirements.
+ - https://jira.onap.org/browse/VNFSDK-585
+
+### Fixed
+- Fixed package integrity issue with non mano arifacts.
+ - https://jira.onap.org/browse/VNFSDK-581
+- Fixed VNF/PNF package integrity issue with CMS signature not containing certificate.
+ - https://jira.onap.org/browse/VNFSDK-582
+- Fixed bug that was showing errors during validation of CSAR,
+ when any other non_mano_artifact_set than onap_pnf_sw_information was present in manifest file.
+ - https://jira.onap.org/browse/VNFSDK-585
+
+## [1.2.6]
+
+### Added
+- Added file extension validation of file related in onap_pnf_sw_information artifact set.
+ - https://jira.onap.org/browse/VNFSDK-585
+
+### Fixed
+- Fixed bug that was generating invalid report when user run validation with all rules and single validation fails.
+ - https://jira.onap.org/browse/VNFSDK-586
+
+
+## [1.2.7]
+
+### Fixed
+- Fixed bug that was causing problem with loading rules properties.
+ - https://jira.onap.org/browse/VNFSDK-587
+- Fixed package security SOL004 Option 1 make rule less restrictive as this rule is not implemented in SDC Onboarding
+ - https://jira.onap.org/browse/VNFSDK-595
+
+## [1.2.8]
+
+## Fixed
+- Fixed VNFSDK doesn't check if all files in package are listed in manifest file
+ - https://jira.onap.org/browse/VNFSDK-583
+
+## [1.2.9]
+
+### Added
+- Added rule R972082 to validate PM_Dictionary using schema.
+ - https://jira.onap.org/browse/VNFSDK-594
+
+## Fixed
+- Fixed rule R01123 that was reporting all files in ZIP as not present in manifest
+ - https://jira.onap.org/browse/VNFSDK-583
+
+
+## [1.2.10]
+
+### Added
+- Added parameters list validation to PM Dictionary .
+ - https://jira.onap.org/browse/VNFSDK-594
+
+
+## [1.2.11]
+
+## Fixed
+- Fixed rule R816745 that wasn't sending all exceptions connected with YAML parsing as validation error
+ - https://jira.onap.org/browse/VNFSDK-644
+
+## [1.2.12]
+
+## Fixed
+- Fixed rule R816745 that was searching for the path to PM_Dictionary in manifest file under name source,
+ instead of Source (starting with a capital letter).
+ Now both versions (source and Source) are accepted by this rule.
+ - https://jira.onap.org/browse/VNFSDK-645
+- Fixed commons-codec vulnerability
+ - https://jira.onap.org/browse/VNFSDK-584
+
+## Added
+- Added non-vulnerable log4j version
+ - https://jira.onap.org/browse/VNFSDK-553
+
+## Upgrade
+- Upgraded from java 8 to java 11
+ - https://jira.onap.org/browse/VNFSDK-631
+
+## [1.2.13]
+
+## Fixed
+- Fixed rule R130206 CMS and certificate searching and validation mechanism
+ - https://jira.onap.org/browse/VNFSDK-595
+
+## Added
+- Add new field called "warnings" to oclip json response. All ignored errors are now reported as warnings.
+ - https://jira.onap.org/browse/VNFSDK-596
+
+## [1.2.14]
+
+## Fixed
+- Fixed rule R130206 handling of CSARs with no TOSCA meta and no Certificate in root directory
+ - https://jira.onap.org/browse/VNFSDK-481
+- Fixed rule R816745 that was not reporting error when CMS and TOSCA meta file were present,
+ however TOSCA did not contain ETSI-Entry-Certificate
+ - https://jira.onap.org/browse/VNFSDK-660
+
+## [1.2.15]
diff --git a/csarvalidation/pom.xml b/csarvalidation/pom.xml
index 968d242..729c82d 100644
--- a/csarvalidation/pom.xml
+++ b/csarvalidation/pom.xml
@@ -14,7 +14,7 @@
<parent>
<groupId>org.onap.vnfsdk.validation</groupId>
<artifactId>validation</artifactId>
- <version>1.2.4-SNAPSHOT</version>
+ <version>1.2.15-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>validation-csar</artifactId>
@@ -34,11 +34,29 @@
</repository>
</repositories>
+ <properties>
+ <log4j-slf4j-impl.version>2.13.3</log4j-slf4j-impl.version>
+ <snakeyaml.version>1.26</snakeyaml.version>
+ <jackson-core.version>2.9.4</jackson-core.version>
+ <junit.version>4.12</junit.version>
+ <commons-lang3.version>3.2.1</commons-lang3.version>
+ <commons-io.version>2.7</commons-io.version>
+ <bcpkix-jdk15on.version>1.61</bcpkix-jdk15on.version>
+ <cli-framework.version>5.0.3</cli-framework.version>
+ <cli-main.version>5.0.2</cli-main.version>
+ <assertj-core.version>3.11.1</assertj-core.version>
+ <lombok.version>1.18.2</lombok.version>
+ <commons-collections.version>3.2.2</commons-collections.version>
+ <maven-war-plugin.version>2.6</maven-war-plugin.version>
+ <maven-dependency-plugin.version>3.0.0</maven-dependency-plugin.version>
+ <mockito-core.version>3.5.0</mockito-core.version>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
- <version>2.13.0</version>
+ <version>${log4j-slf4j-impl.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
@@ -49,69 +67,85 @@
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
- <version>1.18</version>
+ <version>${snakeyaml.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
- <version>2.9.4</version>
+ <version>${jackson-core.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
+
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
- <version>3.2.1</version>
+ <version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.5</version>
+ <version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
- <version>1.61</version>
+ <version>${bcpkix-jdk15on.version}</version>
</dependency>
<dependency>
<groupId>org.onap.cli</groupId>
<artifactId>cli-framework</artifactId>
- <version>5.0.3</version>
+ <version>${cli-framework.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
-
<dependency>
- <groupId>org.onap.cli</groupId>
- <artifactId>cli-main</artifactId>
- <version>5.0.2</version>
- <scope>test</scope>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.14</version>
</dependency>
-
- <dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <version>3.11.1</version>
- <scope>test</scope>
- </dependency>
-
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
- <version>1.18.2</version>
+ <version>${lombok.version}</version>
</dependency>
<dependency>
<artifactId>commons-collections</artifactId>
<groupId>commons-collections</groupId>
- <version>3.2.2</version>
+ <version>${commons-collections.version}</version>
</dependency>
+ <!-- TEST dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito-core.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.cli</groupId>
+ <artifactId>cli-main</artifactId>
+ <version>${cli-main.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj-core.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
@@ -124,7 +158,6 @@
</profile>
</profiles>
-
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
@@ -132,7 +165,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <version>3.0.2</version>
+ <version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<manifest>
@@ -142,20 +175,11 @@
</archive>
</configuration>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
- <version>3.0.0</version>
+ <version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<id>copy-artifact</id>
@@ -186,7 +210,7 @@
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
- <excludeArtifactIds>junit,jmockit</excludeArtifactIds>
+ <excludeArtifactIds>junit</excludeArtifactIds>
</configuration>
</execution>
</executions>
@@ -194,7 +218,7 @@
<plugin>
<artifactId>maven-war-plugin</artifactId>
- <version>2.6</version>
+ <version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/CSARArchive.java b/csarvalidation/src/main/java/org/onap/cvc/csar/CSARArchive.java
index 1c05948..05f2070 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/CSARArchive.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/CSARArchive.java
@@ -92,6 +92,9 @@ public class CSARArchive implements AutoCloseable {
public static final String CSAR_ARCHIVE = "CSAR Archive";
public static final String DOESS_NOT_EXIST = " does not exist";
+ public static final String CERT = ".cert";
+ public static final String YAML = ".yaml";
+ public static final String MF = ".mf";
public enum Mode {
WITH_TOSCA_META_DIR,
@@ -496,7 +499,7 @@ public class CSARArchive implements AutoCloseable {
CSAR_ARCHIVE,
-1,
"Manifest file name should match the definition YAML name",
- definitionYaml + ".mf", //fix the name part
+ definitionYaml + MF, //fix the name part
manifest);
this.setCode("0x0013");
@@ -521,13 +524,20 @@ public class CSARArchive implements AutoCloseable {
CSAR_ARCHIVE,
-1,
"certificate file name should match the definition YAML name",
- definitionYaml + ".cert", //fix the name part
+ definitionYaml + CERT, //fix the name part
certificate);
this.setCode("0x0015");
}
}
+ public static class CSARErrorNoManifestsFound extends CSARError {
+ public CSARErrorNoManifestsFound() {
+ super("0x0016");
+ this.message = "No manifest file found in CSAR!";
+ }
+ }
+
/**
* Holds the CSAR meta data values in both Modes
*
@@ -966,32 +976,29 @@ public class CSARArchive implements AutoCloseable {
lineNo ++;
line = line.trim();
- if (line.startsWith("#") || line.trim().isEmpty()) {
- continue;
- }
-
- String []lineTokens = line.split(":");
+ if (!line.startsWith("#") && !line.trim().isEmpty()) {
+ String []lineTokens = line.split(":");
- if (lineTokens.length != 2) {
- errors.add(
- new CSARErrorIgnored(
- line,
- TOSCA_METADATA_TOSCA_META,
- lineNo,
- null));
- continue;
- }
+ if (lineTokens.length != 2) {
+ errors.add(
+ new CSARErrorIgnored(
+ line,
+ TOSCA_METADATA_TOSCA_META,
+ lineNo,
+ null));
+ continue;
+ }
- String key = lineTokens[0].trim();
- String value = lineTokens[1].trim();
+ String key = lineTokens[0].trim();
+ String value = lineTokens[1].trim();
- if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_TOSCA_META_FILE_VERSION)) {
+ if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_TOSCA_META_FILE_VERSION)) {
this.toscaMeta.setMetaDataFileVersion(value);
- } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_CSAR_VERSION)){
+ } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_CSAR_VERSION)){
this.toscaMeta.setCsarVersion(value);
- } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_CREATED_BY)) {
+ } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_CREATED_BY)) {
this.toscaMeta.setCompanyName(value);
- } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_DEFINITIONS)) {
+ } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_DEFINITIONS)) {
this.toscaMeta.setEntryDefinitionYaml(value);
this.definitionYamlFile = new File(this.tempDir.toFile().getAbsolutePath() + File.separator + (this.toscaMeta.getEntryDefinitionYaml()));
@@ -1001,7 +1008,7 @@ public class CSARArchive implements AutoCloseable {
this.toscaMeta.getEntryDefinitionYaml(),
lineNo));
}
- } else if(key.equalsIgnoreCase(getEntryManifestParamName())) {
+ } else if(key.equalsIgnoreCase(getEntryManifestParamName())) {
this.toscaMeta.setEntryManifestMf(value);
this.manifestMfFile = this.tempDir.resolve(this.toscaMeta.getEntryManifestMf()).toFile();
if (!this.manifestMfFile.exists()) {
@@ -1009,7 +1016,7 @@ public class CSARArchive implements AutoCloseable {
this.toscaMeta.getEntryManifestMf(),
lineNo, getEntryManifestParamName()));
}
- } else if(key.equalsIgnoreCase(getEntryChangeLogParamName())) {
+ } else if(key.equalsIgnoreCase(getEntryChangeLogParamName())) {
this.toscaMeta.setEntryChangeLog(value);
this.changeLogTxtFile = this.tempDir.resolve(this.toscaMeta.getEntryChangeLog()).toFile();
if (!this.changeLogTxtFile.exists()) {
@@ -1017,37 +1024,38 @@ public class CSARArchive implements AutoCloseable {
this.toscaMeta.getEntryChangeLog(),
lineNo, getEntryChangeLogParamName()));
}
- } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_TESTS)) {
+ } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_TESTS)) {
this.toscaMeta.setEntryTest(value);
- this.testsFolder= this.tempDir.resolve(this.toscaMeta.getEntryTest()).toFile();
+ this.testsFolder = this.tempDir.resolve(this.toscaMeta.getEntryTest()).toFile();
if (!this.testsFolder.exists() || !this.testsFolder.isDirectory()) {
errors.add(new CSARErrorInvalidEntryValueTestsNotFound(
this.toscaMeta.getEntryTest(),
lineNo));
}
- } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_LICENSES)) {
+ } else if(key.equalsIgnoreCase(TOSCA_METADATA_TOSCA_META_ENTRY_LICENSES)) {
this.toscaMeta.setEntryLicense(value);
- this.licensesFolder= this.tempDir.resolve(this.toscaMeta.getEntryLicense()).toFile();
+ this.licensesFolder = this.tempDir.resolve(this.toscaMeta.getEntryLicense()).toFile();
if (!this.licensesFolder.exists() || !this.licensesFolder.isDirectory()) {
errors.add(new CSARErrorInvalidEntryValueLicenseNotFound(
this.toscaMeta.getEntryLicense(),
lineNo));
}
- } else if(key.equalsIgnoreCase(getEntryCertificateParamName())) {
+ } else if(key.equalsIgnoreCase(getEntryCertificateParamName())) {
this.toscaMeta.setEntryCertificate(value);
- this.certificatesFile= this.tempDir.resolve(this.toscaMeta.getEntryCertificate()).toFile();
+ this.certificatesFile = this.tempDir.resolve(this.toscaMeta.getEntryCertificate()).toFile();
if (!this.certificatesFile.exists()) {
errors.add(new CSARErrorInvalidEntryValueCertificatesNotFound(
this.toscaMeta.getEntryCertificate(),
lineNo));
}
- } else {
+ } else {
errors.add(
new CSARErrorIgnored(
key,
TOSCA_METADATA_TOSCA_META,
lineNo,
null));
+ }
}
}
@@ -1071,7 +1079,7 @@ public class CSARArchive implements AutoCloseable {
} else {
//definition files
- File []files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(".yaml"));
+ File []files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(YAML));
if (files.length == 0) {
errors.add(
@@ -1088,9 +1096,12 @@ public class CSARArchive implements AutoCloseable {
this.toscaMeta.setEntryDefinitionYaml(this.definitionYamlFile.getName());
//manifest
- files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(".mf"));
+ files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(MF));
- if (files.length > 1) {
+ if (files.length == 0) {
+ errors.add(new CSARErrorNoManifestsFound());
+ this.toscaMeta.setEntryManifestMf(null);
+ } else if (files.length > 1) {
List<String> fileNames = new ArrayList<>();
for (File f: files) {
fileNames.add(f.getName());
@@ -1102,9 +1113,9 @@ public class CSARArchive implements AutoCloseable {
//name should match the definition yaml
String defYaml = this.toscaMeta.getEntryDefinitionYaml().substring(
- 0, this.toscaMeta.getEntryDefinitionYaml().lastIndexOf(".yaml"));
+ 0, this.toscaMeta.getEntryDefinitionYaml().lastIndexOf(YAML));
String mfFile = this.toscaMeta.getEntryManifestMf().substring(
- 0, this.toscaMeta.getEntryManifestMf().lastIndexOf(".mf"));
+ 0, this.toscaMeta.getEntryManifestMf().lastIndexOf(MF));
if (!defYaml.equalsIgnoreCase(mfFile)) {
errors.add(new CSARErrorMismatchDefinitionYamlVsManifestMf(
@@ -1115,9 +1126,11 @@ public class CSARArchive implements AutoCloseable {
}
//certificate
- files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(".cert"));
+ files = this.tempDir.toFile().listFiles((dir, name) -> name.endsWith(CERT));
- if (files.length > 1) {
+ if (files.length == 0) {
+ this.toscaMeta.setEntryCertificate(null);
+ } else if (files.length > 1) {
List<String> fileNames = new ArrayList<>();
for (File f: files) {
fileNames.add(f.getName());
@@ -1130,9 +1143,9 @@ public class CSARArchive implements AutoCloseable {
//name should match the definition yaml
String defYaml = this.toscaMeta.getEntryDefinitionYaml().substring(
- 0, this.toscaMeta.getEntryDefinitionYaml().lastIndexOf(".yaml"));
+ 0, this.toscaMeta.getEntryDefinitionYaml().lastIndexOf(YAML));
String certFile = this.toscaMeta.getEntryCertificate().substring(
- 0, this.toscaMeta.getEntryCertificate().lastIndexOf(".cert"));
+ 0, this.toscaMeta.getEntryCertificate().lastIndexOf(CERT));
if (!defYaml.equalsIgnoreCase(certFile)) {
errors.add(new CSARErrorMismatchDefinitionYamlVsCertificateCert(
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java b/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java
index 30eb043..74697f1 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java
@@ -16,11 +16,12 @@
package org.onap.cvc.csar;
+import com.google.gson.Gson;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Properties;
-
import org.onap.cli.fw.cmd.OnapCommand;
import org.onap.cli.fw.error.OnapCommandException;
import org.onap.cli.fw.error.OnapCommandExecutionFailed;
@@ -33,19 +34,20 @@ import org.onap.cvc.csar.CSARArchive.CSARError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.Gson;
-
/**
* Validates CSAR
*/
@OnapCommandSchema(schema = "vtp-validate-csar.yaml")
public class VTPValidateCSAR extends OnapCommand {
+
private static Gson gson = new Gson();
private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSAR.class);
public static final String PNF_ATTRIBUTE_NAME = "pnf";
public static class CSARValidation {
+
public static class VNF {
+
private String name;
private String vendor;
private String version;
@@ -55,30 +57,39 @@ public class VTPValidateCSAR extends OnapCommand {
public String getName() {
return name;
}
+
public void setName(String name) {
this.name = name;
}
+
public String getVendor() {
return vendor;
}
+
public void setVendor(String vendor) {
this.vendor = vendor;
}
+
public String getVersion() {
return version;
}
+
public void setVersion(String version) {
this.version = version;
}
+
public String getType() {
return type;
}
+
public void setType(String type) {
this.type = type;
}
+
public String getMode() {
return mode;
}
+
public void setMode(String mode) {
this.mode = mode;
}
@@ -89,35 +100,52 @@ public class VTPValidateCSAR extends OnapCommand {
private String criteria;
public static class Result {
+
private boolean passed;
private String vnfreqName;
private String description;
private List<CSARError> errors = new ArrayList<>();
+ private List<CSARError> warnings = new ArrayList<>();
+
public boolean isPassed() {
return passed;
}
+
public void setPassed(boolean passed) {
this.passed = passed;
}
+
public String getVnfreqName() {
return vnfreqName;
}
+
public void setVnfreqName(String vnfreqName) {
this.vnfreqName = vnfreqName;
}
+
public List<CSARError> getErrors() {
- return errors;
+ return Collections.unmodifiableList(errors);
}
- public void setErrors(List<CSARError> errors) {
- this.errors = errors;
+
+ public void addError(CSARError error) {
+ this.errors.add(error);
}
+
public String getDescription() {
return description;
}
+
public void setDescription(String description) {
this.description = description;
}
+ public List<CSARError> getWarnings() {
+ return Collections.unmodifiableList(warnings);
+ }
+
+ public void addErrorAsWarning(CSARError error) {
+ this.warnings.add(error);
+ }
}
private List<Result> results = new ArrayList<>();
@@ -176,9 +204,10 @@ public class VTPValidateCSAR extends OnapCommand {
}
private static Properties properties = new Properties();
+
static {
try {
- properties.load(VTPValidateCSAR.class.getClass().getResourceAsStream("/vnfreqs.properties"));
+ properties.load(VTPValidateCSAR.class.getResourceAsStream("/vnfreqs.properties"));
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
@@ -191,23 +220,23 @@ public class VTPValidateCSAR extends OnapCommand {
boolean isPnf = (boolean) getParametersMap().get(PNF_ATTRIBUTE_NAME).getValue();
boolean overallPass = true;
- try(CSARArchive csar = isPnf ? new PnfCSARArchive(): new CSARArchive()){
+ try (CSARArchive csar = isPnf ? new PnfCSARArchive() : new CSARArchive()) {
csar.init(path);
csar.parse();
CSARValidation validation = createCsarValidationFor(csar);
String keyErrors = isPnf ? "pnferrors.ignored" : "vnferrors.ignored";
- List <String> ignoreCodes = this.getPropertiesList(keyErrors);
+ List<String> ignoreCodes = this.getPropertiesList(keyErrors);
//Add SOL004 error codes
CSARValidation.Result resultSOL004 = new CSARValidation.Result();
resultSOL004.setVnfreqName("SOL004");
resultSOL004.setDescription(csar.getSOL004Version());
- for (CSARError error: csar.getErrors()) {
+ for (CSARError error : csar.getErrors()) {
if (!ignoreCodes.contains(error.getCode())) {
- resultSOL004.getErrors().add(error);
+ resultSOL004.addError(error);
overallPass = false;
}
}
@@ -217,34 +246,11 @@ public class VTPValidateCSAR extends OnapCommand {
//Run thru the vnfreqs requirement checks
String keyReqs = isPnf ? "pnfreqs.enabled" : "vnfreqs.enabled";
- for (String vnfreq: this.getPropertiesList(keyReqs)) {
+ for (String vnfreq : this.getPropertiesList(keyReqs)) {
CSARValidation.Result result = new CSARValidation.Result();
result.setVnfreqName(vnfreq);
- try {
- String command = "csar-validate-" + vnfreq;
- OnapCommand cmd = OnapCommandRegistrar.getRegistrar().get(command, this.getInfo().getProduct());
- cmd.getParametersMap().get("csar").setValue(path);
- setPnfValueIfAvailable(isPnf, cmd);
-
- result.setDescription(cmd.getDescription());
- cmd.execute();
-
- for (CSARError error: (List<CSARError>) cmd.getResult().getOutput()) {
- if (!ignoreCodes.contains(error.getCode()) && !ignoreCodes.contains(vnfreq + "-"+ error.getCode())) {
- result.getErrors().add(error);
- overallPass = false;
- }
- }
-
- result.setPassed(overallPass);
- validation.getResults().add(result);
- } catch (Exception e) {
- result.setPassed(false);
- overallPass = false;
- result.getErrors().add(new CSARArchive.CSARErrorUnknown(e.getMessage()));
- validation.getResults().add(result);
- }
+ overallPass = validateVnfOrPnf(path, validation, ignoreCodes, vnfreq, result, isPnf, overallPass);
}
validation.setDate(new Date().toString());
@@ -257,6 +263,41 @@ public class VTPValidateCSAR extends OnapCommand {
}
}
+ private boolean validateVnfOrPnf(String path, CSARValidation validation,
+ List<String> ignoreCodes, String vnfreq, CSARValidation.Result result, boolean isPnf, boolean overallPass) {
+ try {
+ String command = "csar-validate-" + vnfreq;
+ OnapCommand cmd = OnapCommandRegistrar.getRegistrar().get(command, this.getInfo().getProduct());
+ cmd.getParametersMap().get("csar").setValue(path);
+ setPnfValueIfAvailable(isPnf, cmd);
+
+ result.setDescription(cmd.getDescription());
+ cmd.execute();
+
+ for (CSARError error : (List<CSARError>) cmd.getResult().getOutput()) {
+ if (!isErrorIgnored(ignoreCodes, vnfreq, error)) {
+ result.addError(error);
+ overallPass = false;
+ } else {
+ result.addErrorAsWarning(error);
+ }
+ }
+
+ result.setPassed(result.getErrors().isEmpty());
+ validation.getResults().add(result);
+ } catch (Exception e) {
+ result.setPassed(false);
+ overallPass = false;
+ result.addError(new CSARArchive.CSARErrorUnknown(e.getMessage()));
+ validation.getResults().add(result);
+ }
+ return overallPass;
+ }
+
+ private boolean isErrorIgnored(List<String> ignoreCodes, String vnfreq, CSARError error) {
+ return ignoreCodes.contains(error.getCode()) || ignoreCodes.contains(vnfreq + "-" + error.getCode());
+ }
+
static CSARValidation createCsarValidationFor(CSARArchive csar) {
//Fill up the basic details
CSARValidation validation = new CSARValidation();
@@ -270,11 +311,11 @@ public class VTPValidateCSAR extends OnapCommand {
private void setOperationResult(CSARValidation validation) throws Exception { //NOSONAR
this.getResult().getRecordsMap().get("vnf").getValues().add(
- gson.toJson(validation.getVnf()));
+ gson.toJson(validation.getVnf()));
this.getResult().getRecordsMap().get("date").getValues().add(validation.getDate());
this.getResult().getRecordsMap().get("criteria").getValues().add(validation.getCriteria());
this.getResult().getRecordsMap().get("results").getValues().add(
- gson.toJson(validation.getResults()));
+ gson.toJson(validation.getResults()));
this.getResult().setOutput(gson.toJson(validation));
this.getResult().setType(OnapCommandResultType.TEXT);
@@ -282,7 +323,7 @@ public class VTPValidateCSAR extends OnapCommand {
private void setPnfValueIfAvailable(boolean isPnf, OnapCommand cmd) throws OnapCommandInvalidParameterValue {
final OnapCommandParameter pnf = cmd.getParametersMap().get(PNF_ATTRIBUTE_NAME);
- if(pnf!=null) {
+ if (pnf != null) {
pnf.setValue(isPnf);
}
}
@@ -290,7 +331,7 @@ public class VTPValidateCSAR extends OnapCommand {
private List<String> getPropertiesList(String key) {
String[] enabledReqs = properties.getProperty(key, "").split(",");
List<String> list = new ArrayList<>();
- for(String req: enabledReqs) {
+ for (String req : enabledReqs) {
if (!req.isEmpty()) {
list.add(req);
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/VTPValidateCSARBase.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/VTPValidateCSARBase.java
index a5a13e3..b004858 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/VTPValidateCSARBase.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/VTPValidateCSARBase.java
@@ -34,7 +34,7 @@ public abstract class VTPValidateCSARBase extends OnapCommand {
protected List<CSARError> errors = new ArrayList<>();
- protected abstract void validateCSAR(CSARArchive csar) throws Exception;
+ protected abstract void validateCSAR(CSARArchive csar) throws Exception; //NOSONAR
protected abstract String getVnfReqsNo();
@@ -57,7 +57,7 @@ public abstract class VTPValidateCSARBase extends OnapCommand {
this.validateCSAR(csar);
} catch (Exception e) {
- LOG.error(this.getVnfReqsNo() + ": Failed to validate CSAR" , e);
+ LOG.error("{}: Failed to validate CSAR {}", this.getVnfReqsNo(), e);
throw new OnapCommandExecutionFailed(e.getMessage());
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR02454.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR02454.java
index 7d0489e..4270d87 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR02454.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR02454.java
@@ -60,10 +60,11 @@ public class VTPValidateCSARR02454 extends VTPValidateCSARBase {
}
}
- if (!vlExist)
- this.errors.add(new CSARErrorEntryMissingSwImage(
+ if (!vlExist) {
+ this.errors.add(new CSARErrorEntryMissingSwImage(
csar.getDefinitionYamlFile().getName(),
"Software Image"));
+ }
}
}
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR35851.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR35851.java
index 52582a6..78be3e6 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR35851.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol001/VTPValidateCSARR35851.java
@@ -59,7 +59,7 @@ public class VTPValidateCSARR35851 extends VTPValidateCSARBase {
yaml = (Map<String, ?>) yaml.get("topology_template");
Map<String, ?> nodeTmpls = (Map<String,?>) yaml.get("node_templates");
- boolean vlExist[] = new boolean[3];
+ boolean[] vlExist = new boolean[3];
for (Object nodeO: nodeTmpls.values()) {
Map<String, ?> node = (Map<String, ?>) nodeO;
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123.java
index 5afc1d9..a7c5737 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123.java
@@ -1,5 +1,6 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd.
+ * Modified 2020 Nokia.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +21,16 @@ import org.onap.cli.fw.schema.OnapCommandSchema;
import org.onap.cvc.csar.CSARArchive;
import org.onap.cvc.csar.CSARArchive.CSARErrorEntryMissing;
import org.onap.cvc.csar.cc.VTPValidateCSARBase;
+import org.onap.cvc.csar.parser.SourcesParser;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
@OnapCommandSchema(schema = "vtp-validate-csar-r01123.yaml")
public class VTPValidateCSARR01123 extends VTPValidateCSARBase {
@@ -27,19 +38,115 @@ public class VTPValidateCSARR01123 extends VTPValidateCSARBase {
public static class CSARErrorEntryVNFProviderDetailsNotFound extends CSARErrorEntryMissing {
public CSARErrorEntryVNFProviderDetailsNotFound() {
super("VNF Vendor details",
- CSARArchive.TOSCA_METADATA + " or " + CSARArchive.TOSCA_METADATA_TOSCA_META_ENTRY_DEFINITIONS + " file");
+ CSARArchive.TOSCA_METADATA + " or " + CSARArchive.TOSCA_METADATA_TOSCA_META_ENTRY_DEFINITIONS + " file");
this.setCode("0x1000");
}
}
+ public static class CSARErrorNotAllFilesLocatedInCSARWhereListedInManifest extends CSARErrorEntryMissing {
+ CSARErrorNotAllFilesLocatedInCSARWhereListedInManifest(List<String> fileInCsarThatAreNotLocatedInManifest) {
+ super("Source",
+ CSARArchive.TOSCA_METADATA);
+ this.setCode("0x1001");
+ this.message = "file(s): ["
+ + String.join(", ", fileInCsarThatAreNotLocatedInManifest)
+ + "] available in CSAR, but cannot be found in Manifest as Source";
+ }
+ }
+
+ public static class CSARErrorNotAllFilesLocatedInManifestWhereListedInCsar extends CSARErrorEntryMissing {
+ CSARErrorNotAllFilesLocatedInManifestWhereListedInCsar(List<String> fileInCsarThatAreNotLocatedInManifest) {
+ super("Source",
+ CSARArchive.TOSCA_METADATA);
+ this.setCode("0x1002");
+ this.message = "file(s): ["
+ + String.join(", ", fileInCsarThatAreNotLocatedInManifest)
+ + "] defined in Manifest as Source, but cannot be found in CSAR";
+ }
+ }
+
@Override
protected void validateCSAR(CSARArchive csar) throws Exception {
+ verifyThatProviderDataAreDefined(csar);
+ verifyPackageFileStructure(csar);
+ }
+
+ private void verifyPackageFileStructure(CSARArchive csar) throws IOException {
+ Path rootFolder = getRootFolder(csar);
+ List<String> filesInCsar = getAllFilesInDirectory(rootFolder);
+ List<String> sourcesInManifest = getAllFilesFromManifestSources(csar.getManifest());
+
+ if (areAllFilesDefinedInManifest(filesInCsar, sourcesInManifest)) {
+ verifyThatAllFilesFromCsarAreDefinedInManifest(filesInCsar, sourcesInManifest);
+ verifyThatAllFilesDefinedInManifestAreAvailableInCsar(sourcesInManifest, filesInCsar);
+ }
+ }
+
+ private void verifyThatProviderDataAreDefined(CSARArchive csar) {
if (csar.getVendorName() == null ||
- csar.getVersion() == null) {
+ csar.getVersion() == null) {
errors.add(new CSARErrorEntryVNFProviderDetailsNotFound());
}
}
+ private Path getRootFolder(CSARArchive csar) throws IOException {
+ return csar.getWorkspace().getPathToCsarFolder()
+ .orElseThrow(() -> new IOException("Couldn't find CSAR root catalog"));
+ }
+
+
+ private void verifyThatAllFilesDefinedInManifestAreAvailableInCsar(List<String> sourcesInManifest, List<String> filesInCsar) {
+ if(!filesInCsar.containsAll(sourcesInManifest)){
+ List<String> sourcesNotAvailableInCsarFile = fetchElementsNotAvailableAtSecondList(sourcesInManifest, filesInCsar);
+ errors.add(new CSARErrorNotAllFilesLocatedInManifestWhereListedInCsar(sourcesNotAvailableInCsarFile));
+ }
+ }
+
+ private void verifyThatAllFilesFromCsarAreDefinedInManifest(List<String> filesInCsar, List<String> sourcesInManifest) {
+ if(!sourcesInManifest.containsAll(filesInCsar) ){
+ List<String> filesNotDefinedInManifestFile = fetchElementsNotAvailableAtSecondList(filesInCsar, sourcesInManifest);
+ errors.add(new CSARErrorNotAllFilesLocatedInCSARWhereListedInManifest(filesNotDefinedInManifestFile));
+ }
+ }
+
+ private List<String> fetchElementsNotAvailableAtSecondList(List<String> firstList, List<String> secondList) {
+ List<String> copyOfFirstList = new ArrayList<>(firstList);
+ copyOfFirstList.removeAll(secondList);
+ return copyOfFirstList;
+ }
+
+ private boolean areAllFilesDefinedInManifest(List<String> filesInCsar, List<String> sourcesInManifest) {
+ return filesInCsar.size() != sourcesInManifest.size();
+ }
+
+ private List<String> getAllFilesFromManifestSources(CSARArchive.Manifest manifest) {
+ return manifest.getSources()
+ .stream()
+ .map(SourcesParser.Source::getValue)
+ .filter(filterOutManifestFile())
+ .collect(Collectors.toList());
+ }
+
+ private List<String> getAllFilesInDirectory(Path rootPath) throws IOException {
+ try (Stream<Path> paths = Files.walk(rootPath, Integer.MAX_VALUE)) {
+ return paths
+ .filter(filterOutDirectories())
+ .map(rootPath::relativize)
+ .map(String::valueOf)
+ .filter(filterOutManifestFile())
+ .collect(Collectors.toList());
+ }
+ }
+
+ private Predicate<Path> filterOutDirectories() {
+ return path -> !Files.isDirectory(path);
+ }
+
+
+ private Predicate<String> filterOutManifestFile() {
+ return path -> !path.endsWith(".mf");
+ }
+
@Override
protected String getVnfReqsNo() {
return "R01123";
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java
index fefe65b..05feb54 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java
@@ -26,6 +26,10 @@ import org.onap.cvc.csar.cc.VTPValidateCSARBase;
import org.onap.cvc.csar.parser.ManifestFileModel;
import org.onap.cvc.csar.parser.ManifestFileSplitter;
import org.onap.cvc.csar.parser.SourcesParser;
+import org.onap.cvc.csar.security.CertificateLoadingException;
+import org.onap.cvc.csar.security.CmsSignatureData;
+import org.onap.cvc.csar.security.CmsSignatureDataFactory;
+import org.onap.cvc.csar.security.CmsSignatureLoadingException;
import org.onap.cvc.csar.security.CmsSignatureValidator;
import org.onap.cvc.csar.security.CmsSignatureValidatorException;
import org.onap.cvc.csar.security.ShaHashCodeGenerator;
@@ -50,23 +54,31 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSARR130206.class);
private static final String SHA_256 = "SHA-256";
private static final String SHA_512 = "SHA-512";
+ private static final String EMPTY_STRING = "";
private final ShaHashCodeGenerator shaHashCodeGenerator = new ShaHashCodeGenerator();
private final ManifestFileSignatureValidator manifestFileSignatureValidator = new ManifestFileSignatureValidator();
public static class CSARErrorUnableToFindCertificate extends CSARArchive.CSARError {
- CSARErrorUnableToFindCertificate(String paramName) {
+ CSARErrorUnableToFindCertificate() {
super("0x4001");
- this.message = String.format("Unable to find cert file defined by %s!", paramName);
+ this.message = "Unable to find cert file!";
}
}
- public static class CSARErrorUnableToFindCmsSection extends CSARArchive.CSARError {
+ public static class CSARErrorUnableToFindCms extends CSARArchive.CSARError {
- CSARErrorUnableToFindCmsSection() {
+ CSARErrorUnableToFindCms() {
super("0x4002");
- this.message = "Unable to find CMS section in manifest!";
+ this.message = "Unable to find cms signature!";
+ }
+ }
+
+ public static class CSARErrorUnableToLoadCms extends CSARArchive.CSARError {
+ CSARErrorUnableToLoadCms() {
+ super("0x4002");
+ this.message = "Unable to load cms signature!";
}
}
@@ -106,7 +118,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
CSARErrorInvalidSignature() {
super("0x4007");
- this.message = "File has invalid CMS signature!";
+ this.message = "File has invalid signature!";
}
}
@@ -118,6 +130,61 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
}
}
+ public static class CSARErrorUnableToFindEntryCertificate extends CSARArchive.CSARError {
+
+ CSARErrorUnableToFindEntryCertificate() {
+ super("0x4009");
+ this.message = "Unable to find cert file defined by ETSI-Entry-Certificate!";
+ }
+ }
+
+ public static class CSARErrorEntryCertificateIsDefinedDespiteTheCms extends CSARArchive.CSARError {
+
+ CSARErrorEntryCertificateIsDefinedDespiteTheCms() {
+ super("0x4011");
+ this.message = "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container";
+ }
+ }
+
+ public static class CSARErrorEntryCertificateIsPresentDespiteTheCms extends CSARArchive.CSARError {
+
+ CSARErrorEntryCertificateIsPresentDespiteTheCms() {
+ super("0x4012");
+ this.message = "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container";
+ }
+ }
+
+ public static class CSARErrorRootCertificateIsPresentDespiteTheCms extends CSARArchive.CSARError {
+
+ CSARErrorRootCertificateIsPresentDespiteTheCms() {
+ super("0x4013");
+ this.message = "Certificate present in root catalog despite the certificate is included in the signature container";
+ }
+ }
+
+ public static class CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate extends CSARArchive.CSARError {
+
+ CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate() {
+ super("0x4013");
+ this.message = "Certificate present in root catalog despite the TOSCA.meta file";
+ }
+ }
+
+ public static class CSARErrorUnableToFindCertificateEntryInTosca extends CSARArchive.CSARError {
+
+ CSARErrorUnableToFindCertificateEntryInTosca() {
+ super("0x4014");
+ this.message = "Unable to find ETSI-Entry-Certificate in Tosca file";
+ }
+ }
+
+ public static class CSARWarningNoSecurity extends CSARArchive.CSARErrorWarning {
+ CSARWarningNoSecurity() {
+ super(EMPTY_STRING, EMPTY_STRING, -1, EMPTY_STRING);
+ this.message = "Warning. Consider adding package integrity and authenticity assurance according to ETSI NFV-SOL 004 Security Option 1";
+ }
+ }
+
@Override
protected void validateCSAR(CSARArchive csar) throws OnapCommandException {
@@ -137,20 +204,146 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
}
private void validate(CSARArchive csar, Path csarRootDirectory) throws IOException, NoSuchAlgorithmException {
- final CSARArchive.Manifest manifest = csar.getManifest();
+ if (containsCms(csar.getManifest())) {
+ validateCmsSignature(csar, csarRootDirectory);
+ } else if (
+ ( containsToscaMeta(csar) && containsCertificateInTosca(csar.getToscaMeta()) ) ||
+ containsCertificateInRootCatalog(csar) ||
+ containsHashOrAlgorithm(csar.getManifest())) {
+ this.errors.add(new CSARErrorUnableToFindCms());
+ } else {
+ this.errors.add(new CSARWarningNoSecurity());
+ }
+ }
+
+ private void validateCmsSignature(CSARArchive csar, Path csarRootDirectory) throws NoSuchAlgorithmException, IOException {
+ try {
+ CmsSignatureData signatureData = this.manifestFileSignatureValidator.createSignatureData(csar.getManifestMfFile());
+ if (signatureData.getCertificate().isPresent()) {
+ validateCertificationUsingCmsCertificate(signatureData, csar, csarRootDirectory);
+ } else if (containsToscaMeta(csar)) {
+ validateCertificationUsingTosca(signatureData, csar, csarRootDirectory);
+ } else if (containsCertificateInRootCatalog(csar)) {
+ validateCertificationUsingCertificateFromRootDirectory(signatureData, csar, csarRootDirectory);
+ } else {
+ this.errors.add(new CSARErrorUnableToFindCertificate());
+ }
+ } catch (CmsSignatureLoadingException e) {
+ LOG.error("Unable to load CMS!", e);
+ this.errors.add(new CSARErrorUnableToLoadCms());
+ }
+ }
+
+ private boolean containsCms(CSARArchive.Manifest manifest) {
+ String cms = manifest.getCms();
+ return cms != null && !cms.equals(EMPTY_STRING);
+ }
+
+ private boolean containsToscaMeta(CSARArchive archive) {
+ return archive.getToscaMetaFile() != null;
+ }
+
+ private boolean containsCertificateInTosca(CSARArchive.TOSCAMeta toscaMeta) {
+ String certificate = toscaMeta.getEntryCertificate();
+ return certificate != null && !certificate.equals(EMPTY_STRING);
+ }
+
+ private boolean containsCertificateInRootCatalog(CSARArchive csar) {
+ File potentialCertificateFileInRootDirectory = getCertificateFromRootDirectory(csar);
+ return potentialCertificateFileInRootDirectory.exists();
+ }
- validateSecurityStructure(csar, csarRootDirectory);
+ private boolean containsHashOrAlgorithm(CSARArchive.Manifest manifest) {
+ return manifest.getSources().stream().anyMatch(
+ source ->
+ !source.getAlgorithm().equals(EMPTY_STRING) ||
+ !source.getHash().equals(EMPTY_STRING)
+ );
+ }
+
+ private void validateCertificationUsingCmsCertificate(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory)
+ throws NoSuchAlgorithmException, IOException {
+ validateAllSources(csar, csarRootDirectory);
+ validateFileSignature(signatureData);
+ if (containsCertificateInTosca(csar.getToscaMeta())) {
+ errors.add(new CSARErrorEntryCertificateIsDefinedDespiteTheCms());
+ if (csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).exists()) {
+ errors.add(new CSARErrorEntryCertificateIsPresentDespiteTheCms());
+ }
+ }
+ if (containsCertificateInRootCatalog(csar)) {
+ errors.add(new CSARErrorRootCertificateIsPresentDespiteTheCms());
+ }
+ }
+
+ private void validateCertificationUsingTosca(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory)
+ throws NoSuchAlgorithmException, IOException {
+ validateAllSources(csar, csarRootDirectory);
+ if (loadCertificateFromTosca(signatureData, csar)) {
+ validateFileSignature(signatureData);
+ }
+ if (containsCertificateInRootCatalog(csar) && rootCertificateIsNotReferredAsToscaEtsiEntryCertificate(csar)) {
+ errors.add(new CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate());
+ }
+ }
+
+ private boolean loadCertificateFromTosca(CmsSignatureData signatureData, CSARArchive csar) {
+ if(csar.getToscaMeta().getEntryCertificate() != null) {
+ try {
+ final Path absolutePathToEntryCertificate = csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).toPath();
+ signatureData.loadCertificate(absolutePathToEntryCertificate);
+ return true;
+ } catch (CertificateLoadingException e) {
+ this.errors.add(new CSARErrorUnableToFindEntryCertificate());
+ return false;
+ }
+ } else {
+ this.errors.add(new CSARErrorUnableToFindCertificateEntryInTosca());
+ return false;
+ }
+ }
+
+ private boolean rootCertificateIsNotReferredAsToscaEtsiEntryCertificate(CSARArchive csar) {
+ String pathToRootCertificate = getCertificateFromRootDirectory(csar).getPath();
+ String pathToEntryEtsiCertificate = csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).getPath();
+ return !pathToRootCertificate.equals(pathToEntryEtsiCertificate);
+ }
+
+ private void validateCertificationUsingCertificateFromRootDirectory(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory)
+ throws NoSuchAlgorithmException, IOException {
+ validateAllSources(csar, csarRootDirectory);
+ if (loadCertificateFromRootDirectory(signatureData, csar)) {
+ validateFileSignature(signatureData);
+ }
+ }
+
+ private boolean loadCertificateFromRootDirectory(CmsSignatureData signatureData, CSARArchive csar) {
+ try {
+ File certificateFileFromRootDirectory = getCertificateFromRootDirectory(csar);
+ signatureData.loadCertificate(certificateFileFromRootDirectory.toPath());
+ return true;
+ } catch (CertificateLoadingException e) {
+ LOG.error("Uable to read ETSI entry certificate file!", e);
+ return false;
+ }
+ }
+
+ private File getCertificateFromRootDirectory(CSARArchive csar) {
+ String nameOfCertificate =
+ csar.getManifestMfFile().getName().split("\\.")[0] +
+ ".cert";
+ return csar.getFileFromCsar(nameOfCertificate);
+ }
+
+ private void validateAllSources(CSARArchive csar, Path csarRootDirectory)
+ throws NoSuchAlgorithmException, IOException {
+ final CSARArchive.Manifest manifest = csar.getManifest();
validateSources(csarRootDirectory, manifest);
final Map<String, Map<String, List<String>>> nonMano = manifest.getNonMano();
final List<SourcesParser.Source> sources = manifest.getSources();
validateNonManoCohesionWithSources(nonMano, sources);
-
- final File manifestMfFile = csar.getManifestMfFile();
- if (manifestMfFile != null) {
- validateFileSignature(manifestMfFile);
- }
}
private void validateNonManoCohesionWithSources(final Map<String, Map<String, List<String>>> nonMano,
@@ -174,36 +367,13 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
}
- private void validateFileSignature(File manifestMfFile) {
- final boolean isValid = this.manifestFileSignatureValidator.isValid(manifestMfFile);
+ private void validateFileSignature(CmsSignatureData signatureData) {
+ final boolean isValid = this.manifestFileSignatureValidator.isValid(signatureData);
if (!isValid) {
this.errors.add(new CSARErrorInvalidSignature());
}
}
- private void validateSecurityStructure(CSARArchive csar, Path csarRootDirectory) {
- final CSARArchive.Manifest manifest = csar.getManifest();
- final CSARArchive.TOSCAMeta toscaMeta = csar.getToscaMeta();
- final String entryCertificateParamName = csar.getEntryCertificateParamName();
- final Optional<File> entryCertificate = resolveCertificateFilePath(toscaMeta, csarRootDirectory);
- if (!entryCertificate.isPresent() || !entryCertificate.get().exists()) {
- this.errors.add(new CSARErrorUnableToFindCertificate(entryCertificateParamName));
- }
-
- if (manifest.getCms() == null || manifest.getCms().isEmpty()) {
- this.errors.add(new CSARErrorUnableToFindCmsSection());
- }
- }
-
- private Optional<File> resolveCertificateFilePath(CSARArchive.TOSCAMeta toscaMeta, Path csarRootDirectory) {
- final String certificatePath = toscaMeta.getEntryCertificate();
- if (certificatePath == null) {
- return Optional.empty();
- } else {
- return Optional.of(csarRootDirectory.resolve(certificatePath).toFile());
- }
- }
-
private void validateSources(Path csarRootDirectory, CSARArchive.Manifest manifest)
throws NoSuchAlgorithmException, IOException {
final List<SourcesParser.Source> sources = manifest.getSources();
@@ -256,18 +426,23 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
}
- class ManifestFileSignatureValidator {
+ static class ManifestFileSignatureValidator {
- private final Logger LOG = LoggerFactory.getLogger(ManifestFileSignatureValidator.class);
private final ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter();
private final CmsSignatureValidator cmsSignatureValidator = new CmsSignatureValidator();
+ private final CmsSignatureDataFactory cmsSignatureDataFactory = new CmsSignatureDataFactory();
+
+ CmsSignatureData createSignatureData(File manifestFile) throws CmsSignatureLoadingException {
+ ManifestFileModel mf = manifestFileSplitter.split(manifestFile);
+ return cmsSignatureDataFactory.createForFirstSigner(
+ toBytes(mf.getCMS(), mf.getNewLine()),
+ toBytes(mf.getData(), mf.getNewLine())
+ );
+ }
- boolean isValid(File manifestFile) {
+ boolean isValid(CmsSignatureData signatureData) {
try {
- ManifestFileModel mf = manifestFileSplitter.split(manifestFile);
- return cmsSignatureValidator.verifySignedData(toBytes(mf.getCMS(), mf.getNewLine()),
- Optional.empty(),
- toBytes(mf.getData(), mf.getNewLine()));
+ return cmsSignatureValidator.verifySignedData(signatureData);
} catch (CmsSignatureValidatorException e) {
LOG.error("Unable to verify signed data!", e);
return false;
@@ -279,4 +454,5 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase {
return updatedData.getBytes(Charset.defaultCharset());
}
}
+
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745.java
new file mode 100644
index 0000000..b43dbba
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2020 Nokia.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.cvc.csar.cc.sol004;
+
+import org.onap.cli.fw.schema.OnapCommandSchema;
+import org.onap.cvc.csar.CSARArchive;
+import org.onap.cvc.csar.cc.VTPValidateCSARBase;
+import org.onap.validation.yaml.YamlFileValidator;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.error.YAMLException;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@OnapCommandSchema(schema = "vtp-validate-csar-r816745.yaml")
+public class VTPValidateCSARR816745 extends VTPValidateCSARBase {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(VTPValidateCSARR816745.class);
+
+ private static class CSARPmDictionaryValidationError extends CSARArchive.CSARError {
+
+ CSARPmDictionaryValidationError(int documentNumber, String file, String path, String message) {
+ super("0x1000");
+ this.message = String.format(
+ "Invalid YAML document in PM_Dictionary file. %n" +
+ "In document number %s (excluding document with schema) error occur. %n" +
+ "Path: %s%n" +
+ "%s",
+ documentNumber, path, message
+ );
+ this.file = file;
+ }
+
+ }
+
+ private static class CSARPmDictionaryLoadingError extends CSARArchive.CSARError {
+
+ CSARPmDictionaryLoadingError(String file, String message) {
+ super("0x2000");
+ this.message = String.format(
+ "Fail to load PM_Dictionary With error: %s",
+ message
+ );
+ this.file = file;
+ }
+
+ }
+
+ private static final String PM_DICTIONARY = "onap_pm_dictionary";
+ private static final String SOURCE_ELEMENT_TAG = "Source";
+
+ @Override
+ protected void validateCSAR(CSARArchive csar) {
+ Map<String, Map<String, List<String>>> nonManoFields = csar.getManifest().getNonMano();
+ String rootPath = csar.getWorkspace().getPathToCsarFolder().map(Path::toString).orElse("/");
+ if (nonManoFields.containsKey(PM_DICTIONARY)) {
+ getLocationOfPmDictionaryFile(nonManoFields, csar.getManifestMfFile().getName()).ifPresent(pmDictionary ->
+ validateYamlFile(rootPath+"/",pmDictionary)
+ );
+ }
+ }
+
+ private Optional<String> getLocationOfPmDictionaryFile(Map<String, Map<String, List<String>>> nonManoFields, String manifestFileName) {
+ if(nonManoFields.get(PM_DICTIONARY).containsKey(SOURCE_ELEMENT_TAG)) {
+ return getPathToPmDictionary(nonManoFields, SOURCE_ELEMENT_TAG);
+ } else if(nonManoFields.get(PM_DICTIONARY).containsKey(SOURCE_ELEMENT_TAG.toLowerCase())) {
+ return getPathToPmDictionary(nonManoFields, SOURCE_ELEMENT_TAG.toLowerCase());
+ } else {
+ addPmDictionaryLoadingError(manifestFileName, PM_DICTIONARY +" in manifest does not contains key 'Source'");
+ return Optional.empty();
+ }
+ }
+
+ private Optional<String> getPathToPmDictionary(Map<String, Map<String, List<String>>> nonManoFields, String sourceElementTag) {
+ return Optional.ofNullable(nonManoFields.get(PM_DICTIONARY).get(sourceElementTag).get(0));
+ }
+
+ private void validateYamlFile(String rootPath, String artifactPath) {
+ try {
+ List<YamlDocumentValidationError> validationErrors =
+ new YamlFileValidator().validateYamlFileWithSchema(rootPath+artifactPath);
+ addAllErrorsReportedByVaidator(artifactPath, validationErrors);
+ } catch (YamlProcessingException | YAMLException e) {
+ LOGGER.error("Failed to load PM_Dictionary file.", e);
+ addPmDictionaryLoadingError(artifactPath, e);
+ }
+
+ }
+
+ private void addPmDictionaryLoadingError(String artifactPath, Exception e) {
+ addPmDictionaryLoadingError(artifactPath,e.getMessage());
+ }
+
+ private void addPmDictionaryLoadingError(String artifactPath, String message) {
+ errors.add(new CSARPmDictionaryLoadingError(
+ artifactPath,
+ message
+ ));
+ }
+
+ private void addAllErrorsReportedByVaidator(String artifactPath, List<YamlDocumentValidationError> validationErrors) {
+ for(YamlDocumentValidationError validationError: validationErrors) {
+ addPmDictionaryValidationError(artifactPath, validationError);
+ }
+ }
+
+ private void addPmDictionaryValidationError(String artifactPath, YamlDocumentValidationError validationError) {
+ errors.add(new CSARPmDictionaryValidationError(
+ validationError.getYamlDocumentNumber(),
+ artifactPath,
+ validationError.getPath(),
+ validationError.getMessage()
+ ));
+ }
+
+ @Override
+ protected String getVnfReqsNo() {
+ return "R816745";
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java
index 1061480..27e3ce9 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java
@@ -23,13 +23,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
+
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
@@ -113,15 +114,24 @@ public class VTPValidateCSARR972082 extends VTPValidateCSARBase {
}
}
+ private static class InvalidFileExtensionError extends PnfCSARError {
+
+ private InvalidFileExtensionError(final String fileName) {
+ super(ERROR_CODE,
+ String.format("Invalid. File extension %s is invalid", fileName),
+ UNKNOWN_LINE_NUMBER,
+ fileName);
+ }
+ }
+
private static class ValidateNonManoSection {
+ private static final String ATTRIBUTE_NAME = "onap_pnf_sw_information";
+
private final CSARArchive csar;
private final String fileName;
private final Map<String, Map<String, List<String>>> nonMano;
private final List<CSARError> errors = new ArrayList<>();
- private final List<String> attributeNames = Arrays.asList(
- "onap_pnf_sw_information"
- );
private ValidateNonManoSection(final CSARArchive csar, final String fileName,
final Map<String, Map<String, List<String>>> nonMano) {
@@ -141,28 +151,20 @@ public class VTPValidateCSARR972082 extends VTPValidateCSARBase {
}
private List<CSARError> validate() {
- if (nonMano.keySet().stream().filter(Objects::nonNull).count() > 0) {
- nonMano.keySet().stream().filter(Objects::nonNull).forEach(this::validateAttribute);
+ List<String> attributesNotNull = nonMano.keySet().stream()
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ if (!attributesNotNull.isEmpty()) {
+ attributesNotNull.forEach(this::validateAttribute);
} else {
- errors.add(new PnfCSARErrorEntryMissing(
- attributeNames.toString(),
- fileName,
- UNKNOWN_LINE_NUMBER)
- );
+ errors.add(new PnfCSARErrorEntryMissing(ATTRIBUTE_NAME, fileName, UNKNOWN_LINE_NUMBER));
}
return errors;
}
private void validateAttribute(final String nonManoAttributes) {
-
- if (!attributeNames.contains(nonManoAttributes)) {
- errors.add(new PnfCSARErrorEntryMissing(
- nonManoAttributes,
- fileName,
- UNKNOWN_LINE_NUMBER)
- );
- } else {
+ if (ATTRIBUTE_NAME.equals(nonManoAttributes)) {
validateSourceElementsUnderAttribute(nonManoAttributes);
}
}
@@ -194,6 +196,9 @@ public class VTPValidateCSARR972082 extends VTPValidateCSARBase {
if (StringUtils.isEmpty(swInformationFilePath)) {
errors.add(new MissingSourceElementUnderAttributeError("", swInformationFilePath));
return;
+ } else if (!swInformationFilePath.matches(".*\\.yaml$")) {
+ errors.add(new InvalidFileExtensionError(swInformationFilePath));
+ return;
}
final Optional<PnfSoftwareInformation> parsedYaml = parse(swInformationFilePath);
if (!parsedYaml.isPresent()) {
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestLine.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestLine.java
index 390c534..eefc771 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestLine.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestLine.java
@@ -54,4 +54,8 @@ public class ManifestLine {
return line.trim().isEmpty();
}
+ boolean contains(String word) {
+ return line.contains(word);
+ }
+
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java
index b0c06ee..f529c45 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java
@@ -85,7 +85,7 @@ public class MetadataParser {
private boolean isNewSection(Pair<String, String> data) {
String key = data.getKey().trim();
String value = data.getValue().trim();
- return key.matches("[a-zA-z_0-9]+") && (value.isEmpty() || ManifestLine.of(value).startsWith("#"));
+ return key.matches("[a-zA-Z_0-9]+") && (value.isEmpty() || ManifestLine.of(value).startsWith("#"));
}
private boolean isSourceSection(Pair<String, String> data) {
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/NonManoArtifactsParser.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/NonManoArtifactsParser.java
index d27ef68..1aa7d32 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/NonManoArtifactsParser.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/NonManoArtifactsParser.java
@@ -26,10 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
+import static org.onap.cvc.csar.parser.ManifestConsts.BEGIN_CMS_SECTION;
import static org.onap.cvc.csar.parser.ManifestConsts.NON_MANO_ARTIFACT_SETS_TAG_SECTION;
public class NonManoArtifactsParser {
+
public Optional<Pair<Map<String, Map<String, List<String>>>, List<CSARArchive.CSARError>>> parse(List<String> lines) {
Map<String, Map<String, List<String>>> nonManoArtifacts = new HashMap<>();
List<CSARArchive.CSARError> errors = new ArrayList<>();
@@ -41,16 +43,17 @@ public class NonManoArtifactsParser {
ManifestLine manifestLine = ManifestLine.of(line);
if (manifestLine.startsWith(NON_MANO_ARTIFACT_SETS_TAG_SECTION)) {
isNonManoArtifactsSectionAvailable = true;
+ } else if (manifestLine.contains(BEGIN_CMS_SECTION)) {
+ break;
} else if (isNonManoArtifactsSectionAvailable) {
Pair<String, String> data = manifestLine.parse();
if (isNewSection(data)) {
attributeName = data.getKey();
nonManoArtifacts.put(attributeName, new HashMap<>());
- continue;
- }
-
+ } else {
handleNonManoArtifactLine(nonManoArtifacts, attributeName, data);
+ }
}
}
@@ -64,7 +67,7 @@ public class NonManoArtifactsParser {
private boolean isNewSection(Pair<String, String> data) {
String key = data.getKey().trim();
String value = data.getValue().trim();
- return key.matches("[a-zA-z_0-9]+") && (value.isEmpty() || ManifestLine.of(value).startsWith("#"));
+ return key.matches("[a-zA-Z_0-9]+") && (value.isEmpty() || ManifestLine.of(value).startsWith("#"));
}
private void handleNonManoArtifactLine(
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CertificateLoadingException.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CertificateLoadingException.java
new file mode 100644
index 0000000..2be5be2
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CertificateLoadingException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ *
+ */
+
+package org.onap.cvc.csar.security;
+
+public class CertificateLoadingException extends RuntimeException {
+
+ public CertificateLoadingException(String s, Throwable t) {
+ super(s, t);
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureData.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureData.java
new file mode 100644
index 0000000..456f365
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureData.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ *
+ */
+
+package org.onap.cvc.csar.security;
+
+import org.bouncycastle.cms.SignerInformation;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Optional;
+
+public class CmsSignatureData {
+
+ private X509Certificate certificate;
+ private final SignerInformation signerInformation;
+
+ public CmsSignatureData(X509Certificate certificate, SignerInformation signerInformation) {
+ this.certificate = certificate;
+ this.signerInformation = signerInformation;
+ }
+
+ public CmsSignatureData(SignerInformation signerInformation) {
+ this.signerInformation = signerInformation;
+ }
+
+ public Optional<X509Certificate> getCertificate() {
+ return Optional.ofNullable(certificate);
+ }
+
+ public SignerInformation getSignerInformation() {
+ return signerInformation;
+ }
+
+ public void loadCertificate(Path pathToCertificate) throws CertificateLoadingException {
+ try {
+ loadCertificate(Files.readAllBytes(pathToCertificate));
+ } catch (IOException e) {
+ final String errorMessage = String.format(
+ "Error during loading Certificate from given path: %s !"
+ ,pathToCertificate
+ );
+ throw new CertificateLoadingException(errorMessage, e);
+ }
+ }
+
+ public void loadCertificate(final byte[] certificate) throws CertificateLoadingException {
+ try (InputStream in = new ByteArrayInputStream(certificate)) {
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ this.certificate = (X509Certificate) factory.generateCertificate(in);
+ } catch (IOException | CertificateException e) {
+ throw new CertificateLoadingException("Error during loading Certificate from bytes!", e);
+ }
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java
new file mode 100644
index 0000000..2744bc6
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureDataFactory.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ *
+ */
+
+package org.onap.cvc.csar.security;
+
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cms.SignerInformation;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.util.Store;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.Optional;
+
+public class CmsSignatureDataFactory {
+
+ public CmsSignatureData createForFirstSigner(final byte[] cmsSignature, final byte[] fileContent)
+ throws CmsSignatureLoadingException{
+
+ try (ByteArrayInputStream cmsSignatureStream = new ByteArrayInputStream(cmsSignature)) {
+ CMSSignedData signedData = getCMSSignedData(fileContent, cmsSignatureStream);
+ Collection<SignerInformation> signers = signedData.getSignerInfos().getSigners();
+ Store<X509CertificateHolder> certificates = signedData.getCertificates();
+ SignerInformation firstSigner = getFirstSigner(signers);
+ CmsSignatureData signatureData = new CmsSignatureData(firstSigner);
+ getFirstSignerCertificate(certificates, firstSigner).ifPresent(
+ signatureData::loadCertificate
+ );
+ return signatureData;
+ } catch (CertificateLoadingException | IOException | CMSException e) {
+ throw new CmsSignatureLoadingException("Unexpected error occurred during signature validation!", e);
+ }
+ }
+
+ private SignerInformation getFirstSigner(Collection<SignerInformation> signers) {
+ return signers.iterator().next();
+ }
+
+ private Optional<byte[]> getFirstSignerCertificate(
+ Store<X509CertificateHolder> certificates,
+ SignerInformation firstSigner)
+ throws IOException {
+ Collection<X509CertificateHolder> firstSignerCertificates = certificates.getMatches(firstSigner.getSID());
+ Optional<byte[]> cert;
+ if (!firstSignerCertificates.isEmpty()) {
+ X509CertificateHolder firstSignerFirstCertificate = firstSignerCertificates.iterator().next();
+ cert = Optional.of(firstSignerFirstCertificate.getEncoded());
+ } else {
+ cert = Optional.empty();
+ }
+ return cert;
+ }
+
+
+ private CMSSignedData getCMSSignedData(byte[] innerPackageFileCSAR, ByteArrayInputStream signatureStream) throws IOException, CmsSignatureLoadingException, CMSException {
+ ContentInfo signature = produceSignature(signatureStream);
+ CMSTypedData signedContent = new CMSProcessableByteArray(innerPackageFileCSAR);
+ return new CMSSignedData(signedContent, signature);
+ }
+
+ private ContentInfo produceSignature(ByteArrayInputStream signatureStream) throws IOException, CmsSignatureLoadingException {
+ Object parsedObject = new PEMParser(new InputStreamReader(signatureStream, Charset.defaultCharset())).readObject();
+ if (!(parsedObject instanceof ContentInfo)) {
+ throw new CmsSignatureLoadingException("Signature is not recognized!");
+ }
+ return ContentInfo.getInstance(parsedObject);
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureLoadingException.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureLoadingException.java
new file mode 100644
index 0000000..0e203b2
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureLoadingException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ *
+ */
+
+package org.onap.cvc.csar.security;
+
+public class CmsSignatureLoadingException extends Exception {
+
+ public CmsSignatureLoadingException(String s) {
+ super(s);
+ }
+
+ public CmsSignatureLoadingException(String s, Throwable t) {
+ super(s, t);
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java
index b8b3714..5d7b879 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidator.java
@@ -17,30 +17,14 @@
package org.onap.cvc.csar.security;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSException;
-import org.bouncycastle.cms.CMSProcessableByteArray;
-import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignerDigestMismatchException;
-import org.bouncycastle.cms.CMSTypedData;
-import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
-import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.util.Store;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.Charset;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import java.util.Collection;
import java.util.Optional;
public class CmsSignatureValidator {
@@ -52,63 +36,30 @@ public class CmsSignatureValidator {
final Optional<byte[]> certificate,
final byte[] fileContent) throws CmsSignatureValidatorException {
- try (ByteArrayInputStream cmsSignatureStream = new ByteArrayInputStream(cmsSignature)) {
- CMSSignedData signedData = getCMSSignedData(fileContent, cmsSignatureStream);
- Collection<SignerInformation> signers = signedData.getSignerInfos().getSigners();
- SignerInformation firstSigner = signers.iterator().next();
-
- Store certificates = signedData.getCertificates();
- X509Certificate cert;
- if (!certificate.isPresent()) {
- X509CertificateHolder firstSignerFirstCertificate = getX509CertificateHolder(firstSigner, certificates);
- cert = loadCertificate(firstSignerFirstCertificate.getEncoded());
- } else {
- cert = loadCertificate(certificate.get());
+ try {
+ CmsSignatureData signatureData = new CmsSignatureDataFactory().createForFirstSigner(cmsSignature, fileContent);
+ if( signatureData.getCertificate().isEmpty() ) {
+ signatureData.loadCertificate(certificate.orElseThrow(() -> new CmsSignatureValidatorException("No certificate found in cms signature and ETSI-Entry-Certificate doesn't exist")));
}
+ return verifySignedData(signatureData);
+ } catch ( CmsSignatureLoadingException e) {
+ throw new CmsSignatureValidatorException("Unexpected error occurred during signature validation!", e);
+ }
+ }
- return firstSigner.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert));
+ public boolean verifySignedData(final CmsSignatureData signatureData) throws CmsSignatureValidatorException {
+ try {
+ X509Certificate certificate = signatureData.getCertificate().orElseThrow(() -> new CMSException("No certificate found in signature data!"));
+ return signatureData.getSignerInformation().verify(new JcaSimpleSignerInfoVerifierBuilder().build(certificate));
} catch (CMSSignerDigestMismatchException e){
//message-digest attribute value does not match calculated value
LOG.warn("CMS signer digest mismatch.", e);
return false;
}
- catch (OperatorCreationException | IOException | CMSException e) {
+ catch (OperatorCreationException | CMSException e) {
throw new CmsSignatureValidatorException("Unexpected error occurred during signature validation!", e);
}
}
- private X509CertificateHolder getX509CertificateHolder(SignerInformation firstSigner, Store certificates) throws CmsSignatureValidatorException {
- Collection<X509CertificateHolder> firstSignerCertificates = certificates.getMatches(firstSigner.getSID());
- if(!firstSignerCertificates.iterator().hasNext()){
- throw new CmsSignatureValidatorException("No certificate found in cms signature that should contain one!");
- }
- return firstSignerCertificates.iterator().next();
- }
-
- private CMSSignedData getCMSSignedData(byte[] innerPackageFileCSAR, ByteArrayInputStream signatureStream) throws IOException, CmsSignatureValidatorException, CMSException {
- ContentInfo signature = produceSignature(signatureStream);
- CMSTypedData signedContent = new CMSProcessableByteArray(innerPackageFileCSAR);
- return new CMSSignedData(signedContent, signature);
- }
-
- private ContentInfo produceSignature(ByteArrayInputStream signatureStream) throws IOException, CmsSignatureValidatorException {
- Object parsedObject = new PEMParser(new InputStreamReader(signatureStream, Charset.defaultCharset())).readObject();
- if (!(parsedObject instanceof ContentInfo)) {
- throw new CmsSignatureValidatorException("Signature is not recognized!");
- }
- return ContentInfo.getInstance(parsedObject);
- }
-
-
- private X509Certificate loadCertificate(byte[] certFile) throws CmsSignatureValidatorException {
- try (InputStream in = new ByteArrayInputStream(certFile)) {
- CertificateFactory factory = CertificateFactory.getInstance("X.509");
- return (X509Certificate) factory.generateCertificate(in);
- } catch (CertificateException | IOException e) {
- throw new CmsSignatureValidatorException("Error during loading Certificate from bytes!", e);
- }
- }
-
-
}
diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java
index 75cd8de..1f708fd 100644
--- a/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java
+++ b/csarvalidation/src/main/java/org/onap/cvc/csar/security/CmsSignatureValidatorException.java
@@ -25,4 +25,5 @@ public class CmsSignatureValidatorException extends Exception {
public CmsSignatureValidatorException(String s, Throwable t) {
super(s, t);
}
+
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/CsarUtil.java b/csarvalidation/src/main/java/org/onap/validation/csar/CsarUtil.java
index c498479..7d48b06 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/CsarUtil.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/CsarUtil.java
@@ -28,133 +28,135 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Enumeration;
-
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-
-
-public class CsarUtil {
-
- private static final Logger logger = LoggerFactory.getLogger(CsarUtil.class);
-
- public static String getUnzipDir(String dirName) {
- File tmpDir = new File(File.separator + dirName);
- return tmpDir.getAbsolutePath().replace(".csar", "");
- }
-
- /**
- * unzip zip file.
- *
- * @param zipFileName
- * file name to zip
- * @param extPlace
- * extPlace
- * @return unzip file names in zip
- * @throws IOException
- * e1
- * @throws ValidationException
- */
- public static HashMap<String, String> unzip(String zipFileName, String extPlace) throws IOException {
- HashMap<String, String> unzipFileNames = new HashMap<>();
-
- try(ZipFile zipFile = new ZipFile(zipFileName)) {
-
- Enumeration<?> fileEn = zipFile.entries();
- byte[] buffer = new byte[CommonConstants.BUFFER_SIZE];
-
- while (fileEn.hasMoreElements()) {
- InputStream input = null;
- BufferedOutputStream bos = null;
- try {
- ZipEntry entry = (ZipEntry) fileEn.nextElement();
- if (entry.isDirectory()) {
- continue;
- }
-
- input = zipFile.getInputStream(entry);
- File file = new File(extPlace, entry.getName());
-
- //Currently it does not support xml based VNF descriptors.
- //So skip and proceed to YAML defined files validation only.
- if (file.getAbsolutePath().contains("xml"+System.getProperty("file.separator"))) {
- continue;
- }
-
- if (!file.getParentFile().exists()) {
- FileUtil.createDirectory(file.getParentFile().getAbsolutePath());
- }
-
- bos = new BufferedOutputStream(new FileOutputStream(file));
- while (true) {
- int length = input.read(buffer);
- if (length == -1) {
- break;
- }
- bos.write(buffer, 0, length);
- }
-
- unzipFileNames.put(file.getName(), file.getAbsolutePath());
-
- } finally {
- closeOutputStream(bos);
- closeInputStream(input);
- }
- }
- }
- return unzipFileNames;
- }
-
- /**
- * close InputStream.
- *
- * @param inputStream
- * the inputstream to close
- * @throws ValidationException
- */
- public static void closeInputStream(InputStream inputStream) {
- try {
- if (inputStream != null) {
- inputStream.close();
- }
- } catch (Exception e1) {
- logger.error("FILE_IO" + ":" + "close InputStream error! " +ErrorCodes.FILE_IO+" "+ e1.getMessage(), e1);
- throw new ValidationException(ErrorCodes.FILE_IO);
- }
- }
-
- /**
- * close OutputStream.
- *
- * @param outputStream
- * the output stream to close
- * @throws ValidationException
- */
- public static void closeOutputStream(OutputStream outputStream) {
- try {
- if (outputStream != null) {
- outputStream.close();
- }
- } catch (Exception e1) {
- logger.error("FILE_IO" + ":" + "close OutputStream error! " +ErrorCodes.FILE_IO, e1);
- throw new ValidationException(ErrorCodes.FILE_IO);
-
- }
- }
- /**
- *
- * @param filePath
- * @return HashMap<String, String>
- */
- public static HashMap<String, String> csarExtract(String filePath) {
-
- try {
- String tempfolder = CsarUtil.getUnzipDir(filePath);
- return CsarUtil.unzip(filePath, tempfolder);
-
- } catch (IOException e1) {
- logger.error("CSAR_EXTRACTION" + ":" + "CSAR extraction error ! " +ErrorCodes.FILE_IO+" "+ e1.getMessage(), e1);
- throw new ValidationException(ErrorCodes.FILE_IO);
- }
- }
+import java.util.Map;
+
+public final class CsarUtil {
+
+ private static final Logger logger = LoggerFactory.getLogger(CsarUtil.class);
+
+ private CsarUtil(){
+ //It is made private in order to resolve: Utility classes should not have public constructors
+ }
+ public static String getUnzipDir(String dirName) {
+ File tmpDir = new File(File.separator + dirName);
+ return tmpDir.getAbsolutePath().replace(".csar", "");
+ }
+
+ /**
+ * unzip zip file.
+ *
+ * @param zipFileName
+ * file name to zip
+ * @param extPlace
+ * extPlace
+ * @return unzip file names in zip
+ * @throws IOException
+ * e1
+ * @throws ValidationException
+ */
+ public static Map<String, String> unzip(String zipFileName, String extPlace) throws IOException {
+ HashMap<String, String> unzipFileNames = new HashMap<>();
+ InputStream input = null;
+ try(ZipFile zipFile = new ZipFile(zipFileName)) {
+
+ Enumeration<?> fileEn = zipFile.entries();
+ byte[] buffer = new byte[CommonConstants.BUFFER_SIZE];
+
+ while (fileEn.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) fileEn.nextElement();
+ if (entry.isDirectory()) {
+ continue;
+ }
+
+ input = zipFile.getInputStream(entry);
+ File file = new File(extPlace, entry.getName());
+
+ //Currently it does not support xml based VNF descriptors.
+ //So skip and proceed to YAML defined files validation only.
+ if (file.getAbsolutePath().contains("xml"+System.getProperty("file.separator"))) {
+ continue;
+ }
+
+ updateUnzipFileNames(input, buffer, unzipFileNames, file);
+ }
+ } finally {
+ closeInputStream(input);
+ }
+ return unzipFileNames;
+ }
+
+ private static void updateUnzipFileNames(InputStream input, byte[] buffer, HashMap<String, String> unzipFileNames, File file) throws IOException {
+ if (!file.getParentFile().exists()) {
+ FileUtil.createDirectory(file.getParentFile().getAbsolutePath());
+ }
+ try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+ while (true) {
+ int length = input.read(buffer);
+ if (length == -1) {
+ break;
+ }
+ bos.write(buffer, 0, length);
+ }
+
+ unzipFileNames.put(file.getName(), file.getAbsolutePath());
+ }
+ }
+
+ /**
+ * close InputStream.
+ *
+ * @param inputStream
+ * the inputstream to close
+ * @throws ValidationException
+ */
+ public static void closeInputStream(InputStream inputStream) {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (Exception e1) {
+ String errCodeMessage = ErrorCodes.FILE_IO+" "+ e1.getMessage();
+ logger.error("FILE_IO:close InputStream error! {} {}", errCodeMessage, e1);
+ throw new ValidationException(ErrorCodes.FILE_IO);
+ }
+ }
+
+ /**
+ * close OutputStream.
+ *
+ * @param outputStream
+ * the output stream to close
+ * @throws ValidationException
+ */
+ public static void closeOutputStream(OutputStream outputStream) {
+ try {
+ if (outputStream != null) {
+ outputStream.close();
+ }
+ } catch (Exception e1) {
+ logger.error("FILE_IO:close OutputStream error! {} {}", ErrorCodes.FILE_IO, e1);
+ throw new ValidationException(ErrorCodes.FILE_IO);
+
+ }
+ }
+ /**
+ *
+ * @param filePath
+ * @return HashMap<String, String>
+ */
+ public static Map<String, String> csarExtract(String filePath) {
+
+ try {
+ String tempfolder = CsarUtil.getUnzipDir(filePath);
+ return CsarUtil.unzip(filePath, tempfolder);
+
+ } catch (IOException e1) {
+ String errCodeMessage = ErrorCodes.FILE_IO+" "+ e1.getMessage();
+ logger.error("CSAR_EXTRACTION:CSAR extraction error ! {} {}", errCodeMessage, e1);
+ throw new ValidationException(ErrorCodes.FILE_IO);
+ }
+ }
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/CsarValidator.java b/csarvalidation/src/main/java/org/onap/validation/csar/CsarValidator.java
index e92f2b2..bc18f8e 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/CsarValidator.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/CsarValidator.java
@@ -49,14 +49,14 @@ public class CsarValidator {
private static ValidatorSchemaLoader vsl;
// Map of CSAR file and un-zipped file indices
- private static HashMap<String, String> csarFiles;
+ private static Map<String, String> csarFiles;
// Map of packageId and CSAR files
- private static HashMap<String, HashMap<String, String>> csar = new HashMap<>();
+ private static Map<String, Map<String, String>> csar = new HashMap<>();
- private static String MAINSERV_TEMPLATE = CommonConstants.MAINSERV_TEMPLATE;
+ private static String mainServiceTemplate = CommonConstants.MAINSERV_TEMPLATE;
- private static String MAINSERV_MANIFEST;
+ private static String mainServiceManifest;
/**
* @param packageId
@@ -65,10 +65,8 @@ public class CsarValidator {
*/
public CsarValidator(String packageId, String csarWithPath) throws IOException {
- try (FileInputStream is = new FileInputStream(csarWithPath)) {
-
- } catch(FileNotFoundException e2) {
- LOG.error(csarWithPath + ":CSAR is not found! " + ErrorCodes.RESOURCE_MISSING, e2);
+ if (!isCsarExist(csarWithPath)) {
+ LOG.error(csarWithPath + ":CSAR is not found! " + ErrorCodes.RESOURCE_MISSING);
throw new ValidationException(ErrorCodes.RESOURCE_MISSING,
"RESOURCE MISSING" + csarWithPath + ":CSAR is not found!");
}
@@ -80,8 +78,8 @@ public class CsarValidator {
LOG.debug("CSAR extracted sucessfully.");
}
} catch(Exception e1) {
- LOG.error("INVALID_CSAR_CONTENT" + ":" + csarWithPath + ": CSAR is not a valid CSAR/ZIP file! "
- + ErrorCodes.INVALID_CSAR_CONTENT, e1);
+ LOG.error("INVALID_CSAR_CONTENT:{}: CSAR is not a valid CSAR/ZIP file! {} {}",
+ csarWithPath, ErrorCodes.INVALID_CSAR_CONTENT, e1);
throw new ValidationException(ErrorCodes.INVALID_CSAR_CONTENT,
"INVALID_CSAR_CONTENT" + ":" + csarWithPath + ": CSAR is not a valid CSAR/ZIP file! ");
}
@@ -89,40 +87,50 @@ public class CsarValidator {
try {
vsl = new ValidatorSchemaLoader();
} catch(Exception e) {
- LOG.error(
- "SCHEMA_LOAD_ERROR" + ":" + "CSAR schema is not loaded correctly! " + ErrorCodes.SCHEMA_LOAD_ERROR,
- e);
+ LOG.error("SCHEMA_LOAD_ERROR:CSAR schema is not loaded correctly! {} {}", ErrorCodes.SCHEMA_LOAD_ERROR, e);
throw new ValidationException(ErrorCodes.SCHEMA_LOAD_ERROR,
"SCHEMA_LOAD_ERROR" + ":" + "CSAR schema is not loaded correctly! ");
}
}
+ static class CsarValidatorSeam {
+ public String validateCsarMeta() {
+ return CsarValidator.validateCsarMeta();
+ }
+
+ public String validateAndScanToscaMeta(){
+ return CsarValidator.validateAndScanToscaMeta();
+ }
+
+ public String validateMainService() {
+ return CsarValidator.validateMainService();
+ }
+
+ }
+
/**
* @return true if all validations are successful
*/
public static String validateCsar() {
+ return CsarValidator.validateCsarContent(new CsarValidatorSeam());
+ }
- String vsm = validateCsarMeta();
+ static String validateCsarContent(CsarValidatorSeam csarValidatorSeam) {
- String vtm = validateAndScanToscaMeta();
+ String vsm = csarValidatorSeam.validateCsarMeta();
- String vms = validateMainService();
+ String vtm = csarValidatorSeam.validateAndScanToscaMeta();
- //String r02454 = r02454();
+ String vms = csarValidatorSeam.validateMainService();
- if((CommonConstants.SUCCESS_STR != vsm) && (CommonConstants.SUCCESS_STR != vms)) {
+ if((!CommonConstants.SUCCESS_STR.equals(vsm)) && (!CommonConstants.SUCCESS_STR.equals(vms))) {
return vsm + " OR " + vms;
}
- if(CommonConstants.SUCCESS_STR != vtm) {
+ if(!CommonConstants.SUCCESS_STR.equals(vtm)) {
return vtm;
}
-/*
- if (CommonConstants.SUCCESS_STR != r02454) {
- return r02454;
- }
-*/
return CommonConstants.SUCCESS_STR;
}
@@ -134,23 +142,32 @@ public class CsarValidator {
try {
RandomAccessFile raf = new RandomAccessFile(csarWithPath, "r");
- try {
- long n = raf.readInt();
+ return checkCsarIntegrity(raf);
+ } catch(IOException e1) {
+ LOG.error("CSAR %s is not a valid CSAR/ZIP file! ", e1);
+ return false;
+ }
+ }
- // Check for the CSAR's integrity
- if(n != 0x504B0304) {
- LOG.error("CSAR %s contents are not a valid! ");
- return false;
- }
- } catch(FileNotFoundException e1) {
- LOG.error("CSAR %s is not a valid CSAR/ZIP file! ", e1);
+ /**
+ * @param raf
+ * @throws IOException
+ */
+ private static boolean checkCsarIntegrity(RandomAccessFile raf) throws IOException {
+
+ try {
+ long n = raf.readInt();
+
+ // Check for the CSAR's integrity
+ if (n != 0x504B0304) {
+ LOG.error("CSAR %s contents are not a valid! ");
return false;
- } finally {
- raf.close();
}
- } catch(IOException e1) {
+ } catch (FileNotFoundException e1) {
LOG.error("CSAR %s is not a valid CSAR/ZIP file! ", e1);
return false;
+ } finally {
+ raf.close();
}
return true;
}
@@ -192,7 +209,6 @@ public class CsarValidator {
}
}
}
- reader.close();
return CommonConstants.SUCCESS_STR;
}
} catch(IOException e2) {
@@ -220,14 +236,14 @@ public class CsarValidator {
}
try {
- MAINSERV_MANIFEST = checkAndGetMRF(cfile, "Entry-Manifest");
- if(MAINSERV_MANIFEST == null) {
- MAINSERV_MANIFEST = CommonConstants.MAINSERV_MANIFEST;
+ mainServiceManifest = checkAndGetMRF(cfile, "Entry-Manifest");
+ if(mainServiceManifest == null) {
+ mainServiceManifest = CommonConstants.MAINSERV_MANIFEST;
}
- MAINSERV_TEMPLATE = checkAndGetMRF(cfile, "Entry-Definitions");
- if(MAINSERV_TEMPLATE == null) {
- MAINSERV_TEMPLATE = CommonConstants.MAINSERV_TEMPLATE;
+ mainServiceTemplate = checkAndGetMRF(cfile, "Entry-Definitions");
+ if(mainServiceTemplate == null) {
+ mainServiceTemplate = CommonConstants.MAINSERV_TEMPLATE;
}
return CommonConstants.SUCCESS_STR;
@@ -256,8 +272,7 @@ public class CsarValidator {
}
}
} catch(IOException | NullPointerException e) {
- LOG.error("CSAR_TOSCA_VALIDATION" + ":" + "Could not read file %s ! " + ErrorCodes.FILE_IO + " "
- + ErrorCodes.RESOURCE_MISSING, e);
+ LOG.error("CSAR_TOSCA_VALIDATION:Could not read file {} {} ! {}", ErrorCodes.FILE_IO, ErrorCodes.RESOURCE_MISSING, e);
throw new ValidationException(ErrorCodes.RESOURCE_MISSING);
}
@@ -276,9 +291,9 @@ public class CsarValidator {
Arrays.asList("vnf_product_name", "vnf_provider_id", "vnf_package_version", "vnf_release_data_time");
@SuppressWarnings("unused")
- boolean mfResult = checkEntryFor(CommonConstants.MAINSERV_MANIFEST, mListMetadata, key);
+ boolean mfResult = checkEntryFor(CommonConstants.MAINSERV_MANIFEST, mListMetadata, key); //NOSONAR
- String mainServManifest = MAINSERV_MANIFEST;
+ String mainServManifest = mainServiceManifest;
if(!Paths.get(mainServManifest).isAbsolute()) {
mainServManifest = csarFiles.get(FilenameUtils.getName(mainServManifest));
}
@@ -287,8 +302,8 @@ public class CsarValidator {
// Do nothing for Rel-1
}
- String mainservTemplate = MAINSERV_TEMPLATE;
- if(!Paths.get(MAINSERV_TEMPLATE).isAbsolute()) {
+ String mainservTemplate = mainServiceTemplate;
+ if(!Paths.get(mainServiceTemplate).isAbsolute()) {
mainservTemplate = csarFiles.get(FilenameUtils.getName(mainservTemplate));
}
@@ -306,10 +321,10 @@ public class CsarValidator {
* @return: boolean
**/
public static String r02454() {
- String mainservTemplate = MAINSERV_TEMPLATE;
+ String mainservTemplate = mainServiceTemplate;
mainservTemplate = csarFiles.get(FilenameUtils.getName(mainservTemplate));
- //TODO: Fixme R3 only check the existence of swImage filed inside VNFD.
+ //TODO: Fixme R3 only check the existence of swImage filed inside VNFD. //NOSONAR
File file = new File(mainservTemplate);
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String tempString = null;
@@ -345,8 +360,6 @@ public class CsarValidator {
@SuppressWarnings("unchecked")
private static boolean checkEntryFor(String cFile, List<String> attributes, String key) {
- @SuppressWarnings("unused")
- String tFileWithPath;
if(!Paths.get(cFile).isAbsolute()) {
cFile = csarFiles.get(FilenameUtils.getName(cFile));
@@ -358,14 +371,16 @@ public class CsarValidator {
Yaml yaml = new Yaml();
Map<String, ?> values;
+ String exceptionMessage;
try (InputStream input = new FileInputStream(new File(cFile))) {
values = (Map<String, ?>)yaml.load(input);
} catch(FileNotFoundException e) {
- LOG.error("FILE_NOT_FOUND" + ":" + "Exception caught while trying to find the file ! " + e.getMessage(), e);
+ exceptionMessage = e.getMessage();
+ LOG.error("FILE_NOT_FOUND:Exception caught while trying to find the file ! {} {}", exceptionMessage, e);
return false;
} catch(IOException e1) {
- LOG.error("FILE_NOT_FOUND" + ":" + "Exception caught while trying to open the file ! " + e1.getMessage(),
- e1);
+ exceptionMessage = e1.getMessage();
+ LOG.error("FILE_NOT_FOUND:Exception caught while trying to open the file ! {} {}", exceptionMessage, e1);
return false;
}
@@ -403,7 +418,6 @@ public class CsarValidator {
if(StringUtils.isEmpty(cfile)) {
return false;
} else {
- File file = new File(cfile);
Yaml yaml = new Yaml();
@@ -411,9 +425,9 @@ public class CsarValidator {
try (InputStream input = new FileInputStream(new File(cfile))) {
toscaMeta = (Map<String, ?>)yaml.load(input);
} catch(FileNotFoundException e) {
- LOG.error("CSAR_TOSCA_LOAD" + ":" + "TOSCA metadata is not loaded by Yaml! " + ErrorCodes.FILE_IO, e);
+ LOG.error("CSAR_TOSCA_LOAD:TOSCA metadata is not loaded by Yaml! {} {}", ErrorCodes.FILE_IO, e);
} catch(IOException e1) {
- LOG.error("CSAR_TOSCA_LOAD" + ":" + "TOSCA metadata is not loaded by Yaml! " + ErrorCodes.FILE_IO, e1);
+ LOG.error("CSAR_TOSCA_LOAD:TOSCA metadata is not loaded by Yaml! {} {}", ErrorCodes.FILE_IO, e1);
}
if(toscaMeta != null) {
return toscaMeta.keySet().containsAll((vsl.getToscaMeta().keySet()));
@@ -422,19 +436,23 @@ public class CsarValidator {
}
}
- public static HashMap<String, HashMap<String, String>> getCsar() {
+ public static Map<String, Map<String, String>> getCsar() {
return csar;
}
- public static void setCsar(HashMap<String, HashMap<String, String>> csar) {
+ public static void setCsar(Map<String, Map<String, String>> csar) {
CsarValidator.csar = csar;
}
- public static HashMap<String, String> getCsarFiles() {
+ public static Map<String, String> getCsarFiles() {
return csarFiles;
}
- public static void setCsarFiles(HashMap<String, String> csarFiles) {
+ public static void setCsarFiles(Map<String, String> csarFiles) {
CsarValidator.csarFiles = csarFiles;
}
+
+ public static boolean isCsarExist(String csarWithPath){
+ return new File(csarWithPath).exists();
+ }
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/FileUtil.java b/csarvalidation/src/main/java/org/onap/validation/csar/FileUtil.java
index f7471bd..ccf1c71 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/FileUtil.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/FileUtil.java
@@ -23,13 +23,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipFile;
-
+import java.nio.file.Files;
+import java.nio.file.Paths;
public final class FileUtil {
public static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
private static final int TRY_COUNT = 3;
+ public static final String FILE_IO_STR = "FILE_IO";
private FileUtil() {
@@ -46,9 +48,7 @@ public final class FileUtil {
int tryCount = 0;
while (tryCount < TRY_COUNT) {
tryCount++;
- if (!folder.exists() && !folder.mkdirs()) {
- continue;
- } else {
+ if (folder.exists() || folder.mkdirs()) {
return true;
}
}
@@ -65,15 +65,16 @@ public final class FileUtil {
String hintInfo = file.isDirectory() ? "dir " : "file ";
boolean isFileDeleted = file.delete();
boolean isFileExist = file.exists();
+ String fileAbsolutePath = file.getAbsolutePath();
if (!isFileExist) {
if (isFileDeleted) {
- logger.info("delete " + hintInfo + file.getAbsolutePath());
+ logger.info("delete {}{}", hintInfo, fileAbsolutePath);
} else {
isFileDeleted = true;
- logger.info("file not exist. no need delete " + hintInfo + file.getAbsolutePath());
+ logger.info("file not exist. no need delete {}{}", hintInfo, fileAbsolutePath);
}
} else {
- logger.info("fail to delete " + hintInfo + file.getAbsolutePath());
+ logger.info("fail to delete {}{}", hintInfo, fileAbsolutePath);
}
return isFileDeleted;
@@ -92,7 +93,8 @@ public final class FileUtil {
inputStream.close();
}
} catch (Exception e1) {
- logger.error("FILE_IO" + ":" + "close InputStream error! "+ErrorCodes.FILE_IO+ " " + e1.getMessage(), e1);
+ String errCodeMessage = ErrorCodes.FILE_IO+ " " + e1.getMessage();
+ logger.error("FILE_IO:close InputStream error! {}{}", errCodeMessage, e1);
throw new ValidationException(ErrorCodes.FILE_IO);
}
}
@@ -109,7 +111,8 @@ public final class FileUtil {
outputStream.close();
}
} catch (Exception e1) {
- logger.error("FILE_IO" + ":" + "close OutputStream error! "+ErrorCodes.FILE_IO+ " " + e1.getMessage(), e1);
+ String errCodeMessage = ErrorCodes.FILE_IO+ " " + e1.getMessage();
+ logger.error("FILE_IO:close OutputStream error! {}{}", errCodeMessage, e1);
throw new ValidationException(ErrorCodes.FILE_IO);
}
}
@@ -120,7 +123,8 @@ public final class FileUtil {
ifs.close();
}
} catch (Exception e1) {
- logger.error("FILE_IO" + ":" + "close OutputStream error! "+ErrorCodes.FILE_IO+ " " + e1.getMessage(), e1);
+ String errCodeMessage = ErrorCodes.FILE_IO+ " " + e1.getMessage();
+ logger.error("FILE_IO:close OutputStream error! {}{}", errCodeMessage, e1);
throw new ValidationException(ErrorCodes.FILE_IO);
}
}
@@ -137,7 +141,8 @@ public final class FileUtil {
zipFile.close();
}
} catch (IOException e1) {
- logger.error("CLOSE_ZIPFILE" + ":" + "close ZipFile error! "+ErrorCodes.FILE_IO+ " " + e1.getMessage(), e1);
+ String errCodeMessage = ErrorCodes.FILE_IO+ " " + e1.getMessage();
+ logger.error("CLOSE_ZIPFILE:close ZipFile error! {}{}", errCodeMessage, e1);
throw new ValidationException(ErrorCodes.FILE_IO);
}
}
@@ -172,6 +177,13 @@ public final class FileUtil {
deleteDirectory(f);
}
}
- return file.delete();
+ boolean isFileDeleted=false;
+ try {
+ Files.delete(Paths.get(file.getPath()));
+ isFileDeleted=true;
+ } catch (IOException e) {
+ logger.error("fail to delete {} {} ", file.getAbsolutePath(), ", exception :: ", e);
+ }
+ return isFileDeleted;
}
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/VTPValidateCSAR.java b/csarvalidation/src/main/java/org/onap/validation/csar/VTPValidateCSAR.java
index b97b488..1624e46 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/VTPValidateCSAR.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/VTPValidateCSAR.java
@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
*/
@OnapCommandSchema(schema = "vtp-validate-csar-casablanca.yaml")
public class VTPValidateCSAR extends OnapCommand {
- private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSAR.class);
+ private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSAR.class); //NOSONAR
@Override
protected void run() throws OnapCommandException {
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/ValidationException.java b/csarvalidation/src/main/java/org/onap/validation/csar/ValidationException.java
index 7c124d7..ac4c1eb 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/ValidationException.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/ValidationException.java
@@ -36,7 +36,7 @@ public class ValidationException extends RuntimeException {
return wrappedInfo(exception, null);
}
- public ValidationException(ErrorCodes errCode, String message) {
+ public ValidationException(ErrorCodes errCode, String message) { //NOSONAR
super(message);
}
@@ -58,7 +58,8 @@ public class ValidationException extends RuntimeException {
super(message, cause);
this.errorCode = errorCode;
}
-
+
+ @Override
public String toString(){
return ("Exception Number = "+errorMessage) ;
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/csar/ValidatorSchemaLoader.java b/csarvalidation/src/main/java/org/onap/validation/csar/ValidatorSchemaLoader.java
index 0ed0bdc..b96275f 100644
--- a/csarvalidation/src/main/java/org/onap/validation/csar/ValidatorSchemaLoader.java
+++ b/csarvalidation/src/main/java/org/onap/validation/csar/ValidatorSchemaLoader.java
@@ -22,7 +22,6 @@ import java.io.*;
import java.net.URISyntaxException;
import java.util.*;
import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.scanner.ScannerException;
public class ValidatorSchemaLoader {
@@ -31,13 +30,13 @@ public class ValidatorSchemaLoader {
private static final Logger LOG = LoggerFactory.getLogger(ValidatorSchemaLoader.class);
// Map of Schema files
- private Map<String, ?> toscaMeta;
+ private Map<String, Object> toscaMeta;
- private Map<String, ?> csarentryd;
+ private Map<String, Object> csarentryd;
- private Map<String, ?> mrfYaml;
+ private Map<String, Object> mrfYaml;
- private Map<String, ?> mrfManifest;
+ private Map<String, Object> mrfManifest;
// List of configured schemas
static List<String> schemaFileList = new ArrayList<>();
@@ -47,28 +46,18 @@ public class ValidatorSchemaLoader {
static HashMap<String, String> optionTwoSchema;
- private String schemaFolder;
-
public ValidatorSchemaLoader() {
- try {
loadResources();
- } catch(FileNotFoundException e1) {
- LOG.error("Schema file not found or schema repository corrupted", e1);
-
- } catch(URISyntaxException e) {
- // TODO Auto-generated catch block
- LOG.error("Illegal character in query at index", e);
- }
}
- private Map<String, ?> readYaml(String fileName) {
+ private Map<String, Object> readYaml(String fileName) {
Yaml yaml = new Yaml();
- return (Map<String, ?>)yaml.load(this.getClass().getResourceAsStream(fileName));
+ return (Map<String, Object>)yaml.load(this.getClass().getResourceAsStream(fileName));
}
@SuppressWarnings("unchecked")
- private boolean loadResources() throws FileNotFoundException, URISyntaxException {
+ private boolean loadResources() {
for (String metaFile: new String []{"TOSCA.meta", "CSAR.meta", "MRF.mf" }) {
switch(metaFile) {
case "TOSCA.meta":
@@ -88,19 +77,19 @@ public class ValidatorSchemaLoader {
return true;
}
- public Map<String, ?> getToscaMeta() {
+ public Map<String, Object> getToscaMeta() {
return toscaMeta;
}
- public Map<String, ?> getCsarentryd() {
+ public Map<String, Object> getCsarentryd() {
return csarentryd;
}
- public Map<String, ?> getMrfYaml() {
+ public Map<String, Object> getMrfYaml() {
return mrfYaml;
}
- public Map<String, ?> getMrfManifest() {
+ public Map<String, Object> getMrfManifest() {
return mrfManifest;
}
}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/YamlFileValidator.java b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlFileValidator.java
new file mode 100644
index 0000000..2de4f48
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlFileValidator.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class YamlFileValidator {
+
+ private static final int FIRST_DOCUMENT_INDEX = 1;
+
+ public List<YamlDocumentValidationError> validateYamlFileWithSchema(String pathToFile)
+ throws YamlProcessingException {
+
+ List<YamlDocument> documents = new YamlLoader().loadMultiDocumentYamlFile(pathToFile);
+ if(!documents.isEmpty()) {
+ return validateDocuments(documents);
+ } else {
+ throw new YamlProcessingException("PM_Dictionary YAML file is empty");
+ }
+ }
+
+ private List<YamlDocumentValidationError> validateDocuments(List<YamlDocument> documents)
+ throws YamlProcessingException {
+
+ List<YamlDocumentValidationError> yamlFileValidationErrors = new ArrayList<>();
+ YamlSchema schema = extractSchema(documents);
+ YamlValidator validator = new YamlValidator(schema);
+
+ for (int index = FIRST_DOCUMENT_INDEX; index < documents.size(); index++) {
+ List<SchemaValidationError> validationErrors = validator.validate(documents.get(index));
+ yamlFileValidationErrors.addAll(transformErrors(index,validationErrors));
+ }
+
+ return yamlFileValidationErrors;
+ }
+
+ private List<YamlDocumentValidationError> transformErrors(int index, List<SchemaValidationError> validationErrors) {
+ return validationErrors
+ .stream()
+ .map(error->new YamlDocumentValidationError(index, error.getPath(), error.getMessage()))
+ .collect(Collectors.toList());
+ }
+
+ private YamlSchema extractSchema(List<YamlDocument> documents) throws YamlProcessingException {
+ return new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java
new file mode 100644
index 0000000..1a5eef9
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+class YamlLoader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(YamlLoader.class);
+
+ List<YamlDocument> loadMultiDocumentYamlFile(URL path)
+ throws YamlDocumentFactory.YamlDocumentParsingException {
+ List<YamlDocument> documentsFromFile = new ArrayList<>();
+ try (InputStream yamlStream = path.openStream()) {
+ for (Object yamlDocument : new Yaml().loadAll(yamlStream)) {
+ documentsFromFile.add(
+ new YamlDocumentFactory().createYamlDocument(yamlDocument)
+ );
+ }
+ } catch (IOException e) {
+ LOGGER.error("Failed to load multi document YAML file",e);
+ }
+ return documentsFromFile;
+ }
+
+ List<YamlDocument> loadMultiDocumentYamlFile(String path)
+ throws YamlProcessingException {
+ try {
+ return loadMultiDocumentYamlFile(new URL("file://" + path));
+ } catch (MalformedURLException e) {
+ throw new YamlProcessingException("Fail to read file under given path.", e);
+ }
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java
new file mode 100644
index 0000000..9430df4
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.process.YamlValidationProcess;
+import org.onap.validation.yaml.schema.YamlSchema;
+
+import java.util.List;
+
+public class YamlValidator {
+
+ private final YamlSchema schema;
+
+ YamlValidator(YamlSchema schema) {
+ this.schema = schema;
+ }
+
+ public List<SchemaValidationError> validate(YamlDocument document) throws YamlProcessingException {
+ return new YamlValidationProcess(schema,document).validate();
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java b/csarvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java
new file mode 100644
index 0000000..6ffe6d4
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.error;
+
+public class SchemaValidationError {
+ private final String path;
+ private final String message;
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public SchemaValidationError(String path, String message) {
+ this.path = path;
+ this.message = message;
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java b/csarvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java
new file mode 100644
index 0000000..f04708f
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.error;
+
+public class YamlDocumentValidationError {
+ private final int yamlDocumentNumber;
+ private final String path;
+ private final String message;
+
+ public YamlDocumentValidationError(int yamlDocumentNumber, String path, String message) {
+ this.yamlDocumentNumber = yamlDocumentNumber;
+ this.path = path;
+ this.message = message;
+ }
+
+ public int getYamlDocumentNumber() {
+ return yamlDocumentNumber;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java b/csarvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java
new file mode 100644
index 0000000..99c2437
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.exception;
+
+public class YamlProcessingException extends Exception {
+
+ public YamlProcessingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+ public YamlProcessingException(String message) {
+ super(message);
+ }
+
+ public YamlProcessingException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java
new file mode 100644
index 0000000..557b6fd
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.Map;
+
+public class YamlDocument {
+
+ private final Map<String, Object> yaml;
+
+ YamlDocument(Map<String, Object> yaml) {
+ this.yaml = yaml;
+ }
+
+ public Map<String, Object> getYaml() {
+ return yaml;
+ }
+
+ public boolean containsKey(String key) {
+ return yaml.containsKey(key);
+ }
+
+ public String getValue(String key) {
+ return yaml.get(key).toString();
+ }
+
+ public YamlParametersList getListOfValues(String key) {
+ return new YamlParameterListFactory().createYamlParameterList(
+ yaml.get(key)
+ );
+ }
+
+ public YamlDocument getSubStructure(String name)
+ throws YamlDocumentFactory.YamlDocumentParsingException {
+ return new YamlDocumentFactory().createYamlDocument(
+ yaml.get(name)
+ );
+ }
+}
+
+
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java
new file mode 100644
index 0000000..b56422c
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class YamlDocumentFactory {
+
+ public YamlDocument createYamlDocument(Object yaml) throws YamlDocumentParsingException {
+ try {
+ Map<String, Object> parsedYaml = transformMap((Map) yaml);
+ return new YamlDocument(parsedYaml);
+ } catch (ClassCastException e) {
+ throw new YamlDocumentParsingException(
+ String.format("Fail to parse given objects: %s as yaml document.", yaml), e
+ );
+ }
+ }
+
+ private Map<String, Object> transformMap(Map<Object, Object> yaml) {
+ Map<String, Object> parsedYaml = new HashMap<>();
+ for (Map.Entry<Object, Object> entry: yaml.entrySet()) {
+ parsedYaml.put(entry.getKey().toString(), entry.getValue());
+ }
+ return parsedYaml;
+ }
+
+ public static class YamlDocumentParsingException extends YamlProcessingException {
+ YamlDocumentParsingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java
new file mode 100644
index 0000000..5f41c5c
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class YamlParameterListFactory {
+
+ public YamlParametersList createEmptyYamlParameterList() {
+ return new YamlParametersList(Collections.emptyList());
+ }
+
+ public YamlParametersList createYamlParameterList(Object yaml) {
+ List<String> parametersList = new ArrayList<>();
+ if( yaml instanceof List) {
+ for (Object element : (List) yaml) {
+ parametersList.add(element.toString());
+ }
+ } else {
+ parametersList.add(yaml.toString());
+ }
+ return new YamlParametersList(parametersList);
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java
new file mode 100644
index 0000000..2b93c74
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.List;
+
+public class YamlParametersList {
+
+ private final List<String> parameters;
+
+ YamlParametersList(List<String> parameters) {
+ this.parameters = parameters;
+ }
+
+ public List<String> getParameters() {
+ return parameters;
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java b/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java
new file mode 100644
index 0000000..273014b
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+public class YamlValidationProcess {
+
+ private final Queue<YamlValidationStep> validationSteps;
+ private final List<SchemaValidationError> errors;
+ private final YamlSchema schema;
+ private final YamlDocument document;
+
+ public YamlValidationProcess(YamlSchema schema, YamlDocument document) {
+ this.schema = schema;
+ this.document = document;
+ errors = new ArrayList<>();
+ validationSteps = new LinkedList<>();
+ }
+
+ public List<SchemaValidationError> validate() throws YamlProcessingException {
+ validationSteps.add(new YamlValidationStep(schema.getRootNodes(), document));
+ while (!validationSteps.isEmpty()) {
+ YamlValidationStep nextValidationNode = validationSteps.poll();
+ validateStep(nextValidationNode);
+ }
+ return errors;
+ }
+
+ private void validateStep(YamlValidationStep validationNode)
+ throws YamlProcessingException {
+ for (YamlSchemaNode schemaNode : validationNode.getSchemaNodes()) {
+ validateNode(validationNode.getDocument(), schemaNode);
+ }
+ }
+
+ private void validateNode(YamlDocument document, YamlSchemaNode schemaNode)
+ throws YamlProcessingException {
+
+ if (document.containsKey(schemaNode.getName())) {
+ if (schemaNode.isContainingSubStructure()) {
+ addNextLevelNodeToValidationNodesQueue(document, schemaNode);
+ } else if (!isValueOfNodeInAcceptedValuesList(document, schemaNode)) {
+ addIncorrectValueError(document, schemaNode);
+ }
+ } else if (schemaNode.isRequired()) {
+ addRequiredKeyNotFoundError(schemaNode);
+ }
+ }
+
+ private boolean isValueOfNodeInAcceptedValuesList(YamlDocument document, YamlSchemaNode node) {
+ return node.getAcceptedValues().isEmpty() ||
+ node.getAcceptedValues().containsAll(
+ document.getListOfValues(node.getName()).getParameters()
+ );
+ }
+
+ private void addNextLevelNodeToValidationNodesQueue(YamlDocument document, YamlSchemaNode node)
+ throws YamlProcessingException {
+ validationSteps.add(
+ new YamlValidationStep(
+ node.getNextNodes(),
+ document.getSubStructure(node.getName())
+ )
+ );
+ }
+
+ private void addRequiredKeyNotFoundError(YamlSchemaNode node) {
+ errors.add(
+ new SchemaValidationError(
+ node.getPath(),
+ String.format("Key not found: %s", node.getName())
+ )
+ );
+ }
+
+ private void addIncorrectValueError(YamlDocument document, YamlSchemaNode node) {
+ errors.add(
+ new SchemaValidationError(
+ node.getPath() + node.getName(),
+ String.format(
+ "Value(s) is/are not in array of accepted values.%n value(s): %s%n accepted value(s): %s",
+ document.getValue(node.getName()), node.getAcceptedValues())
+ )
+ );
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java b/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java
new file mode 100644
index 0000000..eb5ab8e
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+class YamlValidationStep {
+
+ private final List<YamlSchemaNode> schemaNodes;
+ private final YamlDocument document;
+
+ YamlValidationStep(List<YamlSchemaNode> nodes, YamlDocument yaml) {
+ this.schemaNodes = new ArrayList<>(nodes);
+ this.document = yaml;
+ }
+
+ List<YamlSchemaNode> getSchemaNodes() {
+ return Collections.unmodifiableList(schemaNodes);
+ }
+
+ YamlDocument getDocument() {
+ return document;
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java
new file mode 100644
index 0000000..69bb6cd
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema;
+
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class YamlSchema {
+
+ private final List<YamlSchemaNode> rootNodes;
+
+ public List<YamlSchemaNode> getRootNodes() {
+ return Collections.unmodifiableList(rootNodes);
+ }
+
+ YamlSchema(List<YamlSchemaNode> rootNodes) {
+ this.rootNodes = new ArrayList<>(rootNodes);
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java
new file mode 100644
index 0000000..df7d673
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.onap.validation.yaml.schema;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+import org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class YamlSchemaFactory {
+
+
+ private static final String ROOT_PATH = "/";
+
+ public YamlSchema createTreeStructuredYamlSchema(YamlDocument schema)
+ throws YamlProcessingException {
+
+ return new YamlSchema(getRootNodes(schema));
+ }
+
+ private List<YamlSchemaNode> getRootNodes(YamlDocument yamlDocument)
+ throws YamlProcessingException {
+
+ List<YamlSchemaNode> nextNodes = new ArrayList<>();
+ for(String nodeName: yamlDocument.getYaml().keySet()) {
+ nextNodes.add(
+ new YamlSchemaNodeFactory().createNode(
+ nodeName,
+ ROOT_PATH,
+ new YamlDocumentFactory().createYamlDocument(
+ yamlDocument.getYaml().get(nodeName)
+ )
+ )
+ );
+ }
+ return nextNodes;
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java
new file mode 100644
index 0000000..0f5b480
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class YamlSchemaBranchNode extends YamlSchemaNode {
+
+ private final YamlDocument nextNodesInLazyForm;
+ private Optional<List<YamlSchemaNode>> nextNodes;
+
+ YamlSchemaBranchNode(String name, String path, boolean required, String comment,
+ YamlDocument nextNodesInLazyForm) {
+ super(name, path, required, comment);
+ this.nextNodesInLazyForm = nextNodesInLazyForm;
+ this.nextNodes = Optional.empty();
+ }
+
+ @Override
+ public boolean isContainingSubStructure() {
+ return true;
+ }
+
+ @Override
+ public List<String> getAcceptedValues() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public synchronized List<YamlSchemaNode> getNextNodes() throws YamlSchemaProcessingException {
+ try {
+ return nextNodes.orElseGet(this::loadNextNodes);
+ } catch (YamlSchemaLazyLoadingException lazyLoadingException) {
+ throw new YamlSchemaProcessingException(lazyLoadingException);
+ }
+ }
+
+ private List<YamlSchemaNode> loadNextNodes() {
+ try {
+ List<YamlSchemaNode> loadedNextNodes = new ArrayList<>();
+ for (String key : nextNodesInLazyForm.getYaml().keySet()) {
+ YamlDocument substructure = new YamlDocumentFactory()
+ .createYamlDocument(nextNodesInLazyForm.getYaml().get(key));
+ loadedNextNodes.add(new YamlSchemaNodeFactory().createNode(key, getPath() + getName() + "/", substructure));
+ }
+ nextNodes = Optional.of(loadedNextNodes);
+ return loadedNextNodes;
+ } catch (YamlProcessingException e) {
+ throw new YamlSchemaLazyLoadingException("Lazy loading failed, due to yaml parsing exception.",e);
+ }
+ }
+
+ static class YamlSchemaLazyLoadingException extends RuntimeException {
+ YamlSchemaLazyLoadingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java
new file mode 100644
index 0000000..c98f41e
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.model.YamlParametersList;
+
+import java.util.Collections;
+import java.util.List;
+
+public class YamlSchemaLeafNode extends YamlSchemaNode {
+
+ private final YamlParametersList acceptedValues;
+
+ YamlSchemaLeafNode(String name, String path, boolean required, String comment,
+ YamlParametersList acceptedValues) {
+ super(name, path, required, comment);
+ this.acceptedValues = acceptedValues;
+ }
+
+ @Override
+ public List<String> getAcceptedValues() {
+ return acceptedValues.getParameters();
+ }
+
+ @Override
+ public List<YamlSchemaNode> getNextNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isContainingSubStructure() {
+ return false;
+ }
+
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java
new file mode 100644
index 0000000..28913a2
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+
+import java.util.List;
+
+public abstract class YamlSchemaNode {
+
+ private final String path;
+ private final String name;
+ private final boolean required;
+ private final String comment;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public abstract List<String> getAcceptedValues();
+
+ public abstract List<YamlSchemaNode> getNextNodes() throws YamlSchemaProcessingException;
+
+ public abstract boolean isContainingSubStructure();
+
+ public String getComment() {
+ return comment;
+ }
+
+ YamlSchemaNode(String name, String path, boolean required, String comment) {
+ this.name = name;
+ this.path = path;
+ this.required = required;
+ this.comment = comment;
+ }
+
+ static class YamlSchemaProcessingException extends YamlProcessingException {
+ YamlSchemaProcessingException(Throwable throwable) {
+ super(throwable);
+ }
+ }
+}
diff --git a/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java
new file mode 100644
index 0000000..79a8f14
--- /dev/null
+++ b/csarvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.onap.validation.yaml.model.YamlParameterListFactory;
+import org.onap.validation.yaml.model.YamlParametersList;
+
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+public class YamlSchemaNodeFactory {
+
+ public static final String EMPTY_COMMENT = "no comment available";
+ static final String STRUCTURE_KEY = "structure";
+ static final String COMMENT_KEY = "comment";
+ static final String VALUE_KET = "value";
+ static final String PRESENCE_KEY = "presence";
+ static final String PRESENCE_REQUIRED_KEY = "required";
+
+ public YamlSchemaNode createNode(String nodeName, String path, YamlDocument yamlDocument)
+ throws YamlProcessingException {
+
+ YamlSchemaNode yamlSchemaNode;
+ if(isYamlContainingKey(yamlDocument, STRUCTURE_KEY)) {
+ yamlSchemaNode = new YamlSchemaBranchNode(
+ nodeName, path, getIsPresenceRequired(yamlDocument), getComment(yamlDocument),
+ getNextNodes(yamlDocument)
+ );
+ } else {
+ yamlSchemaNode = new YamlSchemaLeafNode(
+ nodeName, path, getIsPresenceRequired(yamlDocument), getComment(yamlDocument),
+ getAcceptedValues(yamlDocument)
+ );
+ }
+ return yamlSchemaNode;
+ }
+
+ private YamlDocument getNextNodes(YamlDocument yamlDocument)
+ throws YamlDocumentParsingException {
+ return new YamlDocumentFactory().createYamlDocument(yamlDocument.getYaml().get(STRUCTURE_KEY));
+ }
+
+ private String getComment(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, COMMENT_KEY)
+ ? yamlDocument.getYaml().get(COMMENT_KEY).toString()
+ : EMPTY_COMMENT;
+ }
+
+ private YamlParametersList getAcceptedValues(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, VALUE_KET)
+ ? new YamlParameterListFactory().createYamlParameterList(yamlDocument.getYaml().get(VALUE_KET))
+ : new YamlParameterListFactory().createEmptyYamlParameterList();
+ }
+
+ private boolean getIsPresenceRequired(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, PRESENCE_KEY)
+ && yamlDocument.getYaml().get(PRESENCE_KEY).equals(PRESENCE_REQUIRED_KEY);
+ }
+
+ private boolean isYamlContainingKey(YamlDocument yamlDocument, String structureKey) {
+ return yamlDocument.getYaml().containsKey(structureKey);
+ }
+
+}
diff --git a/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand
index 0695555..b9ad72f 100644
--- a/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand
+++ b/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand
@@ -48,4 +48,5 @@ org.onap.cvc.csar.cc.sol004.VTPValidateCSARR77707
org.onap.cvc.csar.cc.sol004.VTPValidateCSARR77786
org.onap.cvc.csar.cc.sol004.VTPValidateCSARR787965
org.onap.cvc.csar.cc.sol004.VTPValidateCSARR87234
+org.onap.cvc.csar.cc.sol004.VTPValidateCSARR816745
org.onap.cvc.csar.cc.sol004.VTPValidateCSARR972082
diff --git a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r01123.yaml b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r01123.yaml
index 59bb955..577b2ca 100644
--- a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r01123.yaml
+++ b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r01123.yaml
@@ -17,13 +17,13 @@ open_cli_schema_version: 1.0
name: csar-validate-r01123
description: |
- The VNF package Manifest file MUST contain: VNF package meta-data, a list of all artifacts
- (both internal and external) entry’s including their respected URI’s, an algorithm to calculate
- a digest and a digest result calculated on the content of each artifacts, as specified in
- ETSI GS NFV-SOL004. The VNF Package MUST include VNF Identification Data to uniquely
- identify the resource for a given VNF provider. The identification data must include:
- an identifier for the VNF, the name of the VNF as was given by the VNF provider, VNF
- description, VNF provider, and version.
+ The VNF or PNF CSAR package Manifest file MUST contain: VNF or PNF package meta-data,
+ a list of all artifacts (both internal and external) entry’s including their respected URI’s,
+ an algorithm to calculate a digest and a digest result calculated on the content of each artifacts,
+ as specified in ETSI GS NFV-SOL004. The VNF or PNF Package MUST include VNF or PNF Identification Data to uniquely
+ identify the resource for a given provider. The identification data must include:
+ an identifier for the VNF or PNF, the name of the VNF or PNF as was given by the provider,
+ description, provider and version.
info:
product: onap-dublin
@@ -38,6 +38,13 @@ parameters:
short_option: b
type: binary
is_optional: false
+ - name: pnf
+ description: CSAR file contains PNF
+ long_option: pnf
+ short_option: p
+ type: bool
+ is_optional: true
+ default_value: false
results:
direction: landscape
diff --git a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r816745.yaml b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r816745.yaml
new file mode 100644
index 0000000..8ef80dd
--- /dev/null
+++ b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r816745.yaml
@@ -0,0 +1,66 @@
+# Copyright 2020 Nokia.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+open_cli_schema_version: 1.0
+
+name: csar-validate-r816745
+
+description: |
+ The VNF or PNF PROVIDER MUST provide the Service Provider with PM Meta Data (PM Dictionary)
+ to support the analysis of PM events delivered to DCAE.
+ The PM Dictionary is to be provided as a separate YAML artifact at onboarding and must follow
+ the VES Event Listener Specification and VES Event Registration Specification
+ which contain the format and content required.
+
+
+info:
+ product: onap-dublin
+ version: 1.0
+ service: vnf-compliance
+ author: ONAP VTP Team onap-discuss@lists.onap.org
+
+parameters:
+ - name: csar
+ description: CSAR file path
+ long_option: csar
+ short_option: b
+ type: binary
+ is_optional: false
+ - name: pnf
+ description: CSAR file contains PNF
+ long_option: pnf
+ short_option: p
+ type: bool
+ is_optional: true
+ default_value: false
+
+results:
+ direction: landscape
+ attributes:
+ - name: code
+ description: Error code
+ scope: short
+ type: string
+ - name: message
+ description: Error message
+ scope: short
+ type: string
+ - name: file
+ description: File in which error occured
+ scope: short
+ type: string
+ - name: line-no
+ description: Line no at which error occured
+ scope: short
+ type: string
diff --git a/csarvalidation/src/main/resources/vnfreqs.properties b/csarvalidation/src/main/resources/vnfreqs.properties
index abbdb73..2e0baaf 100644
--- a/csarvalidation/src/main/resources/vnfreqs.properties
+++ b/csarvalidation/src/main/resources/vnfreqs.properties
@@ -1,5 +1,5 @@
-vnfreqs.enabled=r02454,r04298,r07879,r09467,r13390,r23823,r26881,r27310,r35851,r40293,r43958,r66070,r77707,r77786,r87234,r10087,r21322,r26885,r40820,r35854,r65486,r17852,r46527,r15837,r54356,r67895,r95321,r32155,r01123,r51347,r787965,r130206
-pnfreqs.enabled=r10087,r87234,r35854,r15837,r17852,r293901,r146092,r57019,r787965,r130206
+vnfreqs.enabled=r01123,r02454,r04298,r07879,r09467,r10087,r13390,r15837,r17852,r21322,r23823,r26881,r26885,r27310,r32155,r35851,r35854,r40293,r40820,r43958,r46527,r51347,r54356,r65486,r67895,r66070,r77707,r77786,r87234,r95321,r130206,r787965
+pnfreqs.enabled=r01123,r10087,r15837,r17852,r35854,r57019,r87234,r130206,r146092,r293901,r787965,r816745,r972082
# ignored all chef and ansible related tests
vnferrors.ignored=0x1005,0x1006,r07879-0x1000,r13390-0x1000,r27310-0x1000,r40293-0x1000,r77786-0x1000,r04298-0x1000,r07879-0x1000,r10087-0x1000,r13390-0x1000,r23823-0x1000,r26881-0x1000,r40820-0x1000,r35851-0x1000,r32155-0x1000,r54356-0x1000,r67895-0x1000,r95321-0x1000,r46527-0x1000,r02454-0x1000
-pnferrors.ignored=
+pnferrors.ignored=0x1006,r130206-0x1006
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/CSARArchiveTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/CSARArchiveTest.java
index 2831532..3b18a1b 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/CSARArchiveTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/CSARArchiveTest.java
@@ -20,8 +20,9 @@ import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
-
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
public class CSARArchiveTest {
@Test
@@ -35,6 +36,7 @@ public class CSARArchiveTest {
csar.init("./src/test/resources/" + csarFileName + ".csar");
csar.parse();
csar.cleanup();
+ assertTrue(csar.getErrors().size() > 0);
System.out.println(csar.getErrors());
} catch (Exception e) {
// TODO Auto-generated catch block
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/CsarValidatorTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/CsarValidatorTest.java
deleted file mode 100644
index 2969b42..0000000
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/CsarValidatorTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Copyright 2017 Huawei Technologies Co., Ltd.
- *
- * 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.
- */
-
-package org.onap.cvc.csar;
-
-import org.junit.Test;
-import org.onap.cli.main.OnapCli;
-
-import java.net.URISyntaxException;
-
-import static org.junit.Assert.assertEquals;
-import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.absoluteFilePath;
-
-
-public class CsarValidatorTest {
-
-
- @Test
- public void testAllTestCasesForVNF() throws URISyntaxException {
- OnapCli cli = new OnapCli(new String [] {
- "--product", "onap-dublin",
- "csar-validate",
- "--format", "json",
- "--csar", absoluteFilePath("VoLTE.csar")});
- cli.handle();
- assertEquals(0, cli.getExitCode());
- }
-
-
- @Test
- public void testAllTestCasesForPNF_CsarCase() throws URISyntaxException {
- OnapCli cli = new OnapCli(new String [] {
- "--product", "onap-dublin",
- "csar-validate",
- "--format", "json",
- "--pnf",
- "--csar", absoluteFilePath("pnf/r57019/allMandatoryEntriesDefinedInMetadataManifest.csar")});
- cli.handle();
- assertEquals(0, cli.getExitCode());
- }
-
-
- @Test
- public void testAllTestCasesForPNF_ZipCase() throws URISyntaxException {
- OnapCli cli = new OnapCli(new String [] {
- "--product", "onap-dublin",
- "csar-validate",
- "--format", "json",
- "--pnf",
- "--csar", absoluteFilePath("pnf/signed-package-valid-signature.zip")});
- cli.handle();
- assertEquals(0, cli.getExitCode());
- }
-
-}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfCSARArchiveTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfCSARArchiveTest.java
index cf24e53..4f46b74 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfCSARArchiveTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfCSARArchiveTest.java
@@ -19,11 +19,11 @@ package org.onap.cvc.csar;
import com.google.common.collect.Lists;
import org.junit.Test;
import org.onap.cvc.csar.parser.SourcesParser;
-
import java.util.List;
import java.util.Map;
-
import static org.assertj.core.api.Assertions.assertThat;
+import java.util.Collections;
+import java.util.HashMap;
public class PnfCSARArchiveTest {
@@ -45,7 +45,7 @@ public class PnfCSARArchiveTest {
verifyThatCmsSectionWasSet(manifest);
verifyThatSourcesSectionWasSet(manifest);
verifyThatNonManoArtifactsWereSet(manifest);
- assertThat(pnfCSARArchive.getErrors().size()).isEqualTo(0);
+ assertThat(pnfCSARArchive.getErrors().size()).isZero();
}
}
@@ -76,23 +76,27 @@ public class PnfCSARArchiveTest {
private void verifyThatNonManoArtifactsWereSet(CSARArchive.Manifest manifest) {
Map<String, Map<String, List<String>>> nonManoArtifacts = manifest.getNonMano();
- assertThat(nonManoArtifacts.get("onap_ves_events").get(SOURCE_TAG))
- .isEqualTo(Lists.newArrayList("Artifacts/Events/VES_registration.yml")
- );
- assertThat(nonManoArtifacts.get("onap_pm_dictionary").get(SOURCE_TAG))
- .isEqualTo(Lists.newArrayList("Artifacts/Measurements/PM_Dictionary.yaml")
- );
- assertThat(nonManoArtifacts.get("onap_yang_modules").get(SOURCE_TAG))
- .isEqualTo(Lists.newArrayList("Artifacts/Yang_module/Yang_module.yaml")
- );
- assertThat(nonManoArtifacts.get("onap_others").get(SOURCE_TAG))
- .isEqualTo(Lists.newArrayList(
- "Artifacts/scripts/install.sh",
+ Map<String, List<String>>mapValue1=new HashMap<>();
+ Map<String, List<String>>mapValue2=new HashMap<>();
+ Map<String, List<String>>mapValue3=new HashMap<>();
+ Map<String, List<String>>mapValue4=new HashMap<>();
+
+ mapValue1.put("", Collections.singletonList(""));
+ mapValue1.put(SOURCE_TAG,Lists.newArrayList("Artifacts/Events/VES_registration.yml"));
+ mapValue2.put("", Collections.singletonList(""));
+ mapValue2.put(SOURCE_TAG,Lists.newArrayList("Artifacts/Measurements/PM_Dictionary.yaml"));
+ mapValue3.put("", Collections.singletonList(""));
+ mapValue3.put(SOURCE_TAG,Lists.newArrayList("Artifacts/Yang_module/Yang_module.yaml"));
+ mapValue4.put("", Collections.singletonList(""));
+ mapValue4.put(SOURCE_TAG,Lists.newArrayList
+ ("Artifacts/scripts/install.sh",
"Artifacts/Informational/user_guide.txt",
"Artifacts/Other/installation_guide.txt",
- "Artifacts/Other/review_log.txt"
- )
- );
+ "Artifacts/Other/review_log.txt"));
+ assertThat(nonManoArtifacts).containsEntry("onap_ves_events",mapValue1);
+ assertThat(nonManoArtifacts).containsEntry("onap_pm_dictionary",mapValue2);
+ assertThat(nonManoArtifacts).containsEntry("onap_yang_modules",mapValue3);
+ assertThat(nonManoArtifacts).containsEntry("onap_others",mapValue4);
}
} \ No newline at end of file
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfManifestParserTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfManifestParserTest.java
index a708f47..5749a73 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfManifestParserTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfManifestParserTest.java
@@ -25,6 +25,8 @@ import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
+import java.util.Collections;
+import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
@@ -48,7 +50,7 @@ public class PnfManifestParserTest {
assertThat(metadata.getProviderId()).isEqualTo("Ericsson");
assertThat(metadata.getPackageVersion()).isEqualTo("1.0");
assertThat(metadata.getReleaseDateTime()).isEqualTo("2019-01-14T11:25:00+00:00");
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@@ -64,7 +66,7 @@ public class PnfManifestParserTest {
new SourcesParser.Source("scripts/install.sh", "SHA-256", "d0e7828293355a07c2dccaaa765c80b507e60e6167067c950dc2e6b0da0dbd8b"),
new SourcesParser.Source("https://www.vendor_org.com/MRF/v4.1/scripts/scale/scale.sh", "SHA-256", "36f945953929812aca2701b114b068c71bd8c95ceb3609711428c26325649165")
);
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@@ -81,7 +83,7 @@ public class PnfManifestParserTest {
new SourcesParser.Source("some_file.sh", "", ""),
new SourcesParser.Source("scripts/install.sh", "", "d0e7828293355a07c2dccaaa765c80b507e60e6167067c950dc2e6b0da0dbd8b"),
new SourcesParser.Source("https://www.vendor_org.com/MRF/v4.1/scripts/scale/scale.sh", "SHA-256", ""));
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@@ -90,25 +92,28 @@ public class PnfManifestParserTest {
Pair<Map<String, Map<String, List<String>>>, List<CSARArchive.CSARError>> mapListPair = pnfManifestParser.fetchNonManoArtifacts().get();
Map<String, Map<String, List<String>>> nonManoArtifacts = mapListPair.getKey();
List<CSARArchive.CSARError> errors = mapListPair.getValue();
-
- assertThat(nonManoArtifacts.get("onap_ves_events").get("source"))
- .isEqualTo(Lists.newArrayList("Artifacts/Events/VES_registration.yml")
- );
- assertThat(nonManoArtifacts.get("onap_pm_dictionary").get("source"))
- .isEqualTo(Lists.newArrayList("Artifacts/Measurements/PM_Dictionary.yaml")
- );
- assertThat(nonManoArtifacts.get("onap_yang_module").get("source"))
- .isEqualTo(Lists.newArrayList("Artifacts/Yang_module/Yang_module.yaml")
- );
- assertThat(nonManoArtifacts.get("onap_others").get("source"))
- .isEqualTo(Lists.newArrayList(
- "Artifacts/scripts/install.sh",
+ Map<String, List<String>>mapValue1=new HashMap<>();
+ Map<String, List<String>>mapValue2=new HashMap<>();
+ Map<String, List<String>>mapValue3=new HashMap<>();
+ Map<String, List<String>>mapValue4=new HashMap<>();
+
+ mapValue1.put("", Collections.singletonList(""));
+ mapValue1.put("source",Lists.newArrayList("Artifacts/Events/VES_registration.yml"));
+ mapValue2.put("", Collections.singletonList(""));
+ mapValue2.put("source",Lists.newArrayList("Artifacts/Measurements/PM_Dictionary.yaml"));
+ mapValue3.put("", Collections.singletonList(""));
+ mapValue3.put("source",Lists.newArrayList("Artifacts/Yang_module/Yang_module.yaml"));
+ mapValue4.put("", Collections.singletonList(""));
+ mapValue4.put("source",Lists.newArrayList
+ ("Artifacts/scripts/install.sh",
"Artifacts/Informational/user_guide.txt",
"Artifacts/Other/installation_guide.txt",
- "Artifacts/Other/review_log.txt"
- )
- );
- assertThat(errors.size()).isEqualTo(0);
+ "Artifacts/Other/review_log.txt"));
+ assertThat(nonManoArtifacts).containsEntry("onap_ves_events",mapValue1);
+ assertThat(nonManoArtifacts).containsEntry("onap_pm_dictionary",mapValue2);
+ assertThat(nonManoArtifacts).containsEntry("onap_yang_module",mapValue3);
+ assertThat(nonManoArtifacts).containsEntry("onap_others",mapValue4);
+ assertThat(errors.size()).isZero();
}
@@ -154,7 +159,7 @@ public class PnfManifestParserTest {
"HhE7UbSCHDlDDgrOosJkbuI4UCX/njXrU2ukXbrWz/FjH84Mek039z+w4M6fBnl5"+
"4xuyO1o65LlKHoxwnRH9lQ=="
);
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
@@ -214,6 +219,6 @@ public class PnfManifestParserTest {
new SourcesParser.Source("Artifacts/Other/review_log.txt", "SHA-256", "36f945953929812aca2701b114b068c71bd8c95ceb3609711428c26325649165")
);
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfMetadataParserTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfMetadataParserTest.java
index c409efc..4a08a5d 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfMetadataParserTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfMetadataParserTest.java
@@ -122,7 +122,7 @@ public class PnfMetadataParserTest {
//then
List<CSARArchive.CSARError> errors = data.getRight();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfNonManoArtifactsParserTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfNonManoArtifactsParserTest.java
index 388a98f..2cd648a 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/PnfNonManoArtifactsParserTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/PnfNonManoArtifactsParserTest.java
@@ -56,7 +56,7 @@ public class PnfNonManoArtifactsParserTest {
pnfManifestParser.fetchNonManoArtifacts();
//then
- assertThat(nonManoArtifacts.isPresent()).isFalse();
+ assertThat(nonManoArtifacts).isNotPresent();
}
@Test
@@ -88,7 +88,7 @@ public class PnfNonManoArtifactsParserTest {
//then
List<CSARArchive.CSARError> errors = data.getRight();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/VnfManifestParserTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/VnfManifestParserTest.java
index 91bb6b1..7fa73a7 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/VnfManifestParserTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/VnfManifestParserTest.java
@@ -43,7 +43,7 @@ public class VnfManifestParserTest {
CSARArchive.Manifest.Metadata metadata = metadataListPair.getKey();
List<CSARArchive.CSARError> errors = metadataListPair.getValue();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
assertThat(metadata.getProductName()).isEqualTo(" vCSCF");
assertThat(metadata.getProviderId()).isEqualTo(" ZTE");
assertThat(metadata.getPackageVersion()).isEqualTo(" 1.0");
@@ -64,7 +64,7 @@ public class VnfManifestParserTest {
new SourcesParser.Source("scripts/install.sh", "SHA-256", "d0e7828293355a07c2dccaaa765c80b507e60e6167067c950dc2e6b0da0dbd8b"),
new SourcesParser.Source("https://www.vendor_org.com/MRF/v4.1/scripts/scale/scale.sh", "SHA-256", "36f945953929812aca2701b114b068c71bd8c95ceb3609711428c26325649165")
);
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
@@ -79,6 +79,6 @@ public class VnfManifestParserTest {
"AQcBoFEET3icc87PK0nNK9ENqSxItVIoSa0o0S/ISczMs1ZIzkgsKk4tsQ0N1nUM" +
"dvb05OXi5XLPLEtViMwvLVLwSE0sKlFIVHAqSk3MBkkBAJv0Fx0="
);
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/IntegrationTestUtils.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/IntegrationTestUtils.java
index 6f183d7..6d90b23 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/IntegrationTestUtils.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/IntegrationTestUtils.java
@@ -87,4 +87,8 @@ public class IntegrationTestUtils {
public static List<String> convertToMessagesList(List<CSARArchive.CSARError> errors) {
return errors.stream().map(CSARArchive.CSARError::getMessage).collect(Collectors.toList());
}
+
+ public static List<String> convertToFilesList(List<CSARArchive.CSARError> errors) {
+ return errors.stream().map(CSARArchive.CSARError::getFile).collect(Collectors.toList());
+ }
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123IntegrationTest.java
new file mode 100644
index 0000000..a3112ce
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR01123IntegrationTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.cvc.csar.cc.sol004;
+
+import org.assertj.core.api.Condition;
+import org.assertj.core.api.HamcrestCondition;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.cvc.csar.CSARArchive;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToMessagesList;
+
+public class VTPValidateCSARR01123IntegrationTest {
+
+ private static final boolean IS_PNF = true;
+ private static final String TEST_CSAR_DIRECTORY = "pnf/r01123/";
+
+ private VTPValidateCSARR01123 testCase;
+
+ @Before
+ public void setUp() {
+ testCase = new VTPValidateCSARR01123();
+ }
+
+ @Test
+ public void shouldReturnProperRequestNumber() {
+ assertThat(testCase.getVnfReqsNo()).isEqualTo("R01123");
+ }
+
+ @Test
+ public void shouldReportThatVendorNameAndVersionAreMissing() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option1-invalid-noVendor.csar", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(3);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Missing. Entry [TOSCA-Meta-File-Version]",
+ "Missing. Entry [VNF Vendor details]",
+ "Missing. Entry [Created-by]"
+ );
+ }
+
+ @Test
+ public void shouldReportThatFileAvailableInCsarIsNotPresentInManifestSources() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option1-invalid-noFileInManifest.csar", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ Condition<String> containingMissingFiles = new HamcrestCondition<>(allOf(
+ containsString("TOSCA-Metadata/TOSCA.meta"),
+ containsString("Artifacts/Deployment/Yang_module/yang-module2.yang"),
+ containsString("Artifacts/Deployment/Yang_module/yang-module1.yang"),
+ containsString("Artifacts/Informational/user_guide.txt"),
+ containsString("Artifacts/sample-pnf.cert")
+ ));
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingMissingFiles);
+ }
+
+ @Test
+ public void shouldReportThatFilePresentInManifestIsNotPresentInCsarFile() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option1-invalid-missing-files.csar", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ Condition<String> containingMissingFiles = new HamcrestCondition<>(allOf(
+ containsString("Definitions/a.yaml"),
+ containsString("Definitions/b.yaml")
+ ));
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingMissingFiles);
+ }
+
+ @Test
+ public void shouldReportThatVendorNameIsMissingAndThatFileIsNotPresentInSource() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option1-invalid-noVendor-noFileInManifest.csar", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ Condition<String> containingMissingFiles = new HamcrestCondition<>(allOf(
+ containsString("Artifacts/Informational/user_guide.txt")
+ ));
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(3);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Missing. Entry [VNF Vendor details]",
+ "Missing. Entry [Created-by]"
+ );
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingMissingFiles);
+ }
+
+ @Test
+ public void shouldNotReportAnyErrorWhenAllFilesPresentInCsarArePresentInSources() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option1-valid.csar", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldNotReportAnyErrorWhenValidCsarIsZippedWithCmsFile() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option2-valid-with-cms.zip", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldReportThatFileIsNotPresentInSourcesWhenInvalidCsarFileIsZippedWithCmsFile() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-option2-invalid-with-cms.zip", "vtp-validate-csar-r01123.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ Condition<String> containingMissingFiles = new HamcrestCondition<>(
+ containsString("Artifacts/Informational/user_guide.txt")
+ );
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingMissingFiles);
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR10087IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR10087IntegrationTest.java
index 921e903..2cc739c 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR10087IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR10087IntegrationTest.java
@@ -63,6 +63,19 @@ public class VTPValidateCSARR10087IntegrationTest {
}
@Test
+ public void testWithoutTOSCAMetaDir() throws Exception {
+ // given
+ configureTestCase(testCase, "pnf/toscaMetaFile.csar", "vtp-validate-csar-r10087.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(7);
+ }
+
+ @Test
public void shouldReportThatDefinitionYAMLDoesNotExist() throws Exception {
// given
configureTestCase(testCase, "pnf/r10087/invalidEntryDefinitionsInToscaMeta.csar", "vtp-validate-csar-r10087.yaml", IS_PNF);
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java
index 036e169..2d6d058 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206IntegrationTest.java
@@ -20,8 +20,10 @@ package org.onap.cvc.csar.cc.sol004;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.onap.cli.fw.error.OnapCommandException;
import org.onap.cvc.csar.CSARArchive;
+import java.net.URISyntaxException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -49,24 +51,110 @@ public class VTPValidateCSARR130206IntegrationTest {
"To verify signed package please please follow instructions from test/resources/README.txt file and comment @Ignore tag. " +
"Use instructions for option 1. Test was created for manual verification."
)
- public void manual_shouldValidateProperCsar() throws Exception {
+ public void manual_shouldValidateProperCsarWithCms() throws Exception {
// given
- configureTestCase(testCase, "pnf/r130206/csar-option1-valid.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-valid.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
// when
testCase.execute();
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
- public void shouldReportThatOnlySignatureIsInvalid() throws Exception {
+ @Ignore("It is impossible to write test which will always pass, because certificate used to sign the file has time validity." +
+ "To verify signed package please please follow instructions from test/resources/README.txt file and comment @Ignore tag. " +
+ "Use instructions for option 1. Test was created for manual verification."
+ )
+ public void manual_shouldValidateCsarWithCertificateInToscaEtsiWithValidSignature() throws Exception {
+
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-tosca-valid.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldReportWarningForMissingCertInCmsToscaMetaAndRootCatalogAndMissingHashCodesInManifest()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-not-secure-warning.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Warning. Consider adding package integrity and authenticity assurance according to ETSI NFV-SOL 004 Security Option 1"
+ );
+ }
+
+ @Test
+ public void shouldReturnNoErrorWhenCertIsOnlyInCmsAndAlgorithmAndHashesAreCorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnNoErrorWhenCertIsOnlyInToscaAndAlgorithmAndHashesAreCorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-tosca.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCsarContainsToscaFileHoweverToscaDoesNotContainsCertEntryAndAlgorithmAndHashesAreCorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-with-tosca-no-cert-entry.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Unable to find ETSI-Entry-Certificate in Tosca file"
+ );
+ }
+ @Test
+ public void shouldReturnErrorWhenCertIsOnlyInCmsHoweverHashesAreIncorrect()
+ throws Exception{
// given
- configureTestCase(testCase, "pnf/r130206/csar-option1-validSection.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
// when
testCase.execute();
@@ -75,52 +163,307 @@ public class VTPValidateCSARR130206IntegrationTest {
List<CSARArchive.CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(2);
assertThat(convertToMessagesList(errors)).contains(
- "File has invalid CMS signature!",
- "Mismatch between contents of non-mano-artifact-sets and source files of the package"
+ "Source 'Artifacts/Other/my_script.csh' has wrong hash!",
+ "File has invalid signature!"
);
}
@Test
- public void shouldReportErrorsForInvalidCsar() throws Exception {
+ public void shouldReturnErrorWhenCertIsOnlyInToscaHoweverHashesAreIncorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-tosca-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(2);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Source 'Artifacts/Deployment/Measurements/PM_Dictionary.yml' has wrong hash!",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertIsOnlyInRootDirectoryHoweverHashesAreIncorrect()
+ throws Exception{
// given
- configureTestCase(testCase, "pnf/r130206/csar-option1-invalid.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-root-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
// when
testCase.execute();
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(6);
+ assertThat(errors.size()).isEqualTo(3);
assertThat(convertToMessagesList(errors)).contains(
- "Unable to find CMS section in manifest!",
- "Source 'Definitions/MainServiceTemplate.yaml' has wrong hash!",
- "Source 'Artifacts/Other/my_script.csh' has hash, but unable to find algorithm tag!",
- "Unable to calculate digest - file missing: Artifacts/NonExisting2.txt",
- "Mismatch between contents of non-mano-artifact-sets and source files of the package",
- "File has invalid CMS signature!"
+ "Source 'Artifacts/Deployment/Events/RadioNode_Pnf_v1.yaml' has wrong hash!",
+ "Unable to find ETSI-Entry-Certificate in Tosca file",
+ "Certificate present in root catalog despite the TOSCA.meta file"
);
}
+ @Test
+ public void shouldReturnErrorWhenToscaEtsiEntryCertificatePointToNotExistingFile()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-with-tosca-cert-pointing-non-existing-cert.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(2);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Unable to find cert file defined by ETSI-Entry-Certificate!",
+ "Invalid value. Entry [Entry-Certificate]. Artifacts/sample-pnf.cert does not exist"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInTosca()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-tosca.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(3);
+ assertThat(convertToMessagesList(errors)).contains(
+ "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container",
+ "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container",
+ "File has invalid signature!"
+ );
+ }
@Test
- public void shouldReportThanInVnfPackageCertFileWasNotDefined() throws Exception {
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInToscaAndHashIsIncorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-tosca-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(4);
+ assertThat(convertToMessagesList(errors)).contains(
+ "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container",
+ "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container",
+ "Source 'Artifacts/Informational/user_guide.txt' has wrong hash!",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInToscaAndInRootDirectory()
+ throws Exception{
// given
- configureTestCase(testCase, "sample2.csar", "vtp-validate-csar-r130206.yaml", false);
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-root-and-tosca.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
// when
testCase.execute();
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(4);
assertThat(convertToMessagesList(errors)).contains(
- "Unable to find cert file defined by Entry-Certificate!",
- "Unable to find CMS section in manifest!",
- "Missing. Entry [tosca_definitions_version]"
+ "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container",
+ "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container",
+ "Certificate present in root catalog despite the certificate is included in the signature container",
+ "File has invalid signature!"
);
}
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInToscaAndInRootDirectoryAndHashIsIncorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-root-and-tosca-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(5);
+ assertThat(convertToMessagesList(errors)).contains(
+ "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container",
+ "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container",
+ "Certificate present in root catalog despite the certificate is included in the signature container",
+ "Source 'Artifacts/Informational/user_guide.txt' has wrong hash!",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInRootDirectory()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-root.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(2);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Certificate present in root catalog despite the certificate is included in the signature container",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInCmsAndInRootDirectoryAndHashIsIncorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-cms-and-root-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(3);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Certificate present in root catalog despite the certificate is included in the signature container",
+ "Source 'Artifacts/Informational/user_guide.txt' has wrong hash!",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInToscaAndInRootDirectory()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-root-and-tosca.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(2);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Certificate present in root catalog despite the TOSCA.meta file",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInToscaAndInRootDirectoryAdnHashIsIncorrect()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-root-and-tosca-incorrect-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(3);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Certificate present in root catalog despite the TOSCA.meta file",
+ "Source 'Artifacts/Deployment/Yang_module/yang-module1.yang' has wrong hash!",
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnNoErrorWhenCertificateIsLocatedInToscaAndInRootDirectoryHoweverEtsiEntryIsPointingCertificateInRoot()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-root-pointed-by-tosca.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCertificateIsLocatedInToscaHoweverManifestDoesNotContainsCms()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-tosca-no-cms.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Unable to find cms signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnErrorWhenCsarDoesNotContainsCmsAndCertsHoweverManifestContainsHash()
+ throws Exception{
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-no-cms-no-cert-with-hash.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Unable to find cms signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnNoCertificationErrorWhenCertIsOnlyInRoot() throws Exception {
+
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-cert-in-root.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+
+ // This test returns other errors that are connected with missing tosca entry,
+ // in order to simplify testing, assertion only checks if certificate in root was found and used to validate CMS
+ assertThat(convertToMessagesList(errors)).contains(
+ "File has invalid signature!"
+ );
+ }
+
+ @Test
+ public void shouldReturnCertificateNotFoundErrorWhenCertIsNotPresentInCmsInRootAndTocsaDirectoryIsMissing() throws Exception {
+
+ // given
+ configureTestCase(testCase, "pnf/r130206/csar-no-cert-no-tosca-dir.csar", "vtp-validate-csar-r130206.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+
+ // This test returns other errors that are connected with missing tosca entry,
+ // in order to simplify testing, assertion only checks if "certificate not found" error was reported
+ assertThat(convertToMessagesList(errors)).contains(
+ "Unable to find cert file!"
+ );
+ }
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java
index bf9b094..a10aa91 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java
@@ -19,10 +19,9 @@ package org.onap.cvc.csar.cc.sol004;
import org.junit.Before;
import org.junit.Test;
-import org.onap.cvc.csar.CSARArchive;
+import org.onap.cvc.csar.CSARArchive.CSARError;
import java.util.List;
-import org.onap.cvc.csar.CSARArchive.CSARError;
import static org.assertj.core.api.Assertions.assertThat;
import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase;
@@ -45,24 +44,38 @@ public class VTPValidateCSARR146092IntegrationTest {
}
@Test
- public void shouldDoNotReportErrorWhenNonManoArtifactIsNotAvailable() throws Exception {
+ public void shouldNotReportErrorWhenCSARValid() throws Exception {
+ //given
+ configureTestCase(testCase, "pnf/r146092/validFile.csar",
+ "vtp-validate-csar-r146092.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ final List<CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldNotReportErrorWhenNonManoArtifactIsNotAvailable() throws Exception {
// given
configureTestCase(testCase, "pnf/r146092/missingNonManoArtifactInManifest.csar",
- "vtp-validate-csar-r146092.yaml", IS_PNF);
+ "vtp-validate-csar-r146092.yaml", IS_PNF);
// when
testCase.execute();
// then
final List<CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
public void shouldReportThatMandatoryNonManoArtifactSetEntryHasNotAllFields() throws Exception {
// given
configureTestCase(testCase, "pnf/r146092/missingFieldsInNonManoArtifactManifest.csar",
- "vtp-validate-csar-r146092.yaml", IS_PNF);
+ "vtp-validate-csar-r146092.yaml", IS_PNF);
// when
testCase.execute();
@@ -71,7 +84,7 @@ public class VTPValidateCSARR146092IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Missing. Entry [[onap_ansible_playbooks, onap_others, onap_pm_dictionary, onap_pnf_sw_information, onap_scripts, onap_ves_events, onap_yang_modules]]"
+ "Missing. Entry [[onap_ansible_playbooks, onap_others, onap_pm_dictionary, onap_pnf_sw_information, onap_scripts, onap_ves_events, onap_yang_modules]]"
);
}
@@ -79,7 +92,7 @@ public class VTPValidateCSARR146092IntegrationTest {
public void shouldReportThatNonManoArtifactEntryHasAnySource() throws Exception {
// given
configureTestCase(testCase, "pnf/r146092/noSourceElementInNonManoArtifactEntryManifest.csar",
- "vtp-validate-csar-r146092.yaml", IS_PNF);
+ "vtp-validate-csar-r146092.yaml", IS_PNF);
// when
testCase.execute();
@@ -88,7 +101,7 @@ public class VTPValidateCSARR146092IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Missing. Entry [Source under onap_ves_events]"
+ "Missing. Entry [Source under onap_ves_events]"
);
}
@@ -104,7 +117,7 @@ public class VTPValidateCSARR146092IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Invalid. Entry [Source under onap_ves_events has invalid 'Artifacts/Deployment/Events/RadioNode.yml' path]"
+ "Invalid. Entry [Source under onap_ves_events has invalid 'Artifacts/Deployment/Events/RadioNode.yml' path]"
);
}
@@ -120,7 +133,7 @@ public class VTPValidateCSARR146092IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(4);
assertThat(convertToMessagesList(errors)).contains(
- "Missing. Entry [Definition YAML]"
+ "Missing. Entry [Definition YAML]"
);
}
@@ -128,7 +141,7 @@ public class VTPValidateCSARR146092IntegrationTest {
public void shouldReportThatEntryHasInvalidPathWhenYamlFileIsNotPresent() throws Exception {
// given
configureTestCase(testCase, "pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar", "vtp-validate-csar-r146092.yaml",
- IS_PNF);
+ IS_PNF);
// when
testCase.execute();
@@ -137,7 +150,7 @@ public class VTPValidateCSARR146092IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Invalid. Entry [Source under onap_pnf_sw_information has invalid 'Files/pnf-sw-information/pnf-sw-information.yaml' path]"
+ "Invalid. Entry [Source under onap_pnf_sw_information has invalid 'Files/pnf-sw-information/pnf-sw-information.yaml' path]"
);
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR293901IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR293901IntegrationTest.java
index 2835772..2b9b4f4 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR293901IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR293901IntegrationTest.java
@@ -71,7 +71,7 @@ public class VTPValidateCSARR293901IntegrationTest {
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR57019IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR57019IntegrationTest.java
index 088eab7..d6d06b3 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR57019IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR57019IntegrationTest.java
@@ -73,7 +73,7 @@ public class VTPValidateCSARR57019IntegrationTest {
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965IntegrationTest.java
index 49696e6..33a1754 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR787965IntegrationTest.java
@@ -76,7 +76,7 @@ public class VTPValidateCSARR787965IntegrationTest {
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
@Test
@@ -111,7 +111,7 @@ public class VTPValidateCSARR787965IntegrationTest {
// then
List<CSARArchive.CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
}
}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745IntegrationTest.java
new file mode 100644
index 0000000..17e9de3
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR816745IntegrationTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.cvc.csar.cc.sol004;
+
+import org.assertj.core.api.Condition;
+import org.assertj.core.api.HamcrestCondition;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onap.cvc.csar.CSARArchive;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToMessagesList;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToFilesList;
+
+public class VTPValidateCSARR816745IntegrationTest {
+
+ private static final boolean IS_PNF = true;
+ private static final String TEST_CSAR_DIRECTORY = "pnf/r816745/";
+ private static final int NUMBER_OF_EXPECTED_ERRORS = 4;
+ private static final String LETTER_S_WITH_ASCII_CODE = "s(115)";
+
+ private VTPValidateCSARR816745 testCase;
+
+ @Rule
+ public ExpectedException exceptionRule = ExpectedException.none();
+
+ @Before
+ public void setUp() {
+ testCase = new VTPValidateCSARR816745();
+ }
+
+ @Test
+ public void shouldAddPmDictionaryLoadingErrorWhenPmDictionaryHaveNoSourceInManifest() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-missing-source-value-for-pm-dictionary-in-manifest.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains("Fail to load PM_Dictionary With error: onap_pm_dictionary in manifest does not contains key 'Source'");
+ }
+
+ @Test
+ public void shouldNotReportAnyErrorWhenCsarIsNotContainingPmDictionary() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-no-pm-dictionary.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldReturnNoErrorsWhenCsarContainsValidPmDictionary() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-valid-pm-dictionary.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void shouldReturnNoErrorsWhenZipContainsCsarWithValidPmDictionary() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "zip-with-valid-pm-dictionary.zip", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void shouldReturnListOfErrorsWhenCsarContainsInvalidPmDictionary() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-invalid-pm-dictionary.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ assertThatReturnedErrorsAreCorrect(testCase.getErrors());
+ }
+
+ @Test
+ public void shouldReturnListOfErrorsWhenZipContainsCsarWithInvalidPmDictionary() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "zip-with-invalid-pm-dictionary.zip", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ assertThatReturnedErrorsAreCorrect(testCase.getErrors());
+ }
+
+ @Test
+ public void shouldAddPmDictionaryLoadingErrorWhenGivenInvalidPath() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-empty-pm-dictionary.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when then
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains("Fail to load PM_Dictionary With error: PM_Dictionary YAML file is empty");
+ }
+
+ @Test
+ public void shouldReturnListContainingOneErrorsWhenCsarContainsPmDictionaryWithInvalidKeyMapping() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-invalid-pm-dictionary-invalid-mapping.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors).get(0)).contains(
+ "Fail to load PM_Dictionary With error: mapping values are not allowed here"
+ );
+ }
+
+ @Test
+ public void shouldReturnListContainingOneErrorsWhenCsarContainsPmDictionaryWithIncorrectEscapeCharacter() throws Exception {
+ // given
+ configureTestCase(testCase, TEST_CSAR_DIRECTORY + "csar-with-invalid-pm-dictionary-unknown-escape-character.csar", "vtp-validate-csar-r816745.yaml", IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ List<CSARArchive.CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors).get(0)).contains(
+ "Fail to load PM_Dictionary With error: while scanning a double-quoted scalar",
+ "found unknown escape character " + LETTER_S_WITH_ASCII_CODE
+ );
+ }
+
+ @Test
+ public void shouldReturnProperRequestNumber() {
+ assertThat(testCase.getVnfReqsNo()).isEqualTo("R816745");
+ }
+
+ private void assertThatReturnedErrorsAreCorrect(List<CSARArchive.CSARError> errors) {
+ assertThat(errors.size()).isEqualTo(NUMBER_OF_EXPECTED_ERRORS);
+
+ Condition<String> containingSameFileForAllErrors = new HamcrestCondition<>(
+ containsString("Artifacts/Deployment/Measurements/PM_Dictionary.yml")
+ );
+ assertThat(convertToFilesList(errors))
+ .haveExactly(NUMBER_OF_EXPECTED_ERRORS, containingSameFileForAllErrors);
+
+ Condition<String> containingErrorForMissingValueInFirstDocument = new HamcrestCondition<>(allOf(
+ containsString("Invalid YAML document in PM_Dictionary file."),
+ containsString("In document number 1"),
+ containsString("Path: /pmMetaData/pmFields/"),
+ containsString("Key not found: measChangeType")
+ ));
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingErrorForMissingValueInFirstDocument);
+
+ Condition<String> containingErrorForWrongValueInFirstDocument = new HamcrestCondition<>(allOf(
+ containsString("Invalid YAML document in PM_Dictionary file."),
+ containsString("In document number 1"),
+ containsString("Path: /pmMetaData/pmFields/measResultType"),
+ containsString("Value(s) is/are not in array of accepted values."),
+ containsString("value(s): integer"),
+ containsString("accepted value(s): [float, uint32, uint64]")
+ ));
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingErrorForWrongValueInFirstDocument);
+
+ Condition<String> containingErrorForMissingValueInSecondDocument = new HamcrestCondition<>(allOf(
+ containsString("Invalid YAML document in PM_Dictionary file."),
+ containsString("In document number 2"),
+ containsString("Path: /pmMetaData/pmFields/"),
+ containsString("Key not found: measChangeType")
+ ));
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingErrorForMissingValueInSecondDocument);
+
+ Condition<String> containingErrorForWrongValueInArrayInThirdDocument = new HamcrestCondition<>(allOf(
+ containsString("Invalid YAML document in PM_Dictionary file."),
+ containsString("In document number 3"),
+ containsString("Path: /pmMetaData/pmFields/measAdditionalFields/vendorField1"),
+ containsString("Value(s) is/are not in array of accepted values."),
+ containsString("value(s): [Z, A]"),
+ containsString("accepted value(s): [X, Y, Z]")
+ ));
+ assertThat(convertToMessagesList(errors)).haveExactly(1, containingErrorForWrongValueInArrayInThirdDocument);
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java
index fb9e431..868fad2 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java
@@ -21,10 +21,12 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase;
import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToMessagesList;
+import java.net.URISyntaxException;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.onap.cli.fw.error.OnapCommandException;
import org.onap.cvc.csar.CSARArchive;
import org.onap.cvc.csar.CSARArchive.CSARError;
@@ -55,7 +57,37 @@ public class VTPValidateCSARR972082IntegrationTest {
// then
final List<CSARError> errors = testCase.getErrors();
- assertThat(errors.size()).isEqualTo(0);
+ assertThat(errors.size()).isZero();
+ }
+
+ @Test
+ public void shouldReturnErrorWhenFileExtensionIsNotYaml() throws Exception {
+ // given
+ configureTestCase(testCase, PNF_R_972082 + "fileExtensionOfArtifactIsNotYaml.csar", VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ final List<CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Invalid. File extension Files/pnf-sw-information/pnf-sw-information.json is invalid"
+ );
+ }
+
+ @Test
+ public void shouldReturnNoErrorWhenOptionalNonManoArtifactSetEntryIsNotPresent() throws Exception {
+ // given
+ configureTestCase(testCase, PNF_R_972082 + "missingOnapPnfSwInformationArtifactSetEntry.csar",
+ VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ final List<CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isZero();
}
@Test
@@ -77,9 +109,9 @@ public class VTPValidateCSARR972082IntegrationTest {
}
@Test
- public void shouldReportThatMandatoryNonManoArtifactSetEntryHasNotAllFields_() throws Exception {
+ public void shouldReportMissingPnfSoftwareVersionInYamlFile() throws Exception {
// given
- configureTestCase(testCase, PNF_R_972082 + "missingFieldsInNonManoArtifactManifest.csar",
+ configureTestCase(testCase, PNF_R_972082 + "missingPnfSoftwareVersionInYamlFile.csar",
VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
// when
@@ -89,15 +121,15 @@ public class VTPValidateCSARR972082IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Missing. Entry [[onap_pnf_sw_information]]"
+ "Missing. Entry [pnf_software_version in Files/pnf-sw-information/pnf-sw-information.yaml]"
);
}
@Test
- public void shouldReportMissingPnfSoftwareVersionInYamlFile() throws Exception {
+ public void shouldReportMissingSourceElementUnderAttribute() throws OnapCommandException, URISyntaxException {
// given
- configureTestCase(testCase, PNF_R_972082 + "missingPnfSoftwareVersionInYamlFile.csar",
- VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
+ configureTestCase(testCase, PNF_R_972082 + "missingSourceElementUnderAttributeError.csar",
+ VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
// when
testCase.execute();
@@ -106,8 +138,24 @@ public class VTPValidateCSARR972082IntegrationTest {
final List<CSARError> errors = testCase.getErrors();
assertThat(errors.size()).isEqualTo(1);
assertThat(convertToMessagesList(errors)).contains(
- "Missing. Entry [pnf_software_version in Files/pnf-sw-information/pnf-sw-information.yaml]"
+ "Missing. Entry [Source under onap_pnf_sw_information]"
);
}
+ @Test
+ public void shouldReportInvalidYamlStructure() throws OnapCommandException, URISyntaxException {
+ // given
+ configureTestCase(testCase, PNF_R_972082 + "invalidYamlStructure.csar",
+ VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF);
+
+ // when
+ testCase.execute();
+
+ // then
+ final List<CSARError> errors = testCase.getErrors();
+ assertThat(errors.size()).isEqualTo(1);
+ assertThat(convertToMessagesList(errors)).contains(
+ "Invalid. Yaml file Files/pnf-sw-information/pnf-sw-information.yaml is invalid"
+ );
+ }
} \ No newline at end of file
diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/security/ShaHashCodeGeneratorTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/security/ShaHashCodeGeneratorTest.java
index 1ea5dd5..b5c4efa 100644
--- a/csarvalidation/src/test/java/org/onap/cvc/csar/security/ShaHashCodeGeneratorTest.java
+++ b/csarvalidation/src/test/java/org/onap/cvc/csar/security/ShaHashCodeGeneratorTest.java
@@ -39,8 +39,9 @@ public class ShaHashCodeGeneratorTest {
final String hashCode = shaHashCodeGenerator.generateSha256("test".getBytes());
- assertThat(hashCode).isEqualTo(shaHashCodeGenerator.generateSha256("test".getBytes()));
- assertThat(hashCode).isNotEqualTo(shaHashCodeGenerator.generateSha256("Test".getBytes()));
+ assertThat(hashCode)
+ .isEqualTo(shaHashCodeGenerator.generateSha256("test".getBytes()))
+ .isNotEqualTo(shaHashCodeGenerator.generateSha256("Test".getBytes()));
}
@Test
@@ -48,7 +49,8 @@ public class ShaHashCodeGeneratorTest {
final String hashCode = shaHashCodeGenerator.generateSha512("test".getBytes());
- assertThat(hashCode).isEqualTo(shaHashCodeGenerator.generateSha512("test".getBytes()));
- assertThat(hashCode).isNotEqualTo(shaHashCodeGenerator.generateSha512("Test".getBytes()));
+ assertThat(hashCode)
+ .isEqualTo(shaHashCodeGenerator.generateSha512("test".getBytes()))
+ .isNotEqualTo(shaHashCodeGenerator.generateSha512("Test".getBytes()));
}
} \ No newline at end of file
diff --git a/csarvalidation/src/test/java/org/onap/functional/CsarValidationUtility.java b/csarvalidation/src/test/java/org/onap/functional/CsarValidationUtility.java
new file mode 100644
index 0000000..24ef778
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/functional/CsarValidationUtility.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.onap.functional;
+
+import com.google.gson.Gson;
+import org.onap.cli.fw.output.OnapCommandResult;
+import org.onap.functional.cli.OnapCliValidationResponseWrapper;
+import org.onap.functional.cli.OnapCliWrapper;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public final class CsarValidationUtility {
+
+ private static final int NOR_ERROR_CODE = 0;
+ private static final String UNKNOWN_LINE_NUMBER = "-1";
+ private static final String UNKNOWN_FILE = "";
+
+ private CsarValidationUtility(){}
+
+ public static final String CERTIFICATION_RULE = "r130206";
+ public static final String OPERATION_STATUS_FAILED = "FAILED";
+ public static final String OPERATION_STATUS_PASS = "PASS";
+
+ public static OnapCliValidationResponseWrapper getCliCommandValidationResult(OnapCliWrapper cli) {
+ final OnapCommandResult onapCommandResult = cli.getCommandResult();
+ return new Gson().fromJson(onapCommandResult.getOutput().toString(), OnapCliValidationResponseWrapper.class);
+ }
+
+ public static OnapCliValidationResponseWrapper.ValidationResultWrapper.ValidationErrorWrapper createExpectedError(
+ String rule, String errorCode, String errorMessage
+ ) {
+ return new OnapCliValidationResponseWrapper.ValidationResultWrapper.ValidationErrorWrapper(
+ rule.toUpperCase(), errorCode,
+ errorMessage,
+ UNKNOWN_FILE, UNKNOWN_LINE_NUMBER
+ );
+ }
+
+ public static boolean ruleHaveOneOfCodes(String ruleCode, String... codes ) {
+ return Arrays.asList(codes).contains(ruleCode);
+ }
+
+ public static void verifyThatOperationFinishedWithoutAnyError(OnapCliWrapper cli) {
+ assertThat(cli.getExitCode()).isEqualTo(NOR_ERROR_CODE);
+ }
+
+
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java b/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java
new file mode 100644
index 0000000..903691e
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/functional/PnfValidationFunctionalTest.java
@@ -0,0 +1,132 @@
+/**
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.onap.functional;
+
+import org.junit.Test;
+import org.onap.functional.cli.OnapCliValidationResponseWrapper;
+import org.onap.functional.cli.OnapCliWrapper;
+
+import java.net.URISyntaxException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.absoluteFilePath;
+import static org.onap.functional.CsarValidationUtility.CERTIFICATION_RULE;
+import static org.onap.functional.CsarValidationUtility.OPERATION_STATUS_FAILED;
+import static org.onap.functional.CsarValidationUtility.OPERATION_STATUS_PASS;
+import static org.onap.functional.CsarValidationUtility.createExpectedError;
+import static org.onap.functional.CsarValidationUtility.getCliCommandValidationResult;
+import static org.onap.functional.CsarValidationUtility.verifyThatOperationFinishedWithoutAnyError;
+
+
+public class PnfValidationFunctionalTest {
+
+ @Test
+ public void shouldReportOnlyWarningWhenCsarDoNotHaveCertificateAndHashesInManifest() throws URISyntaxException {
+ // given
+ OnapCliValidationResponseWrapper.ValidationResultWrapper.ValidationErrorWrapper expectedWarning =
+ createExpectedError(CERTIFICATION_RULE, "0x1006",
+ "Warning. Consider adding package integrity and authenticity assurance according to ETSI NFV-SOL 004 Security Option 1");
+
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo( "pnf/validFile.csar"));
+
+ // when
+ cli.handle();
+
+ // then
+ final OnapCliValidationResponseWrapper result = getCliCommandValidationResult(cli);
+
+ assertThat(result.criteria).isEqualTo(OPERATION_STATUS_PASS);
+ result.results.forEach((ruleValidationResult)->{
+ assertThat(ruleValidationResult.errors).hasSize(0);
+ if (ruleValidationResult.vnfreqName.equals(CERTIFICATION_RULE)) {
+ assertThat(ruleValidationResult.warnings)
+ .hasSize(1)
+ .containsOnly(expectedWarning);
+ } else {
+ assertThat(ruleValidationResult.warnings).hasSize(0);
+ }
+ });
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldNotReportThatPnfValidationFailedWhenZipDoNotHaveCertificatesAndHashesInManifest() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo( "pnf/signed-package-valid-signature.zip"));
+
+ // when
+ cli.handle();
+
+ // then
+ final OnapCliValidationResponseWrapper result = getCliCommandValidationResult(cli);
+
+ assertThat(result.criteria).isEqualTo(OPERATION_STATUS_PASS);
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldReportThatPnfValidationFailedWhenCsarContainsCertificateInCmsAndInToscaAndInRootAndHashIsIncorrect_allOtherRulesShouldPass() throws URISyntaxException {
+ // given
+
+ List<OnapCliValidationResponseWrapper.ValidationResultWrapper.ValidationErrorWrapper> expectedErrors =
+ List.of(
+ createExpectedError(CERTIFICATION_RULE, "0x4007",
+ "File has invalid signature!"),
+ createExpectedError(CERTIFICATION_RULE, "0x4004",
+ "Source 'Files/pnf-sw-information/pnf-sw-information.yaml' has wrong hash!"),
+ createExpectedError(CERTIFICATION_RULE, "0x4011",
+ "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container"),
+ createExpectedError(CERTIFICATION_RULE, "0x4012",
+ "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container"),
+ createExpectedError(CERTIFICATION_RULE, "0x4013",
+ "Certificate present in root catalog despite the certificate is included in the signature container")
+ );
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo( "pnf/r130206/cert-in-cms-and-root-and-tosca-incorrect-hash.csar"));
+
+ // when
+ cli.handle();
+
+ // then
+ final OnapCliValidationResponseWrapper result = getCliCommandValidationResult(cli);
+
+ assertThat(result.criteria).isEqualTo(OPERATION_STATUS_FAILED);
+ result.results.forEach((ruleValidationResult)->{
+ assertThat(ruleValidationResult.warnings).hasSize(0);
+ if (ruleValidationResult.vnfreqName.equals(CERTIFICATION_RULE)) {
+ assertThat(ruleValidationResult.errors)
+ .hasSize(5)
+ .containsAll(expectedErrors);
+ } else {
+ assertThat(ruleValidationResult.errors).hasSize(0);
+ }
+ });
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ private String[] createPnfValidationRequestInfo(String csarPath) throws URISyntaxException {
+ return new String[]{
+ "--product", "onap-dublin",
+ "csar-validate",
+ "--format", "json",
+ "--pnf",
+ "--csar", absoluteFilePath(csarPath)
+ };
+ }
+
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/functional/VnfValidationFunctionalTest.java b/csarvalidation/src/test/java/org/onap/functional/VnfValidationFunctionalTest.java
new file mode 100644
index 0000000..adaea59
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/functional/VnfValidationFunctionalTest.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2017 Huawei Technologies Co., Ltd.
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.onap.functional;
+
+import org.junit.Test;
+import org.onap.functional.cli.OnapCliValidationResponseWrapper;
+import org.onap.functional.cli.OnapCliWrapper;
+
+import java.net.URISyntaxException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.absoluteFilePath;
+import static org.onap.functional.CsarValidationUtility.OPERATION_STATUS_FAILED;
+import static org.onap.functional.CsarValidationUtility.getCliCommandValidationResult;
+import static org.onap.functional.CsarValidationUtility.ruleHaveOneOfCodes;
+import static org.onap.functional.CsarValidationUtility.verifyThatOperationFinishedWithoutAnyError;
+
+public class VnfValidationFunctionalTest {
+
+
+ @Test
+ public void shouldReportThanVnfValidationFailed() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createVnfValidationRequestInfo("VoLTE.csar"));
+
+ // when
+ cli.handle();
+
+ // then
+ final OnapCliValidationResponseWrapper result = getCliCommandValidationResult(cli);
+ assertThat(result.criteria).isEqualTo(OPERATION_STATUS_FAILED);
+ result.results.forEach((ruleValidationResult)->{
+ if ( ruleHaveOneOfCodes(ruleValidationResult.vnfreqName,
+ "r01123", "r09467")
+ ) {
+ assertThat(ruleValidationResult.errors)
+ .hasSize(2);
+ } else if ( ruleHaveOneOfCodes(ruleValidationResult.vnfreqName,
+ "r21322","r26885","r43958" ,"r66070","r130206")
+ ) {
+ assertThat(ruleValidationResult.errors)
+ .hasSize(1);
+ } else {
+ assertThat(ruleValidationResult.errors).hasSize(0);
+ }
+ });
+
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ private String[] createVnfValidationRequestInfo(String csarPath) throws URISyntaxException {
+ return new String[]{
+ "--product", "onap-dublin",
+ "csar-validate",
+ "--format", "json",
+ "--csar", absoluteFilePath(csarPath)
+ };
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliValidationResponseWrapper.java b/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliValidationResponseWrapper.java
new file mode 100644
index 0000000..d011a6e
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliValidationResponseWrapper.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.onap.functional.cli;
+
+
+import java.util.List;
+import java.util.Objects;
+
+public class OnapCliValidationResponseWrapper {
+
+ public final VnfDataWrapper vnf;
+ public final String data;
+ public final String criteria;
+ public final List<ValidationResultWrapper> results;
+ public final String contact;
+ public final String platform;
+
+ public OnapCliValidationResponseWrapper(VnfDataWrapper vnf, String data, String criteria, List<ValidationResultWrapper> results, String contact, String platform) {
+ this.vnf = vnf;
+ this.data = data;
+ this.criteria = criteria;
+ this.results = results;
+ this.contact = contact;
+ this.platform = platform;
+ }
+
+ public static class VnfDataWrapper {
+ public String name;
+ public String vendor;
+ public String version;
+ public String type;
+ public String mode;
+ }
+
+ public static class ValidationResultWrapper {
+ public Boolean passed;
+ public String vnfreqName;
+ public String description;
+ public List<ValidationErrorWrapper> errors;
+ public List<ValidationErrorWrapper> warnings;
+
+ public static class ValidationErrorWrapper {
+ public String vnfreqNo;
+ public String code;
+ public String message;
+ public String file;
+ public String lineNumber;
+
+ public ValidationErrorWrapper(String vnfreqNo, String code, String message, String file, String lineNumber) {
+ this.vnfreqNo = vnfreqNo;
+ this.code = code;
+ this.message = message;
+ this.file = file;
+ this.lineNumber = lineNumber;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ return o.hashCode() == this.hashCode();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(vnfreqNo, code, message, file, lineNumber);
+ }
+ }
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliWrapper.java b/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliWrapper.java
new file mode 100644
index 0000000..b5cf589
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/functional/cli/OnapCliWrapper.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2020 Nokia
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.onap.functional.cli;
+
+
+import org.onap.cli.fw.cmd.OnapCommand;
+import org.onap.cli.fw.error.OnapCommandException;
+import org.onap.cli.fw.output.OnapCommandResult;
+import org.onap.cli.main.OnapCli;
+
+public class OnapCliWrapper extends OnapCli {
+
+ private OnapCommandResult commandResult;
+
+ public OnapCliWrapper(String[] args) {
+ super(args);
+ }
+
+ @Override
+ public void handleTracking(OnapCommand cmd) throws OnapCommandException {
+ super.handleTracking(cmd);
+ this.commandResult = cmd.getResult();
+ }
+
+ public OnapCommandResult getCommandResult() {
+ return this.commandResult;
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/CsarValidatorTest.java b/csarvalidation/src/test/java/org/onap/validation/csar/CsarValidatorTest.java
index f9a8d8a..bd363fc 100644
--- a/csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/CsarValidatorTest.java
+++ b/csarvalidation/src/test/java/org/onap/validation/csar/CsarValidatorTest.java
@@ -1,27 +1,30 @@
-/**
+/*
* Copyright 2017 Huawei Technologies Co., Ltd.
- *
+ * Copyright 2020 Nokia
+ * <p>
* 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* 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.
+ *
*/
-package org.onap.validation.csarvalidationtest;
+package org.onap.validation.csar;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -31,11 +34,12 @@ import java.util.regex.Pattern;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
-import org.junit.Test;
-import org.onap.validation.csar.CommonConstants;
-import org.onap.validation.csar.CsarValidator;
-import org.onap.validation.csar.FileUtil;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+@RunWith(MockitoJUnitRunner.class)
public class CsarValidatorTest {
String regex = "^\\/[a-zA-Z]\\:\\/";
@@ -156,12 +160,20 @@ public class CsarValidatorTest {
}
@Test
- public void testCloseInputStream() {
+ public void testCloseInputStreamForNonExistingDirectory() {
InputStream dir = null;
FileUtil.closeInputStream(dir);
assertTrue(true);
}
+ @Test(expected = ValidationException.class)
+ public void testCloseInputStream() throws IOException {
+ InputStream inputStream = mock(InputStream.class);
+ Mockito.doThrow(new IOException()).when(inputStream).close();
+ FileUtil.closeInputStream(inputStream);
+ assertTrue(true);
+ }
+
@Test
public void testCloseZipFile() throws ZipException, IOException {
File file = new File(sample1);
@@ -170,10 +182,19 @@ public class CsarValidatorTest {
assertTrue(true);
}
- @Test
- public void testCloseFileStream() throws FileNotFoundException {
+ @Test(expected = IOException.class)
+ public void testCloseFileStream() throws IOException {
FileInputStream dir3 = new FileInputStream(sample1);
FileUtil.closeFileStream(dir3);
+ dir3.available();
+
+ }
+
+ @Test(expected = ValidationException.class)
+ public void testCloseFileStream_reportErrorWhenIOExceptionOccurs() throws IOException {
+ FileInputStream fileInputStream = mock(FileInputStream.class);
+ Mockito.doThrow(new IOException()).when(fileInputStream).close();
+ FileUtil.closeFileStream(fileInputStream);
}
@Test
@@ -186,6 +207,14 @@ public class CsarValidatorTest {
}
};
FileUtil.closeOutputStream(dir4);
+ assertTrue(true);
+ }
+
+ @Test(expected = ValidationException.class)
+ public void testCloseOutptutStream_reportErrorWhenIOExceptionOccurs() throws IOException {
+ OutputStream outputStream = mock(OutputStream.class);
+ Mockito.doThrow(new IOException()).when(outputStream).close();
+ FileUtil.closeOutputStream(outputStream);
}
private void testValidateCsarMeta(CsarValidator cv) {
@@ -219,4 +248,44 @@ public class CsarValidatorTest {
String result = CsarValidator.r02454();
assertEquals(true, result == CommonConstants.SUCCESS_STR);
}
+
+ @Test
+ public void testValidateCsar_csarMetaFailed() {
+ CsarValidator.CsarValidatorSeam csarValidatorSeam = mock(CsarValidator.CsarValidatorSeam.class);
+ Mockito.when(csarValidatorSeam.validateCsarMeta()).thenReturn("FAIL");
+ Mockito.when(csarValidatorSeam.validateAndScanToscaMeta()).thenReturn("SUCCESS");
+ Mockito.when(csarValidatorSeam.validateMainService()).thenReturn("FAIL");
+
+
+ String res=CsarValidator.validateCsarContent(csarValidatorSeam);
+ assertEquals("FAIL OR FAIL",res);
+
+ }
+
+ @Test
+ public void testValidateCsar_toscaMetaFailed() {
+ CsarValidator.CsarValidatorSeam csarValidatorSeam = mock(CsarValidator.CsarValidatorSeam.class);
+ Mockito.when(csarValidatorSeam.validateCsarMeta()).thenReturn("SUCCESS");
+ Mockito.when(csarValidatorSeam.validateAndScanToscaMeta()).thenReturn("FAIL");
+ Mockito.when(csarValidatorSeam.validateMainService()).thenReturn("SUCCESS");
+
+
+ String res=CsarValidator.validateCsarContent(csarValidatorSeam);
+ assertEquals("FAIL",res);
+ }
+
+ @Test
+ public void testDeleteDir(){
+ String dstPath = "./dstPathForTest1";
+ File dst = new File(dstPath);
+ dst.mkdir();
+ assertTrue(FileUtil.deleteFile(dstPath));
+ }
+
+ @Test
+ public void testCreateDirectory() {
+ String dirPath = "src//test//resources//TestDirectory";
+ boolean res = FileUtil.createDirectory(dirPath);
+ assertTrue(res);
+ }
}
diff --git a/csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/ValidationExceptionTest.java b/csarvalidation/src/test/java/org/onap/validation/csar/ValidationExceptionTest.java
index 8ab498e..fcbc439 100644
--- a/csarvalidation/src/test/java/org/onap/validation/csarvalidationtest/ValidationExceptionTest.java
+++ b/csarvalidation/src/test/java/org/onap/validation/csar/ValidationExceptionTest.java
@@ -1,20 +1,21 @@
-/**
- * Copyright 2017 Huawei Technologies Co., Ltd.
+/*
+ * Copyright 2020 Nokia
* <p>
* 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
* <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* 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.
+ *
*/
-package org.onap.validation.csarvalidationtest;
+package org.onap.validation.csar;
import static org.junit.Assert.assertTrue;
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/YamlFileValidatorTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlFileValidatorTest.java
new file mode 100644
index 0000000..f89cc68
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlFileValidatorTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.yaml.snakeyaml.parser.ParserException;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class YamlFileValidatorTest {
+
+ @Test
+ public void shouldReturnCorrectErrorsWhenGivenPathToValidPmDictionaryFile() throws YamlProcessingException {
+ // given
+ String path = getFullPathForGivenResources(YamlLoadingUtils.PATH_TO_VALID_YAML);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors =
+ new YamlFileValidator().validateYamlFileWithSchema(path);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+
+ }
+
+ @Test
+ public void shouldReturnCorrecErrorsWhenGivenPathToValidJsonStylePmDictionaryFile() throws YamlProcessingException {
+ // given
+ String path = getFullPathForGivenResources(YamlLoadingUtils.PATH_TO_VALID_JSON_STYLE_YAML);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors =
+ new YamlFileValidator().validateYamlFileWithSchema(path);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+ }
+
+
+ private void assertValidationReturnedExpectedErrors(List<YamlDocumentValidationError> validationErrors) {
+ assertThat(validationErrors).isNotNull();
+ assertThat(validationErrors).hasSize(4);
+ assertThat(validationErrors).usingRecursiveFieldByFieldElementComparator().containsAll(
+ Lists.list(
+ new YamlDocumentValidationError(1,
+ "/pmMetaData/pmFields/measResultType",
+ "Value(s) is/are not in array of accepted values.\n" +
+ " value(s): integer\n" +
+ " accepted value(s): [float, uint32, uint64]"),
+ new YamlDocumentValidationError(1,
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"),
+ new YamlDocumentValidationError(2,
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"),
+ new YamlDocumentValidationError(3,
+ "/pmMetaData/pmFields/measAdditionalFields/vendorField1",
+ "Value(s) is/are not in array of accepted values.\n" +
+ " value(s): [Z, A]\n" +
+ " accepted value(s): [X, Y, Z]")
+ )
+ );
+ }
+ @Test
+ public void shouldThrowErrorWhenGivenPathToInvalidPmDictionaryFile() {
+ // given
+ String path = getFullPathForGivenResources(YamlLoadingUtils.PATH_TO_MULTI_DOCUMENT_INVALID_YAML);
+ // when then
+ assertThatThrownBy(() ->
+ new YamlFileValidator().validateYamlFileWithSchema(path)
+ ).isInstanceOf(ParserException.class)
+ .hasMessageContaining(
+ "expected the node content, but found '<document end>'"
+ );
+ }
+
+ @Test
+ public void shouldThrowErrorWhenGivenInvalidPath() {
+ // given
+ String path ="invalid/path/to/pm_dictionary";
+
+ // when then
+ assertThatThrownBy(() ->
+ new YamlFileValidator().validateYamlFileWithSchema(path)
+ ).isInstanceOf(YamlProcessingException.class)
+ .hasMessageContaining(
+ "PM_Dictionary YAML file is empty"
+ );
+ }
+
+ private String getFullPathForGivenResources(String pathToValidYaml) {
+ return this.getClass().getClassLoader().getResource(
+ pathToValidYaml
+ ).getPath();
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java
new file mode 100644
index 0000000..4c68d60
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.junit.Test;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.yaml.snakeyaml.parser.ParserException;
+import org.yaml.snakeyaml.scanner.ScannerException;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+
+public class YamlLoaderTest {
+
+ private static final int EXPECTED_NUMBER_OF_DOCUMENTS = 5;
+ private static final String LETTER_S_WITH_ASCII_CODE = "s(115)";
+
+ @Test
+ public void shouldLoadAllDocumentsFromYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ public void shouldLoadAllDocumentsFromJsonStyleYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidJsonStyleMultiDocumentYamlFile();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ public void shouldLoadAllDocumentsFromYamlFileUsingPathInString() throws YamlProcessingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFileUsingStringPath();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ public void shouldThrowExceptionWhenLoadingDocumentsFromInvalidYamlFile() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadMultiDocumentInvalidYamlFile
+ ).isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+ @Test
+ public void shouldThrowExceptionWhenLoadingDocumentsFromInvalidYamlFileUsingPathInString() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadMultiDocumentInvalidYamlFileUsingStringPath
+ ).isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+
+ @Test
+ public void shouldThrowExceptionWhenLoadingInvalidYamlFileWithIncorrectKeyMapping() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadInvalidYamlFileWithIncorrectKeyMapping
+ ).isInstanceOf(ScannerException.class)
+ .hasMessageContaining("mapping values are not allowed here");
+ }
+
+
+ @Test
+ public void shouldThrowExceptionWhenLoadingInvalidYamlFileWithUnknownEscapeCharacter() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadInvalidYamlFileWithUnknownEscapeCharacter
+ ).isInstanceOf(ScannerException.class)
+ .hasMessageContaining("found unknown escape character " + LETTER_S_WITH_ASCII_CODE);
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java
new file mode 100644
index 0000000..8d03910
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+
+import java.net.URL;
+import java.util.List;
+
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+public final class YamlLoadingUtils {
+
+ private YamlLoadingUtils() {}
+
+ public static final int VALID_YAML_DOCUMENT_INDEX = 4;
+ public static final int YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX = 3;
+ public static final int YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX = 2;
+ public static final int YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX = 1;
+
+ static final String PATH_TO_VALID_YAML = "yaml_schema/PM_Dictionary.yaml";
+ static final String PATH_TO_VALID_JSON_STYLE_YAML = "yaml_schema/PM_Dictionary_JSON_Style.yaml";
+ private static final String PATH_TO_SIMPLE_VALID_SCHEMA = "yaml_schema/Simple_Valid_Schema.yaml";
+ private static final String PATH_TO_SIMPLE_VALID_SCHEMA_MULTI_ROOT = "yaml_schema/Simple_Valid_Schema_Multi_Root.yaml";
+ private static final String PATH_TO_SIMPLE_INVALID_SCHEMA = "yaml_schema/Simple_Invalid_Schema_Construction.yaml";
+ private static final String PATH_TO_SIMPLE_INVALID_SCHEMA_FOR_LAZY_LOADING = "yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml";
+ static final String PATH_TO_MULTI_DOCUMENT_INVALID_YAML = "yaml_schema/Multi_Document_Invalid.yaml";
+ private static final String PATH_TO_INVALID_YAML_WITH_INCORRECT_KEY_MAPPING = "yaml_schema/Simple_Invalid_Mapping_Value.yaml";
+ private static final String PATH_TO_INVALID_YAML_WITH_UNKNOWN_ESCAPE_CHARACTER = "yaml_schema/Simple_Unknown_Escape_Character.yaml";
+
+ public static List<YamlDocument> loadValidMultiDocumentYamlFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_VALID_YAML));
+ }
+
+ public static List<YamlDocument> loadValidJsonStyleMultiDocumentYamlFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_VALID_JSON_STYLE_YAML));
+ }
+
+ public static List<YamlDocument> loadValidMultiDocumentYamlFileUsingStringPath() throws YamlProcessingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_VALID_YAML).getPath());
+ }
+
+ public static YamlDocument loadSimpleValidYamlSchemaFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_VALID_SCHEMA)).get(0);
+ }
+
+ public static YamlDocument loadSimpleInvalidYamlSchemaFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_INVALID_SCHEMA)).get(0);
+ }
+
+ public static YamlDocument loadSimpleInvalidYamlSchemaForLazyLoadingFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_INVALID_SCHEMA_FOR_LAZY_LOADING)).get(0);
+ }
+
+ public static YamlDocument loadSimpleValidYamlSchemaWithMultiRootFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_VALID_SCHEMA_MULTI_ROOT)).get(0);
+ }
+
+ public static List<YamlDocument> tryToLoadMultiDocumentInvalidYamlFile() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_MULTI_DOCUMENT_INVALID_YAML));
+ }
+
+ public static List<YamlDocument> tryToLoadMultiDocumentInvalidYamlFileUsingStringPath() throws YamlProcessingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_MULTI_DOCUMENT_INVALID_YAML).getPath());
+ }
+
+ public static List<YamlDocument> tryToLoadInvalidYamlFileWithIncorrectKeyMapping() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_INVALID_YAML_WITH_INCORRECT_KEY_MAPPING));
+ }
+
+ public static List<YamlDocument> tryToLoadInvalidYamlFileWithUnknownEscapeCharacter() throws YamlDocumentParsingException {
+ return new YamlLoader().loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_INVALID_YAML_WITH_UNKNOWN_ESCAPE_CHARACTER));
+ }
+
+ private static URL getUrlForGivenPath(String path) {
+ return YamlLoadingUtils.class.getClassLoader().getResource(path);
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java
new file mode 100644
index 0000000..efe9d69
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.validation.yaml.YamlLoadingUtils.VALID_YAML_DOCUMENT_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX;
+
+public class YamlValidatorTest {
+
+
+ @Test
+ public void shouldCreateValidatorUsingSchemaLoadedFromYamlFileAndValidatedJsonStyleDocumentsFromThatFile()
+ throws YamlProcessingException {
+
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidJsonStyleMultiDocumentYamlFile();
+ YamlValidator validator = new YamlValidator(new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0)));
+ Map<Integer,List<SchemaValidationError>> validationErrors = new HashMap<>();
+
+ // when
+ for (int documentIndex = 1 ; documentIndex < documents.size() ; documentIndex++) {
+ validationErrors.put(documentIndex, validator.validate(documents.get(documentIndex)));
+ }
+
+ // then
+ assertValidatorReturnedCorrectErrors(validationErrors);
+ }
+
+ @Test
+ public void shouldCreateValidatorUsingSchemaLoadedFromYamlFileAndValidatedDocumentsFromThatFile()
+ throws YamlProcessingException {
+
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlValidator validator = new YamlValidator(new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0)));
+ Map<Integer,List<SchemaValidationError>> validationErrors = new HashMap<>();
+
+ // when
+ for (int documentIndex = 1 ; documentIndex < documents.size() ; documentIndex++) {
+ validationErrors.put(documentIndex, validator.validate(documents.get(documentIndex)));
+ }
+
+ // then
+ assertValidatorReturnedCorrectErrors(validationErrors);
+ }
+
+ private void assertValidatorReturnedCorrectErrors(Map<Integer, List<SchemaValidationError>> validationErrors) {
+
+ SchemaValidationError expectedValidationValueError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/measResultType",
+ "Value(s) is/are not in array of accepted values.\n"
+ + " value(s): integer\n"
+ + " accepted value(s): [float, uint32, uint64]"
+ );
+ SchemaValidationError expectedValidationKeyError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"
+ );
+ SchemaValidationError expectedValidationValuesInArrayError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/measAdditionalFields/vendorField1",
+ "Value(s) is/are not in array of accepted values.\n"
+ + " value(s): [Z, A]\n"
+ + " accepted value(s): [X, Y, Z]"
+ );
+
+ assertThat(validationErrors.size()).isEqualTo(4);
+ assertThat(validationErrors).containsKeys(1,2,3);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX)).hasSize(2);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX))
+ .usingFieldByFieldElementComparator()
+ .containsAll(
+ Lists.list(
+ expectedValidationValueError,
+ expectedValidationKeyError
+ ));
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX)).hasSize(1);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX))
+ .usingFieldByFieldElementComparator()
+ .contains(
+ expectedValidationKeyError
+ );
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX)).hasSize(1);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX))
+ .usingFieldByFieldElementComparator()
+ .contains(
+ expectedValidationValuesInArrayError
+ );
+ assertThat(validationErrors.get(VALID_YAML_DOCUMENT_INDEX)).hasSize(0);
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java
new file mode 100644
index 0000000..7879d4e
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+public class YamlDocumentFactoryTest {
+
+ @Test
+ public void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToReturnStringifyValues()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = new HashMap<>();
+ List<String> testList = Lists.list("element1", "element11");
+ Map<Object, Object> testEmptyMap = Collections.emptyMap();
+
+ inputMap.put("test", testList);
+ inputMap.put(345, "element2");
+ inputMap.put("test2", "element3");
+ inputMap.put(2.67, testEmptyMap);
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertThat(document).isNotNull();
+ assertThat(document.getYaml()).containsKeys("test", "345", "test2", "2.67");
+
+ assertThat(document.getYaml()).containsEntry("test", testList);
+ assertThat(document.getValue("test")).isEqualTo("[element1, element11]");
+
+ assertThat(document.getValue("345")).isEqualTo("element2");
+ assertThat(document.getValue("test2")).isEqualTo("element3");
+
+ assertThat(document.getYaml()).containsEntry("2.67", testEmptyMap);
+ assertThat(document.getValue("2.67")).isEqualTo("{}");
+ }
+
+ @Test
+ public void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToExtractSubStructure()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = new HashMap<>();
+ Map<Object, Object> subStructureMap = new HashMap<>();
+
+ inputMap.put("test", "element1");
+ inputMap.put("structure", subStructureMap);
+
+ subStructureMap.put("subTest1", "subElement1");
+ subStructureMap.put("subTest2", "subElement2");
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertThat(document).isNotNull();
+ assertThat(document.getYaml()).containsKeys("test", "structure");
+ assertThat(document.getValue("test")).isEqualTo("element1");
+
+ assertThat(document.getSubStructure("structure")).isNotNull();
+ assertThat(document.getSubStructure("structure").getValue("subTest1")).isEqualTo("subElement1");
+ assertThat(document.getSubStructure("structure").getValue("subTest2")).isEqualTo("subElement2");
+ }
+
+ @Test
+ public void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToExtractParametersList()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = new HashMap<>();
+ List<String> parametersList = new LinkedList<>();
+
+ inputMap.put("test", "element1");
+ inputMap.put("parameters", parametersList);
+
+ parametersList.add("parameter1");
+ parametersList.add("parameter2");
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertThat(document).isNotNull();
+ assertThat(document.getYaml()).containsKeys("test", "parameters");
+ assertThat(document.getValue("test")).isEqualTo("element1");
+
+ assertThat(document.getListOfValues("parameters")).isNotNull();
+ assertThat(document.getListOfValues("parameters").getParameters()).contains("parameter1","parameter2");
+ }
+
+ @Test
+ public void shouldThrowExceptionIfGetSubStructureIsCalledOnList()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = new HashMap<>();
+ List<String> testList = Lists.list("element1", "element2");
+
+ inputMap.put("test", testList);
+
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // when then
+ assertThatThrownBy(() ->
+ document.getSubStructure("test")
+ ).isInstanceOf(YamlDocumentParsingException.class)
+ .hasMessageContaining(
+ String.format("Fail to parse given objects: %s as yaml document", testList)
+ );
+ }
+
+ @Test
+ public void shouldThrowExceptionIfGetSubStructureIsCalledOnString()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = new HashMap<>();
+
+ inputMap.put("test", "testElement");
+
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // when then
+ assertThatThrownBy(() ->
+ document.getSubStructure("test")
+ ).isInstanceOf(YamlDocumentParsingException.class)
+ .hasMessageContaining(
+ String.format("Fail to parse given objects: %s as yaml document.", "testElement")
+ );
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java
new file mode 100644
index 0000000..34e61c5
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class YamlParameterListFactoryTest {
+
+ @Test
+ public void shouldCreateEmptyParametersList() {
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createEmptyYamlParameterList();
+
+ // then
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters()).isEmpty();
+ }
+
+ @Test
+ public void shouldCreateParametersListContainingStringsFromListContainingSimpleTypes() {
+ // given
+ List<Object> testList = Lists.list("test1",3,23.45,'a',"test2");
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testList);
+
+ // then
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters()).hasSize(5);
+ assertThat(parametersList.getParameters()).contains("test1","test2","3","23.45","a");
+ }
+
+ @Test
+ public void shouldCreateParametersListContainingStringsFromListContainingVariousTypes() {
+ // given
+ List<Object> testList = Lists.list("test1",3,Lists.list(2,3,4),"test2");
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testList);
+
+ // then
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters()).hasSize(4);
+ assertThat(parametersList.getParameters()).contains("test1","test2","3","[2, 3, 4]");
+ }
+
+ @Test
+ public void shouldCreateListWithOneStringWhenGivenObjectIsNotList() {
+ // given
+ Object testObject = "test";
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testObject);
+
+ // then
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters()).hasSize(1);
+ assertThat(parametersList.getParameters()).contains("test");
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java
new file mode 100644
index 0000000..12fe9ec
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.junit.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.YamlLoadingUtils.VALID_YAML_DOCUMENT_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX;
+
+
+public class YamlValidationProcessTest {
+
+ @Test
+ public void shouldReturnNoErrorWhenProcessingValidPmDictionaryYaml()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(VALID_YAML_DOCUMENT_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema,document).validate();
+
+ // then
+ assertThat(errors).isEmpty();
+ }
+
+ @Test
+ public void shouldReturnOneErrorWhenProcessingPmDictionaryYamlWithMissingField()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema,document).validate();
+
+ // then
+ assertThat(errors).hasSize(1);
+ }
+
+ @Test
+ public void shouldReturnTwoErrorsWhenProcessingPmDictionaryYamlWithMissingFieldAndIncorrectValue()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema,document).validate();
+
+ // then
+ assertThat(errors).hasSize(2);
+ }
+
+ @Test
+ public void shouldThrowExceptionWhenProcessingPmDictionaryIsNotValidYaml()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlDocument schemaInYaml = YamlLoadingUtils.loadSimpleInvalidYamlSchemaForLazyLoadingFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(schemaInYaml);
+ YamlDocument document = documents.get(VALID_YAML_DOCUMENT_INDEX);
+
+ // when then
+ assertThatThrownBy(() ->
+ new YamlValidationProcess(schema,document).validate()
+ ).isInstanceOf(YamlProcessingException.class)
+ .hasMessageContaining(
+ String.format("Lazy loading failed, due to yaml parsing exception.")
+ );
+ }
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java
new file mode 100644
index 0000000..4c05d71
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema;
+
+import org.junit.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory.EMPTY_COMMENT;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactoryTest.assertThatBranchNodeIsValid;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactoryTest.assertThatLeafNodeIsValid;
+
+
+public class YamlSchemaFactoryTest {
+
+ @Test
+ public void shouldCreateYamlSchemaFromYamlDocumentWithMultipleRoots()
+ throws YamlProcessingException {
+
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleValidYamlSchemaWithMultiRootFile();
+
+ // when
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents);
+
+ // then
+ assertThat(schema).isNotNull();
+ assertThat(schema.getRootNodes()).hasSize(3);
+ assertThat(schema.getRootNodes().get(0).getName()).isEqualTo("root1");
+ assertThat(schema.getRootNodes().get(1).getName()).isEqualTo("root2");
+ assertThat(schema.getRootNodes().get(2).getName()).isEqualTo("root3");
+ }
+
+
+ @Test
+ public void shouldCreateYamlSchemaFromYamlDocument()
+ throws YamlProcessingException {
+
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleValidYamlSchemaFile();
+
+ // when
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents);
+
+ // then
+ assertThat(schema).isNotNull();
+ assertThat(schema.getRootNodes()).hasSize(1);
+ YamlSchemaNode pmMetaData = schema.getRootNodes().get(0);
+ assertThatBranchNodeIsValid(pmMetaData, "pmMetaData","/", true, EMPTY_COMMENT,
+ 2);
+
+ YamlSchemaNode pmHeader = pmMetaData.getNextNodes().get(1);
+ assertThatBranchNodeIsValid(pmHeader, "pmHeader","/pmMetaData/", true, EMPTY_COMMENT,
+ 1);
+
+ YamlSchemaNode nfType = pmHeader.getNextNodes().get(0);
+ assertThatLeafNodeIsValid(nfType, "nfType", "/pmMetaData/pmHeader/", true, "nfType comment");
+
+ YamlSchemaNode pmFields = pmMetaData.getNextNodes().get(0);
+ assertThatBranchNodeIsValid(pmFields, "pmFields", "/pmMetaData/", true, EMPTY_COMMENT,
+ 2);
+
+ YamlSchemaNode measChangeType = pmFields.getNextNodes().get(1);
+ assertThatLeafNodeIsValid(measChangeType, "measChangeType", "/pmMetaData/pmFields/",
+ true, "measChangeType comment",
+ "added", "modified", "deleted");
+
+ YamlSchemaNode measAdditionalFields = pmFields.getNextNodes().get(0);
+ assertThatBranchNodeIsValid(measAdditionalFields, "measAdditionalFields", "/pmMetaData/pmFields/",
+ true, "measAdditionalFields comment",
+ 2);
+
+ YamlSchemaNode vendorField1 = measAdditionalFields.getNextNodes().get(0);
+ assertThatLeafNodeIsValid(vendorField1, "vendorField1", "/pmMetaData/pmFields/measAdditionalFields/",
+ true, "vendorField1 comment",
+ "X", "Y", "Z");
+ YamlSchemaNode vendorField2 = measAdditionalFields.getNextNodes().get(1);
+ assertThatLeafNodeIsValid(vendorField2, "vendorField2", "/pmMetaData/pmFields/measAdditionalFields/",
+ false, "vendorField2 comment",
+ "A", "B");
+ }
+
+ @Test
+ public void shouldThrowYamlParsingExceptionWhenLoadedSchemaIsInvalid()
+ throws YamlDocumentParsingException {
+
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleInvalidYamlSchemaFile();
+
+ // when/then
+ assertThatThrownBy(() ->
+ new YamlSchemaFactory().createTreeStructuredYamlSchema(documents)
+ ).isInstanceOf(YamlDocumentParsingException.class)
+ .hasMessageContaining(
+ String.format(
+ "Fail to parse given objects: %s as yaml document",
+ documents.getSubStructure("pmMetaData").getYaml().get("structure")
+ )
+ );
+ }
+
+}
diff --git a/csarvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java b/csarvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java
new file mode 100644
index 0000000..d35e3b2
--- /dev/null
+++ b/csarvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory.EMPTY_COMMENT;
+
+public class YamlSchemaNodeFactoryTest {
+
+ private static final String ROOT_PATH = "/";
+
+ @Test
+ public void shouldThrowExceptionDuringLazyLoadingWhenLoadedSchemaHaveInvalidSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "pmMetaData";
+
+ YamlDocument document = YamlLoadingUtils.loadSimpleInvalidYamlSchemaForLazyLoadingFile();
+ YamlSchemaNode node = new YamlSchemaNodeFactory()
+ .createNode(nodeName, ROOT_PATH, document.getSubStructure(nodeName));
+
+ // when/then
+ assertThatThrownBy(node::getNextNodes
+ ).isInstanceOf(YamlSchemaNode.YamlSchemaProcessingException.class)
+ .hasMessageContaining(
+ "Lazy loading failed, due to yaml parsing exception."
+ );
+ }
+
+ @Test
+ public void shouldCreateLeafNodeIfGivenYamlDocumentHaveNoSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "leaf_test";
+ String comment = "test leaf node";
+ List<String> acceptedValues = Lists.list("val1", "val2");
+ Map<Object, Object> nodeInYamlFormat = new HashMap<>();
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.PRESENCE_KEY, YamlSchemaNodeFactory.PRESENCE_REQUIRED_KEY);
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.COMMENT_KEY, comment);
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.VALUE_KET, acceptedValues);
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(
+ nodeInYamlFormat
+ );
+
+ // when
+ YamlSchemaNode yamlSchemaNode = new YamlSchemaNodeFactory().createNode(nodeName, ROOT_PATH, document);
+
+ // then
+ assertThatLeafNodeIsValid(
+ yamlSchemaNode, nodeName, ROOT_PATH, true, comment,
+ acceptedValues.toArray(new String[acceptedValues.size()])
+ );
+ }
+
+ @Test
+ public void shouldCreateBranchNodeIfGivenYamlDocumentHaveSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "branch_test";
+ String comment = "test branch node";
+
+ Map<Object, Object> subStructure = new HashMap<>();
+ String subNode1Name = "branch_test_node1";
+ String subNode2Name = "branch_test_node2";
+ subStructure.put(subNode1Name, new HashMap<>());
+ subStructure.put(subNode2Name, new HashMap<>());
+
+ Map<Object, Object> nodeInYamlFormat = new HashMap<>();
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.PRESENCE_KEY, YamlSchemaNodeFactory.PRESENCE_REQUIRED_KEY);
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.COMMENT_KEY, comment);
+ nodeInYamlFormat.put(YamlSchemaNodeFactory.STRUCTURE_KEY, subStructure);
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(
+ nodeInYamlFormat
+ );
+
+ // when
+ YamlSchemaNode yamlSchemaNode = new YamlSchemaNodeFactory().createNode(nodeName, ROOT_PATH, document);
+
+ // then
+ assertThatBranchNodeIsValid(
+ yamlSchemaNode, nodeName, ROOT_PATH, true, comment, 2);
+
+ List<YamlSchemaNode> subNodes = yamlSchemaNode.getNextNodes();
+ assertThat(subNodes).hasSize(2);
+ assertThatLeafNodeIsValid(
+ subNodes.get(1), subNode1Name, ROOT_PATH + nodeName + "/", false, EMPTY_COMMENT);
+ assertThatLeafNodeIsValid(
+ subNodes.get(0), subNode2Name, ROOT_PATH + nodeName + "/", false, EMPTY_COMMENT);
+ }
+
+ public static void assertThatBranchNodeIsValid(
+ YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment,
+ int numberOfSubNodes
+ ) throws YamlSchemaNode.YamlSchemaProcessingException {
+ assertThatNodeIsValid(yamlSchemaNode, name, path, isRequired, comment);
+
+ assertThat(yamlSchemaNode.getClass()).isEqualTo(YamlSchemaBranchNode.class);
+ assertThat(yamlSchemaNode.isContainingSubStructure()).isTrue();
+ assertThat(yamlSchemaNode.getNextNodes()).hasSize(numberOfSubNodes);
+ assertThat(yamlSchemaNode.getAcceptedValues()).isEmpty();
+ }
+
+ public static void assertThatLeafNodeIsValid(
+ YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment,
+ String... acceptedValues
+ ) throws YamlSchemaNode.YamlSchemaProcessingException {
+ assertThatNodeIsValid(yamlSchemaNode, name, path, isRequired, comment);
+
+ assertThat(yamlSchemaNode.getClass()).isEqualTo(YamlSchemaLeafNode.class);
+ assertThat(yamlSchemaNode.isContainingSubStructure()).isFalse();
+ assertThat(yamlSchemaNode.getAcceptedValues()).containsExactly(acceptedValues);
+ assertThat(yamlSchemaNode.getNextNodes()).isEmpty();
+ }
+
+ private static void assertThatNodeIsValid(YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment) {
+ assertThat(yamlSchemaNode).isNotNull();
+ assertThat(yamlSchemaNode.getName()).isEqualTo(name);
+ assertThat(yamlSchemaNode.getPath()).isEqualTo(path);
+ if (comment.isEmpty()) {
+ assertThat(yamlSchemaNode.getComment()).isNotEmpty();
+ } else {
+ assertThat(yamlSchemaNode.getComment()).isEqualTo(comment);
+ }
+ assertThat(yamlSchemaNode.isRequired()).isEqualTo(isRequired);
+ }
+}
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-missing-files.csar b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-missing-files.csar
new file mode 100644
index 0000000..bab095d
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-missing-files.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-invalid.csar b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noFileInManifest.csar
index 187c008..26e3971 100644
--- a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-invalid.csar
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noFileInManifest.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor-noFileInManifest.csar b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor-noFileInManifest.csar
new file mode 100644
index 0000000..b9136c8
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor-noFileInManifest.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor.csar b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor.csar
new file mode 100644
index 0000000..11bddbb
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-invalid-noVendor.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option1-valid.csar b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-valid.csar
new file mode 100644
index 0000000..62b18eb
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option1-valid.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option2-invalid-with-cms.zip b/csarvalidation/src/test/resources/pnf/r01123/csar-option2-invalid-with-cms.zip
new file mode 100644
index 0000000..8c30c68
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option2-invalid-with-cms.zip
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r01123/csar-option2-valid-with-cms.zip b/csarvalidation/src/test/resources/pnf/r01123/csar-option2-valid-with-cms.zip
new file mode 100644
index 0000000..6965b95
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r01123/csar-option2-valid-with-cms.zip
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/cert-in-cms-and-root-and-tosca-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/cert-in-cms-and-root-and-tosca-incorrect-hash.csar
new file mode 100644
index 0000000..bf19010
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/cert-in-cms-and-root-and-tosca-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca-incorrect-hash.csar
new file mode 100644
index 0000000..c8a4c39
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca.csar
new file mode 100644
index 0000000..b47f565
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-and-tosca.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-incorrect-hash.csar
new file mode 100644
index 0000000..392d41e
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root.csar
new file mode 100644
index 0000000..f9112c7
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-root.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca-incorrect-hash.csar
new file mode 100644
index 0000000..f331233
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca.csar
new file mode 100644
index 0000000..0854291
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-and-tosca.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-incorrect-hash.csar
new file mode 100644
index 0000000..12c90a2
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid.csar
new file mode 100644
index 0000000..ece4064
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms-valid.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms.csar
new file mode 100644
index 0000000..5ddbe1a
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-cms.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca-incorrect-hash.csar
new file mode 100644
index 0000000..be19521
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca.csar
new file mode 100644
index 0000000..e4dbef9
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-and-tosca.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-incorrect-hash.csar
new file mode 100644
index 0000000..b926aac
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-pointed-by-tosca.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-pointed-by-tosca.csar
new file mode 100644
index 0000000..0d9c3f3
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root-pointed-by-tosca.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root.csar
new file mode 100644
index 0000000..66c1a71
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-root.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-incorrect-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-incorrect-hash.csar
new file mode 100644
index 0000000..9b651d0
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-incorrect-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-no-cms.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-no-cms.csar
new file mode 100644
index 0000000..fe34a61
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-no-cms.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-valid.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-valid.csar
new file mode 100644
index 0000000..3446aaf
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca-valid.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca.csar
new file mode 100644
index 0000000..c4168dc
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-cert-in-tosca.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-no-cert-no-tosca-dir.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-no-cert-no-tosca-dir.csar
new file mode 100644
index 0000000..0b00af1
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-no-cert-no-tosca-dir.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-no-cms-no-cert-with-hash.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-no-cms-no-cert-with-hash.csar
new file mode 100644
index 0000000..826425e
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-no-cms-no-cert-with-hash.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-not-secure-warning.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-not-secure-warning.csar
new file mode 100644
index 0000000..6520a61
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-not-secure-warning.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-valid.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-option1-valid.csar
deleted file mode 100644
index 08c3605..0000000
--- a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-valid.csar
+++ /dev/null
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-validSection.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-option1-validSection.csar
deleted file mode 100644
index bc90a75..0000000
--- a/csarvalidation/src/test/resources/pnf/r130206/csar-option1-validSection.csar
+++ /dev/null
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-cert-pointing-non-existing-cert.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-cert-pointing-non-existing-cert.csar
new file mode 100644
index 0000000..b392fac
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-cert-pointing-non-existing-cert.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-no-cert-entry.csar b/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-no-cert-entry.csar
new file mode 100644
index 0000000..d5c27e1
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r130206/csar-with-tosca-no-cert-entry.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r146092/validFile.csar b/csarvalidation/src/test/resources/pnf/r146092/validFile.csar
new file mode 100644
index 0000000..e805765
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r146092/validFile.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-empty-pm-dictionary.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-empty-pm-dictionary.csar
new file mode 100644
index 0000000..d0dbdf0
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-empty-pm-dictionary.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-invalid-mapping.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-invalid-mapping.csar
new file mode 100644
index 0000000..b69b79a
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-invalid-mapping.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-unknown-escape-character.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-unknown-escape-character.csar
new file mode 100644
index 0000000..9ed6270
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary-unknown-escape-character.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary.csar
new file mode 100644
index 0000000..81a0e23
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-invalid-pm-dictionary.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-missing-source-value-for-pm-dictionary-in-manifest.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-missing-source-value-for-pm-dictionary-in-manifest.csar
new file mode 100644
index 0000000..cd35d37
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-missing-source-value-for-pm-dictionary-in-manifest.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-no-pm-dictionary.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-no-pm-dictionary.csar
new file mode 100644
index 0000000..f0d4216
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-no-pm-dictionary.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/csar-with-valid-pm-dictionary.csar b/csarvalidation/src/test/resources/pnf/r816745/csar-with-valid-pm-dictionary.csar
new file mode 100644
index 0000000..528a002
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/csar-with-valid-pm-dictionary.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/zip-with-invalid-pm-dictionary.zip b/csarvalidation/src/test/resources/pnf/r816745/zip-with-invalid-pm-dictionary.zip
new file mode 100644
index 0000000..032dc78
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/zip-with-invalid-pm-dictionary.zip
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r816745/zip-with-valid-pm-dictionary.zip b/csarvalidation/src/test/resources/pnf/r816745/zip-with-valid-pm-dictionary.zip
new file mode 100644
index 0000000..b8c26d3
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r816745/zip-with-valid-pm-dictionary.zip
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r972082/fileExtensionOfArtifactIsNotYaml.csar b/csarvalidation/src/test/resources/pnf/r972082/fileExtensionOfArtifactIsNotYaml.csar
new file mode 100644
index 0000000..f485172
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r972082/fileExtensionOfArtifactIsNotYaml.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r972082/invalidYamlStructure.csar b/csarvalidation/src/test/resources/pnf/r972082/invalidYamlStructure.csar
new file mode 100644
index 0000000..3360ce4
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r972082/invalidYamlStructure.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingOnapPnfSwInformationArtifactSetEntry.csar b/csarvalidation/src/test/resources/pnf/r972082/missingOnapPnfSwInformationArtifactSetEntry.csar
new file mode 100644
index 0000000..518aaa8
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r972082/missingOnapPnfSwInformationArtifactSetEntry.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingSourceElementUnderAttributeError.csar b/csarvalidation/src/test/resources/pnf/r972082/missingSourceElementUnderAttributeError.csar
new file mode 100644
index 0000000..e11093c
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/r972082/missingSourceElementUnderAttributeError.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/toscaMetaFile.csar b/csarvalidation/src/test/resources/pnf/toscaMetaFile.csar
new file mode 100644
index 0000000..9370df9
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/toscaMetaFile.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/pnf/validFile.csar b/csarvalidation/src/test/resources/pnf/validFile.csar
new file mode 100644
index 0000000..11d1945
--- /dev/null
+++ b/csarvalidation/src/test/resources/pnf/validFile.csar
Binary files differ
diff --git a/csarvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml b/csarvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml
new file mode 100644
index 0000000..aab34fa
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml
@@ -0,0 +1,86 @@
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 1,
+
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.",
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: integer,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChAttempt,
+ measAdditionalFields: {
+ vendorField1: X,
+ vendorField2: B
+ }
+ }
+}
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 2,
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message.",
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp,
+ measAdditionalFields: {
+ vendorField1: Y
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: Z,
+ vendorField2: A
+ }
+ }
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml b/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml
new file mode 100644
index 0000000..12a4af9
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml
@@ -0,0 +1,228 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange."
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 2
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message."
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp
+ measAdditionalFields:
+ vendorField1:
+ - Y
+ - X
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2206
+ iMeasType: 1
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message."
+ measCollectionMethod: CC
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G19_1906_002
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measChangeType: added
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef
+ measAdditionalFields:
+ vendorField1:
+ - Z
+ - A
+ vendorField2: A
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2206
+ iMeasType: 1
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message."
+ measCollectionMethod: CC
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G19_1906_002
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measChangeType: added
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef
+ measAdditionalFields:
+ vendorField1:
+ - X
+ - Y
+ vendorField2: A
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml b/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml
new file mode 100644
index 0000000..f4cbddf
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml
@@ -0,0 +1,239 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 1,
+
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.",
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: integer,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChAttempt,
+ measAdditionalFields: {
+ vendorField1: X,
+ vendorField2: B
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 2,
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message.",
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp,
+ measAdditionalFields: {
+ vendorField1: [Y,Z]
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: [Z,A],
+ vendorField2: A
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: [X,Y],
+ vendorField2: A
+ }
+ }
+}
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml
new file mode 100644
index 0000000..25c72cd
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml
@@ -0,0 +1,149 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.
+ measDescription: This counter indicates the number of intra gNB intra frequency PSCell change attempts.
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml
new file mode 100644
index 0000000..c5e7b7c
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: [
+ -pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ -pmFields: {
+ presence: required,
+ structure: {
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ }
+ }
+]}
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml
new file mode 100644
index 0000000..7f9f946
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: [
+ -measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ -measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ ]
+ }
+}}
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml
new file mode 100644
index 0000000..2cac9e6
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml
@@ -0,0 +1,149 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is \sent\ to MeNB
+ with the SCG Change Indication set as PSCellChange."
+ measDescription: This counter indicates the number of intra gNB intra frequency PSCell change attempts.
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml
new file mode 100644
index 0000000..a125b13
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ }
+ }
+}}
+...
diff --git a/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml b/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml
new file mode 100644
index 0000000..d73ca4f
--- /dev/null
+++ b/csarvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml
@@ -0,0 +1,23 @@
+---
+root1: { presence: required, structure: {
+ field1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+root2: { presence: required, structure: {
+ field2: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+root3: { presence: required, structure: {
+ field3: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+...
diff --git a/deployment/pom.xml b/deployment/pom.xml
index d4b11db..fb720d2 100644
--- a/deployment/pom.xml
+++ b/deployment/pom.xml
@@ -16,11 +16,15 @@
-->
<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>
+ <properties>
+ <groovy-maven-plugin.version>2.0</groovy-maven-plugin.version>
+ <gmaven-plugin.version>1.5</gmaven-plugin.version>
+ </properties>
<parent>
<groupId>org.onap.vnfsdk.validation</groupId>
<artifactId>validation</artifactId>
- <version>1.2.4-SNAPSHOT</version>
+ <version>1.2.15-SNAPSHOT</version>
</parent>
<artifactId>csarvalidation-deployment</artifactId>
@@ -33,7 +37,7 @@
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
- <version>2.0</version>
+ <version>${groovy-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
@@ -41,7 +45,7 @@
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
- <version>1.5</version>
+ <version>${gmaven-plugin.version}</version>
<executions>
<execution>
<id>CSAR validator</id>
diff --git a/pom.xml b/pom.xml
index 0455d8b..c150b7f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,11 +10,12 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.vnfsdk.validation</groupId>
<artifactId>validation</artifactId>
- <version>1.2.4-SNAPSHOT</version>
+ <version>1.2.15-SNAPSHOT</version>
<name>vnfsdk-validation</name>
<packaging>pom</packaging>
<properties>
+ <java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.language>java</sonar.language>
<sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
@@ -22,8 +23,10 @@
<sonar.jacoco.reportMissing.force.zero>true</sonar.jacoco.reportMissing.force.zero>
<sonar.projectVersion>${project.version}</sonar.projectVersion>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
+ <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
+ <maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
</properties>
-
+
<scm>
<tag>HEAD</tag>
</scm>
@@ -40,7 +43,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <version>3.0.2</version>
+ <version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<manifest>
@@ -56,10 +59,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
+ <version>${maven-compiler-plugin.version}</version>
<configuration>
- <source>1.8</source>
- <target>1.8</target>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
</configuration>
</plugin>
<plugin>
diff --git a/releases/1.2.10-maven.yaml b/releases/1.2.10-maven.yaml
new file mode 100644
index 0000000..a515add
--- /dev/null
+++ b/releases/1.2.10-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.10'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/394'
diff --git a/releases/1.2.11-maven.yaml b/releases/1.2.11-maven.yaml
new file mode 100644
index 0000000..f0e7073
--- /dev/null
+++ b/releases/1.2.11-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.11'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/425'
diff --git a/releases/1.2.12-maven.yaml b/releases/1.2.12-maven.yaml
new file mode 100644
index 0000000..44dcb3a
--- /dev/null
+++ b/releases/1.2.12-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.12'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/446'
diff --git a/releases/1.2.13-maven.yaml b/releases/1.2.13-maven.yaml
new file mode 100644
index 0000000..405d742
--- /dev/null
+++ b/releases/1.2.13-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.13'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/461'
diff --git a/releases/1.2.14-maven.yaml b/releases/1.2.14-maven.yaml
new file mode 100644
index 0000000..9ccef59
--- /dev/null
+++ b/releases/1.2.14-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.14'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/490'
diff --git a/releases/1.2.5-maven.yaml b/releases/1.2.5-maven.yaml
new file mode 100644
index 0000000..1ce8c35
--- /dev/null
+++ b/releases/1.2.5-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.5'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/327'
diff --git a/releases/1.2.6-maven.yaml b/releases/1.2.6-maven.yaml
new file mode 100644
index 0000000..55e3c6a
--- /dev/null
+++ b/releases/1.2.6-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.6'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/330'
diff --git a/releases/1.2.7-maven.yaml b/releases/1.2.7-maven.yaml
new file mode 100644
index 0000000..9fc362a
--- /dev/null
+++ b/releases/1.2.7-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.7'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/373' \ No newline at end of file
diff --git a/releases/1.2.8-maven.yaml b/releases/1.2.8-maven.yaml
new file mode 100644
index 0000000..7ba12e7
--- /dev/null
+++ b/releases/1.2.8-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.8'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/375'
diff --git a/releases/1.2.9-maven.yaml b/releases/1.2.9-maven.yaml
new file mode 100644
index 0000000..109148f
--- /dev/null
+++ b/releases/1.2.9-maven.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: maven
+version: '1.2.9'
+project: 'vnfsdk-validation'
+log_dir: 'vnfsdk-validation-maven-stage-master/388'
diff --git a/version.properties b/version.properties
index 79ab23a..c34e299 100644
--- a/version.properties
+++ b/version.properties
@@ -5,7 +5,7 @@
major=1
minor=2
-patch=4
+patch=15
base_version=${major}.${minor}.${patch}