Adjust to mdsal DOM read/exists FluentFuture change
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / TransactionProxyTest.java
index da47b222dfa083daa42746ae3ba77c7d81c12364..62c03d7617ad12b2992903dda19c3d08c74e0a8d 100644 (file)
@@ -29,21 +29,24 @@ import akka.actor.ActorSystem;
 import akka.actor.Props;
 import akka.dispatch.Futures;
 import akka.util.Timeout;
-import com.google.common.base.Optional;
 import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
+import java.util.SortedSet;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import org.junit.Assert;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 import org.opendaylight.controller.cluster.access.concepts.MemberName;
@@ -57,6 +60,7 @@ import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyLocalTransaction;
 import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
 import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
@@ -66,8 +70,8 @@ import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
 import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -78,7 +82,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import scala.concurrent.Promise;
 
-@SuppressWarnings("resource")
+@SuppressWarnings({"resource", "checkstyle:IllegalThrows", "checkstyle:AvoidHidingCauseException"})
 public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
     @SuppressWarnings("serial")
@@ -86,7 +90,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
     }
 
     interface Invoker {
-        CheckedFuture<?, ReadFailedException> invoke(TransactionProxy proxy) throws Exception;
+        FluentFuture<?> invoke(TransactionProxy proxy) throws Exception;
     }
 
     @Test
@@ -116,7 +120,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
     }
 
     @Test(expected = ReadFailedException.class)
