Do not start devices with invalid configuration
[netconf.git] / apps / netconf-topology-impl / src / test / java / org / opendaylight / netconf / topology / impl / NetconfTopologyImplTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.topology.impl;
9
10 import static org.mockito.Mockito.doReturn;
11 import static org.mockito.Mockito.spy;
12 import static org.mockito.Mockito.times;
13 import static org.mockito.Mockito.verify;
14
15 import com.google.common.util.concurrent.MoreExecutors;
16 import io.netty.util.concurrent.EventExecutor;
17 import java.util.List;
18 import org.junit.jupiter.api.Test;
19 import org.junit.jupiter.api.extension.ExtendWith;
20 import org.mockito.Mock;
21 import org.mockito.junit.jupiter.MockitoExtension;
22 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
23 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
24 import org.opendaylight.controller.config.threadpool.ThreadPool;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.binding.api.DataObjectModification;
27 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
28 import org.opendaylight.mdsal.binding.api.DataTreeModification;
29 import org.opendaylight.mdsal.binding.api.RpcProviderService;
30 import org.opendaylight.mdsal.binding.api.WriteTransaction;
31 import org.opendaylight.mdsal.common.api.CommitInfo;
32 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
33 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
34 import org.opendaylight.netconf.client.NetconfClientDispatcher;
35 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
36 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
37 import org.opendaylight.netconf.client.mdsal.impl.DefaultBaseNetconfSchemas;
38 import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactory;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPasswordBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeBuilder;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
56 import org.opendaylight.yangtools.yang.common.Uint16;
57 import org.opendaylight.yangtools.yang.common.Uint32;
58 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
59
60 @ExtendWith(MockitoExtension.class)
61 class NetconfTopologyImplTest {
62     private static final TopologyKey TOPOLOGY_KEY = new TopologyKey(new TopologyId("testing-topology"));
63     private static final KeyedInstanceIdentifier<Topology, TopologyKey> TOPOLOGY_PATH =
64         InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class, TOPOLOGY_KEY).build();
65
66     @Mock
67     private NetconfClientDispatcher mockedClientDispatcher;
68     @Mock
69     private EventExecutor mockedEventExecutor;
70     @Mock
71     private ScheduledThreadPool mockedKeepaliveExecutor;
72     @Mock
73     private ThreadPool mockedProcessingExecutor;
74     @Mock
75     private SchemaResourceManager mockedResourceManager;
76     @Mock
77     private DataBroker dataBroker;
78     @Mock
79     private DOMMountPointService mountPointService;
80     @Mock
81     private AAAEncryptionService encryptionService;
82     @Mock
83     private RpcProviderService rpcProviderService;
84     @Mock
85     private NetconfClientConfigurationBuilderFactory builderFactory;
86     @Mock
87     private WriteTransaction wtx;
88     @Mock
89     private DataObjectModification<Node> objMod;
90     @Mock
91     private DataTreeModification<Node> treeMod;
92
93     private TestingNetconfTopologyImpl topology;
94     private TestingNetconfTopologyImpl spyTopology;
95
96     @Test
97     void testOnDataTreeChange() throws Exception {
98         doReturn(MoreExecutors.newDirectExecutorService()).when(mockedProcessingExecutor).getExecutor();
99         doReturn(wtx).when(dataBroker).newWriteOnlyTransaction();
100         doReturn(CommitInfo.emptyFluentFuture()).when(wtx).commit();
101
102         topology = new TestingNetconfTopologyImpl(TOPOLOGY_KEY.getTopologyId().getValue(), mockedClientDispatcher,
103             mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker,
104             mountPointService, encryptionService, builderFactory, rpcProviderService,
105             new DefaultBaseNetconfSchemas(new DefaultYangParserFactory()));
106         //verify initialization of topology
107         verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, TOPOLOGY_PATH,
108             new TopologyBuilder().withKey(TOPOLOGY_KEY).build());
109
110         spyTopology = spy(topology);
111
112         final var key = new NodeKey(new NodeId("testing-node"));
113         final var node = new NodeBuilder()
114             .withKey(key)
115             .addAugmentation(new NetconfNodeBuilder()
116                 .setLockDatastore(true)
117                 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
118                 .setPort(new PortNumber(Uint16.valueOf(9999)))
119                 .setReconnectOnChangedSchema(true)
120                 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
121                 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
122                 .setKeepaliveDelay(Uint32.valueOf(1000))
123                 .setTcpOnly(true)
124                 .setCredentials(new LoginPasswordBuilder()
125                     .setUsername("testuser")
126                     .setPassword("testpassword")
127                     .build())
128                 .build())
129             .build();
130
131         doReturn(DataObjectModification.ModificationType.WRITE).when(objMod).getModificationType();
132         doReturn(node).when(objMod).getDataAfter();
133
134         doReturn(DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, TOPOLOGY_PATH.child(Node.class, key)))
135             .when(treeMod).getRootPath();
136         final var changes = List.of(treeMod);
137
138         doReturn(objMod).when(treeMod).getRootNode();
139         spyTopology.onDataTreeChanged(changes);
140         verify(spyTopology).ensureNode(node);
141
142         doReturn(DataObjectModification.ModificationType.DELETE).when(objMod).getModificationType();
143         spyTopology.onDataTreeChanged(changes);
144         verify(spyTopology).deleteNode(key.getNodeId());
145
146         doReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED).when(objMod).getModificationType();
147         spyTopology.onDataTreeChanged(changes);
148
149         // one in previous creating and deleting node and one in updating
150         verify(spyTopology, times(2)).ensureNode(node);
151     }
152
153     private static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
154         TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
155                 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
156                 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
157                 final DataBroker dataBroker, final DOMMountPointService mountPointService,
158                 final AAAEncryptionService encryptionService,
159                 final NetconfClientConfigurationBuilderFactory builderFactory,
160                 final RpcProviderService rpcProviderService, final BaseNetconfSchemas baseSchemas) {
161             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
162                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, builderFactory,
163                 rpcProviderService, baseSchemas);
164         }
165
166         @Override
167         public void ensureNode(final Node configNode) {
168             // No-op
169         }
170
171         @Override
172         public void deleteNode(final NodeId nodeId) {
173             // No-op
174         }
175     }
176 }