BUG-9048 Fix actor crash when writing incorrect data
[netconf.git] / netconf / netconf-topology-singleton / src / test / java / org / opendaylight / netconf / topology / singleton / impl / actors / ReadWriteTransactionActorTest.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies 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
9 package org.opendaylight.netconf.topology.singleton.impl.actors;
10
11 import static org.mockito.Mockito.timeout;
12 import static org.mockito.Mockito.verify;
13 import static org.mockito.Mockito.when;
14
15 import akka.actor.ActorSystem;
16 import akka.pattern.Patterns;
17 import akka.testkit.JavaTestKit;
18 import akka.testkit.TestActorRef;
19 import akka.testkit.TestProbe;
20 import akka.util.Timeout;
21 import com.google.common.base.Optional;
22 import com.google.common.util.concurrent.Futures;
23 import java.util.concurrent.TimeUnit;
24 import org.junit.After;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.Mock;
29 import org.mockito.MockitoAnnotations;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
32 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
33 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
34 import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
35 import org.opendaylight.netconf.topology.singleton.messages.transactions.CancelRequest;
36 import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
37 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
38 import org.opendaylight.netconf.topology.singleton.messages.transactions.ExistsRequest;
39 import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
40 import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
41 import org.opendaylight.netconf.topology.singleton.messages.transactions.ReadRequest;
42 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
43 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
44 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.common.RpcError;
47 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
49 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
50 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
51 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
52 import scala.concurrent.Await;
53 import scala.concurrent.Future;
54 import scala.concurrent.duration.Duration;
55
56 public class ReadWriteTransactionActorTest {
57
58     private static final YangInstanceIdentifier PATH = YangInstanceIdentifier.EMPTY;
59     private static final LogicalDatastoreType STORE = LogicalDatastoreType.CONFIGURATION;
60     private static final Timeout TIMEOUT = Timeout.apply(5, TimeUnit.SECONDS);
61
62     @Mock
63     private DOMDataReadWriteTransaction deviceReadWriteTx;
64     private TestProbe probe;
65     private ActorSystem system;
66     private TestActorRef<WriteTransactionActor> actorRef;
67     private NormalizedNode<?, ?> node;
68
69     @Before
70     public void setUp() throws Exception {
71         MockitoAnnotations.initMocks(this);
72         system = ActorSystem.apply();
73         probe = TestProbe.apply(system);
74         node = Builders.containerBuilder()
75                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("cont")))
76                 .build();
77         actorRef = TestActorRef.create(system, ReadWriteTransactionActor.props(deviceReadWriteTx,
78                 Duration.apply(2, TimeUnit.SECONDS)), "testA");
79     }
80
81     @After
82     public void tearDown() throws Exception {
83         JavaTestKit.shutdownActorSystem(system, null, true);
84     }
85
86     @Test
87     public void testRead() throws Exception {
88         final ContainerNode node = Builders.containerBuilder()
89                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("cont")))
90                 .build();
91         when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(Optional.of(node)));
92         actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
93         verify(deviceReadWriteTx).read(STORE, PATH);
94         probe.expectMsgClass(NormalizedNodeMessage.class);
95     }
96
97     @Test
98     public void testReadEmpty() throws Exception {
99         when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
100         actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
101         verify(deviceReadWriteTx).read(STORE, PATH);
102         probe.expectMsgClass(EmptyReadResponse.class);
103     }
104
105     @Test
106     public void testReadFailure() throws Exception {
107         final ReadFailedException cause = new ReadFailedException("fail");
108         when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateFailedCheckedFuture(cause));
109         actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
110         verify(deviceReadWriteTx).read(STORE, PATH);
111         probe.expectMsg(cause);
112     }
113
114     @Test
115     public void testExists() throws Exception {
116         when(deviceReadWriteTx.exists(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(true));
117         actorRef.tell(new ExistsRequest(STORE, PATH), probe.ref());
118         verify(deviceReadWriteTx).exists(STORE, PATH);
119         probe.expectMsg(true);
120     }
121
122     @Test
123     public void testExistsFailure() throws Exception {
124         final ReadFailedException cause = new ReadFailedException("fail");
125         when(deviceReadWriteTx.exists(STORE, PATH)).thenReturn(Futures.immediateFailedCheckedFuture(cause));
126         actorRef.tell(new ExistsRequest(STORE, PATH), probe.ref());
127         verify(deviceReadWriteTx).exists(STORE, PATH);
128         probe.expectMsg(cause);
129     }
130
131     @Test
132     public void testPut() throws Exception {
133         final NormalizedNodeMessage normalizedNodeMessage = new NormalizedNodeMessage(PATH, node);
134         actorRef.tell(new PutRequest(STORE, normalizedNodeMessage), probe.ref());
135         verify(deviceReadWriteTx).put(STORE, PATH, node);
136     }
137
138     @Test
139     public void testMerge() throws Exception {
140         final NormalizedNodeMessage normalizedNodeMessage = new NormalizedNodeMessage(PATH, node);
141         actorRef.tell(new MergeRequest(STORE, normalizedNodeMessage), probe.ref());
142         verify(deviceReadWriteTx).merge(STORE, PATH, node);
143     }
144
145     @Test
146     public void testDelete() throws Exception {
147         actorRef.tell(new DeleteRequest(STORE, PATH), probe.ref());
148         verify(deviceReadWriteTx).delete(STORE, PATH);
149     }
150
151     @Test
152     public void testCancel() throws Exception {
153         when(deviceReadWriteTx.cancel()).thenReturn(true);
154         final Future<Object> cancelFuture = Patterns.ask(actorRef, new CancelRequest(), TIMEOUT);
155         final Object result = Await.result(cancelFuture, TIMEOUT.duration());
156         Assert.assertTrue(result instanceof Boolean);
157         verify(deviceReadWriteTx).cancel();
158         Assert.assertTrue((Boolean) result);
159     }
160
161     @Test
162     public void testSubmit() throws Exception {
163         when(deviceReadWriteTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
164         final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
165         final Object result = Await.result(submitFuture, TIMEOUT.duration());
166         Assert.assertTrue(result instanceof SubmitReply);
167         verify(deviceReadWriteTx).submit();
168     }
169
170     @Test
171     public void testSubmitFail() throws Exception {
172         final RpcError rpcError =
173                 RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION, "fail", "fail");
174         final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail", rpcError);
175         when(deviceReadWriteTx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(cause));
176         final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
177         final Object result = Await.result(submitFuture, TIMEOUT.duration());
178         Assert.assertTrue(result instanceof SubmitFailedReply);
179         Assert.assertEquals(cause, ((SubmitFailedReply)result).getThrowable());
180         verify(deviceReadWriteTx).submit();
181     }
182
183     @Test
184     public void testIdleTimeout() throws Exception {
185         final TestProbe probe = new TestProbe(system);
186         probe.watch(actorRef);
187         verify(deviceReadWriteTx, timeout(3000)).cancel();
188         probe.expectTerminated(actorRef, TIMEOUT.duration());
189     }
190 }