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