/* * Copyright (c) 2017 Red Hat, 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.mdsal.binding.util; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_FOO_KEY; import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path; import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList; import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL; import java.io.IOException; import java.util.Optional; import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.ReadTransaction; import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest; import org.opendaylight.mdsal.binding.testutils.DataBrokerFailuresImpl; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.mdsal.common.api.OptimisticLockFailedException; import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugmentBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /** * Test for {@link ManagedNewTransactionRunnerImpl}. * * @author Michael Vorburger.ch * @author Stephen Kitt */ public class ManagedNewTransactionRunnerImplTest extends AbstractConcurrentDataBrokerTest { static final InstanceIdentifier TEST_PATH = path(TOP_FOO_KEY); DataBrokerFailuresImpl testableDataBroker; ManagedNewTransactionRunner managedNewTransactionRunner; public ManagedNewTransactionRunnerImplTest() { super(true); } protected ManagedNewTransactionRunner createManagedNewTransactionRunnerToTest(DataBroker dataBroker) { return new ManagedNewTransactionRunnerImpl(dataBroker); } @Before public void beforeTest() throws Exception { setup(); testableDataBroker = new DataBrokerFailuresImpl(getDataBroker()); managedNewTransactionRunner = createManagedNewTransactionRunnerToTest(testableDataBroker); } @Test public void testApplyWithNewReadTransactionAndCloseEmptySuccessfully() { assertEquals(Long.valueOf(1), managedNewTransactionRunner.applyWithNewReadOnlyTransactionAndClose(OPERATIONAL, tx -> 1L)); } @Test public void testCallWithNewReadTransactionAndCloseEmptySuccessfully() { managedNewTransactionRunner.callWithNewReadOnlyTransactionAndClose(OPERATIONAL, tx -> { }); } @Test public void testCallWithNewTypedWriteOnlyTransactionAndSubmitEmptySuccessfully() throws Exception { managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeTx -> { }).get(); } @Test public void testCallWithNewTypedReadWriteTransactionAndSubmitEmptySuccessfully() throws Exception { managedNewTransactionRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { }).get(); } @Test public void testApplyWithNewReadWriteTransactionAndSubmitEmptySuccessfully() throws Exception { assertEquals(1, (long) managedNewTransactionRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> 1).get()); } @Test public void testCallWithNewTypedWriteOnlyTransactionAndSubmitPutSuccessfully() throws Exception { TopLevelList data = newTestDataObject(); managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeTx -> writeTx.put(TEST_PATH, data)).get(); assertEquals(data, syncRead(LogicalDatastoreType.OPERATIONAL, TEST_PATH)); } @Test public void testCallWithNewTypedReadWriteTransactionAndSubmitPutSuccessfully() throws Exception { TopLevelList data = newTestDataObject(); managedNewTransactionRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> tx.put(TEST_PATH, data)).get(); assertEquals(data, syncRead(LogicalDatastoreType.OPERATIONAL, TEST_PATH)); } @Test public void testApplyWithNewReadWriteTransactionAndSubmitPutSuccessfully() throws Exception { TopLevelList data = newTestDataObject(); assertEquals(1, (long) managedNewTransactionRunner.applyWithNewReadWriteTransactionAndSubmit( OPERATIONAL, tx -> { tx.put(TEST_PATH, data); return 1; }).get()); assertEquals(data, syncRead(LogicalDatastoreType.OPERATIONAL, TEST_PATH)); } @Test public void testCallWithNewReadTransactionAndCloseReadSuccessfully() throws Exception { TopLevelList data = newTestDataObject(); managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> tx.put(TEST_PATH, data)).get(); assertEquals(data, managedNewTransactionRunner.applyWithNewReadOnlyTransactionAndClose(OPERATIONAL, tx -> tx.read(TEST_PATH)).get().get()); } TopLevelList newTestDataObject() { TreeComplexUsesAugment fooAugment = new TreeComplexUsesAugmentBuilder() .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build()).build(); return topLevelList(TOP_FOO_KEY, fooAugment); } @Test public void testCallWithNewTypedWriteOnlyTransactionAndSubmitPutButLaterException() throws Exception { try { managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeTx -> { writeTx.put(TEST_PATH, newTestDataObject()); // We now throw an arbitrary kind of checked (not unchecked!) exception here throw new IOException("something didn't quite go as expected..."); }).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof IOException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testCallWithNewTypedReadWriteTransactionAndSubmitPutButLaterException() throws Exception { try { managedNewTransactionRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> { writeTx.put(TEST_PATH, newTestDataObject()); // We now throw an arbitrary kind of checked (not unchecked!) exception here throw new IOException("something didn't quite go as expected..."); }).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof IOException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testApplyWithNewReadWriteTransactionAndSubmitPutButLaterException() throws Exception { try { managedNewTransactionRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> { writeTx.put(TEST_PATH, newTestDataObject()); // We now throw an arbitrary kind of checked (not unchecked!) exception here throw new IOException("something didn't quite go as expected..."); }).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof IOException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testCallWithNewTypedWriteOnlyTransactionCommitFailedException() throws Exception { try { testableDataBroker.failCommits(new TransactionCommitFailedException("bada boum bam!")); managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeTx -> writeTx.put(TEST_PATH, newTestDataObject())).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TransactionCommitFailedException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testCallWithNewTypedReadWriteTransactionCommitFailedException() throws Exception { try { testableDataBroker.failCommits(new TransactionCommitFailedException("bada boum bam!")); managedNewTransactionRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> writeTx.put(TEST_PATH, newTestDataObject())).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TransactionCommitFailedException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testApplyWithNewReadWriteTransactionCommitFailedException() throws Exception { try { testableDataBroker.failCommits(new TransactionCommitFailedException("bada boum bam!")); managedNewTransactionRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> { writeTx.put(TEST_PATH, newTestDataObject()); return 1; }).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TransactionCommitFailedException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testCallWithNewTypedWriteOnlyTransactionOptimisticLockFailedException() throws Exception { try { testableDataBroker.failCommits(2, new OptimisticLockFailedException("bada boum bam!")); managedNewTransactionRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeTx -> writeTx.put(TEST_PATH, newTestDataObject())).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof OptimisticLockFailedException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testCallWithNewTypedReadWriteTransactionOptimisticLockFailedException() throws Exception { try { testableDataBroker.failCommits(2, new OptimisticLockFailedException("bada boum bam!")); managedNewTransactionRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> writeTx.put(TEST_PATH, newTestDataObject())).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof OptimisticLockFailedException); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } @Test public void testApplyWithNewReadWriteTransactionOptimisticLockFailedException() throws Exception { try { testableDataBroker.failCommits(2, new OptimisticLockFailedException("bada boum bam!")); managedNewTransactionRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL, writeTx -> { writeTx.put(TEST_PATH, newTestDataObject()); return 1; }).get(); fail("This should have led to an ExecutionException!"); } catch (ExecutionException e) { assertThat(e.getCause() instanceof OptimisticLockFailedException).isTrue(); } assertThat(syncReadOptional(LogicalDatastoreType.OPERATIONAL, TEST_PATH)).isEmpty(); } private Optional syncReadOptional(LogicalDatastoreType datastoreType, InstanceIdentifier path) throws ExecutionException, InterruptedException { try (ReadTransaction tx = getDataBroker().newReadOnlyTransaction()) { return tx.read(datastoreType, path).get(); } } T syncRead(LogicalDatastoreType datastoreType, InstanceIdentifier path) throws ExecutionException, InterruptedException { return syncReadOptional(datastoreType, path).get(); } }