Move integration test for moduleService 48/134548/2
authorToineSiebelink <toine.siebelink@est.tech>
Mon, 8 May 2023 16:54:46 +0000 (17:54 +0100)
committerToineSiebelink <toine.siebelink@est.tech>
Thu, 11 May 2023 15:47:29 +0000 (16:47 +0100)
- all modules service interation test moved
- added some aditional scenarios to increase coverage
- removed unused method(s)
- remove javdoc on private methods
- some minor refactoring like replace 'var' with correct type

Issue-ID: CPS-1687
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Change-Id: I03ff1f3562cfe38318e8b9af81be47a1fe667da2

cps-ri/pom.xml
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy [deleted file]
cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy [new file with mode: 0644]

index 3ef57cf..db274f7 100644 (file)
@@ -33,8 +33,8 @@
     <artifactId>cps-ri</artifactId>\r
 \r
     <properties>\r
-        <minimum-coverage>0.45</minimum-coverage>\r
-        <!-- Coverage is provided by integration-test module instead -->\r
+        <minimum-coverage>0.64</minimum-coverage>\r
+        <!-- Additional coverage is provided by integration-test module -->\r
     </properties>\r
 \r
     <dependencies>\r
index cd1457e..5eda15a 100755 (executable)
@@ -37,6 +37,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import javax.transaction.Transactional;
@@ -94,19 +95,13 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
 
     @Override
     public Map<String, String> getYangSchemaResources(final String dataspaceName, final String schemaSetName) {
-        final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
-        final var schemaSetEntity =
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final SchemaSetEntity schemaSetEntity =
             schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName);
         return schemaSetEntity.getYangResources().stream().collect(
             Collectors.toMap(YangResourceEntity::getFileName, YangResourceEntity::getContent));
     }
 
-    @Override
-    public Map<String, String> getYangSchemaSetResources(final String dataspaceName, final String anchorName) {
-        final var anchor = cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName);
-        return getYangSchemaResources(dataspaceName, anchor.getSchemaSetName());
-    }
-
     @Override
     public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) {
         final Set<YangResourceModuleReference> yangResourceModuleReferenceList =
@@ -143,9 +138,9 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         @Backoff(random = true, delay = 200, maxDelay = 2000, multiplier = 2))
     public void storeSchemaSet(final String dataspaceName, final String schemaSetName,
         final Map<String, String> moduleReferenceNameToContentMap) {
-        final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
-        final var yangResourceEntities = synchronizeYangResources(moduleReferenceNameToContentMap);
-        final var schemaSetEntity = new SchemaSetEntity();
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final Set<YangResourceEntity> yangResourceEntities = synchronizeYangResources(moduleReferenceNameToContentMap);
+        final SchemaSetEntity schemaSetEntity = new SchemaSetEntity();
         schemaSetEntity.setName(schemaSetName);
         schemaSetEntity.setDataspace(dataspaceEntity);
         schemaSetEntity.setYangResources(yangResourceEntities);
@@ -185,8 +180,8 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
     @Override
     @Transactional
     public void deleteSchemaSet(final String dataspaceName, final String schemaSetName) {
-        final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
-        final var schemaSetEntity =
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final SchemaSetEntity schemaSetEntity =
             schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName);
         schemaSetRepository.delete(schemaSetEntity);
     }
@@ -194,7 +189,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
     @Override
     @Transactional
     public void deleteSchemaSets(final String dataspaceName, final Collection<String> schemaSetNames) {
-        final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
         schemaSetRepository.deleteByDataspaceAndNameIn(dataspaceEntity, schemaSetNames);
     }
 
@@ -217,7 +212,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
                 final String checksum = DigestUtils.sha256Hex(entry.getValue().getBytes(StandardCharsets.UTF_8));
                 final Map<String, String> moduleNameAndRevisionMap = createModuleNameAndRevisionMap(entry.getKey(),
                             entry.getValue());
-                final var yangResourceEntity = new YangResourceEntity();
+                final YangResourceEntity yangResourceEntity = new YangResourceEntity();
                 yangResourceEntity.setFileName(entry.getKey());
                 yangResourceEntity.setContent(entry.getValue());
                 yangResourceEntity.setModuleName(moduleNameAndRevisionMap.get("moduleName"));
