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