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().setUsername("testuser").setPassword("testpassword").build())
167 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
169 when(newNode.getDataAfter()).thenReturn(nn.build());
172 final Collection<DataTreeModification<Node>> changes = Sets.newHashSet();
173 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
174 when(ch.getRootNode()).thenReturn(newNode);
176 spyTopology.onDataTreeChanged(changes);
177 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
179 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
180 spyTopology.onDataTreeChanged(changes);
181 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
183 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
184 spyTopology.onDataTreeChanged(changes);
186 //one in previous creating and deleting node and one in updating
187 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
188 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
193 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
195 public TestingNetconfTopologyImpl(
196 final String topologyId, final NetconfClientDispatcher clientDispatcher,
197 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
198 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
199 final DataBroker dataBroker, final DOMMountPointService mountPointService,
200 final AAAEncryptionService encryptionService) {
201 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
202 processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
206 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
207 return Futures.immediateFuture(new NetconfDeviceCapabilities());
211 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
212 return Futures.immediateFuture(null);