Refactor TransactionContext.executeModification()
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / LocalTransactionContextTest.java
index 7593eeadd383144f0c02001004f61608562a839f..42d8d798286def837cfafa6fe3feadc143688dd3 100644 (file)
@@ -1,40 +1,53 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
 package org.opendaylight.controller.cluster.datastore;
 
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.Futures;
+
+import akka.actor.ActorSelection;
 import com.google.common.util.concurrent.SettableFuture;
-import java.util.concurrent.Semaphore;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.cluster.datastore.identifiers.TransactionIdentifier;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadTransaction;
+import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction;
+import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.util.concurrent.FluentFutures;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import scala.concurrent.Future;
 
 public class LocalTransactionContextTest {
 
     @Mock
-    Semaphore limiter;
+    private OperationLimiter limiter;
 
     @Mock
-    TransactionIdentifier identifier;
+    private DOMStoreReadWriteTransaction readWriteTransaction;
 
     @Mock
-    DOMStoreReadWriteTransaction readWriteTransaction;
+    private LocalTransactionReadySupport mockReadySupport;
 
-    LocalTransactionContext localTransactionContext;
+    private LocalTransactionContext localTransactionContext;
 
     @Before
-    public void setUp(){
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
-        localTransactionContext = new LocalTransactionContext(identifier, readWriteTransaction, new OperationCompleter(limiter)) {
+        localTransactionContext = new LocalTransactionContext(readWriteTransaction, limiter.getIdentifier(),
+                mockReadySupport) {
             @Override
             protected DOMStoreWriteTransaction getWriteDelegate() {
                 return readWriteTransaction;
@@ -48,58 +61,109 @@ public class LocalTransactionContextTest {
     }
 
     @Test
-    public void testWrite(){
-        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().build();
-        NormalizedNode normalizedNode = mock(NormalizedNode.class);
-        localTransactionContext.writeData(yangInstanceIdentifier, normalizedNode);
-        verify(limiter).release();
+    public void testWrite() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        NormalizedNode<?, ?> normalizedNode = mock(NormalizedNode.class);
+        localTransactionContext.executeWrite(yangInstanceIdentifier, normalizedNode, null);
         verify(readWriteTransaction).write(yangInstanceIdentifier, normalizedNode);
     }
 
     @Test
-    public void testMerge(){
-        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().build();
-        NormalizedNode normalizedNode = mock(NormalizedNode.class);
-        localTransactionContext.mergeData(yangInstanceIdentifier, normalizedNode);
-        verify(limiter).release();
+    public void testMerge() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        NormalizedNode<?, ?> normalizedNode = mock(NormalizedNode.class);
+        localTransactionContext.executeMerge(yangInstanceIdentifier, normalizedNode, null);
         verify(readWriteTransaction).merge(yangInstanceIdentifier, normalizedNode);
     }
 
     @Test
-    public void testDelete(){
-        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().build();
-        localTransactionContext.deleteData(yangInstanceIdentifier);
-        verify(limiter).release();
+    public void testDelete() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        localTransactionContext.executeDelete(yangInstanceIdentifier, null);
         verify(readWriteTransaction).delete(yangInstanceIdentifier);
     }
 
-
     @Test
-    public void testRead(){
-        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().build();
-        NormalizedNode normalizedNode = mock(NormalizedNode.class);
-        doReturn(Futures.immediateCheckedFuture(Optional.of(normalizedNode))).when(readWriteTransaction).read(yangInstanceIdentifier);
-        localTransactionContext.readData(yangInstanceIdentifier, SettableFuture.<Optional<NormalizedNode<?,?>>>create());
-        verify(limiter).release();
+    public void testRead() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        NormalizedNode<?, ?> normalizedNode = mock(NormalizedNode.class);
+        doReturn(FluentFutures.immediateFluentFuture(Optional.of(normalizedNode))).when(readWriteTransaction)
+            .read(yangInstanceIdentifier);
+        localTransactionContext.executeRead(new ReadData(yangInstanceIdentifier, DataStoreVersions.CURRENT_VERSION),
+                SettableFuture.create(), null);
         verify(readWriteTransaction).read(yangInstanceIdentifier);
     }
 
     @Test
-    public void testExists(){
-        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().build();
-        doReturn(Futures.immediateCheckedFuture(true)).when(readWriteTransaction).exists(yangInstanceIdentifier);
-        localTransactionContext.dataExists(yangInstanceIdentifier, SettableFuture.<Boolean> create());
-        verify(limiter).release();
+    public void testExists() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        doReturn(FluentFutures.immediateTrueFluentFuture()).when(readWriteTransaction).exists(yangInstanceIdentifier);
+        localTransactionContext.executeRead(new DataExists(yangInstanceIdentifier, DataStoreVersions.CURRENT_VERSION),
+                SettableFuture.create(), null);
         verify(readWriteTransaction).exists(yangInstanceIdentifier);
     }
 
     @Test
-    public void testReady(){
-        doReturn(mock(LocalThreePhaseCommitCohort.class)).when(readWriteTransaction).ready();
-        localTransactionContext.readyTransaction();
-        verify(limiter).release();
-        verify(readWriteTransaction).ready();
+    public void testReady() {
+        final LocalThreePhaseCommitCohort mockCohort = mock(LocalThreePhaseCommitCohort.class);
+        doReturn(akka.dispatch.Futures.successful(null)).when(mockCohort).initiateCoordinatedCommit(Optional.empty());
+        doReturn(mockCohort).when(mockReadySupport).onTransactionReady(readWriteTransaction, null);
+
+        Future<ActorSelection> future = localTransactionContext.readyTransaction(null, Optional.empty());
+        assertTrue(future.isCompleted());
+
+        verify(mockReadySupport).onTransactionReady(readWriteTransaction, null);
+    }
+
+    @Test
+    public void testReadyWithWriteError() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        NormalizedNode<?, ?> normalizedNode = mock(NormalizedNode.class);
+        RuntimeException error = new RuntimeException("mock");
+        doThrow(error).when(readWriteTransaction).write(yangInstanceIdentifier, normalizedNode);
+
+        localTransactionContext.executeWrite(yangInstanceIdentifier, normalizedNode, null);
+        localTransactionContext.executeWrite(yangInstanceIdentifier, normalizedNode, null);
+
+        verify(readWriteTransaction).write(yangInstanceIdentifier, normalizedNode);
+
+        doReadyWithExpectedError(error);
+    }
+
+    @Test
+    public void testReadyWithMergeError() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        NormalizedNode<?, ?> normalizedNode = mock(NormalizedNode.class);
+        RuntimeException error = new RuntimeException("mock");
+        doThrow(error).when(readWriteTransaction).merge(yangInstanceIdentifier, normalizedNode);
+
+        localTransactionContext.executeMerge(yangInstanceIdentifier, normalizedNode, null);
+        localTransactionContext.executeMerge(yangInstanceIdentifier, normalizedNode, null);
+
+        verify(readWriteTransaction).merge(yangInstanceIdentifier, normalizedNode);
+
+        doReadyWithExpectedError(error);
     }
 
+    @Test
+    public void testReadyWithDeleteError() {
+        YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.empty();
+        RuntimeException error = new RuntimeException("mock");
+        doThrow(error).when(readWriteTransaction).delete(yangInstanceIdentifier);
+
+        localTransactionContext.executeDelete(yangInstanceIdentifier, null);
+        localTransactionContext.executeDelete(yangInstanceIdentifier, null);
 
-}
\ No newline at end of file
+        verify(readWriteTransaction).delete(yangInstanceIdentifier);
+
+        doReadyWithExpectedError(error);
+    }
+
+    private void doReadyWithExpectedError(final RuntimeException expError) {
+        LocalThreePhaseCommitCohort mockCohort = mock(LocalThreePhaseCommitCohort.class);
+        doReturn(akka.dispatch.Futures.successful(null)).when(mockCohort).initiateCoordinatedCommit(Optional.empty());
+        doReturn(mockCohort).when(mockReadySupport).onTransactionReady(readWriteTransaction, expError);
+
+        localTransactionContext.readyTransaction(null, Optional.empty());
+    }
+}