From af2b9832ea22ea7a5e45dc3dd4424c816505ce1e Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 4 Mar 2016 12:32:10 +0100 Subject: Data-tree based DataBroker for Honeycomb agent. Change-Id: I2cda490bfc47d748052587066b3f63d5c27d518c Signed-off-by: Marek Gradzki --- .../v3po/impl/data/ReadWriteTransaction.java | 101 ++++++++++++++ .../fd/honeycomb/v3po/impl/data/VppDataBroker.java | 95 ++++++++++++++ .../v3po/impl/data/VppReadOnlyTransaction.java | 103 +++++++++++++++ .../v3po/impl/data/VppWriteTransaction.java | 145 +++++++++++++++++++++ .../v3po/impl/data/ReadWriteTransactionTest.java | 111 ++++++++++++++++ .../v3po/impl/data/VppDataBrokerTest.java | 108 +++++++++++++++ .../v3po/impl/data/VppReadOnlyTransactionTest.java | 66 ++++++++++ .../v3po/impl/data/VppWriteTransactionTest.java | 134 +++++++++++++++++++ 8 files changed, 863 insertions(+) create mode 100644 v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransaction.java create mode 100644 v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBroker.java create mode 100644 v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransaction.java create mode 100644 v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransactionTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransactionTest.java create mode 100644 v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransactionTest.java diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransaction.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransaction.java new file mode 100644 index 000000000..7faeba54a --- /dev/null +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransaction.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +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.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Composite DOM transaction that delegates reads to a {@link DOMDataReadTransaction} delegate and writes to a {@link + * DOMDataWriteTransaction} delegate. + */ +final class ReadWriteTransaction implements DOMDataReadWriteTransaction { + + private final DOMDataReadOnlyTransaction delegateReadTx; + private final DOMDataWriteTransaction delegateWriteTx; + + ReadWriteTransaction(@Nonnull final DOMDataReadOnlyTransaction delegateReadTx, + @Nonnull final DOMDataWriteTransaction delegateWriteTx) { + this.delegateReadTx = Preconditions.checkNotNull(delegateReadTx, "delegateReadTx should not be null"); + this.delegateWriteTx = Preconditions.checkNotNull(delegateWriteTx, "delegateWriteTx should not be null"); + } + + @Override + public boolean cancel() { + delegateReadTx.close(); + return delegateWriteTx.cancel(); + } + + @Override + public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, + final NormalizedNode data) { + delegateWriteTx.put(store, path, data); + } + + @Override + public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, + final NormalizedNode data) { + delegateWriteTx.merge(store, path, data); + } + + @Override + public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) { + delegateWriteTx.delete(store, path); + } + + @Override + public CheckedFuture submit() { + return delegateWriteTx.submit(); + } + + @Override + public ListenableFuture> commit() { + return delegateWriteTx.commit(); + } + + @Override + public CheckedFuture>, ReadFailedException> read(final LogicalDatastoreType store, + final YangInstanceIdentifier path) { + return delegateReadTx.read(store, path); + } + + @Override + public CheckedFuture exists(final LogicalDatastoreType store, + final YangInstanceIdentifier path) { + return delegateReadTx.exists(store, path); + } + + @Override + public Object getIdentifier() { + return this; + } +} + diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBroker.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBroker.java new file mode 100644 index 000000000..97697da65 --- /dev/null +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppDataBroker.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.Map; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Data Broker which provides data transaction functionality for VPP using {@link NormalizedNode} data format. + */ +public class VppDataBroker implements DOMDataBroker { + + private final ReadableVppDataTree operationalData; + private final VppDataTree configDataTree; + + /** + * Creates VppDataBroker instance. + * + * @param operationalData VPP operational data + * @param configDataTree VPP configuration data + */ + public VppDataBroker(@Nonnull final ReadableVppDataTree operationalData, + @Nonnull final VppDataTree configDataTree) { + this.operationalData = Preconditions.checkNotNull(operationalData, "operationalData should not be null"); + this.configDataTree = Preconditions.checkNotNull(configDataTree, "configDataProxy should not be null"); + } + + @Override + public DOMDataReadOnlyTransaction newReadOnlyTransaction() { + return new VppReadOnlyTransaction(operationalData, configDataTree.takeSnapshot()); + } + + @Override + public DOMDataReadWriteTransaction newReadWriteTransaction() { + // todo use the same snapshot + final VppDataTreeSnapshot configSnapshot = configDataTree.takeSnapshot(); + final DOMDataReadOnlyTransaction readOnlyTx = new VppReadOnlyTransaction(operationalData, configSnapshot); + final DOMDataWriteTransaction writeOnlyTx = new VppWriteTransaction(configDataTree, configSnapshot); + return new ReadWriteTransaction(readOnlyTx, writeOnlyTx); + } + + @Override + public DOMDataWriteTransaction newWriteOnlyTransaction() { + return new VppWriteTransaction(configDataTree); + } + + @Override + public ListenerRegistration registerDataChangeListener(final LogicalDatastoreType store, + final YangInstanceIdentifier path, + final DOMDataChangeListener listener, + final DataChangeScope triggeringScope) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) { + throw new UnsupportedOperationException("Not supported"); + } + + @Nonnull + @Override + public Map, DOMDataBrokerExtension> getSupportedExtensions() { + return Collections.emptyMap(); + } +} + + diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransaction.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransaction.java new file mode 100644 index 000000000..94cef679f --- /dev/null +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransaction.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +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.DOMDataReadOnlyTransaction; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class VppReadOnlyTransaction implements DOMDataReadOnlyTransaction { + + private static final Logger LOG = LoggerFactory.getLogger(VppReadOnlyTransaction.class); + private volatile ReadableVppDataTree operationalData; + private volatile VppDataTreeSnapshot configSnapshot; + + VppReadOnlyTransaction(@Nonnull final ReadableVppDataTree operationalData, + @Nonnull final VppDataTreeSnapshot configSnapshot) { + this.operationalData = Preconditions.checkNotNull(operationalData, "operationalData should not be null"); + this.configSnapshot = Preconditions.checkNotNull(configSnapshot, "config should not be null"); + } + + @Override + public void close() { + configSnapshot = null; + operationalData = null; + } + + @Override + public CheckedFuture>, ReadFailedException> read( + final LogicalDatastoreType store, + final YangInstanceIdentifier path) { + LOG.debug("VppReadOnlyTransaction.read(), store={}, path={}", store, path); + + Preconditions.checkState(configSnapshot != null, "Transaction was closed"); + + if (store == LogicalDatastoreType.OPERATIONAL) { + return operationalData.read(path); + } else { + return configSnapshot.read(path); + } + } + + @Override + public CheckedFuture exists(final LogicalDatastoreType store, + final YangInstanceIdentifier path) { + LOG.debug("VppReadOnlyTransaction.exists() store={}, path={}", store, path); + + ListenableFuture listenableFuture = Futures.transform(read(store, path), IS_NODE_PRESENT); + + return Futures.makeChecked(listenableFuture, ANY_EX_TO_READ_FAILED_EXCEPTION_MAPPER); + } + + @Nonnull + @Override + public Object getIdentifier() { + return this; + } + + + private static final Function>, ? extends Boolean> IS_NODE_PRESENT = + new Function>, Boolean>() { + @Nullable + @Override + public Boolean apply(@Nullable final Optional> input) { + return input == null + ? Boolean.FALSE + : input.isPresent(); + } + }; + + private static final Function ANY_EX_TO_READ_FAILED_EXCEPTION_MAPPER = + new Function() { + @Override + public ReadFailedException apply(@Nullable final Exception e) { + return new ReadFailedException("Exists failed", e); + } + }; +} \ No newline at end of file diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java new file mode 100644 index 000000000..b7aa2f854 --- /dev/null +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransaction.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.CANCELED; +import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.COMMITED; +import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.FAILED; +import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW; +import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.SUBMITED; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import io.fd.honeycomb.v3po.impl.trans.VppApiInvocationException; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.NotThreadSafe; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +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.DOMDataWriteTransaction; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@NotThreadSafe +final class VppWriteTransaction implements DOMDataWriteTransaction { + + private static final Logger LOG = LoggerFactory.getLogger(VppWriteTransaction.class); + private final VppDataTree configDataTree; + private DataTreeModification modification; + private TransactionStatus status; + + VppWriteTransaction(@Nonnull final VppDataTree configDataTree, + @Nonnull final VppDataTreeSnapshot configSnapshot) { + this.configDataTree = Preconditions.checkNotNull(configDataTree, "configDataTree should not be null"); + Preconditions.checkNotNull(configSnapshot, "configSnapshot should not be null"); + // initialize transaction state: + modification = configSnapshot.newModification(); + status = NEW; + } + + VppWriteTransaction(@Nonnull final VppDataTree configDataTree) { + this(configDataTree, configDataTree.takeSnapshot()); + } + + private static void checkConfigurationWrite(final LogicalDatastoreType store) { + Preconditions.checkArgument(LogicalDatastoreType.CONFIGURATION == store, "Write is not supported for operational data store"); + } + + private void checkIsNew() { + Preconditions.checkState(status == NEW, "Transaction was submitted or canceled"); + Preconditions.checkState(modification != null, "VPPDataTree modification should not be null"); + } + + @Override + public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, + final NormalizedNode data) { + LOG.debug("VppWriteTransaction.put() store={}, path={}, data={}", store, path, data); + checkIsNew(); + checkConfigurationWrite(store); + modification.write(path, data); + } + + @Override + public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, + final NormalizedNode data) { + LOG.debug("VppWriteTransaction.merge() store={}, path={}, data={}", store, path, data); + checkIsNew(); + checkConfigurationWrite(store); + modification.merge(path, data); + } + + @Override + public boolean cancel() { + if (status != NEW) { + // only NEW transactions can be cancelled + return false; + } else { + status = CANCELED; + modification = null; + return true; + } + } + + @Override + public void delete(LogicalDatastoreType store, final YangInstanceIdentifier path) { + LOG.debug("VppWriteTransaction.delete() store={}, path={}", store, path); + checkIsNew(); + checkConfigurationWrite(store); + modification.delete(path); + } + + @Override + public CheckedFuture submit() { + LOG.debug("VppWriteTransaction.submit()"); + checkIsNew(); + + // seal transaction: + modification.ready(); + status = SUBMITED; + + try { + configDataTree.commit(modification); + status = COMMITED; + } catch (DataValidationFailedException | VppApiInvocationException e) { + status = FAILED; + LOG.error("Failed to commit VPP state modification", e); + return Futures.immediateFailedCheckedFuture( + new TransactionCommitFailedException("Failed to validate DataTreeModification", e)); + } finally { + modification = null; + } + return Futures.immediateCheckedFuture(null); + } + + @Override + @Deprecated + public ListenableFuture> commit() { + throw new UnsupportedOperationException("deprecated"); + } + + @Override + public Object getIdentifier() { + return this; + } +} diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransactionTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransactionTest.java new file mode 100644 index 000000000..f0fd66de5 --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/ReadWriteTransactionTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +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.NormalizedNode; + +public class ReadWriteTransactionTest { + + @Mock + private DOMDataReadOnlyTransaction readTx; + + @Mock + private DOMDataWriteTransaction writeTx; + + private LogicalDatastoreType store; + + @Mock + private YangInstanceIdentifier path; + + @Mock + private NormalizedNode data; + + private ReadWriteTransaction readWriteTx; + + @Before + public void setUp() { + initMocks(this); + store = LogicalDatastoreType.CONFIGURATION; + readWriteTx = new ReadWriteTransaction(readTx, writeTx); + } + + @Test + public void testCancel() { + readWriteTx.cancel(); + verify(writeTx).cancel(); + } + + @Test + public void testPut() { + readWriteTx.put(store, path, data); + verify(writeTx).put(store, path, data); + } + + @Test + public void testMerge() { + readWriteTx.merge(store, path, data); + verify(writeTx).merge(store, path, data); + } + + @Test + public void testDelete() { + readWriteTx.delete(store, path); + verify(writeTx).delete(store, path); + } + + @Test + public void testSubmit() throws Exception { + readWriteTx.submit(); + verify(writeTx).submit(); + } + + + @SuppressWarnings("deprecation") + @Test + public void testCommit() throws Exception { + readWriteTx.commit(); + verify(writeTx).commit(); + } + + @Test + public void testRead() { + readWriteTx.read(store, path); + verify(readTx).read(store, path); + } + + @Test + public void testExists() { + readWriteTx.exists(store, path); + verify(readTx).exists(store, path); + } + + @Test + public void testGetIdentifier() throws Exception { + assertNotNull(readWriteTx.getIdentifier()); + } +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerTest.java new file mode 100644 index 000000000..2550f458b --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppDataBrokerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; +import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class VppDataBrokerTest { + + @Mock + private ReadableVppDataTree operationalData; + @Mock + private VppDataTree confiDataTree; + @Mock + private VppDataTreeSnapshot configSnapshot; + private VppDataBroker broker; + + @Before + public void setUp() { + initMocks(this); + when(confiDataTree.takeSnapshot()).thenReturn(configSnapshot); + broker = new VppDataBroker(operationalData, confiDataTree); + } + + @Test + public void testNewReadWriteTransaction() { + final DOMDataReadWriteTransaction readWriteTx = broker.newReadWriteTransaction(); + final YangInstanceIdentifier path = mock(YangInstanceIdentifier.class); + readWriteTx.read(LogicalDatastoreType.CONFIGURATION, path); + + // verify that read and write transactions use the same config snapshot + verify(configSnapshot).read(path); + verify(configSnapshot).newModification(); + } + + @Test + public void testNewWriteOnlyTransaction() { + final DOMDataWriteTransaction writeTx = broker.newWriteOnlyTransaction(); + + // verify that write transactions use config snapshot + verify(configSnapshot).newModification(); + } + + @Test + public void testNewReadOnlyTransaction() { + final DOMDataReadOnlyTransaction readTx = broker.newReadOnlyTransaction(); + + final YangInstanceIdentifier path = mock(YangInstanceIdentifier.class); + readTx.read(LogicalDatastoreType.CONFIGURATION, path); + + // verify that read transactions use config snapshot + verify(configSnapshot).read(path); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRegisterDataChangeListener() { + final YangInstanceIdentifier path = mock(YangInstanceIdentifier.class); + final DOMDataChangeListener listener = mock(DOMDataChangeListener.class); + broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, path, listener, + AsyncDataBroker.DataChangeScope.BASE); + } + + @Test(expected = UnsupportedOperationException.class) + public void testCreateTransactionChain() { + final TransactionChainListener listener = mock(TransactionChainListener.class); + broker.createTransactionChain(listener); + } + + @Test + public void testGetSupportedExtensions() { + final Map, DOMDataBrokerExtension> supportedExtensions = + broker.getSupportedExtensions(); + assertTrue(supportedExtensions.isEmpty()); + } + + +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransactionTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransactionTest.java new file mode 100644 index 000000000..5a8a1f72b --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppReadOnlyTransactionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +public class VppReadOnlyTransactionTest { + + @Mock + private ReadableVppDataTree operationalData; + @Mock + private VppDataTreeSnapshot configSnapshot; + + private VppReadOnlyTransaction readOnlyTx; + + @Before + public void setUp() { + initMocks(this); + readOnlyTx = new VppReadOnlyTransaction(operationalData, configSnapshot); + } + + @Test + public void testExists() { + final YangInstanceIdentifier path = mock(YangInstanceIdentifier.class); + final CheckedFuture>, ReadFailedException> + future = mock(CheckedFuture.class); + when(operationalData.read(path)).thenReturn(future); + + readOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, path); + + verify(operationalData).read(path); + } + + @Test + public void testGetIdentifier() { + assertNotNull(readOnlyTx.getIdentifier()); + } +} \ No newline at end of file diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransactionTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransactionTest.java new file mode 100644 index 000000000..905224216 --- /dev/null +++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/data/VppWriteTransactionTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.data; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.util.concurrent.CheckedFuture; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; + +public class VppWriteTransactionTest { + + @Mock + private VppDataTree configDataTree; + @Mock + private VppDataTreeSnapshot configSnapshot; + @Mock + private YangInstanceIdentifier path; + @Mock + private NormalizedNode data; + @Mock + private DataTreeModification dataTreeModification; + + private VppWriteTransaction writeTx; + + @Before + public void setUp() { + initMocks(this); + when(configSnapshot.newModification()).thenReturn(dataTreeModification); + writeTx = new VppWriteTransaction(configDataTree, configSnapshot); + } + + @Test + public void testPut() { + writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data); + verify(dataTreeModification).write(path, data); + } + + @Test(expected = IllegalArgumentException.class) + public void testPutOperational() { + writeTx.put(LogicalDatastoreType.OPERATIONAL, path, data); + verify(dataTreeModification).write(path, data); + } + + @Test(expected = IllegalStateException.class) + public void testOnFinishedTx() { + writeTx.submit(); + writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data); + verify(dataTreeModification).write(path, data); + } + + @Test + public void testMerge() { + writeTx.merge(LogicalDatastoreType.CONFIGURATION, path, data); + verify(dataTreeModification).merge(path, data); + } + + @Test + public void testCancel() { + assertTrue(writeTx.cancel()); + } + + @Test + public void testCancelFinished() { + writeTx.submit(); + assertFalse(writeTx.cancel()); + } + + @Test + public void testDelete() { + writeTx.delete(LogicalDatastoreType.CONFIGURATION, path); + verify(dataTreeModification).delete(path); + } + + @Test + public void testSubmit() throws Exception { + writeTx.submit(); + verify(dataTreeModification).ready(); + verify(configDataTree).commit(dataTreeModification); + } + + @Test + public void testSubmitFailed() throws Exception { + doThrow(mock(DataValidationFailedException.class)).when(configDataTree).commit(dataTreeModification); + final CheckedFuture future = writeTx.submit(); + try { + future.get(); + } catch (Exception e) { + assertTrue(e.getCause() instanceof TransactionCommitFailedException); + return; + } + fail("Expected exception to be thrown"); + + } + + @Test(expected = UnsupportedOperationException.class) + public void testCommit() { + writeTx.commit(); + } + + @Test + public void testGetIdentifier() { + assertNotNull(writeTx.getIdentifier()); + } +} \ No newline at end of file -- cgit 1.2.3-korg