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()).thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
104 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
105 final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
106 when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class))).thenReturn(future);
108 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
109 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
110 dataBroker, mountPointService, encryptionService);
112 spyTopology = spy(topology);
116 public void testInit() {
117 final WriteTransaction wtx = mock(WriteTransaction.class);
118 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
119 doNothing().when(wtx).merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
120 when(wtx.submit()).thenReturn(Futures.<Void, TransactionCommitFailedException>immediateCheckedFuture(null));
123 //verify initialization of topology
124 final InstanceIdentifier<NetworkTopology> networkTopologyId = 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, networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
130 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
134 public void testOnDataTreeChange() {
136 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
137 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
139 InstanceIdentifier.PathArgument pa = null;
141 for (final InstanceIdentifier.PathArgument p : TopologyUtil.createTopologyListPath(TOPOLOGY_ID).child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
145 when(newNode.getIdentifier()).thenReturn(pa);
148 final NetconfNode testingNode = new NetconfNodeBuilder()
149 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
150 .setPort(new PortNumber(9999))
151 .setReconnectOnChangedSchema(true)
152 .setDefaultRequestTimeoutMillis(1000L)
153 .setBetweenAttemptsTimeoutMillis(100)
154 .setKeepaliveDelay(1000L)
156 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
159 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
161 when(newNode.getDataAfter()).thenReturn(nn.build());
164 final Collection<DataTreeModification<Node>> changes = Sets.newHashSet();
165 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
166 when(ch.getRootNode()).thenReturn(newNode);
168 spyTopology.onDataTreeChanged(changes);
169 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
171 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
172 spyTopology.onDataTreeChanged(changes);
173 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
175 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
176 spyTopology.onDataTreeChanged(changes);
178 //one in previous creating and deleting node and one in updating
179 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
180 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
185 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
187 public TestingNetconfTopologyImpl(
188 final String topologyId, final NetconfClientDispatcher clientDispatcher,
189 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
190 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
191 final DataBroker dataBroker, final DOMMountPointService mountPointService,
192 final AAAEncryptionService encryptionService) {
193 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
194 processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
198 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
199 return Futures.immediateFuture(new NetconfDeviceCapabilities());
203 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
204 return Futures.immediateFuture(null);