@@ -264,10 +259,10 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
 
     private static Map<String, String> createModuleNameAndRevisionMap(final String sourceName, final String source) {
         final Map<String, String> metaDataMap = new HashMap<>();
-        final var revisionSourceIdentifier =
-                createIdentifierFromSourceName(checkNotNull(sourceName));
+        final RevisionSourceIdentifier revisionSourceIdentifier =
+            createIdentifierFromSourceName(checkNotNull(sourceName));
 
-        final var tempYangTextSchemaSource = new YangTextSchemaSource(revisionSourceIdentifier) {
+        final YangTextSchemaSource tempYangTextSchemaSource = new YangTextSchemaSource(revisionSourceIdentifier) {
             @Override
             public Optional<String> getSymbolicName() {
                 return Optional.empty();
@@ -285,9 +280,10 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
             }
         };
         try {
-            final var dependencyInfo = YangModelDependencyInfo.forYangText(tempYangTextSchemaSource);
-            metaDataMap.put("moduleName", dependencyInfo.getName());
-            metaDataMap.put("revision", dependencyInfo.getFormattedRevision());
+            final YangModelDependencyInfo yangModelDependencyInfo
+                = YangModelDependencyInfo.forYangText(tempYangTextSchemaSource);
+            metaDataMap.put("moduleName", yangModelDependencyInfo.getName());
+            metaDataMap.put("revision", yangModelDependencyInfo.getFormattedRevision());
         } catch (final YangSyntaxErrorException | IOException e) {
             throw new ModelValidationException("Yang resource is invalid.",
                    String.format("Yang syntax validation failed for resource %s:%n%s", sourceName, e.getMessage()), e);
@@ -296,7 +292,7 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
     }
 
     private static RevisionSourceIdentifier createIdentifierFromSourceName(final String sourceName) {
-        final var matcher = RFC6020_RECOMMENDED_FILENAME_PATTERN.matcher(sourceName);
+        final Matcher matcher = RFC6020_RECOMMENDED_FILENAME_PATTERN.matcher(sourceName);
         if (matcher.matches()) {
             return RevisionSourceIdentifier.create(matcher.group(1), Revision.of(matcher.group(2)));
         }
@@ -335,15 +331,8 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
 
     }
 
-    /**
-     * Get the name of the yang resource having the specified checksum.
-     *
-     * @param checksum the checksum. Null is supported.
-     * @param yangResourceEntities the list of yang resources to search among.
-     * @return the name found or null if none.
-     */
-    private String getNameForChecksum(
-            final String checksum, final Collection<YangResourceEntity> yangResourceEntities) {
+    private String getNameForChecksum(final String checksum,
+                                      final Collection<YangResourceEntity> yangResourceEntities) {
         final Optional<String> optionalFileName = yangResourceEntities.stream()
                         .filter(entity -> StringUtils.equals(checksum, (entity.getChecksum())))
                         .findFirst()
@@ -354,19 +343,12 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         return null;
     }
 
-    /**
-     * Get the checksum that caused the constraint violation exception.
-     *
-     * @param exception the exception having the checksum in error.
-     * @return the checksum in error or null if not found.
-     */
     private String getDuplicatedChecksumFromException(final ConstraintViolationException exception) {
-        String checksum = null;
-        final var matcher = CHECKSUM_EXCEPTION_PATTERN.matcher(exception.getSQLException().getMessage());
+        final Matcher matcher = CHECKSUM_EXCEPTION_PATTERN.matcher(exception.getSQLException().getMessage());
         if (matcher.find() && matcher.groupCount() == 1) {
-            checksum = matcher.group(1);
+            return matcher.group(1);
         }
-        return checksum;
+        return null;
     }
 
     private static ModuleReference toModuleReference(
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceIntegrationSpec.groovy
deleted file mode 100644 (file)
index 3a5d9ef..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2023 Nordix Foundation
- *  Modifications Copyright (C) 2021-2022 Bell Canada.
- *  Modifications Copyright (C) 2022 TechMahindra 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.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-package org.onap.cps.spi.impl
-
-import org.onap.cps.spi.CpsAdminPersistenceService
-import org.onap.cps.spi.CpsModulePersistenceService
-import org.onap.cps.spi.entities.YangResourceEntity
-import org.onap.cps.spi.exceptions.AlreadyDefinedException
-import org.onap.cps.spi.exceptions.DataspaceNotFoundException
-import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
-import org.onap.cps.spi.model.ModuleDefinition
-import org.onap.cps.spi.model.ModuleReference
-import org.onap.cps.spi.model.SchemaSet
-import org.onap.cps.spi.repository.SchemaSetRepository
-import org.onap.cps.spi.repository.SchemaSetYangResourceRepositoryImpl
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.test.context.jdbc.Sql
-
-class CpsModulePersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase {
-
-    @Autowired
-    CpsModulePersistenceService objectUnderTest
-
-    @Autowired
-    SchemaSetRepository schemaSetRepository
-
-    @Autowired
-    CpsAdminPersistenceService cpsAdminPersistenceService
-
-    final static String SET_DATA = '/data/schemaset.sql'
-
-    def static EXISTING_SCHEMA_SET_NAME = SCHEMA_SET_NAME1
-    def SCHEMA_SET_NAME_NO_ANCHORS = 'SCHEMA-SET-100'
-    def NEW_SCHEMA_SET_NAME = 'SCHEMA-SET-NEW'
-    def NEW_RESOURCE_NAME = 'some new resource'
-    def NEW_RESOURCE_CONTENT = 'module stores {\n' +
-            '    yang-version 1.1;\n' +
-            '    namespace "org:onap:ccsdk:sample";\n' +
-            '\n' +
-            '    prefix book-store;\n' +
-            '\n' +
-            '    revision "2020-09-15" {\n' +
-            '        description\n' +
-            '        "Sample Model";\n' +
-            '    }' +
-            '}'
-    def NEW_RESOURCE_CHECKSUM = 'b13faef573ed1374139d02c40d8ce09c80ea1dc70e63e464c1ed61568d48d539'
-    def NEW_RESOURCE_MODULE_NAME = 'stores'
-    def NEW_RESOURCE_REVISION = '2020-09-15'
-    def newYangResourcesNameToContentMap = [(NEW_RESOURCE_NAME):NEW_RESOURCE_CONTENT]
-
-    def dataspaceEntity
-
-    def setup() {
-        dataspaceEntity = dataspaceRepository.getByName(DATASPACE_NAME)
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Getting yang resource ids from module references'() {
-        when: 'getting yang resources for #scenario'
-            def result = yangResourceRepository.getResourceIdsByModuleReferences(moduleReferences)
-        then: 'the result contains the expected number entries'
-            assert result.size() == expectedResultSize
-        where: 'the following module references are provided'
-            scenario                                 | moduleReferences                                                                                                 || expectedResultSize
-            '2 valid module references'              | [ new ModuleReference('MODULE-NAME-002','REVISION-002'), new ModuleReference('MODULE-NAME-003','REVISION-002') ] || 2
-            '1 invalid module reference'             | [ new ModuleReference('NOT EXIST','IRRELEVANT') ]                                                                || 0
-            '1 valid and 1 invalid module reference' | [ new ModuleReference('MODULE-NAME-002','REVISION-002'), new ModuleReference('NOT EXIST','IRRELEVANT') ]         || 1
-            'no module references'                   | []                                                                                                               || 0
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Store schema set error scenario: #scenario.'() {
-        when: 'attempt to store schema set #schemaSetName in dataspace #dataspaceName'
-            objectUnderTest.storeSchemaSet(dataspaceName, schemaSetName, newYangResourcesNameToContentMap)
-        then: 'an #expectedException is thrown'
-            thrown(expectedException)
-        where: 'the following data is used'
-            scenario                    | dataspaceName  | schemaSetName            || expectedException
-            'dataspace does not exist'  | 'unknown'      | 'not-relevant'           || DataspaceNotFoundException
-            'schema set already exists' | DATASPACE_NAME | EXISTING_SCHEMA_SET_NAME || AlreadyDefinedException
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Store new schema set with one module'() {
-        when: 'a new schema set with one module is stored'
-            objectUnderTest.storeSchemaSet(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, newYangResourcesNameToContentMap)
-        then: 'the schema set is persisted correctly'
-           assertSchemaSetWithOneModuleIsPersistedCorrectly(NEW_RESOURCE_NAME,
-               NEW_RESOURCE_MODULE_NAME, NEW_RESOURCE_REVISION, NEW_RESOURCE_CONTENT, NEW_RESOURCE_CHECKSUM)
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Store new schema set with multiple modules.'() {
-        given: 'a new schema set with #numberOfModules modules'
-            def numberOfModules =  2
-            String schemaSetName = "NewSchemaWith${numberOfModules}Modules"
-            def newYangResourcesNameToContentMap = [:]
-            (1..numberOfModules).each {
-                def uniqueRevision = String.valueOf(2000 + it) + '-01-01'
-                def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision)
-                newYangResourcesNameToContentMap.put(uniqueRevision, uniqueContent)
-            }
-        when: 'the new schema set is stored'
-            objectUnderTest.storeSchemaSet(DATASPACE_NAME, schemaSetName, newYangResourcesNameToContentMap)
-        then: 'the correct number of modules are persisted'
-            assert getYangResourceEntities(schemaSetName).size() == numberOfModules
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Store and retrieve new schema set from new modules and existing modules.'() {
-        given: 'a new module'
-            def mapOfNewModules = [newModule: 'module newmodule { yang-version 1.1; revision "2022-08-19" { } }']
-        and: 'there are more existing modules in the db than the batch size (100)'
-            def listOfExistingModulesModuleReference = []
-            def mapOfExistingModule = [:]
-            def numberOfModules =  1 + SchemaSetYangResourceRepositoryImpl.MAX_INSERT_BATCH_SIZE
-            (1..numberOfModules).each {
-                def uniqueRevision = String.valueOf(2000 + it) + '-01-01'
-                def uniqueContent = "module test { yang-version 1.1; revision \"${uniqueRevision}\" { } }".toString()
-                mapOfNewModules.put( 'test' + it, uniqueContent)
-                listOfExistingModulesModuleReference.add(new ModuleReference('test',uniqueRevision))
-            }
-            objectUnderTest.storeSchemaSet(DATASPACE_NAME, 'existing schema set ', mapOfExistingModule)
-        when: 'a new schema set is created from these new modules and existing modules'
-            objectUnderTest.storeSchemaSetFromModules(DATASPACE_NAME, NEW_SCHEMA_SET_NAME , mapOfNewModules, listOfExistingModulesModuleReference)
-        then: 'the schema set can be retrieved'
-            def actualYangResourcesMapAfterSchemaSetHasBeenCreated =
-                    objectUnderTest.getYangSchemaResources(DATASPACE_NAME, NEW_SCHEMA_SET_NAME)
-        and: 'it has all the new and existing modules'
-            def expectedYangResourcesMapAfterSchemaSetHasBeenCreated = mapOfNewModules + mapOfExistingModule
-            assert actualYangResourcesMapAfterSchemaSetHasBeenCreated == expectedYangResourcesMapAfterSchemaSetHasBeenCreated
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Retrieving schema set (resources) by anchor.'() {
-        given: 'a new schema set is stored'
-            objectUnderTest.storeSchemaSet(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, newYangResourcesNameToContentMap)
-        and: 'an anchor is created with that schema set'
-            cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, ANCHOR_NAME1)
-        when: 'the schema set resources for that anchor is retrieved'
-            def result = objectUnderTest.getYangSchemaSetResources(DATASPACE_NAME, ANCHOR_NAME1)
-        then: 'the correct resources are returned'
-             result == newYangResourcesNameToContentMap
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Retrieving all yang resources module references for the given dataspace.'() {
-        given: 'a dataspace name'
-            def dataspaceName = 'DATASPACE-002'
-        when: 'all yang resources module references are retrieved for the given dataspace name'
-            def result = objectUnderTest.getYangResourceModuleReferences(dataspaceName)
-        then: 'the correct resources are returned'
-            result.sort() == [new ModuleReference(moduleName: 'MODULE-NAME-005', revision: 'REVISION-002'),
-                              new ModuleReference(moduleName: 'MODULE-NAME-006', revision: 'REVISION-006')]
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Retrieving module names and revisions for the given anchor.'() {
-        given: 'a dataspace name and anchor name'
-            def dataspaceName = 'DATASPACE-001'
-            def anchorName = 'ANCHOR1'
-        when: 'all yang resources module references are retrieved for the given anchor'
-            def result = objectUnderTest.getYangResourceModuleReferences(dataspaceName, anchorName)
-        then: 'the correct module names and revisions are returned'
-            result.sort() == [ new ModuleReference(moduleName: 'MODULE-NAME-003', revision: 'REVISION-002'),
-                              new ModuleReference(moduleName: 'MODULE-NAME-004', revision: 'REVISION-004')]
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Storing duplicate schema content.'() {
-        given: 'a new schema set with a resource with the same content as an existing resource'
-            def existingResourceContent = 'module test { yang-version 1.1; revision "2020-09-15"; }'
-            def newYangResourcesNameToContentMap = [(NEW_RESOURCE_NAME):existingResourceContent]
-        when: 'the schema set with duplicate resource is stored'
-            objectUnderTest.storeSchemaSet(DATASPACE_NAME, NEW_SCHEMA_SET_NAME, newYangResourcesNameToContentMap)
-        then: 'the schema persisted has the new name and has the same checksum'
-            def existingResourceChecksum = 'bea1afcc3d1517e7bf8cae151b3b6bfbd46db77a81754acdcb776a50368efa0a'
-            def existingResourceModuleName = 'test'
-            def existingResourceRevision = '2020-09-15'
-            assertSchemaSetWithOneModuleIsPersistedCorrectly(NEW_RESOURCE_NAME, existingResourceModuleName,
-                existingResourceRevision, existingResourceContent, existingResourceChecksum)
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Retrieve schema sets for a given dataspace name'() {
-        when: 'the schema set resources for a given dataspace name is retrieved'
-            def result = objectUnderTest.getSchemaSetsByDataspaceName(DATASPACE_NAME)
-        then: 'the correct resources are returned'
-             result.contains(new SchemaSet(name: 'SCHEMA-SET-001', dataspaceName: 'DATASPACE-001'))
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Delete schema set'() {
-        when: 'a schema set is deleted with cascade-prohibited option'
-            objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS)
-        then: 'the schema set has been deleted'
-            !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_NO_ANCHORS).isPresent()
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Delete schema sets'() {
-        when: 'schema sets are deleted'
-            objectUnderTest.deleteSchemaSets(DATASPACE_NAME, ['SCHEMA-SET-001', 'SCHEMA-SET-002'])
-        then: 'the schema sets have been deleted'
-            !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, 'SCHEMA-SET-001').isPresent()
-            !schemaSetRepository.findByDataspaceAndName(dataspaceEntity, 'SCHEMA-SET-002').isPresent()
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Identifying new module references where #scenario'() {
-        when: 'identifyNewModuleReferences is called'
-            def result = objectUnderTest.identifyNewModuleReferences(moduleReferences)
-        then: 'the correct module references are returned'
-            assert result.size() == expectedResult.size()
-            assert result.containsAll(expectedResult)
-        where: 'the following data is used'
-            scenario                              | moduleReferences                                                                                  || expectedResult
-            'new module references exist'         | toModuleReference([['some module 1' : 'some revision 1'], ['some module 2' : 'some revision 2']]) || toModuleReference([['some module 1' : 'some revision 1'], ['some module 2' : 'some revision 2']])
-            'no new module references exist'      | []                                                                                                || []
-            'module references collection is null'| null                                                                                              || []
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Delete schema set error scenario: #scenario.'() {
-        when: 'attempt to delete a schema set where #scenario'
-            objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName)
-        then: 'an #expectedException is thrown'
-            thrown(expectedException)
-        where: 'the following data is used'
-            scenario                                   | dataspaceName  | schemaSetName                         || expectedException
-            'dataspace does not exist'                 | 'unknown'      | 'not-relevant'                        || DataspaceNotFoundException
-            'schema set does not exists'               | DATASPACE_NAME | 'unknown'                             || SchemaSetNotFoundException
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Delete only orphan Yang Resources'() {
-        given: 'a schema set is deleted and and yang resource is not used anymore'
-            objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS)
-        when: 'orphan yang resources are deleted'
-            objectUnderTest.deleteUnusedYangResourceModules()
-        then: 'any orphaned (not used by any schema set anymore) yang resources are deleted'
-            def orphanedResourceId = 3100L
-            assert !yangResourceRepository.findById(orphanedResourceId).isPresent()
-        and: 'any shared (still in use by other schema set) yang resources still persists'
-            def sharedResourceId = 3003L
-            assert yangResourceRepository.findById(sharedResourceId).isPresent()
-    }
-
-    @Sql([CLEAR_DATA, SET_DATA])
-    def 'Retrieving all yang resources module definition for the given dataspace and anchor name.'() {
-        when: 'all yang resources module definitions are retrieved for the given dataspace and anchor name'
-            def result = objectUnderTest.getYangResourceDefinitions('DATASPACE-001', 'ANCHOR3')
-        then: 'the correct module definitions (moduleName, revision and yang resource content) are returned'
-            result.sort() == [new ModuleDefinition('MODULE-NAME-004', 'REVISION-004', 'CONTENT-004')]
-    }
-
-    def assertSchemaSetWithOneModuleIsPersistedCorrectly(expectedYangResourceName,
-                                                         expectedYangResourceModuleName,
-                                                         expectedYangResourceRevision,
-                                                         expectedYangResourceContent,
-                                                         expectedYangResourceChecksum) {
-
-        // assert the attached yang resource is persisted
-        def yangResourceEntities = getYangResourceEntities(NEW_SCHEMA_SET_NAME)
-        assert yangResourceEntities.size() == 1
-
-        // assert the attached yang resource content
-        YangResourceEntity yangResourceEntity = yangResourceEntities.iterator().next()
-        assert yangResourceEntity.id != null
-        assert yangResourceEntity.fileName == expectedYangResourceName
-        assert yangResourceEntity.moduleName == expectedYangResourceModuleName
-        assert yangResourceEntity.revision == expectedYangResourceRevision
-        assert yangResourceEntity.content == expectedYangResourceContent
-        assert yangResourceEntity.checksum == expectedYangResourceChecksum
-        return true
-    }
-
-    def getYangResourceEntities(schemaSetName) {
-        def schemaSetEntity = schemaSetRepository
-            .findByDataspaceAndName(dataspaceEntity, schemaSetName).orElseThrow()
-        return schemaSetEntity.getYangResources()
-    }
-
-    def toModuleReference(moduleReferenceAsMap) {
-        def moduleReferences = [].withDefault { [:] }
-        moduleReferenceAsMap.forEach(property ->
-            property.forEach((moduleName, revision) -> {
-                moduleReferences.add(new ModuleReference(moduleName, revision))
-            }))
-        return moduleReferences
-    }
-
-}
index d6c01f7..7d9c472 100644 (file)
@@ -59,9 +59,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     public void createSchemaSet(final String dataspaceName, final String schemaSetName,
         final Map<String, String> yangResourcesNameToContentMap) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+        cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
         final YangTextSchemaSourceSet yangTextSchemaSourceSet =
             timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap);
