53fd4897c9a49618bc601be345d15c8ff93eb500
[netconf.git] / netconf / netconf-topology-singleton / src / test / java / org / opendaylight / netconf / topology / singleton / impl / actors / NetconfDataTreeServiceActorTest.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.actors;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.mockito.Mockito.doReturn;
12 import static org.mockito.Mockito.timeout;
13 import static org.mockito.Mockito.verify;
14 import static org.mockito.Mockito.when;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
16 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
17
18 import akka.actor.ActorRef;
19 import akka.actor.ActorSystem;
20 import akka.actor.Status;
21 import akka.testkit.TestActorRef;
22 import akka.testkit.TestProbe;
23 import akka.testkit.javadsl.TestKit;
24 import akka.util.Timeout;
25 import com.google.common.util.concurrent.Futures;
26 import com.google.common.util.concurrent.ListenableFuture;
27 import java.util.Optional;
28 import java.util.concurrent.TimeUnit;
29 import org.junit.AfterClass;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.mockito.Mock;
34 import org.mockito.junit.MockitoJUnitRunner;
35 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
36 import org.opendaylight.mdsal.common.api.ReadFailedException;
37 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
38 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
39 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
40 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
41 import org.opendaylight.netconf.topology.singleton.impl.netconf.NetconfServiceFailedException;
42 import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
43 import org.opendaylight.netconf.topology.singleton.messages.netconf.CommitRequest;
44 import org.opendaylight.netconf.topology.singleton.messages.netconf.CreateEditConfigRequest;
45 import org.opendaylight.netconf.topology.singleton.messages.netconf.DeleteEditConfigRequest;
46 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetConfigRequest;
47 import org.opendaylight.netconf.topology.singleton.messages.netconf.GetRequest;
48 import org.opendaylight.netconf.topology.singleton.messages.netconf.LockRequest;
49 import org.opendaylight.netconf.topology.singleton.messages.netconf.MergeEditConfigRequest;
50 import org.opendaylight.netconf.topology.singleton.messages.netconf.RemoveEditConfigRequest;
51 import org.opendaylight.netconf.topology.singleton.messages.netconf.ReplaceEditConfigRequest;
52 import org.opendaylight.netconf.topology.singleton.messages.rpc.InvokeRpcMessageReply;
53 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
54 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
55 import org.opendaylight.yangtools.yang.common.QName;
56 import org.opendaylight.yangtools.yang.common.RpcError;
57 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
59 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
60 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
61 import scala.concurrent.duration.Duration;
62
63 @RunWith(MockitoJUnitRunner.StrictStubs.class)
64 public class NetconfDataTreeServiceActorTest {
65     static final YangInstanceIdentifier PATH = YangInstanceIdentifier.empty();
66     static final LogicalDatastoreType STORE = LogicalDatastoreType.CONFIGURATION;
67     static final Timeout TIMEOUT = Timeout.apply(5, TimeUnit.SECONDS);
68     static final NormalizedNode<?, ?> NODE = Builders.containerBuilder()
69         .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("", "cont"))).build();
70
71     private static ActorSystem system = ActorSystem.apply();
72
73     @Mock
74     private NetconfDataTreeService netconfService;
75
76     private TestProbe probe;
77     private ActorRef actorRef;
78
79     @Before
80     public void setUp() {
81         this.actorRef = TestActorRef.create(system,
82             NetconfDataTreeServiceActor.props(netconfService, Duration.apply(2, TimeUnit.SECONDS)));
83         this.probe = TestProbe.apply(system);
84     }
85
86     @AfterClass
87     public static void staticTearDown() {
88         TestKit.shutdownActorSystem(system, true);
89     }
90
91     @Test
92     public void testGet() {
93         doReturn(immediateFluentFuture(Optional.of(NODE))).when(netconfService).get(PATH);
94         actorRef.tell(new GetRequest(PATH), probe.ref());
95
96         verify(netconfService).get(PATH);
97         final NormalizedNodeMessage response = probe.expectMsgClass(NormalizedNodeMessage.class);
98         assertEquals(NODE, response.getNode());
99     }
100
101     @Test
102     public void testGetEmpty() {
103         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(PATH);
104         actorRef.tell(new GetRequest(PATH), probe.ref());
105
106         verify(netconfService).get(PATH);
107         probe.expectMsgClass(EmptyReadResponse.class);
108     }
109
110     @Test
111     public void testGetFailure() {
112         final ReadFailedException cause = new ReadFailedException("fail");
113         doReturn(immediateFailedFluentFuture(cause)).when(netconfService).get(PATH);
114         actorRef.tell(new GetRequest(PATH), probe.ref());
115
116         verify(netconfService).get(PATH);
117         final Status.Failure response = probe.expectMsgClass(Status.Failure.class);
118         assertEquals(cause, response.cause());
119     }
120
121     @Test
122     public void testGetConfig() {
123         doReturn(immediateFluentFuture(Optional.of(NODE))).when(netconfService).getConfig(PATH);
124         actorRef.tell(new GetConfigRequest(PATH), probe.ref());
125
126         verify(netconfService).getConfig(PATH);
127         final NormalizedNodeMessage response = probe.expectMsgClass(NormalizedNodeMessage.class);
128         assertEquals(NODE, response.getNode());
129     }
130
131     @Test
132     public void testGetConfigEmpty() {
133         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH);
134         actorRef.tell(new GetConfigRequest(PATH), probe.ref());
135
136         verify(netconfService).getConfig(PATH);
137         probe.expectMsgClass(EmptyReadResponse.class);
138     }
139
140     @Test
141     public void testGetConfigFailure() {
142         final ReadFailedException cause = new ReadFailedException("fail");
143         doReturn(immediateFailedFluentFuture(cause)).when(netconfService).getConfig(PATH);
144         actorRef.tell(new GetConfigRequest(PATH), probe.ref());
145
146         verify(netconfService).getConfig(PATH);
147         final Status.Failure response = probe.expectMsgClass(Status.Failure.class);
148         assertEquals(cause, response.cause());
149     }
150
151     @Test
152     public void testLock() {
153         final ListenableFuture<? extends DOMRpcResult> future = Futures.immediateFuture(new DefaultDOMRpcResult());
154         doReturn(future).when(netconfService).lock();
155         actorRef.tell(new LockRequest(), probe.ref());
156         verify(netconfService).lock();
157     }
158
159     @Test
160     public void testMerge() {
161         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService)
162             .merge(STORE, PATH, NODE, Optional.empty());
163         final NormalizedNodeMessage node = new NormalizedNodeMessage(PATH, NODE);
164         actorRef.tell(new MergeEditConfigRequest(STORE, node, null), probe.ref());
165         verify(netconfService).merge(STORE, PATH, NODE, Optional.empty());
166     }
167
168     @Test
169     public void testReplace() {
170         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService)
171             .replace(STORE, PATH, NODE, Optional.empty());
172         final NormalizedNodeMessage node = new NormalizedNodeMessage(PATH, NODE);
173         actorRef.tell(new ReplaceEditConfigRequest(STORE, node, null), probe.ref());
174         verify(netconfService).replace(STORE, PATH, NODE, Optional.empty());
175     }
176
177     @Test
178     public void testCreate() {
179         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService)
180             .create(STORE, PATH, NODE, Optional.empty());
181         final NormalizedNodeMessage node = new NormalizedNodeMessage(PATH, NODE);
182         actorRef.tell(new CreateEditConfigRequest(STORE, node, null), probe.ref());
183         verify(netconfService).create(STORE, PATH, NODE, Optional.empty());
184     }
185
186     @Test
187     public void testDelete() {
188         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService)
189             .delete(STORE, PATH);
190         actorRef.tell(new DeleteEditConfigRequest(STORE, PATH), probe.ref());
191         verify(netconfService).delete(STORE, PATH);
192     }
193
194     @Test
195     public void testRemove() {
196         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService)
197             .remove(STORE, PATH);
198         actorRef.tell(new RemoveEditConfigRequest(STORE, PATH), probe.ref());
199         verify(netconfService).remove(STORE, PATH);
200     }
201
202     @Test
203     public void testCommit() {
204         doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
205         actorRef.tell(new CommitRequest(), probe.ref());
206
207         verify(netconfService).commit();
208         probe.expectMsgClass(InvokeRpcMessageReply.class);
209     }
210
211     @Test
212     public void testCommitFail() {
213         final RpcError rpcError = RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION, "fail", "fail");
214         final TransactionCommitFailedException failure = new TransactionCommitFailedException("fail", rpcError);
215         final NetconfServiceFailedException cause = new NetconfServiceFailedException(
216             String.format("%s: Commit of operation failed", 1), failure);
217         when(netconfService.commit()).thenReturn(FluentFutures.immediateFailedFluentFuture(cause));
218         actorRef.tell(new CommitRequest(), probe.ref());
219
220         verify(netconfService).commit();
221         final Status.Failure response = probe.expectMsgClass(Status.Failure.class);
222         assertEquals(cause, response.cause());
223     }
224
225     @Test
226     public void testIdleTimeout() {
227         final TestProbe testProbe = new TestProbe(system);
228         testProbe.watch(actorRef);
229         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
230         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
231         verify(netconfService, timeout(3000)).discardChanges();
232         verify(netconfService, timeout(3000)).unlock();
233         testProbe.expectTerminated(actorRef, TIMEOUT.duration());
234     }
235 }