From 7af02aeff63b4891b87643df8ff6ae8f2debcb9a Mon Sep 17 00:00:00 2001 From: Andrej Mak Date: Wed, 19 Oct 2016 10:24:36 +0200 Subject: [PATCH] Add unit tests for sal-netconf-connector transactions Change-Id: I49cbfacd1c41cb531f6fb003110721ae9cbccf0f Signed-off-by: Andrej Mak --- .../netconf/sal/tx/WriteCandidateTx.java | 30 ++---- .../netconf/sal/tx/ReadOnlyTxTest.java | 23 ++++- .../netconf/sal/tx/ReadWriteTxTest.java | 94 +++++++++++++++++++ .../connect/netconf/sal/tx/TxTestUtils.java | 66 +++++++++++++ .../sal/tx/WriteCandidateRunningTxTest.java | 93 ++++++++++++++++++ .../netconf/sal/tx/WriteCandidateTxTest.java | 64 +++++++++++++ .../netconf/sal/tx/WriteRunningTxTest.java | 44 +-------- 7 files changed, 347 insertions(+), 67 deletions(-) create mode 100644 netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java create mode 100644 netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java create mode 100644 netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java create mode 100644 netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java index 6df2239f51..e2cedbc2a4 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTx.java @@ -22,9 +22,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcFutureCallback; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; -import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; @@ -56,22 +54,6 @@ public class WriteCandidateTx extends AbstractWriteTx { private static final Logger LOG = LoggerFactory.getLogger(WriteCandidateTx.class); - private static final Function> RPC_RESULT_TO_TX_STATUS = new Function>() { - @Override - public RpcResult apply(final DOMRpcResult input) { - if (isSuccess(input)) { - return RpcResultBuilder.success(TransactionStatus.COMMITED).build(); - } else { - final RpcResultBuilder failed = RpcResultBuilder.failed(); - for (final RpcError rpcError : input.getErrors()) { - failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(), - rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause()); - } - return failed.build(); - } - } - }; - public WriteCandidateTx(final RemoteDeviceId id, final NetconfBaseOps rpc, final boolean rollbackSupport) { super(rpc, id, rollbackSupport); } @@ -85,7 +67,7 @@ public class WriteCandidateTx extends AbstractWriteTx { private void lock() { final FutureCallback lockCandidateCallback = new FutureCallback() { @Override - public void onSuccess(DOMRpcResult result) { + public void onSuccess(final DOMRpcResult result) { if (isSuccess(result)) { if (LOG.isTraceEnabled()) { LOG.trace("Lock candidate successful"); @@ -96,7 +78,7 @@ public class WriteCandidateTx extends AbstractWriteTx { } @Override - public void onFailure(Throwable t) { + public void onFailure(final Throwable t) { LOG.warn("Lock candidate operation failed. {}", t); discardChanges(); } @@ -138,16 +120,16 @@ public class WriteCandidateTx extends AbstractWriteTx { @Override public synchronized ListenableFuture> performCommit() { resultsFutures.add(netOps.commit(new NetconfRpcFutureCallback("Commit", id))); - ListenableFuture> txResult = resultsToTxStatus(); + final ListenableFuture> txResult = resultsToTxStatus(); Futures.addCallback(txResult, new FutureCallback>() { @Override - public void onSuccess(@Nullable RpcResult result) { + public void onSuccess(@Nullable final RpcResult result) { cleanupOnSuccess(); } @Override - public void onFailure(Throwable t) { + public void onFailure(final Throwable t) { // TODO If lock is cause of this failure cleanup will issue warning log // cleanup is trying to do unlock, but this will fail cleanup(); @@ -168,7 +150,7 @@ public class WriteCandidateTx extends AbstractWriteTx { final Optional defaultOperation, final String operation) { - NetconfRpcFutureCallback editConfigCallback = new NetconfRpcFutureCallback("Edit candidate", id); + final NetconfRpcFutureCallback editConfigCallback = new NetconfRpcFutureCallback("Edit candidate", id); if (defaultOperation.isPresent()) { resultsFutures.add(netOps.editConfigCandidate( diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java index 1e9c0fcd86..8d67fbc78a 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java @@ -14,9 +14,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import com.google.common.util.concurrent.Futures; - import java.net.InetSocketAddress; - +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -62,4 +61,24 @@ public class ReadOnlyTxTest { readOnlyTx.read(LogicalDatastoreType.OPERATIONAL, path); verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_QNAME)), any(NormalizedNode.class)); } + + @Test + public void testExists() throws Exception { + final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc, mock(SchemaContext.class)); + + final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196))); + + readOnlyTx.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create()); + verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME)), any(NormalizedNode.class)); + readOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, path); + verify(rpc).invokeRpc(Mockito.eq(NetconfMessageTransformUtil.toPath(NetconfMessageTransformUtil.NETCONF_GET_QNAME)), any(NormalizedNode.class)); + } + + @Test + public void testIdentifier() throws Exception { + final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc, mock(SchemaContext.class)); + final ReadOnlyTx tx1 = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196))); + final ReadOnlyTx tx2 = new ReadOnlyTx(netconfOps, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196))); + Assert.assertNotEquals(tx1.getIdentifier(), tx2.getIdentifier()); + } } \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java new file mode 100644 index 0000000000..748c210e53 --- /dev/null +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/ReadWriteTxTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 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.netconf.sal.connect.netconf.sal.tx; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +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.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +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.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +public class ReadWriteTxTest { + @Mock + private DOMDataReadTransaction delegateReadTx; + @Mock + private DOMDataWriteTransaction delegateWriteTx; + private ReadWriteTx tx; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + tx = new ReadWriteTx(delegateReadTx, delegateWriteTx); + } + + @Test + public void submit() throws Exception { + final YangInstanceIdentifier id1 = TxTestUtils.getContainerId(); + final ContainerNode containerNode = TxTestUtils.getContainerNode(); + tx.put(LogicalDatastoreType.CONFIGURATION, id1, containerNode); + verify(delegateWriteTx).put(LogicalDatastoreType.CONFIGURATION, id1, containerNode); + final YangInstanceIdentifier id2 = TxTestUtils.getLeafId(); + final LeafNode leafNode = TxTestUtils.getLeafNode(); + tx.merge(LogicalDatastoreType.CONFIGURATION, id2, leafNode); + verify(delegateWriteTx).merge(LogicalDatastoreType.CONFIGURATION, id2, leafNode); + tx.delete(LogicalDatastoreType.CONFIGURATION, id2); + verify(delegateWriteTx).delete(LogicalDatastoreType.CONFIGURATION, id2); + tx.submit(); + verify(delegateWriteTx).submit(); + } + + @Test + public void commit() throws Exception { + tx.commit(); + verify(delegateWriteTx).commit(); + } + + @Test + public void cancel() throws Exception { + tx.cancel(); + verify(delegateWriteTx).cancel(); + } + + @Test + public void read() throws Exception { + tx.read(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId()); + verify(delegateReadTx).read(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId()); + } + + @Test + public void exists() throws Exception { + final YangInstanceIdentifier id = TxTestUtils.getContainerId(); + final CheckedFuture>, ReadFailedException> resultFuture = + Futures.immediateCheckedFuture(Optional.of(TxTestUtils.getContainerNode())); + when(delegateReadTx.read(LogicalDatastoreType.CONFIGURATION, id)).thenReturn(resultFuture); + final CheckedFuture exists = tx.exists(LogicalDatastoreType.CONFIGURATION, id); + Assert.assertTrue(exists.get()); + } + + @Test + public void getIdentifier() throws Exception { + final ReadWriteTx tx2 = new ReadWriteTx(null, null); + Assert.assertNotEquals(tx.getIdentifier(), tx2.getIdentifier()); + } + +} \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java new file mode 100644 index 0000000000..4b4481e96a --- /dev/null +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/TxTestUtils.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 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.netconf.sal.connect.netconf.sal.tx; + +import com.google.common.collect.ImmutableList; +import java.io.InputStream; +import org.opendaylight.yangtools.yang.common.QName; +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.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline; + +class TxTestUtils { + + private static final QName Q_NAME_1 = QName.create("test:namespace", "2013-07-22", "c"); + private static final QName Q_NAME_2 = QName.create(Q_NAME_1, "a"); + + static YangInstanceIdentifier getContainerId() { + return YangInstanceIdentifier.builder() + .node(Q_NAME_1) + .build(); + } + + static YangInstanceIdentifier getLeafId() { + return YangInstanceIdentifier.builder() + .node(Q_NAME_1) + .node(Q_NAME_2) + .build(); + } + + static ContainerNode getContainerNode() { + return Builders.containerBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(Q_NAME_1)) + .build(); + } + + static LeafNode getLeafNode() { + return Builders.leafBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(Q_NAME_2)) + .withValue("data") + .build(); + } + + static SchemaContext parseYangStreams(final InputStream... streams) { + final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR + .newBuild(); + final SchemaContext schemaContext; + try { + schemaContext = reactor.buildEffective(ImmutableList.copyOf(streams)); + } catch (final ReactorException e) { + throw new RuntimeException("Unable to build schema context from " + streams, e); + } + return schemaContext; + } + +} diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java new file mode 100644 index 0000000000..5f3c986f68 --- /dev/null +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateRunningTxTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016 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.netconf.sal.connect.netconf.sal.tx; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_LOCK_QNAME; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_TARGET_QNAME; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId; + +import com.google.common.util.concurrent.Futures; +import java.net.InetSocketAddress; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +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.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.netconf.base._1._0.rev110601.copy.config.input.target.ConfigTarget; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +public class WriteCandidateRunningTxTest { + @Mock + private DOMRpcService rpc; + private NetconfBaseOps netconfOps; + private RemoteDeviceId id; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang")); + doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any()); + netconfOps = new NetconfBaseOps(rpc, schemaContext); + id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)); + } + + @Test + public void testSubmit() throws Exception { + final WriteCandidateRunningTx tx = new WriteCandidateRunningTx(id, netconfOps, true); + //check, if lock is called + final ContainerNode candidateLock = getLockContent(NETCONF_LOCK_QNAME, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME); + final ContainerNode runningLock = getLockContent(NETCONF_LOCK_QNAME, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME); + verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), runningLock); + verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME), candidateLock); + tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode()); + tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode()); + //check, if both edits are called + verify(rpc, times(2)).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any()); + tx.submit().get(); + //check, if unlock is called + verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT); + final ContainerNode candidateUnlock = getLockContent(NETCONF_UNLOCK_QNAME, NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME); + final ContainerNode runningUnlock = getLockContent(NETCONF_UNLOCK_QNAME, NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME); + verify(rpc).invokeRpc(SchemaPath.create(true, NETCONF_UNLOCK_QNAME), candidateUnlock); + verify(rpc).invokeRpc(SchemaPath.create(true, NETCONF_UNLOCK_QNAME), runningUnlock); + } + + private static ContainerNode getLockContent(final QName op, final QName datastore) { + final LeafNode datastoreLeaf = Builders.leafBuilder().withNodeIdentifier(toId(datastore)).build(); + final ChoiceNode choice = Builders.choiceBuilder() + .withNodeIdentifier(toId(ConfigTarget.QNAME)) + .withChild(datastoreLeaf) + .build(); + final ContainerNode target = Builders.containerBuilder() + .withNodeIdentifier(toId(NETCONF_TARGET_QNAME)) + .withChild(choice).build(); + return Builders.containerBuilder() + .withNodeIdentifier(toId(op)) + .withChild(target) + .build(); + } + +} \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java new file mode 100644 index 0000000000..321450571f --- /dev/null +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteCandidateTxTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 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.netconf.sal.connect.netconf.sal.tx; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import com.google.common.util.concurrent.Futures; +import java.net.InetSocketAddress; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +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.util.NetconfBaseOps; +import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil; +import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +public class WriteCandidateTxTest { + + @Mock + private DOMRpcService rpc; + private NetconfBaseOps netconfOps; + private RemoteDeviceId id; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang")); + doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any()); + netconfOps = new NetconfBaseOps(rpc, schemaContext); + id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)); + } + + @Test + public void testSubmit() throws Exception { + final WriteCandidateTx tx = new WriteCandidateTx(id, netconfOps, true); + //check, if lock is called + verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)), any()); + + tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode()); + tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode()); + //check, if both edits are called + verify(rpc, times(2)).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any()); + tx.submit().get(); + //check, if unlock is called + verify(rpc).invokeRpc(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT); + verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)), any()); + } + +} \ No newline at end of file diff --git a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTxTest.java b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTxTest.java index 67e390410b..9668bb158a 100644 --- a/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTxTest.java +++ b/netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/sal/tx/WriteRunningTxTest.java @@ -15,9 +15,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; -import java.io.InputStream; import java.net.InetSocketAddress; import org.junit.Before; import org.junit.Test; @@ -29,16 +27,8 @@ import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult; 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.yangtools.yang.common.QName; -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.LeafNode; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; -import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline; public class WriteRunningTxTest { @@ -50,7 +40,7 @@ public class WriteRunningTxTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - final SchemaContext schemaContext = parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang")); + final SchemaContext schemaContext = TxTestUtils.parseYangStreams(getClass().getResourceAsStream("/schemas/test-module.yang")); doReturn(Futures.immediateCheckedFuture(new DefaultDOMRpcResult())).when(rpc).invokeRpc(any(), any()); netconfOps = new NetconfBaseOps(rpc, schemaContext); id = new RemoteDeviceId("device1", InetSocketAddress.createUnresolved("0.0.0.0", 17830)); @@ -61,24 +51,8 @@ public class WriteRunningTxTest { final WriteRunningTx tx = new WriteRunningTx(id, netconfOps, true); //check, if lock is called verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_LOCK_QNAME)), any()); - final QName qName1 = QName.create("test:namespace", "2013-07-22", "c"); - final YangInstanceIdentifier yid1 = YangInstanceIdentifier.builder() - .node(qName1) - .build(); - final QName qName2 = QName.create(qName1, "a"); - final YangInstanceIdentifier yid2 = YangInstanceIdentifier.builder() - .node(qName1) - .node(qName2) - .build(); - final ContainerNode data1 = Builders.containerBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName1)) - .build(); - final LeafNode data2 = Builders.leafBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(qName2)) - .withValue("data") - .build(); - tx.put(LogicalDatastoreType.CONFIGURATION, yid1, data1); - tx.merge(LogicalDatastoreType.CONFIGURATION, yid2, data2); + tx.put(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getContainerId(), TxTestUtils.getContainerNode()); + tx.merge(LogicalDatastoreType.CONFIGURATION, TxTestUtils.getLeafId(), TxTestUtils.getLeafNode()); //check, if no edit-config is called before submit verify(rpc, never()).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME)), any()); tx.submit().get(); @@ -87,16 +61,4 @@ public class WriteRunningTxTest { //check, if unlock is called verify(rpc).invokeRpc(eq(SchemaPath.create(true, NetconfMessageTransformUtil.NETCONF_UNLOCK_QNAME)), any()); } - - private static SchemaContext parseYangStreams(final InputStream... streams) { - final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR - .newBuild(); - final SchemaContext schemaContext; - try { - schemaContext = reactor.buildEffective(ImmutableList.copyOf(streams)); - } catch (final ReactorException e) { - throw new RuntimeException("Unable to build schema context from " + streams, e); - } - return schemaContext; - } } \ No newline at end of file -- 2.36.6