Move RemoteDeviceId
[netconf.git] / netconf / netconf-topology-singleton / src / test / java / org / opendaylight / netconf / topology / singleton / impl / netconf / ProxyNetconfServiceTest.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.singleton.impl.netconf;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14
15 import akka.actor.ActorSystem;
16 import akka.actor.Status;
17 import akka.dispatch.Futures;
18 import akka.testkit.TestProbe;
19 import akka.testkit.javadsl.TestKit;
20 import akka.util.Timeout;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import java.net.InetSocketAddress;
23 import java.util.Collections;
24 import java.util.Optional;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.TimeoutException;
28 import org.junit.AfterClass;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
32 import org.opendaylight.mdsal.common.api.ReadFailedException;
33 import org.opendaylight.netconf.api.DocumentedException;
34 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId;
35 import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
36 import org.opendaylight.netconf.topology.singleton.messages.netconf.CommitRequest;
37 import org.opendaylight.netconf.topology.singleton.messages.netconf.CreateEditConfigRequest;
38 import org.opendaylight.netconf.topology.singleton.messages.netconf.DeleteEditConfigRequest;
39 import org.opendaylight.netconf.topology.singleton.messages.netconf.DiscardChangesRequest;
40 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetConfigRequest;
41 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetRequest;
42 import org.opendaylight.netconf.topology.singleton.messages.netconf.LockRequest;
43 import org.opendaylight.netconf.topology.singleton.messages.netconf.MergeEditConfigRequest;
44 import org.opendaylight.netconf.topology.singleton.messages.netconf.RemoveEditConfigRequest;
45 import org.opendaylight.netconf.topology.singleton.messages.netconf.ReplaceEditConfigRequest;
46 import org.opendaylight.netconf.topology.singleton.messages.netconf.UnlockRequest;
47 import org.opendaylight.netconf.topology.singleton.messages.rpc.InvokeRpcMessageReply;
48 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
49 import org.opendaylight.yangtools.yang.common.ErrorSeverity;
50 import org.opendaylight.yangtools.yang.common.ErrorTag;
51 import org.opendaylight.yangtools.yang.common.ErrorType;
52 import org.opendaylight.yangtools.yang.common.QName;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
54 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
56 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
57
58 public class ProxyNetconfServiceTest {
59     private static final RemoteDeviceId DEVICE_ID =
60         new RemoteDeviceId("dev1", InetSocketAddress.createUnresolved("localhost", 17830));
61     private static final YangInstanceIdentifier PATH = YangInstanceIdentifier.empty();
62     private static final LogicalDatastoreType STORE = LogicalDatastoreType.CONFIGURATION;
63
64     private static ActorSystem system = ActorSystem.apply();
65     private TestProbe masterActor;
66     private ContainerNode node;
67
68     @Before
69     public void setUp() {
70         masterActor = new TestProbe(system);
71         node = Builders.containerBuilder()
72             .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("", "cont")))
73             .build();
74     }
75
76     @AfterClass
77     public static void staticTearDown() {
78         TestKit.shutdownActorSystem(system, true);
79     }
80
81     private ProxyNetconfService newSuccessfulProxyNetconfService() {
82         return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
83             system.dispatcher(), Timeout.apply(5, TimeUnit.SECONDS));
84     }
85
86     private ProxyNetconfService newSuccessfulProxyNetconfService(final Timeout timeout) {
87         return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
88             system.dispatcher(), timeout);
89     }
90
91     @Test
92     public void testLock() {
93         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
94         netconf.lock();
95         masterActor.expectMsgClass(LockRequest.class);
96     }
97
98     @Test
99     public void testUnlock() {
100         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
101         netconf.unlock();
102         masterActor.expectMsgClass(UnlockRequest.class);
103     }
104
105     @Test
106     public void testDiscardChanges() {
107         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
108         netconf.discardChanges();
109         masterActor.expectMsgClass(DiscardChangesRequest.class);
110     }
111
112     @Test
113     public void testGet() throws Exception {
114         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
115         final ListenableFuture<Optional<NormalizedNode>> get = netconf.get(PATH);
116         final GetRequest getRequest = masterActor.expectMsgClass(GetRequest.class);
117         assertEquals(PATH, getRequest.getPath());
118
119         masterActor.reply(new NormalizedNodeMessage(PATH, node));
120         final Optional<NormalizedNode> result = get.get(5, TimeUnit.SECONDS);
121         assertTrue(result.isPresent());
122         assertEquals(node, result.get());
123     }
124
125     @Test
126     public void testGetFailure() throws InterruptedException, TimeoutException {
127         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
128
129         final ListenableFuture<Optional<NormalizedNode>> get = netconf.get(PATH);
130         masterActor.expectMsgClass(GetRequest.class);
131         final RuntimeException mockEx = new RuntimeException("fail");
132         masterActor.reply(new Status.Failure(mockEx));
133
134         try {
135             get.get(5, TimeUnit.SECONDS);
136             fail("Exception should be thrown");
137         } catch (final ExecutionException e) {
138             Throwable cause = e.getCause();
139             assertTrue("Unexpected cause " + cause, cause instanceof ReadFailedException);
140             assertEquals(mockEx, cause.getCause());
141         }
142     }
143
144     @Test
145     public void testGetEmpty() throws Exception {
146         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
147         final ListenableFuture<Optional<NormalizedNode>> get = netconf.get(PATH);
148         masterActor.expectMsgClass(GetRequest.class);
149         masterActor.reply(new EmptyReadResponse());
150         final Optional<NormalizedNode> result = get.get(5, TimeUnit.SECONDS);
151         assertFalse(result.isPresent());
152     }
153
154     @Test
155     public void testGetConfig() throws Exception {
156         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
157         final ListenableFuture<Optional<NormalizedNode>> getConfig = netconf.getConfig(PATH);
158         final GetConfigRequest getRequest = masterActor.expectMsgClass(GetConfigRequest.class);
159         assertEquals(PATH, getRequest.getPath());
160
161         masterActor.reply(new NormalizedNodeMessage(PATH, node));
162         final Optional<NormalizedNode> result = getConfig.get(5, TimeUnit.SECONDS);
163         assertTrue(result.isPresent());
164         assertEquals(node, result.get());
165     }
166
167     @Test
168     public void testGetConfigFailure() throws InterruptedException, TimeoutException {
169         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
170
171         final ListenableFuture<Optional<NormalizedNode>> getConfig = netconf.getConfig(PATH);
172         masterActor.expectMsgClass(GetConfigRequest.class);
173         final RuntimeException mockEx = new RuntimeException("fail");
174         masterActor.reply(new Status.Failure(mockEx));
175
176         try {
177             getConfig.get(5, TimeUnit.SECONDS);
178             fail("Exception should be thrown");
179         } catch (final ExecutionException e) {
180             Throwable cause = e.getCause();
181             assertTrue("Unexpected cause " + cause, cause instanceof ReadFailedException);
182             assertEquals(mockEx, cause.getCause());
183         }
184     }
185
186     @Test
187     public void testGetConfigEmpty() throws Exception {
188         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
189         final ListenableFuture<Optional<NormalizedNode>> getConfig = netconf.getConfig(PATH);
190         masterActor.expectMsgClass(GetConfigRequest.class);
191         masterActor.reply(new EmptyReadResponse());
192         final Optional<NormalizedNode> result = getConfig.get(5, TimeUnit.SECONDS);
193         assertFalse(result.isPresent());
194     }
195
196     @Test
197     public void testMerge() {
198         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
199         netconf.merge(STORE, PATH, node, Optional.empty());
200         final MergeEditConfigRequest mergeRequest = masterActor.expectMsgClass(MergeEditConfigRequest.class);
201         assertEquals(STORE, mergeRequest.getStore());
202         assertEquals(PATH, mergeRequest.getNormalizedNodeMessage().getIdentifier());
203         assertEquals(node, mergeRequest.getNormalizedNodeMessage().getNode());
204     }
205
206     @Test
207     public void testReplace() {
208         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
209         netconf.replace(STORE, PATH, node, Optional.empty());
210         final ReplaceEditConfigRequest replaceRequest = masterActor.expectMsgClass(ReplaceEditConfigRequest.class);
211         assertEquals(STORE, replaceRequest.getStore());
212         assertEquals(PATH, replaceRequest.getNormalizedNodeMessage().getIdentifier());
213         assertEquals(node, replaceRequest.getNormalizedNodeMessage().getNode());
214     }
215
216     @Test
217     public void testCreate() {
218         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
219         netconf.create(STORE, PATH, node, Optional.empty());
220         final CreateEditConfigRequest createRequest = masterActor.expectMsgClass(CreateEditConfigRequest.class);
221         assertEquals(STORE, createRequest.getStore());
222         assertEquals(PATH, createRequest.getNormalizedNodeMessage().getIdentifier());
223         assertEquals(node, createRequest.getNormalizedNodeMessage().getNode());
224     }
225
226     @Test
227     public void testDelete() {
228         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
229         netconf.delete(STORE, PATH);
230         final DeleteEditConfigRequest deleteRequest = masterActor.expectMsgClass(DeleteEditConfigRequest.class);
231         assertEquals(STORE, deleteRequest.getStore());
232         assertEquals(PATH, deleteRequest.getPath());
233     }
234
235     @Test
236     public void testRemove() {
237         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
238         netconf.remove(STORE, PATH);
239         final RemoveEditConfigRequest removeRequest = masterActor.expectMsgClass(RemoveEditConfigRequest.class);
240         assertEquals(STORE, removeRequest.getStore());
241         assertEquals(PATH, removeRequest.getPath());
242     }
243
244     @Test
245     public void testCommit() throws InterruptedException, ExecutionException, TimeoutException {
246         ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
247         commit(netconf);
248     }
249
250     @Test
251     public void testFutureOperationsWithMasterDown() throws InterruptedException, TimeoutException {
252         ProxyNetconfService netconf = newSuccessfulProxyNetconfService(
253             Timeout.apply(500, TimeUnit.MILLISECONDS));
254
255         ListenableFuture<?> future = netconf.get(PATH);
256         masterActor.expectMsgClass(GetRequest.class);
257
258         // master doesn't reply
259         try {
260             future.get(5, TimeUnit.SECONDS);
261             fail("Exception should be thrown");
262         } catch (final ExecutionException e) {
263             Throwable cause = e.getCause();
264             assertTrue("Unexpected cause " + cause, cause instanceof ReadFailedException);
265             verifyDocumentedException(cause.getCause());
266         }
267
268         future = netconf.getConfig(PATH);
269         masterActor.expectMsgClass(GetConfigRequest.class);
270
271         // master doesn't reply
272         try {
273             future.get(5, TimeUnit.SECONDS);
274             fail("Exception should be thrown");
275         } catch (final ExecutionException e) {
276             Throwable cause = e.getCause();
277             assertTrue("Unexpected cause " + cause, cause instanceof ReadFailedException);
278             verifyDocumentedException(cause.getCause());
279         }
280
281         future = netconf.commit();
282         masterActor.expectMsgClass(CommitRequest.class);
283
284         // master doesn't reply
285         try {
286             future.get(5, TimeUnit.SECONDS);
287             fail("Exception should be thrown");
288         } catch (final ExecutionException e) {
289             Throwable cause = e.getCause();
290             assertTrue("Unexpected cause " + cause, cause instanceof NetconfServiceFailedException);
291             verifyDocumentedException(cause.getCause());
292         }
293     }
294
295     private void commit(final ProxyNetconfService netconf)
296         throws InterruptedException, ExecutionException, TimeoutException {
297         final ListenableFuture<?> submit = netconf.commit();
298         masterActor.expectMsgClass(CommitRequest.class);
299         masterActor.reply(new InvokeRpcMessageReply(null, Collections.emptyList()));
300         submit.get(5, TimeUnit.SECONDS);
301     }
302
303     private static void verifyDocumentedException(final Throwable cause) {
304         assertTrue("Unexpected cause " + cause, cause instanceof DocumentedException);
305         final DocumentedException de = (DocumentedException) cause;
306         assertEquals(ErrorSeverity.WARNING, de.getErrorSeverity());
307         assertEquals(ErrorTag.OPERATION_FAILED, de.getErrorTag());
308         assertEquals(ErrorType.APPLICATION, de.getErrorType());
309     }
310 }