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.tx;
11 import akka.actor.ActorSystem;
12 import akka.testkit.JavaTestKit;
13 import akka.testkit.TestProbe;
14 import akka.util.Timeout;
15 import com.google.common.base.Optional;
16 import com.google.common.util.concurrent.CheckedFuture;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.net.InetSocketAddress;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.Future;
21 import java.util.concurrent.TimeUnit;
22 import org.junit.After;
23 import org.junit.Assert;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.opendaylight.controller.config.util.xml.DocumentedException;
27 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
31 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
32 import org.opendaylight.netconf.topology.singleton.messages.NormalizedNodeMessage;
33 import org.opendaylight.netconf.topology.singleton.messages.transactions.CancelRequest;
34 import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
35 import org.opendaylight.netconf.topology.singleton.messages.transactions.EmptyReadResponse;
36 import org.opendaylight.netconf.topology.singleton.messages.transactions.ExistsRequest;
37 import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
38 import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
39 import org.opendaylight.netconf.topology.singleton.messages.transactions.ReadRequest;
40 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
41 import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
42 import org.opendaylight.yangtools.yang.common.QName;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
45 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
47 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
49 public class ProxyReadWriteTransactionTest {
50 private static final YangInstanceIdentifier PATH = YangInstanceIdentifier.EMPTY;
51 private static final LogicalDatastoreType STORE = LogicalDatastoreType.CONFIGURATION;
53 private ActorSystem system;
54 private TestProbe masterActor;
55 private ContainerNode node;
56 private ProxyReadWriteTransaction tx;
59 public void setUp() throws Exception {
60 system = ActorSystem.apply();
61 masterActor = new TestProbe(system);
62 final RemoteDeviceId id = new RemoteDeviceId("dev1", InetSocketAddress.createUnresolved("localhost", 17830));
63 node = Builders.containerBuilder()
64 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("cont")))
66 tx = new ProxyReadWriteTransaction(masterActor.ref(), id, system, Timeout.apply(5, TimeUnit.SECONDS));
70 public void tearDown() throws Exception {
71 JavaTestKit.shutdownActorSystem(system, null, true);
75 public void testCancel() throws Exception {
76 final Future<Boolean> submit = Executors.newSingleThreadExecutor().submit(() -> tx.cancel());
77 masterActor.expectMsgClass(CancelRequest.class);
78 masterActor.reply(true);
79 Assert.assertTrue(submit.get());
83 public void testCancelSubmitted() throws Exception {
84 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
85 masterActor.expectMsgClass(SubmitRequest.class);
86 masterActor.reply(new SubmitReply());
87 submitFuture.checkedGet();
88 final Future<Boolean> submit = Executors.newSingleThreadExecutor().submit(() -> tx.cancel());
89 masterActor.expectNoMsg();
90 Assert.assertFalse(submit.get());
94 public void testSubmit() throws Exception {
95 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
96 masterActor.expectMsgClass(SubmitRequest.class);
97 masterActor.reply(new SubmitReply());
98 submitFuture.checkedGet();
102 public void testDoubleSubmit() throws Exception {
103 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
104 masterActor.expectMsgClass(SubmitRequest.class);
105 masterActor.reply(new SubmitReply());
106 submitFuture.checkedGet();
108 tx.submit().checkedGet();
109 Assert.fail("Should throw IllegalStateException");
110 } catch (final IllegalStateException e) {
111 masterActor.expectNoMsg();
116 public void testCommit() throws Exception {
117 final ListenableFuture<RpcResult<TransactionStatus>> submitFuture = tx.commit();
118 masterActor.expectMsgClass(SubmitRequest.class);
119 masterActor.reply(new SubmitReply());
120 Assert.assertEquals(TransactionStatus.SUBMITED, submitFuture.get().getResult());
124 public void testDelete() throws Exception {
125 tx.delete(STORE, PATH);
126 masterActor.expectMsgClass(DeleteRequest.class);
130 public void testDeleteClosed() throws Exception {
133 tx.delete(STORE, PATH);
134 Assert.fail("Should throw IllegalStateException");
135 } catch (final IllegalStateException e) {
136 masterActor.expectNoMsg();
141 public void testPut() throws Exception {
142 tx.put(STORE, PATH, node);
143 masterActor.expectMsgClass(PutRequest.class);
147 public void testPutClosed() throws Exception {
150 tx.put(STORE, PATH, node);
151 Assert.fail("Should throw IllegalStateException");
152 } catch (final IllegalStateException e) {
153 masterActor.expectNoMsg();
158 public void testMerge() throws Exception {
159 tx.merge(STORE, PATH, node);
160 masterActor.expectMsgClass(MergeRequest.class);
164 public void testMergeClosed() throws Exception {
167 tx.merge(STORE, PATH, node);
168 Assert.fail("Should throw IllegalStateException");
169 } catch (final IllegalStateException e) {
170 masterActor.expectNoMsg();
175 public void testGetIdentifier() throws Exception {
176 Assert.assertEquals(tx, tx.getIdentifier());
179 private void submit() throws TransactionCommitFailedException {
180 final CheckedFuture<Void, TransactionCommitFailedException> submit = tx.submit();
181 masterActor.expectMsgClass(SubmitRequest.class);
182 masterActor.reply(new SubmitReply());
187 public void testRead() throws Exception {
188 final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read = tx.read(STORE, PATH);
189 masterActor.expectMsgClass(ReadRequest.class);
190 masterActor.reply(new NormalizedNodeMessage(PATH, node));
191 final Optional<NormalizedNode<?, ?>> result = read.checkedGet();
192 Assert.assertTrue(result.isPresent());
193 Assert.assertEquals(node, result.get());
197 public void testReadEmpty() throws Exception {
198 final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read = tx.read(STORE, PATH);
199 masterActor.expectMsgClass(ReadRequest.class);
200 masterActor.reply(new EmptyReadResponse());
201 final Optional<NormalizedNode<?, ?>> result = read.checkedGet();
202 Assert.assertFalse(result.isPresent());
205 @Test(expected = ReadFailedException.class)
206 public void testReadFail() throws Exception {
207 final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read = tx.read(STORE, PATH);
208 masterActor.expectMsgClass(ReadRequest.class);
209 masterActor.reply(new RuntimeException("fail"));
214 public void testExists() throws Exception {
215 final CheckedFuture<Boolean, ReadFailedException> read = tx.exists(STORE, PATH);
216 masterActor.expectMsgClass(ExistsRequest.class);
217 masterActor.reply(true);
218 final Boolean result = read.checkedGet();
219 Assert.assertTrue(result);
222 @Test(expected = ReadFailedException.class)
223 public void testExistsFail() throws Exception {
224 final CheckedFuture<Boolean, ReadFailedException> read = tx.exists(STORE, PATH);
225 masterActor.expectMsgClass(ExistsRequest.class);
226 masterActor.reply(new RuntimeException("fail"));
231 public void testMasterDownRead() throws Exception {
232 final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read = tx.read(STORE, PATH);
233 masterActor.expectMsgClass(ReadRequest.class);
234 //master doesn't reply
237 Assert.fail("Exception should be thrown");
238 } catch (final ReadFailedException e) {
239 final Throwable cause = e.getCause();
240 Assert.assertTrue(cause instanceof DocumentedException);
241 final DocumentedException de = (DocumentedException) cause;
242 Assert.assertEquals(DocumentedException.ErrorSeverity.WARNING, de.getErrorSeverity());
243 Assert.assertEquals(DocumentedException.ErrorTag.OPERATION_FAILED, de.getErrorTag());
244 Assert.assertEquals(DocumentedException.ErrorType.APPLICATION, de.getErrorType());