From e18239631ff2f2f56961c8534a0edf294ee15fdd Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Tue, 25 Jun 2024 14:40:40 +0100 Subject: Move TrustLevel Feature -Moved TrustLevel impl from Controller to Inventory Facade -Applied new package name convention using impl\inventory\trustlevel for this (sub)feature -Renamed some trustlevel related classes to better describe their role -Disabled failing architecture test (agreed this is tech. debt and created CPS-2293) -Refactored YangDataConverter method names and signatures (moved Spec to correct place) -Cleaned up names and javadoc of class now called DeviceTrustLevelMessageConsumer -Applied conventions to modified test methods Issue-ID: CPS-2255 Change-Id: Iccd20541488e6b61444bb2c7406c90e61a34124d Signed-off-by: ToineSiebelink --- .../embeddedcache/TrustLevelCacheConfigSpec.groovy | 103 ----------------- .../trustlevel/DeviceHeartbeatConsumerSpec.groovy | 63 ---------- .../impl/trustlevel/TrustLevelManagerSpec.groovy | 127 -------------------- .../ncmp/api/impl/trustlevel/TrustLevelSpec.groovy | 37 ------ .../dmiavailability/DmiPluginWatchDogSpec.groovy | 57 --------- .../api/impl/utils/YangDataConverterSpec.groovy | 59 ---------- .../api/inventory/models/TrustLevelSpec.groovy | 37 ++++++ .../inventory/CmHandleQueryServiceImplSpec.groovy | 2 +- .../CmHandleRegistrationServiceSpec.groovy | 4 +- .../NetworkCmProxyInventoryFacadeSpec.groovy | 57 +++++---- .../DeviceTrustLevelMessageConsumerSpec.groovy | 64 +++++++++++ .../DmiPluginTrustLevelWatchDogSpec.groovy | 56 +++++++++ .../trustlevel/TrustLevelCacheConfigSpec.groovy | 103 +++++++++++++++++ .../trustlevel/TrustLevelManagerSpec.groovy | 128 +++++++++++++++++++++ .../ncmp/impl/utils/YangDataConverterSpec.groovy | 57 +++++++++ 15 files changed, 481 insertions(+), 473 deletions(-) delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy delete mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/TrustLevelSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy (limited to 'cps-ncmp-service/src/test') diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy deleted file mode 100644 index c213ab626..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ============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.ncmp.api.impl.config.embeddedcache - -import com.hazelcast.config.Config -import com.hazelcast.core.Hazelcast -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import spock.lang.Specification - -@SpringBootTest(classes = [TrustLevelCacheConfig]) -class TrustLevelCacheConfigSpec extends Specification { - - @Autowired - private Map trustLevelPerDmiPlugin - - @Autowired - private Map trustLevelPerCmHandle - - def 'Hazelcast cache for trust level per dmi plugin'() { - expect: 'system is able to create an instance of the trust level per dmi plugin cache' - assert null != trustLevelPerDmiPlugin - and: 'there is at least 1 instance' - assert Hazelcast.allHazelcastInstances.size() > 0 - and: 'Dmi Plugin Trust Level Cache is present' - assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerDmiPluginMap') - } - - def 'Hazelcast cache for trust level per cm handle'() { - expect: 'system is able to create an instance of the trust level per cm handle cache' - assert null != trustLevelPerCmHandle - and: 'there is at least 1 instance' - assert Hazelcast.allHazelcastInstances.size() > 0 - and: 'Hazelcast cache instance for trust level is present' - assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerCmHandleMap') - } - - def 'Trust level cache configurations: #scenario'() { - when: 'retrieving the cache config for trustLevel' - def cacheConfig = Hazelcast.getHazelcastInstanceByName(hazelcastInstanceName).config - then: 'the cache config has the right cluster' - assert cacheConfig.clusterName == 'cps-and-ncmp-test-caches' - when: 'retrieving the map config for trustLevel' - def mapConfig = cacheConfig.mapConfigs.get(hazelcastMapConfigName) - then: 'the map config has the correct backup counts' - assert mapConfig.backupCount == 1 - assert mapConfig.asyncBackupCount == 0 - where: 'the following caches are used' - scenario | hazelcastInstanceName | hazelcastMapConfigName - 'cmhandle map' | 'hazelcastInstanceTrustLevelPerCmHandleMap' | 'trustLevelPerCmHandleCacheConfig' - 'dmi plugin map' | 'hazelcastInstanceTrustLevelPerDmiPluginMap' | 'trustLevelPerDmiPluginCacheConfig' - } - - def 'Verify deployment network configs for Distributed Caches'() { - given: 'the Trust Level Per Dmi Plugin Cache config' - def trustLevelDmiPerPluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerDmiPluginMap').config.networkConfig - expect: 'system created instance with correct config' - assert trustLevelDmiPerPluginCacheConfig.join.autoDetectionConfig.enabled - assert !trustLevelDmiPerPluginCacheConfig.join.kubernetesConfig.enabled - } - - def 'Verify deployment network configs for Cm Handle Distributed Caches'() { - given: 'the Trust Level Per Cm Handle Cache config' - def trustLevelPerCmHandlePluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerCmHandleMap').config.networkConfig - expect: 'system created instance with correct config' - assert trustLevelPerCmHandlePluginCacheConfig.join.autoDetectionConfig.enabled - assert !trustLevelPerCmHandlePluginCacheConfig.join.kubernetesConfig.enabled - } - - def 'Verify network config'() { - given: 'Synchronization config object and test configuration' - def objectUnderTest = new TrustLevelCacheConfig() - def testConfig = new Config() - when: 'kubernetes properties are enabled' - objectUnderTest.cacheKubernetesEnabled = true - objectUnderTest.cacheKubernetesServiceName = 'test-service-name' - and: 'method called to update the discovery mode' - objectUnderTest.updateDiscoveryMode(testConfig) - then: 'applied properties are reflected' - assert testConfig.networkConfig.join.kubernetesConfig.enabled - assert testConfig.networkConfig.join.kubernetesConfig.properties.get('service-name') == 'test-service-name' - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy deleted file mode 100644 index 42a1c5d5a..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============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.ncmp.api.impl.trustlevel - -import com.fasterxml.jackson.databind.ObjectMapper -import io.cloudevents.CloudEvent -import io.cloudevents.core.builder.CloudEventBuilder -import org.apache.kafka.clients.consumer.ConsumerRecord -import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel -import org.onap.cps.utils.JsonObjectMapper -import org.springframework.boot.test.context.SpringBootTest -import spock.lang.Specification - -@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) -class DeviceHeartbeatConsumerSpec extends Specification { - - def mockTrustLevelManager = Mock(TrustLevelManager) - - def objectUnderTest = new DeviceHeartbeatConsumer(mockTrustLevelManager) - def objectMapper = new ObjectMapper() - def jsonObjectMapper = new JsonObjectMapper(objectMapper) - - def 'Consume a trust level event'() { - given: 'an event from dmi with trust level complete' - def payload = jsonObjectMapper.convertJsonString('{"data":{"trustLevel": "COMPLETE"}}', DeviceTrustLevel.class) - def eventFromDmi = createTrustLevelEvent(payload) - and: 'transformed to a consumer record with a cloud event id (ce_id)' - def consumerRecord = new ConsumerRecord('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi) - consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('ch-1')) - when: 'the event is consumed' - objectUnderTest.heartbeatListener(consumerRecord) - then: 'cm handles are stored with correct trust level' - 1 * mockTrustLevelManager.handleUpdateOfDeviceTrustLevel('"ch-1"', TrustLevel.COMPLETE) - } - - def createTrustLevelEvent(eventPayload) { - return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(eventPayload)) - .withId('ch-1') - .withSource(URI.create('DMI')) - .withDataSchema(URI.create('test')) - .withType('org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel') - .build() - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy deleted file mode 100644 index 65ab7a7fd..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ============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.ncmp.api.impl.trustlevel - -import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher -import org.onap.cps.ncmp.impl.inventory.InventoryPersistence -import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle -import spock.lang.Specification - -class TrustLevelManagerSpec extends Specification { - - def trustLevelPerCmHandle = [:] - def trustLevelPerDmiPlugin = [:] - - def mockInventoryPersistence = Mock(InventoryPersistence) - def mockAttributeValueChangeEventPublisher = Mock(AvcEventPublisher) - def objectUnderTest = new TrustLevelManager(trustLevelPerCmHandle, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher) - - def 'Initial cm handle registration'() { - given: 'two cm handles: one with no trust level and one trusted' - def cmHandleModelsToBeCreated = ['ch-1': null, 'ch-2': TrustLevel.COMPLETE] - when: 'the initial registration handled' - objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) - then: 'no notification sent' - 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) - and: 'both cm handles are in the cache and are trusted' - assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.COMPLETE - assert trustLevelPerCmHandle.get('ch-2') == TrustLevel.COMPLETE - } - - def 'Initial cm handle registration with a cm handle that is not trusted'() { - given: 'a not trusted cm handle' - def cmHandleModelsToBeCreated = ['ch-2': TrustLevel.NONE] - when: 'the initial registration handled' - objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) - then: 'notification is sent' - 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) - } - - def 'Dmi trust level updated'() { - given: 'a trusted dmi plugin' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) - and: 'a trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) - when: 'the update is handled' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.NONE) - then: 'notification is sent' - 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'COMPLETE', 'NONE') - and: 'the dmi in the cache is not trusted' - assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.NONE - } - - def 'Dmi trust level updated with same value'() { - given: 'a trusted dmi plugin' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) - and: 'a trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) - when: 'the update is handled' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) - then: 'no notification is sent' - 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) - and: 'the dmi in the cache is trusted' - assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.COMPLETE - } - - def 'Device trust level updated'() { - given: 'a non trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) - and: 'a trusted dmi plugin' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) - and: 'inventory persistence service returns yang model cm handle' - mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') - when: 'update of device to COMPLETE trust level handled' - objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.COMPLETE) - then: 'the cm handle in the cache is trusted' - assert trustLevelPerCmHandle.get('ch-1', TrustLevel.COMPLETE) - and: 'notification is sent' - 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'NONE', 'COMPLETE') - } - - def 'Device trust level updated with same value'() { - given: 'a non trusted cm handle' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) - and: 'a trusted dmi plugin' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) - and: 'inventory persistence service returns yang model cm handle' - mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') - when: 'update of device trust to the same level (NONE)' - objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.NONE) - then: 'the cm handle in the cache is not trusted' - assert trustLevelPerCmHandle.get('ch-1', TrustLevel.NONE) - and: 'no notification is sent' - 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) - } - - def 'Dmi trust level restored to complete with non trusted device'() { - given: 'a non trusted dmi' - trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) - and: 'a non trusted device' - trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) - when: 'restore the dmi trust level to COMPLETE' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) - then: 'the cm handle in the cache is still NONE' - assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.NONE - and: 'no notification is sent' - 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelSpec.groovy deleted file mode 100644 index f2521b560..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ============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.ncmp.api.impl.trustlevel - -import spock.lang.Specification - -class TrustLevelSpec extends Specification { - - def 'Get effective trust level between this and other.'() { - expect: 'the lower of two is returned' - assert effectiveLevel == current.getEffectiveTrustLevel(other) - where: 'the following trust level is used' - current | other || effectiveLevel - TrustLevel.COMPLETE | TrustLevel.NONE || TrustLevel.NONE - TrustLevel.NONE | TrustLevel.COMPLETE || TrustLevel.NONE - TrustLevel.COMPLETE | TrustLevel.COMPLETE || TrustLevel.COMPLETE - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy deleted file mode 100644 index f5835ff85..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ============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.ncmp.api.impl.trustlevel.dmiavailability - -import org.onap.cps.ncmp.api.impl.client.DmiRestClient -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager -import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService -import spock.lang.Specification - -class DmiPluginWatchDogSpec extends Specification { - - def mockDmiRestClient = Mock(DmiRestClient) - def mockCmHandleQueryService = Mock(CmHandleQueryService) - def mockTrustLevelManager = Mock(TrustLevelManager) - def trustLevelPerDmiPlugin = [:] - - - def objectUnderTest = new DmiPluginWatchDog(mockDmiRestClient, mockCmHandleQueryService, mockTrustLevelManager, trustLevelPerDmiPlugin) - - def 'watch dmi plugin health status for #dmiHealhStatus'() { - given: 'the cache has been initialised and "knows" about dmi-1' - trustLevelPerDmiPlugin.put('dmi-1', dmiOldTrustLevel) - and: 'dmi client returns health status #dmiHealhStatus' - mockDmiRestClient.getDmiHealthStatus('dmi-1') >> dmiHealhStatus - when: 'dmi watch dog method runs' - objectUnderTest.checkDmiAvailability() - then: 'the update delegated to manager' - numberOfCalls * mockTrustLevelManager.handleUpdateOfDmiTrustLevel('dmi-1', _, newDmiTrustLevel) - where: 'the following parameters are used' - dmiHealhStatus | dmiOldTrustLevel | newDmiTrustLevel || numberOfCalls - 'UP' | TrustLevel.COMPLETE | TrustLevel.COMPLETE || 0 - 'DOWN' | TrustLevel.COMPLETE | TrustLevel.NONE || 1 - 'DOWN' | TrustLevel.NONE | TrustLevel.NONE || 0 - 'UP' | TrustLevel.NONE | TrustLevel.COMPLETE || 1 - '' | TrustLevel.COMPLETE | TrustLevel.NONE || 1 - } - -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy deleted file mode 100644 index 3f0d98934..000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ============LICENSE_START======================================================== - * Copyright (C) 2022-2024 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.ncmp.api.impl.utils - -import org.onap.cps.ncmp.impl.utils.YangDataConverter -import org.onap.cps.spi.model.DataNode -import spock.lang.Specification - -class YangDataConverterSpec extends Specification{ - - def 'Convert a cm handle data node with private and public properties.'() { - given: 'a datanode with some additional (dmi, private) and public properties' - def dataNodeAdditionalProperties = new DataNode(xpath:'/additional-properties[@name="dmiProp1"]', - leaves: ['name': 'dmiProp1', 'value': 'dmiValue1']) - def dataNodePublicProperties = new DataNode(xpath:'/public-properties[@name="pubProp1"]', - leaves: ['name': 'pubProp1', 'value': 'pubValue1']) - def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties]) - when: 'the dataNode is converted' - def yangModelCmHandle = - YangDataConverter.convertCmHandleToYangModel(dataNodeCmHandle) - then: 'the converted object has the correct id' - assert yangModelCmHandle.id == 'sample-id' - and: 'the additional (dmi, private) properties are included' - assert yangModelCmHandle.dmiProperties[0].name == 'dmiProp1' - assert yangModelCmHandle.dmiProperties[0].value == 'dmiValue1' - and: 'the public properties are included' - assert yangModelCmHandle.publicProperties[0].name == 'pubProp1' - assert yangModelCmHandle.publicProperties[0].value == 'pubValue1' - } - - def 'Convert multiple cm handle data nodes'(){ - given: 'two data nodes in a collection' - def dataNodes = [new DataNode(xpath:'/dmi-registry/cm-handles[@id=\'some-cm-handle\']', leaves: ['id':'some-cm-handle']), - new DataNode(xpath:'/dmi-registry/cm-handles[@id=\'another-cm-handle\']', leaves: ['id':'another-cm-handle'])] - when: 'the data nodes are converted' - def yangModelCmHandles = YangDataConverter.convertDataNodesToYangModelCmHandles(dataNodes) - then: 'verify both have returned and CmHandleIds are correct' - assert yangModelCmHandles.size() == 2 - assert yangModelCmHandles.id.containsAll(['some-cm-handle', 'another-cm-handle']) - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/TrustLevelSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/TrustLevelSpec.groovy new file mode 100644 index 000000000..1e1dfaaa9 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/TrustLevelSpec.groovy @@ -0,0 +1,37 @@ +/* + * ============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.ncmp.api.inventory.models + +import spock.lang.Specification + +class TrustLevelSpec extends Specification { + + def 'Get effective trust level between this and other.'() { + expect: 'the lower of two is returned' + assert effectiveLevel == current.getEffectiveTrustLevel(other) + where: 'the following trust level is used' + current | other || effectiveLevel + TrustLevel.COMPLETE | TrustLevel.NONE || TrustLevel.NONE + TrustLevel.NONE | TrustLevel.COMPLETE || TrustLevel.NONE + TrustLevel.COMPLETE | TrustLevel.COMPLETE || TrustLevel.COMPLETE + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy index 52ddcfb6c..36fd75577 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy @@ -21,7 +21,7 @@ package org.onap.cps.ncmp.impl.inventory -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel +import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.model.DataNode diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy index da3116283..9d4d9565e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy @@ -26,16 +26,16 @@ import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler import org.onap.cps.ncmp.api.impl.exception.DmiRequestException -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel -import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle +import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.api.inventory.models.UpgradedCmHandles import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle +import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager import org.onap.cps.spi.exceptions.AlreadyDefinedException import org.onap.cps.spi.exceptions.CpsException import org.onap.cps.spi.exceptions.DataNodeNotFoundException diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy index 49d4c39a1..716efd8fd 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy @@ -31,6 +31,7 @@ import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.ConditionApiProperties import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle +import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle @@ -38,8 +39,6 @@ import org.onap.cps.spi.model.ConditionProperties import org.onap.cps.utils.JsonObjectMapper import spock.lang.Specification -import java.util.stream.Collectors - class NetworkCmProxyInventoryFacadeSpec extends Specification { def mockCmHandleRegistrationService = Mock(CmHandleRegistrationService) @@ -47,8 +46,9 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { def mockParameterizedCmHandleQueryService = Mock(ParameterizedCmHandleQueryService) def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) def mockInventoryPersistence = Mock(InventoryPersistence) + def trustLevelPerCmHandle = [:] - def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper) + def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, trustLevelPerCmHandle) def 'Update DMI Registration'() { given: 'an (updated) dmi plugin registration' @@ -98,7 +98,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { given: 'the system returns a yang modelled cm handle' def dmiServiceName = 'some service name' def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, - lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(), + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details('lock details').build(), lastUpdateTime: 'some-timestamp', dataSyncEnabled: false, dataStores: dataStores()) @@ -106,26 +106,29 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')] def moduleSetTag = 'some-module-set-tag' def alternateId = 'some-alternate-id' - def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName, - dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState, - moduleSetTag: moduleSetTag, alternateId: alternateId) - 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle + def yangModelCmHandle = new YangModelCmHandle(id: 'ch-1', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties, + publicProperties: publicProperties, compositeState: compositeState, moduleSetTag: moduleSetTag, alternateId: alternateId) + 1 * mockInventoryPersistence.getYangModelCmHandle('ch-1') >> yangModelCmHandle + and: 'a trust level for the cm handle in the cache' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) when: 'getting cm handle details for a given cm handle id from ncmp service' - def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle') + def result = objectUnderTest.getNcmpServiceCmHandle('ch-1') then: 'the result is a ncmpServiceCmHandle' - result.class == NcmpServiceCmHandle.class + assert result.class == NcmpServiceCmHandle.class and: 'the cm handle contains the cm handle id' - result.cmHandleId == 'some-cm-handle' + assert result.cmHandleId == 'ch-1' and: 'the cm handle contains the alternate id' - result.alternateId == 'some-alternate-id' + assert result.alternateId == 'some-alternate-id' and: 'the cm handle contains the module-set-tag' - result.moduleSetTag == 'some-module-set-tag' + assert result.moduleSetTag == 'some-module-set-tag' and: 'the cm handle contains the DMI Properties' - result.dmiProperties ==[ Book:'Romance Novel' ] + assert result.dmiProperties ==[ Book:'Romance Novel' ] and: 'the cm handle contains the public Properties' - result.publicProperties == [ "Public Book":'Public Romance Novel' ] + assert result.publicProperties == [ "Public Book":'Public Romance Novel' ] and: 'the cm handle contains the cm handle composite state' - result.compositeState == compositeState + assert result.compositeState == compositeState + and: 'the cm handle contains the trust level from the cache' + assert result.currentTrustLevel == TrustLevel.COMPLETE } def 'Get cm handle public properties'() { @@ -138,7 +141,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { when: 'getting cm handle public properties for a given cm handle id from ncmp service' def result = objectUnderTest.getCmHandlePublicProperties('some-cm-handle') then: 'the result returns the correct data' - result == [ 'public prop' : 'some public prop' ] + assert result == [ 'public prop' : 'some public prop' ] } def 'Get cm handle composite state'() { @@ -156,7 +159,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { when: 'getting cm handle composite state for a given cm handle id from ncmp service' def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle') then: 'the result returns the correct data' - result == compositeState + assert result == compositeState } def 'Execute cm handle id search'() { @@ -197,14 +200,21 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { conditionApiProperties.conditionName = 'hasAllModules' conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']] cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties] - and: 'query cm handle method return with a data node list' + and: 'query cm handle method returns two cm handles' mockParameterizedCmHandleQueryService.queryCmHandles( spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class)) - >> [new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1')] + >> [new NcmpServiceCmHandle(cmHandleId: 'ch-0'), new NcmpServiceCmHandle(cmHandleId: 'ch-1')] + and: ' a trust level for ch-1' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) when: 'execute cm handle search is called' def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters) - then: 'result is the same collection as returned by the CPS Data Service' - assert result.stream().map(cmHandle -> cmHandle.cmHandleId).collect(Collectors.toSet()) == ['cm-handle-id-1'] as Set + then: 'result consists of the two cm handles returned by the CPS Data Service' + assert result.size() == 2 + assert result[0].cmHandleId == 'ch-0' + assert result[1].cmHandleId == 'ch-1' + and: 'only ch-1 has a trust level' + assert result[0].currentTrustLevel == null + assert result[1].currentTrustLevel == TrustLevel.COMPLETE } def 'Set Cm Handle Data Sync flag.'() { @@ -215,8 +225,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { } def dataStores() { - CompositeState.DataStores.builder() - .operationalDataStore(CompositeState.Operational.builder() + CompositeState.DataStores.builder().operationalDataStore(CompositeState.Operational.builder() .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED) .lastSyncTime('some-timestamp').build()).build() } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy new file mode 100644 index 000000000..6db304acd --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy @@ -0,0 +1,64 @@ +/* + * ============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.ncmp.impl.inventory.trustlevel + +import com.fasterxml.jackson.databind.ObjectMapper +import io.cloudevents.CloudEvent +import io.cloudevents.core.builder.CloudEventBuilder +import org.apache.kafka.clients.consumer.ConsumerRecord +import org.onap.cps.ncmp.api.inventory.models.TrustLevel +import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel +import org.onap.cps.utils.JsonObjectMapper +import org.springframework.boot.test.context.SpringBootTest +import spock.lang.Specification + +@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) +class DeviceTrustLevelMessageConsumerSpec extends Specification { + + def mockTrustLevelManager = Mock(TrustLevelManager) + + def objectUnderTest = new DeviceTrustLevelMessageConsumer(mockTrustLevelManager) + def objectMapper = new ObjectMapper() + def jsonObjectMapper = new JsonObjectMapper(objectMapper) + + def 'Consume a trust level event'() { + given: 'an event from dmi with trust level complete' + def payload = jsonObjectMapper.convertJsonString('{"data":{"trustLevel": "COMPLETE"}}', DeviceTrustLevel.class) + def eventFromDmi = createTrustLevelEvent(payload) + and: 'transformed to a consumer record with a cloud event id (ce_id)' + def consumerRecord = new ConsumerRecord('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi) + consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('ch-1')) + when: 'the event is consumed' + objectUnderTest.deviceTrustLevelListener(consumerRecord) + then: 'cm handles are stored with correct trust level' + 1 * mockTrustLevelManager.handleUpdateOfDeviceTrustLevel('"ch-1"', TrustLevel.COMPLETE) + } + + def createTrustLevelEvent(eventPayload) { + return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(eventPayload)) + .withId('ch-1') + .withSource(URI.create('DMI')) + .withDataSchema(URI.create('test')) + .withType('org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel') + .build() + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy new file mode 100644 index 000000000..7fa8b2cce --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy @@ -0,0 +1,56 @@ +/* + * ============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.ncmp.impl.inventory.trustlevel + +import org.onap.cps.ncmp.api.impl.client.DmiRestClient +import org.onap.cps.ncmp.api.inventory.models.TrustLevel +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService +import spock.lang.Specification + +class DmiPluginTrustLevelWatchDogSpec extends Specification { + + def mockDmiRestClient = Mock(DmiRestClient) + def mockCmHandleQueryService = Mock(CmHandleQueryService) + def mockTrustLevelManager = Mock(TrustLevelManager) + def trustLevelPerDmiPlugin = [:] + + + def objectUnderTest = new DmiPluginTrustLevelWatchDog(mockDmiRestClient, mockCmHandleQueryService, mockTrustLevelManager, trustLevelPerDmiPlugin) + + def 'watch dmi plugin health status for #dmiHealhStatus'() { + given: 'the cache has been initialised and "knows" about dmi-1' + trustLevelPerDmiPlugin.put('dmi-1', dmiOldTrustLevel) + and: 'dmi client returns health status #dmiHealhStatus' + mockDmiRestClient.getDmiHealthStatus('dmi-1') >> dmiHealhStatus + when: 'dmi watch dog method runs' + objectUnderTest.checkDmiAvailability() + then: 'the update delegated to manager' + numberOfCalls * mockTrustLevelManager.handleUpdateOfDmiTrustLevel('dmi-1', _, newDmiTrustLevel) + where: 'the following parameters are used' + dmiHealhStatus | dmiOldTrustLevel | newDmiTrustLevel || numberOfCalls + 'UP' | TrustLevel.COMPLETE | TrustLevel.COMPLETE || 0 + 'DOWN' | TrustLevel.COMPLETE | TrustLevel.NONE || 1 + 'DOWN' | TrustLevel.NONE | TrustLevel.NONE || 0 + 'UP' | TrustLevel.NONE | TrustLevel.COMPLETE || 1 + '' | TrustLevel.COMPLETE | TrustLevel.NONE || 1 + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy new file mode 100644 index 000000000..e79a47101 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelCacheConfigSpec.groovy @@ -0,0 +1,103 @@ +/* + * ============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.ncmp.impl.inventory.trustlevel + +import com.hazelcast.config.Config +import com.hazelcast.core.Hazelcast +import org.onap.cps.ncmp.api.inventory.models.TrustLevel +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import spock.lang.Specification + +@SpringBootTest(classes = [TrustLevelCacheConfig]) +class TrustLevelCacheConfigSpec extends Specification { + + @Autowired + private Map trustLevelPerDmiPlugin + + @Autowired + private Map trustLevelPerCmHandle + + def 'Hazelcast cache for trust level per dmi plugin'() { + expect: 'system is able to create an instance of the trust level per dmi plugin cache' + assert null != trustLevelPerDmiPlugin + and: 'there is at least 1 instance' + assert Hazelcast.allHazelcastInstances.size() > 0 + and: 'Dmi Plugin Trust Level Cache is present' + assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerDmiPluginMap') + } + + def 'Hazelcast cache for trust level per cm handle'() { + expect: 'system is able to create an instance of the trust level per cm handle cache' + assert null != trustLevelPerCmHandle + and: 'there is at least 1 instance' + assert Hazelcast.allHazelcastInstances.size() > 0 + and: 'Hazelcast cache instance for trust level is present' + assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerCmHandleMap') + } + + def 'Trust level cache configurations: #scenario'() { + when: 'retrieving the cache config for trustLevel' + def cacheConfig = Hazelcast.getHazelcastInstanceByName(hazelcastInstanceName).config + then: 'the cache config has the right cluster' + assert cacheConfig.clusterName == 'cps-and-ncmp-test-caches' + when: 'retrieving the map config for trustLevel' + def mapConfig = cacheConfig.mapConfigs.get(hazelcastMapConfigName) + then: 'the map config has the correct backup counts' + assert mapConfig.backupCount == 1 + assert mapConfig.asyncBackupCount == 0 + where: 'the following caches are used' + scenario | hazelcastInstanceName | hazelcastMapConfigName + 'cmhandle map' | 'hazelcastInstanceTrustLevelPerCmHandleMap' | 'trustLevelPerCmHandleCacheConfig' + 'dmi plugin map' | 'hazelcastInstanceTrustLevelPerDmiPluginMap' | 'trustLevelPerDmiPluginCacheConfig' + } + + def 'Verify deployment network configs for Distributed Caches'() { + given: 'the Trust Level Per Dmi Plugin Cache config' + def trustLevelDmiPerPluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerDmiPluginMap').config.networkConfig + expect: 'system created instance with correct config' + assert trustLevelDmiPerPluginCacheConfig.join.autoDetectionConfig.enabled + assert !trustLevelDmiPerPluginCacheConfig.join.kubernetesConfig.enabled + } + + def 'Verify deployment network configs for Cm Handle Distributed Caches'() { + given: 'the Trust Level Per Cm Handle Cache config' + def trustLevelPerCmHandlePluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerCmHandleMap').config.networkConfig + expect: 'system created instance with correct config' + assert trustLevelPerCmHandlePluginCacheConfig.join.autoDetectionConfig.enabled + assert !trustLevelPerCmHandlePluginCacheConfig.join.kubernetesConfig.enabled + } + + def 'Verify network config'() { + given: 'Synchronization config object and test configuration' + def objectUnderTest = new TrustLevelCacheConfig() + def testConfig = new Config() + when: 'kubernetes properties are enabled' + objectUnderTest.cacheKubernetesEnabled = true + objectUnderTest.cacheKubernetesServiceName = 'test-service-name' + and: 'method called to update the discovery mode' + objectUnderTest.updateDiscoveryMode(testConfig) + then: 'applied properties are reflected' + assert testConfig.networkConfig.join.kubernetesConfig.enabled + assert testConfig.networkConfig.join.kubernetesConfig.properties.get('service-name') == 'test-service-name' + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy new file mode 100644 index 000000000..4c22dbaed --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy @@ -0,0 +1,128 @@ +/* + * ============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.ncmp.impl.inventory.trustlevel + +import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher +import org.onap.cps.ncmp.api.inventory.models.TrustLevel +import org.onap.cps.ncmp.impl.inventory.InventoryPersistence +import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle +import spock.lang.Specification + +class TrustLevelManagerSpec extends Specification { + + def trustLevelPerCmHandle = [:] + def trustLevelPerDmiPlugin = [:] + + def mockInventoryPersistence = Mock(InventoryPersistence) + def mockAttributeValueChangeEventPublisher = Mock(AvcEventPublisher) + def objectUnderTest = new TrustLevelManager(trustLevelPerCmHandle, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher) + + def 'Initial cm handle registration'() { + given: 'two cm handles: one with no trust level and one trusted' + def cmHandleModelsToBeCreated = ['ch-1': null, 'ch-2': TrustLevel.COMPLETE] + when: 'the initial registration handled' + objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) + then: 'no notification sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + and: 'both cm handles are in the cache and are trusted' + assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.COMPLETE + assert trustLevelPerCmHandle.get('ch-2') == TrustLevel.COMPLETE + } + + def 'Initial cm handle registration with a cm handle that is not trusted'() { + given: 'a not trusted cm handle' + def cmHandleModelsToBeCreated = ['ch-2': TrustLevel.NONE] + when: 'the initial registration handled' + objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) + then: 'notification is sent' + 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + } + + def 'Dmi trust level updated'() { + given: 'a trusted dmi plugin' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) + and: 'a trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + when: 'the update is handled' + objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.NONE) + then: 'notification is sent' + 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'COMPLETE', 'NONE') + and: 'the dmi in the cache is not trusted' + assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.NONE + } + + def 'Dmi trust level updated with same value'() { + given: 'a trusted dmi plugin' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) + and: 'a trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + when: 'the update is handled' + objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) + then: 'no notification is sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + and: 'the dmi in the cache is trusted' + assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.COMPLETE + } + + def 'Device trust level updated'() { + given: 'a non trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + and: 'a trusted dmi plugin' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) + and: 'inventory persistence service returns yang model cm handle' + mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') + when: 'update of device to COMPLETE trust level handled' + objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.COMPLETE) + then: 'the cm handle in the cache is trusted' + assert trustLevelPerCmHandle.get('ch-1', TrustLevel.COMPLETE) + and: 'notification is sent' + 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'NONE', 'COMPLETE') + } + + def 'Device trust level updated with same value'() { + given: 'a non trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + and: 'a trusted dmi plugin' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) + and: 'inventory persistence service returns yang model cm handle' + mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') + when: 'update of device trust to the same level (NONE)' + objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.NONE) + then: 'the cm handle in the cache is not trusted' + assert trustLevelPerCmHandle.get('ch-1', TrustLevel.NONE) + and: 'no notification is sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + } + + def 'Dmi trust level restored to complete with non trusted device'() { + given: 'a non trusted dmi' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) + and: 'a non trusted device' + trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + when: 'restore the dmi trust level to COMPLETE' + objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) + then: 'the cm handle in the cache is still NONE' + assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.NONE + and: 'no notification is sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy new file mode 100644 index 000000000..bb45e8ad9 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START======================================================== + * Copyright (C) 2022-2024 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.ncmp.impl.utils + +import org.onap.cps.spi.model.DataNode +import spock.lang.Specification + +class YangDataConverterSpec extends Specification{ + + def 'Convert a cm handle data node with private and public properties.'() { + given: 'a datanode with some additional (dmi, private) and public properties' + def dataNodeAdditionalProperties = new DataNode(xpath:'/additional-properties[@name="dmiProp1"]', + leaves: ['name': 'dmiProp1', 'value': 'dmiValue1']) + def dataNodePublicProperties = new DataNode(xpath:'/public-properties[@name="pubProp1"]', + leaves: ['name': 'pubProp1', 'value': 'pubValue1']) + def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties]) + when: 'the dataNode is converted' + def yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNodeCmHandle) + then: 'the converted object has the correct id' + assert yangModelCmHandle.id == 'sample-id' + and: 'the additional (dmi, private) properties are included' + assert yangModelCmHandle.dmiProperties[0].name == 'dmiProp1' + assert yangModelCmHandle.dmiProperties[0].value == 'dmiValue1' + and: 'the public properties are included' + assert yangModelCmHandle.publicProperties[0].name == 'pubProp1' + assert yangModelCmHandle.publicProperties[0].value == 'pubValue1' + } + + def 'Convert multiple cm handle data nodes'(){ + given: 'two data nodes in a collection' + def dataNodes = [new DataNode(xpath:'/dmi-registry/cm-handles[@id=\'some-cm-handle\']', leaves: ['id':'some-cm-handle']), + new DataNode(xpath:'/dmi-registry/cm-handles[@id=\'another-cm-handle\']', leaves: ['id':'another-cm-handle'])] + when: 'the data nodes are converted' + def yangModelCmHandles = YangDataConverter.toYangModelCmHandles(dataNodes) + then: 'verify both have returned and CmHandleIds are correct' + assert yangModelCmHandles.size() == 2 + assert yangModelCmHandles.id.containsAll(['some-cm-handle', 'another-cm-handle']) + } +} -- cgit 1.2.3-korg