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.api.ClusteredDataTreeChangeListener;
52 import org.opendaylight.mdsal.binding.api.DataBroker;
53 import org.opendaylight.mdsal.binding.api.DataObjectModification;
54 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
55 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
56 import org.opendaylight.mdsal.binding.api.DataTreeModification;
57 import org.opendaylight.mdsal.binding.api.MountPointService;
58 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
59 import org.opendaylight.mdsal.binding.api.RpcProviderService;
60 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
61 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext;
62 import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
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.parser.api.YangParserException;
85 import org.opendaylight.yangtools.yang.parser.api.YangParserFactory;
86 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
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 DefaultYangParserFactory();
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 if(netconfStateService!=null) {
169 netconfStateService.close();
176 public void test1() {
178 System.out.println("Test1: Verify init state");
179 assertTrue("Devicemanager not initialized", netconfStateService.isInitializationSuccessful());
184 public void test2() {
186 System.out.println("Test2: Register state listener");
188 NetconfNodeStateListener nSL = mock(NetconfNodeStateListener.class);
189 ListenerRegistration<NetconfNodeStateListener> res = netconfStateService.registerNetconfNodeStateListener(nSL);
190 assertNotNull("Result should be null", res);
196 public void test3() {
198 System.out.println("Test3: Register connect listener");
200 NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
201 ListenerRegistration<NetconfNodeConnectListener> res =
202 netconfStateService.registerNetconfNodeConnectListener(nCL);
203 assertNotNull("Result should be null", res);
209 public void test4() {
210 System.out.println("Test4: Get status listener");
211 GetStatusInputBuilder inputBuilder = new GetStatusInputBuilder();
212 GetStatusOutputBuilder res = netconfStateService.getStatus(inputBuilder.build());
213 assertNotNull("Result should be null", res);
216 @SuppressWarnings("unchecked")
218 public void test5OnConnect() throws InterruptedException {
219 System.out.println("Test5: On Connect");
220 String nodeIdString = "Test";
221 String capabilityStringForNetworkElement = "network-element";
222 NodeId nodeId = new NodeId(nodeIdString);
223 Node rootNode = TestNetconfHelper.getTestNode(nodeId, capabilityStringForNetworkElement);
225 DataObjectModification<Node> dom = mock(DataObjectModification.class);
226 when(dom.getDataAfter()).thenReturn(rootNode);
227 when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
229 DataTreeModification<Node> ntn = mock(DataTreeModification.class);
230 when(ntn.getRootNode()).thenReturn(dom);
232 NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class);
233 netconfStateService.registerNetconfNodeConnectListener(nCL);
235 Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
236 sendClusteredChanges(changes);
237 sendChanges(changes);
239 //verify that it was called one time and nodeId is the expected
240 ArgumentCaptor<NetconfAccessor> varArgs = ArgumentCaptor.forClass(NetconfAccessor.class);
241 verify(nCL).onEnterConnected(varArgs.capture());
242 NetconfAccessor accessor = varArgs.getValue();
243 System.out.println("Accessor " + accessor.getNodeId());
244 assertEquals(nodeIdString, accessor.getNodeId().getValue());
247 @SuppressWarnings("unchecked")
249 public void test6Update() {
250 System.out.println("Test6: OnChange");
251 NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
252 netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected);
253 NetconfNode rootNodeNetconf = netconfNodeBuilder.build();
255 NodeBuilder nodeBuilder = new NodeBuilder();
256 nodeBuilder.addAugmentation(rootNodeNetconf);
257 nodeBuilder.setNodeId(new NodeId("Test"));
258 Node rootNodeAfter = nodeBuilder.build();
260 DataObjectModification<Node> dom = mock(DataObjectModification.class);
261 when(dom.getDataBefore()).thenReturn(rootNodeAfter);
262 when(dom.getDataAfter()).thenReturn(rootNodeAfter);
263 when(dom.getModificationType()).thenReturn(ModificationType.WRITE);
265 DataTreeModification<Node> ntn = mock(DataTreeModification.class);
266 when(ntn.getRootNode()).thenReturn(dom);
268 Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
269 sendClusteredChanges(changes);
270 sendChanges(changes);
274 public void test7ApiStatus() throws InterruptedException, ExecutionException {
276 NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
278 GetStatusInputBuilder statusInput = new GetStatusInputBuilder();
279 ListenableFuture<RpcResult<GetStatusOutput>> statusOutput = api.getStatus(statusInput.build());
280 RpcResult<GetStatusOutput> res = statusOutput.get();
281 GetStatusOutput output = res.getResult();
282 System.out.println("Output " + output);
287 public void test8ApiPushFault() throws InterruptedException, ExecutionException {
289 NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
291 VesNotificationListener vNL = mock(VesNotificationListener.class);
292 ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
294 FaultNotificationBuilder faultBuilder = new FaultNotificationBuilder();
295 faultBuilder.setProblem("problem1");
296 FaultNotification fault = faultBuilder.build();
297 PushFaultNotificationInputBuilder statusInput = new PushFaultNotificationInputBuilder();
298 statusInput.fieldsFrom(fault);
299 ListenableFuture<RpcResult<PushFaultNotificationOutput>> rpcOutput =
300 api.pushFaultNotification(statusInput.build());
301 RpcResult<PushFaultNotificationOutput> res = rpcOutput.get();
302 PushFaultNotificationOutput output = res.getResult();
304 //verify that it was called one time
305 verify(vNL, times(1)).onNotification(fault);
307 registration.close();
308 System.out.println("Output " + output);
312 public void test9ApiPushNotifiction() throws InterruptedException, ExecutionException {
314 NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl();
316 VesNotificationListener vNL = mock(VesNotificationListener.class);
317 ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL);
319 AttributeChangeNotificationBuilder changeBuilder = new AttributeChangeNotificationBuilder();
320 changeBuilder.setAttributeName("attribute1");
321 AttributeChangeNotification change = changeBuilder.build();
322 PushAttributeChangeNotificationInputBuilder statusInput = new PushAttributeChangeNotificationInputBuilder();
323 statusInput.fieldsFrom(change);
324 ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> rpcOutput =
325 api.pushAttributeChangeNotification(statusInput.build());
326 RpcResult<PushAttributeChangeNotificationOutput> res = rpcOutput.get();
327 PushAttributeChangeNotificationOutput output = res.getResult();
329 //verify that it was called one time
330 verify(vNL, times(1)).onNotification(change);
332 registration.close();
333 System.out.println("Output " + output);
337 public void test10ApiPushNotifiction() throws YangParserException, IOException {
338 ExampleConfig.exampleConfig(netconfStateService.getDomContext());
342 public void test10NetconfAccessorClone() {
346 // ------- private section
348 private static void delete(Path etc) throws IOException {
349 if (Files.exists(etc)) {
350 System.out.println("Found and remove:" + etc.toString());
351 delete(etc.toFile());
355 private static void delete(File f) throws IOException {
356 if (f.isDirectory()) {
357 for (File c : f.listFiles()) {
362 throw new FileNotFoundException("Failed to delete file: " + f);
366 public void sendChanges(Collection<DataTreeModification<Node>> changes) {
367 listener.onDataTreeChanged(changes);
370 public void sendClusteredChanges(Collection<DataTreeModification<Node>> changes) {
371 listenerClustered.onDataTreeChanged(changes);