Further rework of base schemas
[netconf.git] / netconf / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / sal / tx / NetconfDeviceWriteOnlyTxTest.java
index ecb0eeb7796e4582c35690f263dc9a566db0dcfb..31789e96a3c18edd01ae51b2f459ddd20813da95 100644 (file)
@@ -5,49 +5,55 @@
  * 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.netconf.sal.connect.netconf.sal.tx;
 
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_FILTER_QNAME;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME;
 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
 
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.FluentFuture;
 import java.net.InetSocketAddress;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.netconf.sal.connect.netconf.AbstractBaseSchemasTest;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yangtools.util.concurrent.FluentFutures;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 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.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
-public class NetconfDeviceWriteOnlyTxTest {
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
+public class NetconfDeviceWriteOnlyTxTest extends AbstractBaseSchemasTest {
 
     private final RemoteDeviceId id = new RemoteDeviceId("test-mount", new InetSocketAddress(99));
 
@@ -56,45 +62,51 @@ public class NetconfDeviceWriteOnlyTxTest {
     private YangInstanceIdentifier yangIId;
 
     @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        final CheckedFuture<DefaultDOMRpcResult, Exception> successFuture =
-                Futures.immediateCheckedFuture(new DefaultDOMRpcResult(((NormalizedNode<?, ?>) null)));
+    public void setUp() {
+        final FluentFuture<DefaultDOMRpcResult> successFuture =
+                FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null));
 
         doReturn(successFuture)
-                .doReturn(Futures.immediateFailedCheckedFuture(new IllegalStateException("Failed tx")))
+                .doReturn(FluentFutures.immediateFailedFluentFuture(new IllegalStateException("Failed tx")))
                 .doReturn(successFuture)
-                .when(rpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class));
+                .when(rpc).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
 
         yangIId = YangInstanceIdentifier.builder().node(NetconfState.QNAME).build();
     }
 
     @Test
     public void testIgnoreNonVisibleData() {
-        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)),
+        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(EffectiveModelContext.class)),
                 false);
         final MapNode emptyList = ImmutableNodes.mapNodeBuilder(NETCONF_FILTER_QNAME).build();
-        tx.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList);
-        tx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList);
+        tx.merge(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier
+                .create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList);
+        tx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier
+                .create(new YangInstanceIdentifier.NodeIdentifier(NETCONF_FILTER_QNAME)), emptyList);
 
-        verify(rpc, atMost(1)).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class));
+        verify(rpc, atMost(1)).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
     }
 
     @Test
-    public void testDiscardChanges() {
-        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)),
+    public void testDiscardChanges() throws InterruptedException {
+        doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null)))
+                .when(rpc).invokeRpc(any(SchemaPath.class), isNull());
+
+        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(EffectiveModelContext.class)),
                 false);
-        final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
         try {
-            submitFuture.checkedGet();
-        } catch (final TransactionCommitFailedException e) {
+            tx.commit().get();
+        } catch (final ExecutionException e) {
             // verify discard changes was sent
             final InOrder inOrder = inOrder(rpc);
-            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), NetconfBaseOps.getLockContent(NETCONF_CANDIDATE_QNAME));
-            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
-            inOrder.verify(rpc).invokeRpc(eq(toPath(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME)), any(NormalizedNode.class));
-            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME), NetconfBaseOps.getUnLockContent(NETCONF_CANDIDATE_QNAME));
+            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME),
+                    NetconfBaseOps.getLockContent(NETCONF_CANDIDATE_QNAME));
+            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME),
+                    NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
+            inOrder.verify(rpc).invokeRpc(eq(toPath(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME)),
+                    isNull());
+            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME),
+                    NetconfBaseOps.getUnLockContent(NETCONF_CANDIDATE_QNAME));
             return;
         }
 
@@ -103,45 +115,92 @@ public class NetconfDeviceWriteOnlyTxTest {
 
     @Test
     public void testFailedCommit() throws Exception {
-        final CheckedFuture<DefaultDOMRpcResult, Exception> rpcErrorFuture =
-                Futures.immediateCheckedFuture(new DefaultDOMRpcResult(RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION, "a", "m")));
+        final FluentFuture<DefaultDOMRpcResult> rpcErrorFuture = FluentFutures.immediateFluentFuture(
+                new DefaultDOMRpcResult(RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION, "a", "m")));
 
-        doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult(((NormalizedNode<?, ?>) null))))
-        .doReturn(rpcErrorFuture).when(rpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class));
+        doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null)))
+                .doReturn(rpcErrorFuture).when(rpc).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
 
-        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(SchemaContext.class)),
+        final WriteCandidateTx tx = new WriteCandidateTx(id, new NetconfBaseOps(rpc, mock(EffectiveModelContext.class)),
                 false);
 
