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