Retry CM-Handles that are LOCKED, Failed-to-Sync
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / inventory / sync / SyncUtilsSpec.groovy
index 04b2d55..15d1efe 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2022 Nordix Foundation
+ *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.api.inventory.sync
 
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.spi.CpsDataPersistenceService
-import org.onap.cps.spi.FetchDescendantsOption
+import org.onap.cps.ncmp.api.inventory.CmHandleState
+import org.onap.cps.ncmp.api.inventory.CompositeState
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
+import org.onap.cps.ncmp.api.inventory.LockReasonCategory
 import org.onap.cps.spi.model.DataNode
-import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Shared
 import spock.lang.Specification
 
-import java.time.OffsetDateTime
-
 class SyncUtilsSpec extends Specification{
 
-    def mockCpsDataService = Mock(CpsDataService)
-    def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
-    def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
-    def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever)
+    def mockInventoryPersistence = Mock(InventoryPersistence)
 
-    def objectUnderTest = new SyncUtils(mockCpsDataService, mockCpsDataPersistenceService, spiedJsonObjectMapper, mockYangModelCmHandleRetriever)
+    def objectUnderTest = new SyncUtils(mockInventoryPersistence)
 
     @Shared
     def dataNode = new DataNode(leaves: ['id': 'cm-handle-123'])
 
-
-
     def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() {
-        given: 'the cps (persistence service) returns a collection of data nodes'
-            mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin',
-                'ncmp-dmi-registry', '//cm-handles[@state=\"ADVISED\"]',
-                FetchDescendantsOption.OMIT_DESCENDANTS) >> dataNodeCollection
+        given: 'the inventory persistence service returns a collection of data nodes'
+            mockInventoryPersistence.getCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection
         when: 'get advised cm handle is called'
             objectUnderTest.getAnAdvisedCmHandle()
         then: 'the returned data node collection is the correct size'
             dataNodeCollection.size() == expectedDataNodeSize
         and: 'get yang model cm handles is invoked the correct number of times'
-           expectedCallsToGetYangModelCmHandle * mockYangModelCmHandleRetriever.getYangModelCmHandle('cm-handle-123')
+           expectedCallsToGetYangModelCmHandle * mockInventoryPersistence.getYangModelCmHandle('cm-handle-123')
         where: 'the following scenarios are used'
             scenario         | dataNodeCollection || expectedCallsToGetYangModelCmHandle | expectedDataNodeSize
             'exists'         | [ dataNode ]       || 1                                   | 1
@@ -65,14 +54,28 @@ class SyncUtilsSpec extends Specification{
 
     }
 
-    def 'Update cm handle state from Advised to Ready'() {
-        given: 'a yang model cm handle and the expected json data'
-            def yangModelCmHandle = new YangModelCmHandle('id': 'Some-Cm-Handle', 'cmHandleState': 'ADVISED')
-            def expectedJsonData = '{"cm-handles":[{"id":"Some-Cm-Handle","state":"READY"}]}'
-        when: 'update cm handle state is called'
-            objectUnderTest.updateCmHandleState(yangModelCmHandle, 'READY')
-        then: 'update data note leaves is invoked with the correct params'
-            1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', expectedJsonData, _ as OffsetDateTime)
+    def 'Update Lock Reason, Details and Attempts where lock reason #scenario'() {
+        given: 'A locked state'
+           def compositeState = new CompositeState(lockReason: lockReason)
+        when: 'update cm handle details and attempts is called'
+            objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MISBEHAVING, 'new error message')
+        then: 'the composite state lock reason and details are updated'
+            assert compositeState.lockReason.lockReasonCategory == LockReasonCategory.LOCKED_MISBEHAVING
+            assert compositeState.lockReason.details == expectedDetails
+        where:
+            scenario         | lockReason                                                                                   || expectedDetails
+            'does not exist' | null                                                                                         || 'Attempt #1 failed: new error message'
+            'exists'         | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build() || 'Attempt #3 failed: new error message'
+    }
+    def 'Get all locked Cm-Handle where Lock Reason is LOCKED_MISBEHAVING cm handle #scenario'() {
+        given: 'the cps (persistence service) returns a collection of data nodes'
+            mockInventoryPersistence.getCmHandlesByCpsPath(
+                    '//lock-reason[@reason="LOCKED_MISBEHAVING"]/ancestor::cm-handles') >> [dataNode ]
+        when: 'get locked Misbehaving cm handle is called'
+            def result = objectUnderTest.getLockedMisbehavingCmHandles()
+        then: 'the returned cm handle collection is the correct size'
+            result.size() == 1
+        and: 'the correct cm handle is returned'
+            result[0].id == 'cm-handle-123'
     }
-
 }