5de8b70750abc6873865197b297c967635866db0
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
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
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21 package org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test;
22
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;
27 import java.io.File;
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.mock.ClusterSingletonServiceProviderMock;
51 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointMock;
52 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointServiceMock;
53 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.NotificationPublishServiceMock;
54 import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.RpcProviderRegistryMock;
55 import org.opendaylight.binding.runtime.spi.BindingRuntimeHelpers;
56 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
57 import org.opendaylight.mdsal.binding.api.DataBroker;
58 import org.opendaylight.mdsal.binding.api.DataObjectModification;
59 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
60 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
61 import org.opendaylight.mdsal.binding.api.DataTreeModification;
62 import org.opendaylight.mdsal.binding.api.MountPointService;
63 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
64 import org.opendaylight.mdsal.binding.api.RpcProviderService;
65 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
66 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext;
67 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotification;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotificationBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotification;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotificationBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationInputBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationOutput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationInputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
87 import org.opendaylight.yangtools.concepts.ListenerRegistration;
88 import org.opendaylight.yangtools.yang.binding.DataObject;
89 import org.opendaylight.yangtools.yang.common.RpcResult;
90 import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
91 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
92 import org.opendaylight.yangtools.yang.parser.impl.YangParserFactoryImpl;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
95
96
97 public class TestNetconfNodeStateService extends Mockito {
98
99     private static Path KARAF_ETC = Paths.get("etc");
100     private static NetconfNodeStateServiceImpl netconfStateService;
101     private static MountPointMock mountPoint;
102     //private static DataBrokerNetconfMock dataBrokerNetconf;
103     private static DataBroker dataBrokerNetconf;
104     private @NonNull
105     static DataTreeChangeListener<Node> listener;
106     private @NonNull
107     static ClusteredDataTreeChangeListener<Node> listenerClustered;
108
109
110     private static final Logger LOG = LoggerFactory.getLogger(TestNetconfNodeStateService.class);
111
112     @SuppressWarnings("unchecked")
113     @BeforeClass
114     public static <T extends DataObject, L extends DataTreeChangeListener<T>> void before() throws InterruptedException, IOException {
115
116         System.out.println("Logger: " + LOG.getClass().getName() + " " + LOG.getName());
117         // Call System property to get the classpath value
118         Path etc = KARAF_ETC;
119         delete(etc);
120
121         System.out.println("Create empty:" + etc.toString());
122         Files.createDirectories(etc);
123
124         // Create mocks
125         //dataBrokerNetconf = new DataBrokerNetconfMock();
126         //dataBrokerNetconf.newReadWriteTransaction();
127         dataBrokerNetconf = mock(DataBroker.class);
128         when(dataBrokerNetconf.registerDataTreeChangeListener(any(), any())).thenAnswer(
129                 invocation -> {
130                     Object pListener = invocation.getArguments()[1];
131                     System.out.println("Register " + pListener.getClass().getName());
132                     if (pListener instanceof ClusteredDataTreeChangeListener) {
133                         System.out.println("Clustered listener");
134                         listenerClustered = (ClusteredDataTreeChangeListener<Node>) pListener;
135                     } else if (pListener instanceof DataTreeChangeListener) {
136                         System.out.println("Listener");
137                         listener = (DataTreeChangeListener<Node>) pListener;
138                     }
139                     return new ListenerRegistration<L>() {
140                         @Override
141                         public L getInstance() {
142                             return (L) pListener;
143                         }
144
145                         @Override
146                         public void close() {
147                         }
148                     };
149
150                 }
151 );
152
153         mountPoint = new MountPointMock();
154         ClusterSingletonServiceProvider clusterSingletonService = new ClusterSingletonServiceProviderMock();
155         MountPointService mountPointService = new MountPointServiceMock(mountPoint);
156         NotificationPublishService notificationPublishService = new NotificationPublishServiceMock();
157         RpcProviderService rpcProviderRegistry = new RpcProviderRegistryMock();
158         IEntityDataProvider entityProviderMock = mock(IEntityDataProvider.class);
159         YangParserFactory yangParserFactory = new YangParserFactoryImpl();
160         BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer = new BindingCodecContext(BindingRuntimeHelpers.createRuntimeContext());
161         // start using blueprint interface
162         netconfStateService = new NetconfNodeStateServiceImpl();
163
164         netconfStateService.setDataBroker(dataBrokerNetconf);
165         netconfStateService.setMountPointService(mountPointService);
166         netconfStateService.setNotificationPublishService(notificationPublishService);
167         netconfStateService.setRpcProviderRegistry(rpcProviderRegistry);
168         netconfStateService.setClusterSingletonService(clusterSingletonService);
169         netconfStateService.setEntityDataProvider(entityProviderMock);
170         netconfStateService.setYangParserFactory(yangParserFactory);
171         netconfStateService.setBindingNormalizedNodeSerializer(bindingNormalizedNodeSerializer);
172         netconfStateService.init();
173         System.out.println("Initialization done");
174     }
175
176     @AfterClass
177     public static void after() throws InterruptedException, IOException {
178         System.out.println("Start shutdown");
179         // close using blueprint interface
180         netconfStateService.close();
181         delete(KARAF_ETC);
182
183     }
184
185     @Test
186     public void test1() {
187
188         System.out.println("Test1: Verify init state");
189         assertTrue("Devicemanager not initialized", netconfStateService.isInitializationSuccessful());
190     }
191
192
193     @Test
194     public void test2() {
195
196         System.out.println("Test2: Register state listener");
197
198         NetconfNodeStateListener nSL = mock(NetconfNodeStateListener.class);
199         ListenerRegistration<NetconfNodeStateListener> res = netconfStateService.registerNetconfNodeStateListener(nSL);
200         assertNotNull("Result should be null", res);
201         res.getInstance();
202         res.close();
203     }
204
205     @Test
206     public void test3() {
207
208         System.out.println("Test3: Register connect listener");
209
210         NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
211         ListenerRegistration<NetconfNodeConnectListener> res =
212                 netconfStateService.registerNetconfNodeConnectListener(nCL);
213         assertNotNull("Result should be null", res);
214         res.getInstance();
215         res.close();
216     }
217
218     @Test
219     public void test4() {
220         System.out.println("Test4: Get status listener");
221         GetStatusInputBuilder inputBuilder = new GetStatusInputBuilder();
222         GetStatusOutputBuilder res = netconfStateService.getStatus(inputBuilder.build());
223         assertNotNull("Result should be null", res);
224     }
225
226     @SuppressWarnings("unchecked")
227     @Test
228     public void test5OnConnect() throws InterruptedException {
229         System.out.println("Test5: On Connect");
230         NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
231         netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected);
232         AvailableCapabilityBuilder availableCapabilityBuilder = new AvailableCapabilityBuilder();
233         availableCapabilityBuilder.setCapability("network-element");
234         AvailableCapabilitiesBuilder availableCapabilitesBuilder = new AvailableCapabilitiesBuilder();
235         availableCapabilitesBuilder.setAvailableCapability(Arrays.asList(availableCapabilityBuilder.build()));
236         netconfNodeBuilder.setAvailableCapabilities(availableCapabilitesBuilder.build());
237         NetconfNode rootNodeNetconf = netconfNodeBuilder.build();
238
239         String nodeIdString = "Test";
240         NodeId nodeId = new NodeId(nodeIdString);
241         NodeBuilder nodeBuilder = new NodeBuilder();
242
243         nodeBuilder.addAugmentation(rootNodeNetconf);
244         nodeBuilder.setNodeId(nodeId);
245         Node rootNode = nodeBuilder.build();
246
247         DataObjectModification<Node> dom = mock(DataObjectModification.class);
248         when(dom.getDataAfter()).thenReturn(rootNode);
249         when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
250
251         DataTreeModification<Node> ntn = mock(DataTreeModification.class);
252         when(ntn.getRootNode()).thenReturn(dom);
253
254         NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
255         netconfStateService.registerNetconfNodeConnectListener(nCL);
256         mountPoint.setDatabrokerAbsent(false);
257
258         Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
259         sendClusteredChanges(changes);
260         sendChanges(changes);
261         Thread.sleep(300);
262         //verify that it was called one time and nodeId is the expected
263         ArgumentCaptor<NetconfAccessor> varArgs = ArgumentCaptor.forClass(NetconfAccessor.class);
264         verify(nCL).onEnterConnected(varArgs.capture());
265         System.out.println("Accessor " + varArgs.getValue().getNodeId());
266         assertEquals(nodeIdString, varArgs.getValue().getNodeId().getValue());
267
268     }
269
270     @SuppressWarnings("unchecked")
271     @Test
272     public void test6Update() {
273         System.out.println("Test6: OnChange");
274         NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
275         netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected);
276         NetconfNode rootNodeNetconf = netconfNodeBuilder.build();
277
278         NodeBuilder nodeBuilder = new NodeBuilder();
279         nodeBuilder.addAugmentation(rootNodeNetconf);
280         nodeBuilder.setNodeId(new NodeId("Test"));
281         Node rootNodeAfter = nodeBuilder.build();
282
283         DataObjectModification<Node> dom = mock(DataObjectModification.class);
284         when(dom.getDataBefore()).thenReturn(rootNodeAfter);
285         when(dom.getDataAfter()).thenReturn(rootNodeAfter);
286         when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
287
288         DataTreeModification<Node> ntn = mock(DataTreeModification.class);
289         when(ntn.getRootNode()).thenReturn(dom);
290
291         Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
292         sendClusteredChanges(changes);
293         sendChanges(changes);
294     }
295
296     @Test
297     public void test7ApiStatus() throws InterruptedException, ExecutionException {
298
299         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
300
301         GetStatusInputBuilder statusInput = new GetStatusInputBuilder();
302         ListenableFuture<RpcResult<GetStatusOutput>> statusOutput = api.getStatus(statusInput.build());
303         RpcResult<GetStatusOutput> res = statusOutput.get();
304         GetStatusOutput output = res.getResult();
305         System.out.println("Output " + output);
306     }
307
308
309     @Test
310     public void test8ApiPushFault() throws InterruptedException, ExecutionException {
311
312         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
313
314         VesNotificationListener vNL = mock(VesNotificationListener.class);
315         ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
316
317         FaultNotificationBuilder faultBuilder = new FaultNotificationBuilder();
318         faultBuilder.setProblem("problem1");
319         FaultNotification fault = faultBuilder.build();
320         PushFaultNotificationInputBuilder statusInput = new PushFaultNotificationInputBuilder();
321         statusInput.fieldsFrom(fault);
322         ListenableFuture<RpcResult<PushFaultNotificationOutput>> rpcOutput =
323                 api.pushFaultNotification(statusInput.build());
324         RpcResult<PushFaultNotificationOutput> res = rpcOutput.get();
325         PushFaultNotificationOutput output = res.getResult();
326
327         //verify that it was called one time
328         verify(vNL, times(1)).onNotification(fault);
329
330         registration.close();
331         System.out.println("Output " + output);
332     }
333
334     @Test
335     public void test9ApiPushNotifiction() throws InterruptedException, ExecutionException {
336
337         NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
338
339         VesNotificationListener vNL = mock(VesNotificationListener.class);
340         ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
341
342         AttributeChangeNotificationBuilder changeBuilder = new AttributeChangeNotificationBuilder();
343         changeBuilder.setAttributeName("attribute1");
344         AttributeChangeNotification change = changeBuilder.build();
345         PushAttributeChangeNotificationInputBuilder statusInput = new PushAttributeChangeNotificationInputBuilder();
346         statusInput.fieldsFrom(change);
347         ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> rpcOutput =
348                 api.pushAttributeChangeNotification(statusInput.build());
349         RpcResult<PushAttributeChangeNotificationOutput> res = rpcOutput.get();
350         PushAttributeChangeNotificationOutput output = res.getResult();
351
352         //verify that it was called one time
353         verify(vNL, times(1)).onNotification(change);
354
355         registration.close();
356         System.out.println("Output " + output);
357     }
358
359     @Test
360     public void test10ApiPushNotifiction() throws YangParserException, IOException {
361         ExampleConfig.exampleConfig(netconfStateService.getDomContext());
362     }
363
364     // ------- private section
365
366     private static void delete(Path etc) throws IOException {
367         if (Files.exists(etc)) {
368             System.out.println("Found and remove:" + etc.toString());
369             delete(etc.toFile());
370         }
371     }
372
373     private static void delete(File f) throws IOException {
374         if (f.isDirectory()) {
375             for (File c : f.listFiles()) {
376                 delete(c);
377             }
378         }
379         if (!f.delete()) {
380             throw new FileNotFoundException("Failed to delete file: " + f);
381         }
382     }
383
384     public void sendChanges(Collection<DataTreeModification<Node>> changes) {
385         listener.onDataTreeChanged(changes);
386     }
387
388     public void sendClusteredChanges(Collection<DataTreeModification<Node>> changes) {
389         listenerClustered.onDataTreeChanged(changes);
390     }
391
392
393 }