diff options
author | 2023-06-12 16:24:02 +0100 | |
---|---|---|
committer | 2023-06-19 09:01:16 +0000 | |
commit | 08898672e0de04238acdedea4266c58f17c2b7e0 (patch) | |
tree | b0266435c84d1fe5b333b0b95fa70b37638f554e /cps-ri/src/test/groovy/org/onap | |
parent | 75dff29f61825b44a8bf09a3a95cb8ceea2ce444 (diff) |
Move integration test (clean-up, last phase)
- Moved session manager test
- Improved schemaset concurrency test (retry testing)
- Cleaned up all ri (container based) integration test (setup)
- Applied some groovy best practice where needed
- internal ri module cover now down to 29%, covred by integration instead with
- Line coverage up by 41 lines to 99% (was 97%)
- Branch coverage up by 3 branches to 96% (was 93%)
Issue-ID: CPS-1687
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Change-Id: Ifb77a053e5a5db62a3f6a32ae60a3a8b10918efd
Diffstat (limited to 'cps-ri/src/test/groovy/org/onap')
4 files changed, 82 insertions, 201 deletions
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceConcurrencySpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceConcurrencySpec.groovy index 65d63dfe3..2e4dba2e9 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceConcurrencySpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceConcurrencySpec.groovy @@ -20,81 +20,126 @@ */ package org.onap.cps.spi.impl - import org.hibernate.exception.ConstraintViolationException +import org.onap.cps.spi.CpsAdminPersistenceService import org.onap.cps.spi.CpsModulePersistenceService import org.onap.cps.spi.entities.DataspaceEntity +import org.onap.cps.spi.entities.SchemaSetEntity import org.onap.cps.spi.exceptions.DuplicatedYangResourceException import org.onap.cps.spi.model.ModuleReference import org.onap.cps.spi.repository.DataspaceRepository +import org.onap.cps.spi.repository.ModuleReferenceRepository +import org.onap.cps.spi.repository.SchemaSetRepository import org.onap.cps.spi.repository.YangResourceRepository import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest import org.springframework.dao.DataIntegrityViolationException -import spock.lang.Shared +import org.springframework.retry.annotation.EnableRetry +import spock.lang.Specification import java.sql.SQLException -class CpsModulePersistenceServiceConcurrencySpec extends CpsPersistenceSpecBase { +@SpringBootTest(classes=[CpsModulePersistenceServiceImpl]) +@EnableRetry +class CpsModulePersistenceServiceConcurrencySpec extends Specification { @Autowired CpsModulePersistenceService objectUnderTest @SpringBean - YangResourceRepository yangResourceRepositoryMock = Mock() + DataspaceRepository dataspaceRepository = Mock() + + @SpringBean + YangResourceRepository yangResourceRepository = Mock() + + @SpringBean + SchemaSetRepository schemaSetRepository = Mock() @SpringBean - DataspaceRepository dataspaceRepositoryMock = Mock() + CpsAdminPersistenceService cpsAdminPersistenceService = Mock() - static final String DATASPACE_NAME = 'DATASPACE-001' - static final String SCHEMA_SET_NAME_NEW = 'SCHEMA-SET-NEW' - static final String NEW_RESOURCE_NAME = 'some new resource' - static final String NEW_RESOURCE_CONTENT = 'module stores {\n' + + @SpringBean + ModuleReferenceRepository moduleReferenceRepository = Mock() + + 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' + '}' def newYangResourcesNameToContentMap = [(NEW_RESOURCE_NAME):NEW_RESOURCE_CONTENT] - @Shared - yangResourceChecksum = 'b13faef573ed1374139d02c40d8ce09c80ea1dc70e63e464c1ed61568d48d539' + def yangResourceChecksum = 'b13faef573ed1374139d02c40d8ce09c80ea1dc70e63e464c1ed61568d48d539' - @Shared - yangResourceChecksumDbConstraint = 'yang_resource_checksum_key' + def yangResourceChecksumDbConstraint = 'yang_resource_checksum_key' - @Shared - sqlExceptionMessage = String.format('(checksum)=(%s)', yangResourceChecksum) + def sqlExceptionMessage = String.format('(checksum)=(%s)', yangResourceChecksum) - @Shared - checksumIntegrityException = - new DataIntegrityViolationException("checksum integrity exception", + def checksumIntegrityException = new DataIntegrityViolationException("checksum integrity exception", new ConstraintViolationException('', new SQLException(sqlExceptionMessage), yangResourceChecksumDbConstraint)) - def 'Store new schema set, retry mechanism'() { + def 'Store new schema set, maximum retries.'() { given: 'no pre-existing schemaset in database' - dataspaceRepositoryMock.getByName(_) >> new DataspaceEntity() - yangResourceRepositoryMock.findAllByChecksumIn(_) >> Collections.emptyList() + dataspaceRepository.getByName(_) >> new DataspaceEntity() + yangResourceRepository.findAllByChecksumIn(_) >> Collections.emptyList() when: 'a new schemaset is stored' - objectUnderTest.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, newYangResourcesNameToContentMap) - then: ' duplicated yang resource exception is thrown ' - def e = thrown(DuplicatedYangResourceException) + objectUnderTest.storeSchemaSet('some dataspace', 'some new schema set', newYangResourcesNameToContentMap) + then: 'a duplicated yang resource exception is thrown ' + thrown(DuplicatedYangResourceException) and: 'the system will attempt to save the data 5 times (because checksum integrity exception is thrown each time)' - 5 * yangResourceRepositoryMock.saveAll(_) >> { throw checksumIntegrityException } + 5 * yangResourceRepository.saveAll(_) >> { throw checksumIntegrityException } + } + + def 'Store new schema set, succeed on third attempt.'() { + given: 'no pre-existing schemaset in database' + dataspaceRepository.getByName(_) >> new DataspaceEntity() + yangResourceRepository.findAllByChecksumIn(_) >> Collections.emptyList() + when: 'a new schemaset is stored' + objectUnderTest.storeSchemaSet('some dataspace', 'some new schema set', newYangResourcesNameToContentMap) + then: 'no exception is thrown ' + noExceptionThrown() + and: 'the system will attempt to save the data 2 times with checksum integrity exception but then succeed' + 2 * yangResourceRepository.saveAll(_) >> { throw checksumIntegrityException } + 1 * yangResourceRepository.saveAll(_) >> [] } - def 'Store schema set using modules, retry mechanism'() { + def 'Store schema set using modules, maximum retries.'() { given: 'map of new modules, a list of existing modules, module reference' def mapOfNewModules = [newModule1: 'module newmodule { yang-version 1.1; revision "2021-10-12" { } }'] def moduleReferenceForExistingModule = new ModuleReference("test","2021-10-12") def listOfExistingModulesModuleReference = [moduleReferenceForExistingModule] and: 'no pre-existing schemaset in database' - dataspaceRepositoryMock.getByName(_) >> new DataspaceEntity() - yangResourceRepositoryMock.findAllByChecksumIn(_) >> Collections.emptyList() + dataspaceRepository.getByName(_) >> new DataspaceEntity() + yangResourceRepository.findAllByChecksumIn(_) >> Collections.emptyList() when: 'a new schemaset is stored from a module' - objectUnderTest.storeSchemaSetFromModules(DATASPACE_NAME, "newSchemaSetName" , mapOfNewModules, listOfExistingModulesModuleReference) - then: ' duplicated yang resource exception is thrown ' - def e = thrown(DuplicatedYangResourceException) + objectUnderTest.storeSchemaSetFromModules('some dataspace', 'some new schema set' , mapOfNewModules, listOfExistingModulesModuleReference) + then: 'a duplicated yang resource exception is thrown ' + thrown(DuplicatedYangResourceException) and: 'the system will attempt to save the data 5 times (because checksum integrity exception is thrown each time)' - 5 * yangResourceRepositoryMock.saveAll(_) >> { throw checksumIntegrityException } + 5 * yangResourceRepository.saveAll(_) >> { throw checksumIntegrityException } + } + + def 'Store schema set using modules, succeed on third attempt.'() { + given: 'map of new modules, a list of existing modules, module reference' + def mapOfNewModules = [newModule1: 'module newmodule { yang-version 1.1; revision "2021-10-12" { } }'] + def moduleReferenceForExistingModule = new ModuleReference("test","2021-10-12") + def listOfExistingModulesModuleReference = [moduleReferenceForExistingModule] + and: 'no pre-existing schemaset in database' + def dataspaceEntity = new DataspaceEntity() + dataspaceRepository.getByName(_) >> new DataspaceEntity() + yangResourceRepository.findAllByChecksumIn(_) >> Collections.emptyList() + yangResourceRepository.getResourceIdsByModuleReferences(_) >> [] + and: 'can retrieve schemaset details after storing it' + def schemaSetEntity = new SchemaSetEntity() + schemaSetRepository.getByDataspaceAndName(dataspaceEntity, 'new schema set') >> schemaSetEntity + when: 'a new schemaset is stored from a module' + objectUnderTest.storeSchemaSetFromModules('some dataspace', 'new schema set' , mapOfNewModules, listOfExistingModulesModuleReference) + then: 'no exception is thrown ' + noExceptionThrown() + and: 'the system will attempt to save the data 2 times with checksum integrity exception but then succeed' + 2 * yangResourceRepository.saveAll(_) >> { throw checksumIntegrityException } + 1 * yangResourceRepository.saveAll(_) >> [] } + } diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy index 5e42ce04e..52651c6b1 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (c) 2021 Bell Canada. - * Modifications Copyright (C) 2022 Nordix Foundation + * Modifications Copyright (C) 2022-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. @@ -28,7 +28,6 @@ import org.onap.cps.spi.repository.ModuleReferenceRepository import org.onap.cps.spi.repository.SchemaSetRepository import org.onap.cps.spi.repository.YangResourceRepository import org.springframework.dao.DataIntegrityViolationException -import spock.lang.Shared import spock.lang.Specification import java.sql.SQLException @@ -38,17 +37,14 @@ import java.sql.SQLException */ class CpsModulePersistenceServiceSpec extends Specification { - // Instance to test CpsModulePersistenceService objectUnderTest - // Mocks def dataspaceRepositoryMock = Mock(DataspaceRepository) def yangResourceRepositoryMock = Mock(YangResourceRepository) def schemaSetRepositoryMock = Mock(SchemaSetRepository) def cpsAdminPersistenceServiceMock = Mock(CpsAdminPersistenceService) def moduleReferenceRepositoryMock = Mock(ModuleReferenceRepository) - // Constants def yangResourceName = 'my-yang-resource-name' def yangResourceContent = 'module stores {\n' + ' yang-version 1.1;\n' + @@ -62,17 +58,14 @@ class CpsModulePersistenceServiceSpec extends Specification { ' }' + '}' - // Scenario data static yangResourceChecksum = 'b13faef573ed1374139d02c40d8ce09c80ea1dc70e63e464c1ed61568d48d539' static yangResourceChecksumDbConstraint = 'yang_resource_checksum_key' static sqlExceptionMessage = String.format('(checksum)=(%s)', yangResourceChecksum) - static checksumIntegrityException = new DataIntegrityViolationException( - "checksum integrity exception", + static checksumIntegrityException = new DataIntegrityViolationException('checksum integrity exception', new ConstraintViolationException('', new SQLException(sqlExceptionMessage), yangResourceChecksumDbConstraint)) - static checksumIntegrityExceptionWithoutChecksum = new DataIntegrityViolationException( - "checksum integrity exception", + static checksumIntegrityExceptionWithoutChecksum = new DataIntegrityViolationException('checksum integrity exception', new ConstraintViolationException('', new SQLException('no checksum'), yangResourceChecksumDbConstraint)) - static anotherIntegrityException = new DataIntegrityViolationException("another integrity exception") + static otherIntegrityException = new DataIntegrityViolationException('another integrity exception') def setup() { objectUnderTest = new CpsModulePersistenceServiceImpl(yangResourceRepositoryMock, schemaSetRepositoryMock, @@ -94,7 +87,7 @@ class CpsModulePersistenceServiceSpec extends Specification { scenario | dbException || expectedThrownException | expectedThrownExceptionMessage 'checksum data failure' | checksumIntegrityException || DuplicatedYangResourceException | yangResourceChecksum 'checksum failure without checksum' | checksumIntegrityExceptionWithoutChecksum || DuplicatedYangResourceException | 'no checksum found' - 'other data failure' | anotherIntegrityException || DataIntegrityViolationException | 'another integrity exception' + 'other data failure' | otherIntegrityException || DataIntegrityViolationException | 'another integrity exception' } } diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy deleted file mode 100644 index 34a040e60..000000000 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy +++ /dev/null @@ -1,74 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation - * Modifications Copyright (C) 2021 Pantheon.tech - * Modifications Copyright (C) 2021 Bell Canada. - * Modifications Copyright (C) 2023 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 com.fasterxml.jackson.databind.ObjectMapper -import org.onap.cps.DatabaseTestContainer -import org.onap.cps.spi.repository.AnchorRepository -import org.onap.cps.spi.repository.DataspaceRepository -import org.onap.cps.spi.repository.FragmentRepository -import org.onap.cps.spi.repository.YangResourceRepository -import org.onap.cps.utils.JsonObjectMapper -import org.spockframework.spring.SpringBean -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.testcontainers.spock.Testcontainers -import spock.lang.Shared -import spock.lang.Specification - -@SpringBootTest -@Testcontainers -class CpsPersistenceSpecBase extends Specification { - - @Shared - DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance() - - @Autowired - DataspaceRepository dataspaceRepository - - @Autowired - YangResourceRepository yangResourceRepository - - @Autowired - AnchorRepository anchorRepository - - @Autowired - FragmentRepository fragmentRepository - - @SpringBean - JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - - protected static final String CLEAR_DATA = '/data/clear-all.sql' - - static def DATASPACE_NAME = 'DATASPACE-001' - static def SCHEMA_SET_NAME1 = 'SCHEMA-SET-001' - static def SCHEMA_SET_NAME2 = 'SCHEMA-SET-002' - static def ANCHOR_NAME1 = 'ANCHOR-001' - static def ANCHOR_NAME2 = 'ANCHOR-002' - static def ANCHOR_NAME3 = 'ANCHOR-003' - static def ANCHOR_FOR_DATA_NODES_WITH_LEAVES = 'ANCHOR-003' - static def ANCHOR_FOR_SHOP_EXAMPLE = 'ANCHOR-004' - static def ANCHOR_HAVING_SINGLE_TOP_LEVEL_FRAGMENT = 'ANCHOR-005' - static def ANCHOR_WITH_MULTIPLE_TOP_LEVEL_FRAGMENTS = 'ANCHOR-006' -} diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/utils/SessionManagerIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/utils/SessionManagerIntegrationSpec.groovy deleted file mode 100644 index ceb9dd4cf..000000000 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/utils/SessionManagerIntegrationSpec.groovy +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2022 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.spi.utils - -import org.onap.cps.spi.config.CpsSessionFactory -import org.onap.cps.spi.exceptions.SessionManagerException -import org.onap.cps.spi.impl.CpsPersistenceSpecBase -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.test.context.jdbc.Sql - -class SessionManagerIntegrationSpec extends CpsPersistenceSpecBase{ - - final static String SET_DATA = '/data/anchor.sql' - - @Autowired - SessionManager objectUnderTest - - @Autowired - CpsSessionFactory cpsSessionFactory - - def sessionId - def shortTimeoutForTesting = 300L - - def setup(){ - sessionId = objectUnderTest.startSession() - } - - def cleanup(){ - objectUnderTest.closeSession(sessionId, objectUnderTest.WITH_COMMIT) - } - - @Sql([CLEAR_DATA, SET_DATA]) - def 'Lock anchor.'(){ - when: 'session tries to acquire anchor lock by passing anchor entity details' - objectUnderTest.lockAnchor(sessionId, DATASPACE_NAME, ANCHOR_NAME1, shortTimeoutForTesting) - then: 'no exception is thrown' - noExceptionThrown() - } - - @Sql([CLEAR_DATA, SET_DATA]) - def 'Attempt to lock anchor when another session is holding the lock.'(){ - given: 'another session that holds an anchor lock' - def otherSessionId = objectUnderTest.startSession() - objectUnderTest.lockAnchor(otherSessionId,DATASPACE_NAME,ANCHOR_NAME1,shortTimeoutForTesting) - when: 'a session tries to acquire the same anchor lock' - objectUnderTest.lockAnchor(sessionId,DATASPACE_NAME,ANCHOR_NAME1,shortTimeoutForTesting) - then: 'a session manager exception is thrown specifying operation reached timeout' - def thrown = thrown(SessionManagerException) - thrown.message.contains('Timeout') - then: 'when the other session holding the lock is closed, lock can finally be acquired' - objectUnderTest.closeSession(otherSessionId, objectUnderTest.WITH_COMMIT) - objectUnderTest.lockAnchor(sessionId,DATASPACE_NAME,ANCHOR_NAME1,shortTimeoutForTesting) - } - - @Sql([CLEAR_DATA, SET_DATA]) - def 'Lock anchor twice using the same session.'(){ - given: 'session that already holds an anchor lock' - objectUnderTest.lockAnchor(sessionId, DATASPACE_NAME, ANCHOR_NAME1, shortTimeoutForTesting) - when: 'same session tries to acquire same anchor lock' - objectUnderTest.lockAnchor(sessionId, DATASPACE_NAME, ANCHOR_NAME1, shortTimeoutForTesting) - then: 'no exception is thrown' - noExceptionThrown() - } - -} |