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.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;
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;
61 private static ActorSystem system = ActorSystem.apply();
62 private TestProbe masterActor;
63 private ContainerNode node;
67 masterActor = new TestProbe(system);
68 node = Builders.containerBuilder()
69 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("", "cont")))
74 public static void staticTearDown() {
75 TestKit.shutdownActorSystem(system, true);
78 private ProxyNetconfService newSuccessfulProxyNetconfService() {
79 return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
80 system.dispatcher(), Timeout.apply(5, TimeUnit.SECONDS));
83 private ProxyNetconfService newSuccessfulProxyNetconfService(final Timeout timeout) {
84 return new ProxyNetconfService(DEVICE_ID, Futures.successful(masterActor.ref()),
85 system.dispatcher(), timeout);
89 public void testLock() {
90 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
92 masterActor.expectMsgClass(LockRequest.class);
96 public void testUnlock() {
97 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
99 masterActor.expectMsgClass(UnlockRequest.class);
103 public void testDiscardChanges() {
104 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
105 netconf.discardChanges();
106 masterActor.expectMsgClass(DiscardChangesRequest.class);
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());
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());
123 public void testGetFailure() throws InterruptedException, TimeoutException {
124 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
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));
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());
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());
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());
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());
165 public void testGetConfigFailure() throws InterruptedException, TimeoutException {
166 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
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));
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());
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());
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());
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());
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());
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());
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());
242 public void testCommit() throws InterruptedException, ExecutionException, TimeoutException {
243 ProxyNetconfService netconf = newSuccessfulProxyNetconfService();
248 public void testFutureOperationsWithMasterDown() throws InterruptedException, TimeoutException {
249 ProxyNetconfService netconf = newSuccessfulProxyNetconfService(
250 Timeout.apply(500, TimeUnit.MILLISECONDS));
252 ListenableFuture<?> future = netconf.get(PATH);
253 masterActor.expectMsgClass(GetRequest.class);
255 // master doesn't reply
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());
265 future = netconf.getConfig(PATH);
266 masterActor.expectMsgClass(GetConfigRequest.class);
268 // master doesn't reply
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());
278 future = netconf.commit();
279 masterActor.expectMsgClass(CommitRequest.class);
281 // master doesn't reply
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());
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);
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());