2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netconf.topology.impl;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Mockito.doNothing;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.spy;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.when;
19 import com.google.common.collect.Sets;
20 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import com.google.common.util.concurrent.MoreExecutors;
23 import io.netty.util.concurrent.EventExecutor;
24 import io.netty.util.concurrent.Future;
25 import io.netty.util.concurrent.ImmediateEventExecutor;
26 import io.netty.util.concurrent.SucceededFuture;
27 import java.util.Collection;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.mockito.Mock;
31 import org.mockito.MockitoAnnotations;
32 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
33 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
34 import org.opendaylight.controller.config.threadpool.ThreadPool;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
37 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
38 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
41 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
42 import org.opendaylight.netconf.client.NetconfClientDispatcher;
43 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
44 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
45 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
63 import org.opendaylight.yangtools.yang.binding.DataObject;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
67 public class NetconfTopologyImplTest {
69 private static final NodeId NODE_ID = new NodeId("testing-node");
70 private static final String TOPOLOGY_ID = "testing-topology";
73 private NetconfClientDispatcher mockedClientDispatcher;
76 private EventExecutor mockedEventExecutor;
79 private ScheduledThreadPool mockedKeepaliveExecutor;
82 private ThreadPool mockedProcessingExecutor;
85 private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
88 private DataBroker dataBroker;
91 private DOMMountPointService mountPointService;
94 private AAAEncryptionService encryptionService;
96 private TestingNetconfTopologyImpl topology;
97 private TestingNetconfTopologyImpl spyTopology;
100 public void setUp() {
101 MockitoAnnotations.initMocks(this);
103 when(mockedSchemaRepositoryProvider.getSharedSchemaRepository())
104 .thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
105 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
106 final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
107 when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class)))
110 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
111 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
112 dataBroker, mountPointService, encryptionService);
114 spyTopology = spy(topology);
118 public void testInit() {
119 final WriteTransaction wtx = mock(WriteTransaction.class);
120 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
121 doNothing().when(wtx)
122 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
123 when(wtx.submit()).thenReturn(Futures.<Void, TransactionCommitFailedException>immediateCheckedFuture(null));
126 //verify initialization of topology
127 final InstanceIdentifier<NetworkTopology> networkTopologyId =
128 InstanceIdentifier.builder(NetworkTopology.class).build();
129 final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
130 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
131 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION, networkTopologyId, networkTopology);
132 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId, networkTopology);
133 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
134 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
135 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
136 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
140 public void testOnDataTreeChange() {
142 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
143 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
145 InstanceIdentifier.PathArgument pa = null;
147 for (final InstanceIdentifier.PathArgument p
148 : TopologyUtil.createTopologyListPath(TOPOLOGY_ID)
149 .child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
153 when(newNode.getIdentifier()).thenReturn(pa);
156 final NetconfNode testingNode = new NetconfNodeBuilder()
157 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
158 .setPort(new PortNumber(9999))
159 .setReconnectOnChangedSchema(true)
160 .setDefaultRequestTimeoutMillis(1000L)
161 .setBetweenAttemptsTimeoutMillis(100)
162 .setKeepaliveDelay(1000L)
164 .setCredentials(new LoginPasswordBuilder()
165 .setUsername("testuser").setPassword("testpassword").build())
168 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
170 when(newNode.getDataAfter()).thenReturn(nn.build());
173 final Collection<DataTreeModification<Node>> changes = Sets.newHashSet();
174 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
175 when(ch.getRootNode()).thenReturn(newNode);
177 spyTopology.onDataTreeChanged(changes);
178 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
180 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
181 spyTopology.onDataTreeChanged(changes);
182 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
184 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
185 spyTopology.onDataTreeChanged(changes);
187 //one in previous creating and deleting node and one in updating
188 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
189 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
194 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
196 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
197 final EventExecutor eventExecutor,
198 final ScheduledThreadPool keepaliveExecutor,
199 final ThreadPool processingExecutor,
200 final SchemaRepositoryProvider schemaRepositoryProvider,
201 final DataBroker dataBroker, final DOMMountPointService mountPointService,
202 final AAAEncryptionService encryptionService) {
203 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
204 processingExecutor, schemaRepositoryProvider, dataBroker,
205 mountPointService, encryptionService);
209 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
210 return Futures.immediateFuture(new NetconfDeviceCapabilities());
214 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
215 return Futures.immediateFuture(null);