2 * Copyright (c) 2017 Pantheon Technologies 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
9 package org.opendaylight.netconf.topology.singleton.impl.actors;
11 import static org.mockito.Mockito.timeout;
12 import static org.mockito.Mockito.verify;
13 import static org.mockito.Mockito.when;
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.SubmitReply;
43 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
44 import org.opendaylight.yangtools.yang.common.QName;
45 import org.opendaylight.yangtools.yang.common.RpcError;
46 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
49 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
50 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
51 import scala.concurrent.Await;
52 import scala.concurrent.Future;
53 import scala.concurrent.duration.Duration;
55 public class ReadWriteTransactionActorTest {
57 private static final YangInstanceIdentifier PATH = YangInstanceIdentifier.EMPTY;
58 private static final LogicalDatastoreType STORE = LogicalDatastoreType.CONFIGURATION;
59 private static final Timeout TIMEOUT = Timeout.apply(5, TimeUnit.SECONDS);
62 private DOMDataReadWriteTransaction deviceReadWriteTx;
63 private TestProbe probe;
64 private ActorSystem system;
65 private TestActorRef<WriteTransactionActor> actorRef;
66 private NormalizedNode<?, ?> node;
69 public void setUp() throws Exception {
70 MockitoAnnotations.initMocks(this);
71 system = ActorSystem.apply();
72 probe = TestProbe.apply(system);
73 node = Builders.containerBuilder()
74 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("cont")))
76 actorRef = TestActorRef.create(system, ReadWriteTransactionActor.props(deviceReadWriteTx,
77 Duration.apply(2, TimeUnit.SECONDS)), "testA");
81 public void tearDown() throws Exception {
82 JavaTestKit.shutdownActorSystem(system, null, true);
86 public void testRead() throws Exception {
87 final ContainerNode node = Builders.containerBuilder()
88 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("cont")))
90 when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(Optional.of(node)));
91 actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
92 verify(deviceReadWriteTx).read(STORE, PATH);
93 probe.expectMsgClass(NormalizedNodeMessage.class);
97 public void testReadEmpty() throws Exception {
98 when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
99 actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
100 verify(deviceReadWriteTx).read(STORE, PATH);
101 probe.expectMsgClass(EmptyReadResponse.class);
105 public void testReadFailure() throws Exception {
106 final ReadFailedException cause = new ReadFailedException("fail");
107 when(deviceReadWriteTx.read(STORE, PATH)).thenReturn(Futures.immediateFailedCheckedFuture(cause));
108 actorRef.tell(new ReadRequest(STORE, PATH), probe.ref());
109 verify(deviceReadWriteTx).read(STORE, PATH);
110 probe.expectMsg(cause);
114 public void testExists() throws Exception {
115 when(deviceReadWriteTx.exists(STORE, PATH)).thenReturn(Futures.immediateCheckedFuture(true));
116 actorRef.tell(new ExistsRequest(STORE, PATH), probe.ref());
117 verify(deviceReadWriteTx).exists(STORE, PATH);
118 probe.expectMsg(true);
122 public void testExistsFailure() throws Exception {
123 final ReadFailedException cause = new ReadFailedException("fail");
124 when(deviceReadWriteTx.exists(STORE, PATH)).thenReturn(Futures.immediateFailedCheckedFuture(cause));
125 actorRef.tell(new ExistsRequest(STORE, PATH), probe.ref());
126 verify(deviceReadWriteTx).exists(STORE, PATH);
127 probe.expectMsg(cause);
131 public void testPut() throws Exception {
132 final NormalizedNodeMessage normalizedNodeMessage = new NormalizedNodeMessage(PATH, node);
133 actorRef.tell(new PutRequest(STORE, normalizedNodeMessage), probe.ref());
134 verify(deviceReadWriteTx).put(STORE, PATH, node);
138 public void testMerge() throws Exception {
139 final NormalizedNodeMessage normalizedNodeMessage = new NormalizedNodeMessage(PATH, node);
140 actorRef.tell(new MergeRequest(STORE, normalizedNodeMessage), probe.ref());
141 verify(deviceReadWriteTx).merge(STORE, PATH, node);
145 public void testDelete() throws Exception {
146 actorRef.tell(new DeleteRequest(STORE, PATH), probe.ref());
147 verify(deviceReadWriteTx).delete(STORE, PATH);
151 public void testCancel() throws Exception {
152 when(deviceReadWriteTx.cancel()).thenReturn(true);
153 final Future<Object> cancelFuture = Patterns.ask(actorRef, new CancelRequest(), TIMEOUT);
154 final Object result = Await.result(cancelFuture, TIMEOUT.duration());
155 Assert.assertTrue(result instanceof Boolean);
156 verify(deviceReadWriteTx).cancel();
157 Assert.assertTrue((Boolean) result);
161 public void testSubmit() throws Exception {
162 when(deviceReadWriteTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
163 final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
164 final Object result = Await.result(submitFuture, TIMEOUT.duration());
165 Assert.assertTrue(result instanceof SubmitReply);
166 verify(deviceReadWriteTx).submit();
170 public void testSubmitFail() throws Exception {
171 final RpcError rpcError =
172 RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION, "fail", "fail");
173 final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail", rpcError);
174 when(deviceReadWriteTx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(cause));
175 final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
176 final Object result = Await.result(submitFuture, TIMEOUT.duration());
177 Assert.assertEquals(cause, result);
178 verify(deviceReadWriteTx).submit();
182 public void testIdleTimeout() throws Exception {
183 final TestProbe probe = new TestProbe(system);
184 probe.watch(actorRef);
185 verify(deviceReadWriteTx, timeout(3000)).cancel();
186 probe.expectTerminated(actorRef, TIMEOUT.duration());