-        cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
         yangTextSchemaSourceSetCache.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet);
     }
 
index 40d4002..beb3d4f 100755 (executable)
@@ -86,15 +86,6 @@ public interface CpsModulePersistenceService {
      */
     Map<String, String> getYangSchemaResources(String dataspaceName, String schemaSetName);
 
-    /**
-     * Returns YANG resources per specific dataspace / anchorName.
-     *
-     * @param dataspaceName dataspace name
-     * @param anchorName    anchor name
-     * @return YANG resources (files) map where key is a name and value is content
-     */
-    Map<String, String> getYangSchemaSetResources(String dataspaceName, String anchorName);
-
     /**
      * Returns YANG resources module references for the given dataspace name.
      *
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
new file mode 100644 (file)
index 0000000..cfc8ab7
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration.functional
+
+import org.onap.cps.api.impl.CpsModuleServiceImpl
+import org.onap.cps.integration.base.FunctionalSpecBase
+import org.onap.cps.spi.CascadeDeleteAllowed
+import org.onap.cps.spi.exceptions.AlreadyDefinedException
+import org.onap.cps.spi.exceptions.DataspaceNotFoundException
+import org.onap.cps.spi.exceptions.ModelValidationException
+import org.onap.cps.spi.exceptions.SchemaSetInUseException
+import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
+import org.onap.cps.spi.model.ModuleDefinition
+import org.onap.cps.spi.model.ModuleReference
+
+class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
+
+    CpsModuleServiceImpl objectUnderTest
+
+    private static def originalNumberOfModuleReferences = 1
+    private static def existingModuleReference = new ModuleReference('stores','2020-09-15')
+    static def NEW_RESOURCE_REVISION = '2023-05-10'
+    static def NEW_RESOURCE_CONTENT = 'module test_module {\n' +
+        '    yang-version 1.1;\n' +
+        '    namespace "org:onap:ccsdk:sample";\n' +
+        '\n' +
+        '    prefix book-store;\n' +
+        '\n' +
+        '    revision "2023-05-10" {\n' +
+        '        description\n' +
+        '        "Sample Model";\n' +
+        '    }' +
+        '}'
+
+    def newYangResourcesNameToContentMap = [:]
+    def moduleReferences = []
+
+    def setup() {
+        objectUnderTest = cpsModuleService
+    }
+
+    /*
+        C R E A T E   S C H E M A   S E T   U S E - C A S E S
+     */
+
+    def 'Create new schema set from yang resources with #scenario'() {
+        given: 'a new schema set with #numberOfModules modules'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfNewModules)
+        when: 'the new schema set is created'
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', newYangResourcesNameToContentMap)
+        then: 'the number of module references has increased by #expectedIncrease'
+            def yangResourceModuleReferences = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1)
+            originalNumberOfModuleReferences + numberOfNewModules == yangResourceModuleReferences.size()
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, [ 'newSchemaSet' ])
+        where: 'the following parameters are use'
+            scenario                       | numberOfNewModules
+            'two valid new modules'        | 2
+            'empty schema set'             | 0
+            'over max batch size #modules' | 101
+    }
+
+    def 'Create new schema set with recommended filename format but invalid yang'() {
+        given: 'a filename using RFC6020 recommended format (for coverage only)'
+            def fileName = 'test@2023-05-11.yang'
+        when: 'attempt to create a schema set with invalid Yang'
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', [(fileName) :'invalid yang'])
+        then: 'a model validation exception'
+            thrown(ModelValidationException)
+    }
+
+    def 'Create new schema set from modules with #scenario'() {
+        given: 'a new schema set with #numberOfNewModules modules'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfNewModules)
+        and: 'add existing module references (optional)'
+            moduleReferences.addAll(existingModuleReferences)
+        when: 'the new schema set is created'
+            def schemaSetName = "NewSchemaWith${numberOfNewModules}Modules"
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
+        and: 'associated with a new anchor'
+            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor')
+        then: 'the new anchor has the correct number of modules'
+            def yangResourceModuleReferences = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'newAnchor')
+            assert expectedNumberOfModulesForAnchor == yangResourceModuleReferences.size()
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, [ schemaSetName.toString() ])
+        where: 'the following module references are provided'
+            scenario                        | numberOfNewModules | existingModuleReferences                          || expectedNumberOfModulesForAnchor
+            'empty schema set'              | 0                  | [ ]                                               || 0
+            'one existing module'           | 0                  | [ existingModuleReference ]                       || 1
+            'two new modules'               | 2                  | [ ]                                               || 2
+            'two new modules, one existing' | 2                  | [ existingModuleReference ]                       || 3
+            'over max batch size #modules'  | 101                | [ ]                                               || 101
+            'two valid, one invalid module' | 2                  | [ new ModuleReference('NOT EXIST','IRRELEVANT') ] || 2
+    }
+
+    def 'Duplicate schema content.'() {
+        given: 'a map of yang resources'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(1)
+        when: 'a new schema set is created'
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', newYangResourcesNameToContentMap)
+        then: 'the dataspace has one new module (reference)'
+            def numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).size()
+            assert numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded == originalNumberOfModuleReferences + 1
+        when: 'a second new schema set is created'
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema2', newYangResourcesNameToContentMap)
+        then: 'the dataspace has no additional module (reference)'
+            assert numberOfModuleReferencesAfterFirstSchemaSetHasBeenAdded  == objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).size()
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, [ 'newSchema1', 'newSchema2'])
+    }
+
+    def 'Create schema set error scenario: #scenario.'() {
+        when: 'attempt to store schema set #schemaSetName in dataspace #dataspaceName'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(0)
+            objectUnderTest.createSchemaSet(dataspaceName, schemaSetName, newYangResourcesNameToContentMap)
+        then: 'an #expectedException is thrown'
+            thrown(expectedException)
+        where: 'the following data is used'
+            scenario                    | dataspaceName               | schemaSetName        || expectedException
+            'dataspace does not exist'  | 'unknown'                   | 'not-relevant'       || DataspaceNotFoundException
+            'schema set already exists' | FUNCTIONAL_TEST_DATASPACE_1 | BOOKSTORE_SCHEMA_SET || AlreadyDefinedException
+    }
+
+    /*
+        R E A D   S C H E M A   S E T   I N F O   U S E - C A S E S
+     */
+
+    def 'Retrieving module definitions by anchor.'() {
+        when: 'the module definitions for an anchor are retrieved'
+            def result = objectUnderTest.getModuleDefinitionsByAnchorName(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1)
+        then: 'the correct module definitions are returned'
+            result == [new ModuleDefinition('stores','2020-09-15','')]
+    }
+
+    def 'Retrieving yang resource module references by anchor.'() {
+        when: 'the yang resource module references for an anchor are retrieved'
+            def result = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1)
+        then: 'the correct module references are returned'
+            result == [ existingModuleReference ]
+    }
+
+    def 'Identifying new module references with #scenario'() {
+        when: 'identifyNewModuleReferences is called'
+            def result = objectUnderTest.identifyNewModuleReferences(moduleReferences)
+        then: 'the correct module references are returned'
+            assert result.size() == expectedResult.size()
+            assert result.containsAll(expectedResult)
+        where: 'the following data is used'
+            scenario                                | moduleReferences                                                       || expectedResult
+            'just new module references'            | [new ModuleReference('new1', 'r1'), new ModuleReference('new2', 'r1')] || [new ModuleReference('new1', 'r1'), new ModuleReference('new2', 'r1')]
+            'one new module,one existing reference' | [new ModuleReference('new1', 'r1'), existingModuleReference]           || [new ModuleReference('new1', 'r1')]
+            'no new module references'              | [existingModuleReference]                                              || []
+            'no module references'                  | []                                                                     || []
+            'module references collection is null'  | null                                                                   || []
+    }
+
+    def 'Retrieve schema set.'() {
+        when: 'a specific schema set is retreived'
+            def result = objectUnderTest.getSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET)
+        then: 'the result has the correct name and module(s)'
+            assert result.name == 'bookstoreSchemaSet'
+            assert result.moduleReferences == [ new ModuleReference('stores', '2020-09-15', 'org:onap:ccsdk:sample') ]
+    }
+
+    def 'Retrieve all schema sets.'() {
+        given: 'an extra schema set is stored'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(1)
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchema1', newYangResourcesNameToContentMap)
+        when: 'all schema sets are retrieved'
+            def result = objectUnderTest.getSchemaSets(FUNCTIONAL_TEST_DATASPACE_1)
+        then: 'the result contains all expected schema sets'
+            assert result.name == [ 'bookstoreSchemaSet', 'newSchema1' ]
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['newSchema1'])
+    }
+
+    /*
+        D E L E T E   S C H E M A   S E T   U S E - C A S E S
+     */
+
+    def 'Delete schema sets with(out) cascade.'() {
+        given: 'a schema set'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(1)
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', newYangResourcesNameToContentMap)
+        and: 'optionally create anchor for the schema set'
+            if (associateWithAnchor) {
+                cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', 'newAnchor')
+            }
+        when: 'attempt to delete the schema set'
+            try {
+                objectUnderTest.deleteSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', cascadeDeleteAllowedOption)
+            }
+            catch (Exception e) {  // only accept correct exception when schema set cannot be deleted
+                assert e instanceof SchemaSetInUseException && expectSchemaSetStillPresent
+            }
+        then: 'check if the dataspace still contains the new schema set or not'
+            def remainingSchemaSetNames = objectUnderTest.getSchemaSets(FUNCTIONAL_TEST_DATASPACE_1).name
+            assert remainingSchemaSetNames.contains('newSchemaSet') == expectSchemaSetStillPresent
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['newSchemaSet'])
+        where: 'the following options are used'
+            associateWithAnchor | cascadeDeleteAllowedOption                     || expectSchemaSetStillPresent
+            false               | CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED    || false
+            false               | CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED || false
+            true                | CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED    || false
+            true                | CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED || true
+    }
+
+    def 'Delete schema sets with shared resources.'() {
+        given: 'a new schema set'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(1)
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet1', newYangResourcesNameToContentMap)
+        and: 'another schema set which shares one yang resource (module)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences(2)
+            objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet2', newYangResourcesNameToContentMap)
+        when: 'all schema sets are retrieved'
+            def moduleRevisions = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).revision
+        then: 'both modules (revisions) are present'
+            assert moduleRevisions.containsAll(['2000-01-01', '2000-01-01'])
+        when: 'delete the second schema set that has two resources  one of which is a shared resource'
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['newSchemaSet2'])
+        then: 'only the second schema set is deleted'
+            def remainingSchemaSetNames = objectUnderTest.getSchemaSets(FUNCTIONAL_TEST_DATASPACE_1).name
+            assert remainingSchemaSetNames.contains('newSchemaSet1')
+            assert !remainingSchemaSetNames.contains('newSchemaSet2')
+        and: 'only the shared module (revision) remains'
+            def remainingModuleRevisions = objectUnderTest.getYangResourceModuleReferences(FUNCTIONAL_TEST_DATASPACE_1).revision
+            assert remainingModuleRevisions.contains('2000-01-01')
+            assert !remainingModuleRevisions.contains('2001-01-01')
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['newSchemaSet1'])
+    }
+
+    def 'Delete schema set error scenario: #scenario.'() {
+        when: 'attempt to delete a schema set where #scenario'
+            objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName, CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED)
+        then: 'an #expectedException is thrown'
+            thrown(expectedException)
+        where: 'the following data is used'
+            scenario                     | dataspaceName               | schemaSetName   || expectedException
+            'dataspace does not exist'   | 'unknown'                   | 'not-relevant'  || DataspaceNotFoundException
+            'schema set does not exists' | FUNCTIONAL_TEST_DATASPACE_1 | 'unknown'       || SchemaSetNotFoundException
+    }
+
+    /*
+        H E L P E R   M E T H O D S
+     */
+
+    def populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfModules) {
+        numberOfModules.times {
+            def uniqueName = 'name_' + it
+            def uniqueRevision = String.valueOf(2000 + it) + '-01-01'
+            moduleReferences.add(new ModuleReference(uniqueName, uniqueRevision))
+            def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision)
+            newYangResourcesNameToContentMap.put(uniqueRevision, uniqueContent)
+        }
+    }
+
+}