2  * ============LICENSE_START=======================================================
 
   3  * ONAP : ccsdk features
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *     http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  19  * ============LICENSE_END=========================================================
 
  21 package org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test;
 
  23 import static org.junit.Assert.assertEquals;
 
  24 import static org.junit.Assert.assertNotNull;
 
  25 import static org.junit.Assert.assertTrue;
 
  26 import com.google.common.util.concurrent.ListenableFuture;
 
  28 import java.io.FileNotFoundException;
 
  29 import java.io.IOException;
 
  30 import java.nio.file.Files;
 
  31 import java.nio.file.Path;
 
  32 import java.nio.file.Paths;
 
  33 import java.util.Arrays;
 
  34 import java.util.Collection;
 
  35 import java.util.concurrent.ExecutionException;
 
  36 import org.eclipse.jdt.annotation.NonNull;
 
  37 import org.junit.AfterClass;
 
  38 import org.junit.BeforeClass;
 
  39 import org.junit.Test;
 
  40 import org.mockito.ArgumentCaptor;
 
  41 import org.mockito.Mockito;
 
  42 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.IEntityDataProvider;
 
  43 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfAccessor;
 
  44 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeConnectListener;
 
  45 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateListener;
 
  46 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener;
 
  47 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.NetconfNodeStateServiceImpl;
 
  48 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.NetconfnodeStateServiceRpcApiImpl;
 
  49 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.example.ExampleConfig;
 
  50 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.example.TestNetconfHelper;
 
  51 import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
 
  52 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
 
  53 import org.opendaylight.mdsal.binding.api.DataBroker;
 
  54 import org.opendaylight.mdsal.binding.api.DataObjectModification;
 
  55 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
 
  56 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
 
  57 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 
  58 import org.opendaylight.mdsal.binding.api.MountPointService;
 
  59 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 
  60 import org.opendaylight.mdsal.binding.api.RpcProviderService;
 
  61 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
 
  62 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext;
 
  63 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
 
  64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 
  65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
 
  66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
 
  67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotification;
 
  68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotificationBuilder;
 
  69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotification;
 
  70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotificationBuilder;
 
  71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInputBuilder;
 
  72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutput;
 
  73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder;
 
  74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationInputBuilder;
 
  75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationOutput;
 
  76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationInputBuilder;
 
  77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput;
 
  78 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 
  79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 
  80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
 
  81 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 
  82 import org.opendaylight.yangtools.yang.binding.DataObject;
 
  83 import org.opendaylight.yangtools.yang.common.RpcResult;
 
  84 import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
 
  85 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
 
  86 import org.opendaylight.yangtools.yang.parser.impl.YangParserFactoryImpl;
 
  87 import org.slf4j.Logger;
 
  88 import org.slf4j.LoggerFactory;
 
  91 public class TestNetconfNodeStateService extends Mockito {
 
  93     private static Path KARAF_ETC = Paths.get("etc");
 
  94     private static NetconfNodeStateServiceImpl netconfStateService;
 
  95     //private static DataBrokerNetconfMock dataBrokerNetconf;
 
  96     private static DataBroker dataBrokerNetconf;
 
  97     private @NonNull static DataTreeChangeListener<Node> listener;
 
  98     private @NonNull static ClusteredDataTreeChangeListener<Node> listenerClustered;
 
 101     private static final Logger LOG = LoggerFactory.getLogger(TestNetconfNodeStateService.class);
 
 103     @SuppressWarnings("unchecked")
 
 105     public static <T extends DataObject, L extends DataTreeChangeListener<T>> void before()
 
 106             throws InterruptedException, IOException {
 
 108         System.out.println("Logger: " + LOG.getClass().getName() + " " + LOG.getName());
 
 109         // Call System property to get the classpath value
 
 110         Path etc = KARAF_ETC;
 
 113         System.out.println("Create empty:" + etc.toString());
 
 114         Files.createDirectories(etc);
 
 117         //dataBrokerNetconf = new DataBrokerNetconfMock();
 
 118         //dataBrokerNetconf.newReadWriteTransaction();
 
 119         dataBrokerNetconf = mock(DataBroker.class);
 
 120         when(dataBrokerNetconf.registerDataTreeChangeListener(any(), any())).thenAnswer(invocation -> {
 
 121             Object pListener = invocation.getArguments()[1];
 
 122             System.out.println("Register " + pListener.getClass().getName());
 
 123             if (pListener instanceof ClusteredDataTreeChangeListener) {
 
 124                 System.out.println("Clustered listener");
 
 125                 listenerClustered = (ClusteredDataTreeChangeListener<Node>) pListener;
 
 126             } else if (pListener instanceof DataTreeChangeListener) {
 
 127                 System.out.println("Listener");
 
 128                 listener = (DataTreeChangeListener<Node>) pListener;
 
 130             return new ListenerRegistration<L>() {
 
 132                 public L getInstance() {
 
 133                     return (L) pListener;
 
 137                 public void close() {}
 
 141         ClusterSingletonServiceProvider clusterSingletonService = mock(ClusterSingletonServiceProvider.class);
 
 142         MountPointService mountPointService = mock(MountPointService.class);
 
 143         NotificationPublishService notificationPublishService = mock(NotificationPublishService.class);
 
 144         RpcProviderService rpcProviderRegistry = mock(RpcProviderService.class);
 
 145         IEntityDataProvider entityProviderMock = mock(IEntityDataProvider.class);
 
 146         YangParserFactory yangParserFactory = new YangParserFactoryImpl();
 
 147         BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer =
 
 148                 new BindingCodecContext(BindingRuntimeHelpers.createRuntimeContext());
 
 149         // start using blueprint interface
 
 150         netconfStateService = new NetconfNodeStateServiceImpl();
 
 152         netconfStateService.setDataBroker(dataBrokerNetconf);
 
 153         netconfStateService.setMountPointService(mountPointService);
 
 154         netconfStateService.setNotificationPublishService(notificationPublishService);
 
 155         netconfStateService.setRpcProviderRegistry(rpcProviderRegistry);
 
 156         netconfStateService.setClusterSingletonService(clusterSingletonService);
 
 157         netconfStateService.setEntityDataProvider(entityProviderMock);
 
 158         netconfStateService.setYangParserFactory(yangParserFactory);
 
 159         netconfStateService.setBindingNormalizedNodeSerializer(bindingNormalizedNodeSerializer);
 
 160         netconfStateService.init();
 
 161         System.out.println("Initialization done");
 
 165     public static void after() throws InterruptedException, IOException {
 
 166         System.out.println("Start shutdown");
 
 167         // close using blueprint interface
 
 168         netconfStateService.close();
 
 174     public void test1() {
 
 176         System.out.println("Test1: Verify init state");
 
 177         assertTrue("Devicemanager not initialized", netconfStateService.isInitializationSuccessful());
 
 182     public void test2() {
 
 184         System.out.println("Test2: Register state listener");
 
 186         NetconfNodeStateListener nSL = mock(NetconfNodeStateListener.class);
 
 187         ListenerRegistration<NetconfNodeStateListener> res = netconfStateService.registerNetconfNodeStateListener(nSL);
 
 188         assertNotNull("Result should be null", res);
 
 194     public void test3() {
 
 196         System.out.println("Test3: Register connect listener");
 
 198         NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
 
 199         ListenerRegistration<NetconfNodeConnectListener> res =
 
 200                 netconfStateService.registerNetconfNodeConnectListener(nCL);
 
 201         assertNotNull("Result should be null", res);
 
 207     public void test4() {
 
 208         System.out.println("Test4: Get status listener");
 
 209         GetStatusInputBuilder inputBuilder = new GetStatusInputBuilder();
 
 210         GetStatusOutputBuilder res = netconfStateService.getStatus(inputBuilder.build());
 
 211         assertNotNull("Result should be null", res);
 
 214     @SuppressWarnings("unchecked")
 
 216     public void test5OnConnect() throws InterruptedException {
 
 217         System.out.println("Test5: On Connect");
 
 218         String nodeIdString = "Test";
 
 219         String capabilityStringForNetworkElement = "network-element";
 
 220         NodeId nodeId = new NodeId(nodeIdString);
 
 221         Node rootNode = TestNetconfHelper.getTestNode(nodeId, capabilityStringForNetworkElement);
 
 223         DataObjectModification<Node> dom = mock(DataObjectModification.class);
 
 224         when(dom.getDataAfter()).thenReturn(rootNode);
 
 225         when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
 
 227         DataTreeModification<Node> ntn = mock(DataTreeModification.class);
 
 228         when(ntn.getRootNode()).thenReturn(dom);
 
 230         NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
 
 231         netconfStateService.registerNetconfNodeConnectListener(nCL);
 
 233         Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
 
 234         sendClusteredChanges(changes);
 
 235         sendChanges(changes);
 
 237         //verify that it was called one time and nodeId is the expected
 
 238         ArgumentCaptor<NetconfAccessor> varArgs = ArgumentCaptor.forClass(NetconfAccessor.class);
 
 239         verify(nCL).onEnterConnected(varArgs.capture());
 
 240         NetconfAccessor accessor = varArgs.getValue();
 
 241         System.out.println("Accessor " + accessor.getNodeId());
 
 242         assertEquals(nodeIdString, accessor.getNodeId().getValue());
 
 245     @SuppressWarnings("unchecked")
 
 247     public void test6Update() {
 
 248         System.out.println("Test6: OnChange");
 
 249         NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
 
 250         netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected);
 
 251         NetconfNode rootNodeNetconf = netconfNodeBuilder.build();
 
 253         NodeBuilder nodeBuilder = new NodeBuilder();
 
 254         nodeBuilder.addAugmentation(rootNodeNetconf);
 
 255         nodeBuilder.setNodeId(new NodeId("Test"));
 
 256         Node rootNodeAfter = nodeBuilder.build();
 
 258         DataObjectModification<Node> dom = mock(DataObjectModification.class);
 
 259         when(dom.getDataBefore()).thenReturn(rootNodeAfter);
 
 260         when(dom.getDataAfter()).thenReturn(rootNodeAfter);
 
 261         when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
 
 263         DataTreeModification<Node> ntn = mock(DataTreeModification.class);
 
 264         when(ntn.getRootNode()).thenReturn(dom);
 
 266         Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
 
 267         sendClusteredChanges(changes);
 
 268         sendChanges(changes);
 
 272     public void test7ApiStatus() throws InterruptedException, ExecutionException {
 
 274         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
 
 276         GetStatusInputBuilder statusInput = new GetStatusInputBuilder();
 
 277         ListenableFuture<RpcResult<GetStatusOutput>> statusOutput = api.getStatus(statusInput.build());
 
 278         RpcResult<GetStatusOutput> res = statusOutput.get();
 
 279         GetStatusOutput output = res.getResult();
 
 280         System.out.println("Output " + output);
 
 285     public void test8ApiPushFault() throws InterruptedException, ExecutionException {
 
 287         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
 
 289         VesNotificationListener vNL = mock(VesNotificationListener.class);
 
 290         ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
 
 292         FaultNotificationBuilder faultBuilder = new FaultNotificationBuilder();
 
 293         faultBuilder.setProblem("problem1");
 
 294         FaultNotification fault = faultBuilder.build();
 
 295         PushFaultNotificationInputBuilder statusInput = new PushFaultNotificationInputBuilder();
 
 296         statusInput.fieldsFrom(fault);
 
 297         ListenableFuture<RpcResult<PushFaultNotificationOutput>> rpcOutput =
 
 298                 api.pushFaultNotification(statusInput.build());
 
 299         RpcResult<PushFaultNotificationOutput> res = rpcOutput.get();
 
 300         PushFaultNotificationOutput output = res.getResult();
 
 302         //verify that it was called one time
 
 303         verify(vNL, times(1)).onNotification(fault);
 
 305         registration.close();
 
 306         System.out.println("Output " + output);
 
 310     public void test9ApiPushNotifiction() throws InterruptedException, ExecutionException {
 
 312         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
 
 314         VesNotificationListener vNL = mock(VesNotificationListener.class);
 
 315         ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
 
 317         AttributeChangeNotificationBuilder changeBuilder = new AttributeChangeNotificationBuilder();
 
 318         changeBuilder.setAttributeName("attribute1");
 
 319         AttributeChangeNotification change = changeBuilder.build();
 
 320         PushAttributeChangeNotificationInputBuilder statusInput = new PushAttributeChangeNotificationInputBuilder();
 
 321         statusInput.fieldsFrom(change);
 
 322         ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> rpcOutput =
 
 323                 api.pushAttributeChangeNotification(statusInput.build());
 
 324         RpcResult<PushAttributeChangeNotificationOutput> res = rpcOutput.get();
 
 325         PushAttributeChangeNotificationOutput output = res.getResult();
 
 327         //verify that it was called one time
 
 328         verify(vNL, times(1)).onNotification(change);
 
 330         registration.close();
 
 331         System.out.println("Output " + output);
 
 335     public void test10ApiPushNotifiction() throws YangParserException, IOException {
 
 336         ExampleConfig.exampleConfig(netconfStateService.getDomContext());
 
 340     public void test10NetconfAccessorClone() {
 
 344     // ------- private section
 
 346     private static void delete(Path etc) throws IOException {
 
 347         if (Files.exists(etc)) {
 
 348             System.out.println("Found and remove:" + etc.toString());
 
 349             delete(etc.toFile());
 
 353     private static void delete(File f) throws IOException {
 
 354         if (f.isDirectory()) {
 
 355             for (File c : f.listFiles()) {
 
 360             throw new FileNotFoundException("Failed to delete file: " + f);
 
 364     public void sendChanges(Collection<DataTreeModification<Node>> changes) {
 
 365         listener.onDataTreeChanged(changes);
 
 368     public void sendClusteredChanges(Collection<DataTreeModification<Node>> changes) {
 
 369         listenerClustered.onDataTreeChanged(changes);