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;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
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.testkit.TestProbe;
18 import akka.testkit.javadsl.TestKit;
19 import akka.util.Timeout;
20 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import com.google.common.util.concurrent.MoreExecutors;
23 import java.net.InetSocketAddress;
24 import java.util.Collections;
25 import java.util.Optional;
26 import java.util.concurrent.TimeUnit;
27 import org.junit.AfterClass;
28 import org.junit.Test;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
31 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId;
32 import org.opendaylight.netconf.topology.singleton.messages.netconf.CommitRequest;
33 import org.opendaylight.netconf.topology.singleton.messages.netconf.CreateEditConfigRequest;
34 import org.opendaylight.netconf.topology.singleton.messages.netconf.DeleteEditConfigRequest;
35 import org.opendaylight.netconf.topology.singleton.messages.netconf.DiscardChangesRequest;
36 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetConfigRequest;
37 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetRequest;
38 import org.opendaylight.netconf.topology.singleton.messages.netconf.LockRequest;
39 import org.opendaylight.netconf.topology.singleton.messages.netconf.MergeEditConfigRequest;
40 import org.opendaylight.netconf.topology.singleton.messages.netconf.NetconfDataTreeServiceRequest;
41 import org.opendaylight.netconf.topology.singleton.messages.netconf.RemoveEditConfigRequest;
42 import org.opendaylight.netconf.topology.singleton.messages.netconf.ReplaceEditConfigRequest;
43 import org.opendaylight.netconf.topology.singleton.messages.netconf.UnlockRequest;
44 import org.opendaylight.netconf.topology.singleton.messages.rpc.InvokeRpcMessageReply;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
49 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
50 import scala.concurrent.duration.Duration;
51 import scala.concurrent.duration.FiniteDuration;
53 public class ProxyNetconfDataTreeServiceTest {
54 private static final FiniteDuration EXP_NO_MESSAGE_TIMEOUT = Duration.apply(300, TimeUnit.MILLISECONDS);
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 private static final ContainerNode NODE = Builders.containerBuilder()
60 .withNodeIdentifier(new NodeIdentifier(QName.create("", "cont")))
64 private static ActorSystem system = ActorSystem.apply();
66 private final TestProbe masterActor = new TestProbe(system);
67 private final ProxyNetconfDataTreeService proxy = new ProxyNetconfDataTreeService(DEVICE_ID, masterActor.ref(),
68 system.dispatcher(), Timeout.apply(5, TimeUnit.SECONDS));
71 public static void staticTearDown() {
72 TestKit.shutdownActorSystem(system, true);
76 public void testLock() {
81 public void testUnlock() {
84 masterActor.expectMsgClass(UnlockRequest.class);
88 public void testUnlockWithoutLock() {
91 fail("Should throw IllegalStateException");
92 } catch (final IllegalStateException e) {
98 public void testDiscardChanges() {
100 proxy.discardChanges();
101 masterActor.expectMsgClass(DiscardChangesRequest.class);
105 public void testDiscardChangesWithoutLock() {
107 proxy.discardChanges();
108 fail("Should throw IllegalStateException");
109 } catch (final IllegalStateException e) {
115 public void testGet() {
116 proxy.get(YangInstanceIdentifier.empty());
117 masterActor.expectMsgClass(NetconfDataTreeServiceRequest.class);
118 masterActor.reply(new Status.Success(masterActor.ref()));
119 masterActor.expectMsgClass(GetRequest.class);
123 public void testGetConfig() {
124 proxy.getConfig(YangInstanceIdentifier.empty());
125 masterActor.expectMsgClass(NetconfDataTreeServiceRequest.class);
126 masterActor.reply(new Status.Success(masterActor.ref()));
127 masterActor.expectMsgClass(GetConfigRequest.class);
131 public void testMerge() {
133 proxy.merge(STORE, PATH, NODE, Optional.empty());
134 masterActor.expectMsgClass(MergeEditConfigRequest.class);
138 public void testMergeWithoutLock() {
140 proxy.merge(STORE, PATH, NODE, Optional.empty());
141 fail("Should throw IllegalStateException");
142 } catch (final IllegalStateException e) {
148 public void testReplace() {
150 proxy.replace(STORE, PATH, NODE, Optional.empty());
151 masterActor.expectMsgClass(ReplaceEditConfigRequest.class);
155 public void testReplaceWithoutLock() {
157 proxy.replace(STORE, PATH, NODE, Optional.empty());
158 fail("Should throw IllegalStateException");
159 } catch (final IllegalStateException e) {
165 public void testCreate() {
167 proxy.create(STORE, PATH, NODE, Optional.empty());
168 masterActor.expectMsgClass(CreateEditConfigRequest.class);
172 public void testCreateWithoutLock() {
174 proxy.create(STORE, PATH, NODE, Optional.empty());
175 fail("Should throw IllegalStateException");
176 } catch (final IllegalStateException e) {
182 public void testDelete() {
184 proxy.delete(STORE, PATH);
185 masterActor.expectMsgClass(DeleteEditConfigRequest.class);
189 public void testDeleteWithoutLock() {
191 proxy.delete(STORE, PATH);
192 fail("Should throw IllegalStateException");
193 } catch (final IllegalStateException e) {
199 public void testRemove() {
201 proxy.remove(STORE, PATH);
202 masterActor.expectMsgClass(RemoveEditConfigRequest.class);
206 public void testRemoveWithoutLock() {
208 proxy.remove(STORE, PATH);
209 fail("Should throw IllegalStateException");
210 } catch (final IllegalStateException e) {
216 public void testCommit() {
219 masterActor.expectMsgClass(CommitRequest.class);
223 public void testCommitWithoutLock() {
226 fail("Should throw IllegalStateException");
227 } catch (final IllegalStateException e) {
232 private void lock() {
233 final ListenableFuture<DOMRpcResult> lock = proxy.lock();
234 masterActor.expectMsgClass(NetconfDataTreeServiceRequest.class);
235 masterActor.reply(new Status.Success(masterActor.ref()));
236 masterActor.expectMsgClass(LockRequest.class);
237 masterActor.reply(new InvokeRpcMessageReply(null, Collections.emptyList()));
238 Futures.whenAllComplete(lock).run(() -> {
239 assertTrue(lock.isDone());
240 assertNotNull(Futures.getUnchecked(lock));
241 }, MoreExecutors.directExecutor()
245 private void checkException(final IllegalStateException exception) {
246 assertEquals(String.format("%s: Device's datastore must be locked first", DEVICE_ID), exception.getMessage());
247 masterActor.expectNoMessage(EXP_NO_MESSAGE_TIMEOUT);