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