2 * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.netconf.topology.singleton.impl.netconf;
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;
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;
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;
60 private static ActorSystem system = ActorSystem.apply();
61 private TestProbe masterActor;
62 private ContainerNode node;
66 masterActor = new TestProbe(system);
67 node = Builders.containerBuilder()
68 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("", "cont")))
73 public static void staticTearDown() {
74 TestKit.shutdownActorSystem(system, true);
77 private ProxyNetconfService newSuccessfulProxyNetconfService() {
78 return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
79 system.dispatcher(), Timeout.apply(5, TimeUnit.SECONDS));
82 private ProxyNetconfService newSuccessfulProxyNetconfService(final Timeout timeout) {
83 return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
84 system.dispatcher(), timeout);
88 public void testLock() {
89 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
91 masterActor.expectMsgClass(LockRequest.class);
95 public void testUnlock() {
96 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
98 masterActor.expectMsgClass(UnlockRequest.class);
102 public void testDiscardChanges() {
103 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
104 netconf.discardChanges();
105 masterActor.expectMsgClass(DiscardChangesRequest.class);
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());
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());
122 public void testGetFailure() throws InterruptedException, TimeoutException {
123 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
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));
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());
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());
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());
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());
164 public void testGetConfigFailure() throws InterruptedException, TimeoutException {
165 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
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));
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());
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());
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());
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());
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());
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());
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());
241 public void testCommit() throws InterruptedException, ExecutionException, TimeoutException {
242 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
247 public void testFutureOperationsWithMasterDown() throws InterruptedException, TimeoutException {
248 ProxyNetconfService netconf = newSuccessfulProxyNetconfService(
249 Timeout.apply(500, TimeUnit.MILLISECONDS));
251 ListenableFuture<?> future = netconf.get(PATH);
252 masterActor.expectMsgClass(GetRequest.class);
254 // master doesn't reply
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());
264 future = netconf.getConfig(PATH);
265 masterActor.expectMsgClass(GetConfigRequest.class);
267 // master doesn't reply
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());
277 future = netconf.commit(new ArrayList<>());
278 masterActor.expectMsgClass(CommitRequest.class);
280 // master doesn't reply
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());
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);
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());