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.controller.config.threadpool.ScheduledThreadPool;
33 import org.opendaylight.controller.config.threadpool.ThreadPool;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
36 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
37 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
39 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
40 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
41 import org.opendaylight.netconf.client.NetconfClientDispatcher;
42 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
43 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
44 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
62 import org.opendaylight.yangtools.yang.binding.DataObject;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
66 public class NetconfTopologyImplTest {
68 private static final NodeId NODE_ID = new NodeId("testing-node");
69 private static final String TOPOLOGY_ID = "testing-topology";
72 private NetconfClientDispatcher mockedClientDispatcher;
75 private EventExecutor mockedEventExecutor;
78 private ScheduledThreadPool mockedKeepaliveExecutor;
81 private ThreadPool mockedProcessingExecutor;
84 private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
87 private DataBroker dataBroker;
90 private DOMMountPointService mountPointService;
92 private TestingNetconfTopologyImpl topology;
93 private TestingNetconfTopologyImpl spyTopology;
97 MockitoAnnotations.initMocks(this);
99 when(mockedSchemaRepositoryProvider.getSharedSchemaRepository())
100 .thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
101 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
102 final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
103 when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class)))
106 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
107 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
108 dataBroker, mountPointService);
110 spyTopology = spy(topology);
114 public void testInit() {
115 final WriteTransaction wtx = mock(WriteTransaction.class);
116 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
117 doNothing().when(wtx)
118 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
119 when(wtx.submit()).thenReturn(Futures.<Void, TransactionCommitFailedException>immediateCheckedFuture(null));
122 //verify initialization of topology
123 final InstanceIdentifier<NetworkTopology> networkTopologyId =
124 InstanceIdentifier.builder(NetworkTopology.class).build();
125 final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
126 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
127 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION, networkTopologyId, networkTopology);
128 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId, networkTopology);
129 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
130 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
131 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
132 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
136 public void testOnDataTreeChange() {
138 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
139 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
141 InstanceIdentifier.PathArgument pa = null;
143 for (final InstanceIdentifier.PathArgument p
144 : TopologyUtil.createTopologyListPath(TOPOLOGY_ID)
145 .child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
149 when(newNode.getIdentifier()).thenReturn(pa);
152 final NetconfNode testingNode = new NetconfNodeBuilder()
153 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
154 .setPort(new PortNumber(9999))
155 .setReconnectOnChangedSchema(true)
156 .setDefaultRequestTimeoutMillis(1000L)
157 .setBetweenAttemptsTimeoutMillis(100)
158 .setKeepaliveDelay(1000L)
160 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
163 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
165 when(newNode.getDataAfter()).thenReturn(nn.build());
168 final Collection<DataTreeModification<Node>> changes = Sets.newHashSet();
169 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
170 when(ch.getRootNode()).thenReturn(newNode);
172 spyTopology.onDataTreeChanged(changes);
173 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
175 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
176 spyTopology.onDataTreeChanged(changes);
177 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
179 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
180 spyTopology.onDataTreeChanged(changes);
182 //one in previous creating and deleting node and one in updating
183 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
184 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
189 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
191 public TestingNetconfTopologyImpl(
192 final String topologyId, final NetconfClientDispatcher clientDispatcher,
193 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
194 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
195 final DataBroker dataBroker, final DOMMountPointService mountPointService) {
196 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
197 processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService);
201 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
202 return Futures.immediateFuture(new NetconfDeviceCapabilities());
206 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
207 return Futures.immediateFuture(null);