-    public void testReadWithInvalidReplyMessageType() throws Exception {
+    public void testReadWithInvalidReplyMessageType() throws Throwable {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(getSystem(), READ_ONLY);
 
         doReturn(Futures.successful(new Object())).when(mockActorContext)
@@ -124,11 +128,15 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, READ_ONLY);
 
-        transactionProxy.read(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
+        try {
+            transactionProxy.read(TestModel.TEST_PATH).get(5, TimeUnit.SECONDS);
+        } catch (ExecutionException e) {
+            throw e.getCause();
+        }
     }
 
     @Test(expected = TestException.class)
-    public void testReadWithAsyncRemoteOperatonFailure() throws Exception {
+    public void testReadWithAsyncRemoteOperatonFailure() throws Throwable {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(getSystem(), READ_ONLY);
 
         doReturn(Futures.failed(new TestException())).when(mockActorContext)
@@ -140,7 +148,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
     }
 
     private void testExceptionOnInitialCreateTransaction(final Exception exToThrow, final Invoker invoker)
-            throws Exception {
+            throws Throwable {
         ActorRef actorRef = getSystem().actorOf(Props.create(DoNothingActor.class));
 
         if (exToThrow instanceof PrimaryNotFoundException) {
@@ -158,23 +166,23 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
         propagateReadFailedExceptionCause(invoker.invoke(transactionProxy));
     }
 
-    private void testReadWithExceptionOnInitialCreateTransaction(final Exception exToThrow) throws Exception {
+    private void testReadWithExceptionOnInitialCreateTransaction(final Exception exToThrow) throws Throwable {
         testExceptionOnInitialCreateTransaction(exToThrow, proxy -> proxy.read(TestModel.TEST_PATH));
     }
 
     @Test(expected = PrimaryNotFoundException.class)
-    public void testReadWhenAPrimaryNotFoundExceptionIsThrown() throws Exception {
+    public void testReadWhenAPrimaryNotFoundExceptionIsThrown() throws Throwable {
         testReadWithExceptionOnInitialCreateTransaction(new PrimaryNotFoundException("test"));
     }
 
-    @Test(expected = TimeoutException.class)
-    public void testReadWhenATimeoutExceptionIsThrown() throws Exception {
+    @Test(expected = TestException.class)
+    public void testReadWhenATimeoutExceptionIsThrown() throws Throwable {
         testReadWithExceptionOnInitialCreateTransaction(new TimeoutException("test",
-                new Exception("reason")));
+                new TestException()));
     }
 
     @Test(expected = TestException.class)
-    public void testReadWhenAnyOtherExceptionIsThrown() throws Exception {
+    public void testReadWhenAnyOtherExceptionIsThrown() throws Throwable {
         testReadWithExceptionOnInitialCreateTransaction(new TestException());
     }
 
@@ -214,7 +222,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
     }
 
     @Test(expected = IllegalArgumentException.class)
-    public void testInvalidCreateTransactionReply() throws Exception {
+    public void testInvalidCreateTransactionReply() throws Throwable {
         ActorRef actorRef = getSystem().actorOf(Props.create(DoNothingActor.class));
 
         doReturn(getSystem().actorSelection(actorRef.path())).when(mockActorContext)
@@ -241,26 +249,26 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
         doReturn(dataExistsReply(false)).when(mockActorContext).executeOperationAsync(
                 eq(actorSelection(actorRef)), eqDataExists(), any(Timeout.class));
 
-        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet();
+        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).get();
 
         assertEquals("Exists response", false, exists);
 
         doReturn(dataExistsReply(true)).when(mockActorContext).executeOperationAsync(
                 eq(actorSelection(actorRef)), eqDataExists(), any(Timeout.class));
 
-        exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet();
+        exists = transactionProxy.exists(TestModel.TEST_PATH).get();
 
         assertEquals("Exists response", true, exists);
     }
 
     @Test(expected = PrimaryNotFoundException.class)
-    public void testExistsWhenAPrimaryNotFoundExceptionIsThrown() throws Exception {
+    public void testExistsWhenAPrimaryNotFoundExceptionIsThrown() throws Throwable {
         testExceptionOnInitialCreateTransaction(new PrimaryNotFoundException("test"),
             proxy -> proxy.exists(TestModel.TEST_PATH));
     }
 
     @Test(expected = ReadFailedException.class)
-    public void testExistsWithInvalidReplyMessageType() throws Exception {
+    public void testExistsWithInvalidReplyMessageType() throws Throwable {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(getSystem(), READ_ONLY);
 
         doReturn(Futures.successful(new Object())).when(mockActorContext)
@@ -268,11 +276,15 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, READ_ONLY);
 
-        transactionProxy.exists(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
+        try {
+            transactionProxy.exists(TestModel.TEST_PATH).get(5, TimeUnit.SECONDS);
+        } catch (ExecutionException e) {
+            throw e.getCause();
+        }
     }
 
     @Test(expected = TestException.class)
-    public void testExistsWithAsyncRemoteOperatonFailure() throws Exception {
+    public void testExistsWithAsyncRemoteOperatonFailure() throws Throwable {
         ActorRef actorRef = setupActorContextWithInitialCreateTransaction(getSystem(), READ_ONLY);
 
         doReturn(Futures.failed(new TestException())).when(mockActorContext)
@@ -298,7 +310,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
         transactionProxy.write(TestModel.TEST_PATH, nodeToWrite);
 
-        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet();
+        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).get();
 
         assertEquals("Exists response", true, exists);
 
@@ -524,22 +536,59 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
     public void testReadyWithMultipleShardWrites() throws Exception {
         ActorRef actorRef1 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY);
 
-        ActorRef actorRef2 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY, "junk");
+        ActorRef actorRef2 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY,
+                TestModel.JUNK_QNAME.getLocalName());
 
         expectBatchedModificationsReady(actorRef1);
         expectBatchedModificationsReady(actorRef2);
 
+        ActorRef actorRef3 = getSystem().actorOf(Props.create(DoNothingActor.class));
+
+        doReturn(getSystem().actorSelection(actorRef3.path())).when(mockActorContext)
+                .actorSelection(actorRef3.path().toString());
+
+        doReturn(Futures.successful(newPrimaryShardInfo(actorRef3, createDataTree()))).when(mockActorContext)
+                .findPrimaryShardAsync(eq(CarsModel.BASE_QNAME.getLocalName()));
+
+        expectReadyLocalTransaction(actorRef3, false);
+
         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, WRITE_ONLY);
 
         transactionProxy.write(TestModel.JUNK_PATH, ImmutableNodes.containerNode(TestModel.JUNK_QNAME));
         transactionProxy.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+        transactionProxy.write(CarsModel.BASE_PATH, ImmutableNodes.containerNode(CarsModel.BASE_QNAME));
 
         DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
 
         assertTrue(ready instanceof ThreePhaseCommitCohortProxy);
 
         verifyCohortFutures((ThreePhaseCommitCohortProxy)ready, actorSelection(actorRef1),
-                actorSelection(actorRef2));
+                actorSelection(actorRef2), actorSelection(actorRef3));
+
+        SortedSet<String> expShardNames =
+                ImmutableSortedSet.of(DefaultShardStrategy.DEFAULT_SHARD,
+                        TestModel.JUNK_QNAME.getLocalName(), CarsModel.BASE_QNAME.getLocalName());
+
+        ArgumentCaptor<BatchedModifications> batchedMods = ArgumentCaptor.forClass(BatchedModifications.class);
+        verify(mockActorContext).executeOperationAsync(
+                eq(actorSelection(actorRef1)), batchedMods.capture(), any(Timeout.class));
+        assertEquals("Participating shards present", true,
+                batchedMods.getValue().getParticipatingShardNames().isPresent());
+        assertEquals("Participating shards", expShardNames, batchedMods.getValue().getParticipatingShardNames().get());
+
+        batchedMods = ArgumentCaptor.forClass(BatchedModifications.class);
+        verify(mockActorContext).executeOperationAsync(
+                eq(actorSelection(actorRef2)), batchedMods.capture(), any(Timeout.class));
+        assertEquals("Participating shards present", true,
+                batchedMods.getValue().getParticipatingShardNames().isPresent());
+        assertEquals("Participating shards", expShardNames, batchedMods.getValue().getParticipatingShardNames().get());
+
+        ArgumentCaptor<ReadyLocalTransaction> readyLocalTx = ArgumentCaptor.forClass(ReadyLocalTransaction.class);
+        verify(mockActorContext).executeOperationAsync(
+                eq(actorSelection(actorRef3)), readyLocalTx.capture(), any(Timeout.class));
+        assertEquals("Participating shards present", true,
+                readyLocalTx.getValue().getParticipatingShardNames().isPresent());
+        assertEquals("Participating shards", expShardNames, readyLocalTx.getValue().getParticipatingShardNames().get());
     }
 
     @Test
@@ -657,6 +706,12 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
         DOMStoreThreePhaseCommitCohort ready = transactionProxy.ready();
         assertTrue(ready instanceof SingleCommitCohortProxy);
         verifyCohortFutures((SingleCommitCohortProxy)ready, new CommitTransactionReply().toSerializable());
+
+        ArgumentCaptor<ReadyLocalTransaction> readyLocalTx = ArgumentCaptor.forClass(ReadyLocalTransaction.class);
+        verify(mockActorContext).executeOperationAsync(
+                eq(actorSelection(shardActorRef)), readyLocalTx.capture(), any(Timeout.class));
+        assertEquals("Participating shards present", false,
+                readyLocalTx.getValue().getParticipatingShardNames().isPresent());
     }
 
     @Test
@@ -725,7 +780,8 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
         dataStoreContextBuilder.writeOnlyTransactionOptimizationsEnabled(true);
         ActorRef actorRef1 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY);
 
-        ActorRef actorRef2 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY, "junk");
+        ActorRef actorRef2 = setupActorContextWithInitialCreateTransaction(getSystem(), WRITE_ONLY,
+                TestModel.JUNK_QNAME.getLocalName());
 
         doReturn(Futures.successful(new Object())).when(mockActorContext).executeOperationAsync(
                 eq(actorSelection(actorRef1)), isA(BatchedModifications.class), any(Timeout.class));
@@ -1367,7 +1423,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
         transactionProxy.delete(deletePath);
 
-        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet();
+        Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).get();
         assertEquals("Exists response", true, exists);
 
         assertEquals("NormalizedNode isPresent", true, readOptional.isPresent());