-        final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = tx.submit();
         try {
-            submitFuture.checkedGet();
-        } catch (final TransactionCommitFailedException e) {
-            return;
+            tx.commit().get();
+            fail("Submit should fail");
+        } catch (final ExecutionException e) {
+            // Intended
         }
-
-        fail("Submit should fail");
     }
 
     @Test
     public void testDiscardChangesNotSentWithoutCandidate() {
-        doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult(((NormalizedNode<?, ?>) null))))
-                .doReturn(Futures.immediateFailedCheckedFuture(new IllegalStateException("Failed tx")))
-                .when(rpc).invokeRpc(any(SchemaPath.class), any(NormalizedNode.class));
+        doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null)))
+                .doReturn(FluentFutures.immediateFailedFluentFuture(new IllegalStateException("Failed tx")))
+                .when(rpc).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
+
+        final WriteRunningTx tx = new WriteRunningTx(id,
+            new NetconfBaseOps(rpc, BASE_SCHEMAS.getBaseSchemaWithNotifications().getEffectiveModelContext()), false);
+
+        tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+        tx.commit();
+        // verify discard changes was sent
+        final InOrder inOrder = inOrder(rpc);
+        inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME),
+                NetconfBaseOps.getLockContent(NETCONF_RUNNING_QNAME));
+        inOrder.verify(rpc).invokeRpc(eq(toPath(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)),
+                any(ContainerNode.class));
+        inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME),
+                NetconfBaseOps.getUnLockContent(NETCONF_RUNNING_QNAME));
+    }
 
-        final WriteRunningTx tx = new WriteRunningTx(id, new NetconfBaseOps(rpc, NetconfMessageTransformer.BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS.getSchemaContext()),
-                false);
-        try {
-            tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
-        } catch (final Exception e) {
-            // verify discard changes was sent
-            final InOrder inOrder = inOrder(rpc);
-            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), NetconfBaseOps.getLockContent(NETCONF_RUNNING_QNAME));
-            inOrder.verify(rpc).invokeRpc(eq(toPath(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any(NormalizedNode.class));
-            inOrder.verify(rpc).invokeRpc(toPath(NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME), NetconfBaseOps.getUnLockContent(NETCONF_RUNNING_QNAME));
-            return;
-        }
+    @Test
+    public void testListenerSuccess() throws Exception {
+        doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null)))
+                .when(rpc).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
+        final WriteCandidateTx tx = new WriteCandidateTx(
+                id, new NetconfBaseOps(rpc, BASE_SCHEMAS.getBaseSchema().getEffectiveModelContext()), false);
+        final TxListener listener = mock(TxListener.class);
+        tx.addListener(listener);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+        tx.commit();
+        verify(listener).onTransactionSubmitted(tx);
+        verify(listener).onTransactionSuccessful(tx);
+        verify(listener, never()).onTransactionFailed(eq(tx), any());
+        verify(listener, never()).onTransactionCancelled(tx);
+    }
 
-        fail("Delete should fail");
+    @Test
+    public void testListenerCancellation() throws Exception {
+        doReturn(FluentFutures.immediateFluentFuture(new DefaultDOMRpcResult((NormalizedNode<?, ?>) null)))
+                .when(rpc).invokeRpc(any(SchemaPath.class), isNull());
+        final WriteCandidateTx tx = new WriteCandidateTx(
+                id, new NetconfBaseOps(rpc, BASE_SCHEMAS.getBaseSchema().getEffectiveModelContext()), false);
+        final TxListener listener = mock(TxListener.class);
+        tx.addListener(listener);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+        tx.cancel();
+        verify(listener).onTransactionCancelled(tx);
+        verify(listener, never()).onTransactionSubmitted(tx);
+        verify(listener, never()).onTransactionSuccessful(tx);
+        verify(listener, never()).onTransactionFailed(eq(tx), any());
     }
 
+    @Test
+    public void testListenerFailure() throws Exception {
+        final IllegalStateException cause = new IllegalStateException("Failed tx");
+        doReturn(FluentFutures.immediateFailedFluentFuture(cause))
+                .when(rpc).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
+        final WriteCandidateTx tx = new WriteCandidateTx(
+                id, new NetconfBaseOps(rpc, BASE_SCHEMAS.getBaseSchema().getEffectiveModelContext()), false);
+        final TxListener listener = mock(TxListener.class);
+        tx.addListener(listener);
+        tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+        tx.commit();
+        final ArgumentCaptor<Exception> excCaptor = ArgumentCaptor.forClass(Exception.class);
+        verify(listener).onTransactionSubmitted(tx);
+        verify(listener).onTransactionFailed(eq(tx), excCaptor.capture());
+        Assert.assertEquals(cause, excCaptor.getValue().getCause().getCause());
+        verify(listener, never()).onTransactionSuccessful(tx);
+        verify(listener, never()).onTransactionCancelled(tx);
+    }
 }