/* * Copyright (c) 2014 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.md.sal.dom.store.impl; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; 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.DOMStoreThreePhaseCommitCohort; import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain; 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 com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; public class InMemoryDataStoreTest { private SchemaContext schemaContext; private InMemoryDOMDataStore domStore; @Before public void setupStore() { domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor()); schemaContext = TestModel.createTestContext(); domStore.onGlobalContextUpdated(schemaContext); } @Test public void testTransactionIsolation() throws InterruptedException, ExecutionException { assertNotNull(domStore); DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction(); assertNotNull(readTx); DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); assertNotNull(writeTx); /** * * Writes /test in writeTx * */ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)); /** * * Reads /test from writeTx Read should return container. * */ ListenableFuture>> writeTxContainer = writeTx.read(TestModel.TEST_PATH); assertTrue(writeTxContainer.get().isPresent()); /** * * Reads /test from readTx Read should return Absent. * */ ListenableFuture>> readTxContainer = readTx.read(TestModel.TEST_PATH); assertFalse(readTxContainer.get().isPresent()); } @Test public void testTransactionCommit() throws InterruptedException, ExecutionException { DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); assertNotNull(writeTx); /** * * Writes /test in writeTx * */ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)); /** * * Reads /test from writeTx Read should return container. * */ ListenableFuture>> writeTxContainer = writeTx.read(TestModel.TEST_PATH); assertTrue(writeTxContainer.get().isPresent()); DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); assertThreePhaseCommit(cohort); Optional> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH) .get(); assertTrue(afterCommitRead.isPresent()); } @Test public void testTransactionAbort() throws InterruptedException, ExecutionException { DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); assertNotNull(writeTx); assertTestContainerWrite(writeTx); DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); assertTrue(cohort.canCommit().get().booleanValue()); cohort.preCommit().get(); cohort.abort().get(); Optional> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH) .get(); assertFalse(afterCommitRead.isPresent()); } @Test public void testTransactionChain() throws InterruptedException, ExecutionException { DOMStoreTransactionChain txChain = domStore.createTransactionChain(); assertNotNull(txChain); /** * We alocate new read-write transaction and write /test * * */ DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction(); assertTestContainerWrite(firstTx); /** * First transaction is marked as ready, we are able to allocate chained * transactions */ DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready(); /** * We alocate chained transaction - read transaction, note first one is * still not commited to datastore. */ DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction(); /** * * We test if we are able to read data from tx, read should not fail * since we are using chained transaction. * * */ assertTestContainerExists(secondReadTx); /** * * We alocate next transaction, which is still based on first one, but * is read-write. * */ DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction(); /** * We test existence of /test in third transaction container should * still be visible from first one (which is still uncommmited). * * */ assertTestContainerExists(thirdDeleteTx); /** * We delete node in third transaction */ thirdDeleteTx.delete(TestModel.TEST_PATH); /** * third transaction is sealed. */ DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready(); /** * We commit first transaction * */ assertThreePhaseCommit(firstWriteTxCohort); // Alocates store transacion DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction(); /** * We verify transaction is commited to store, container should exists * in datastore. */ assertTestContainerExists(storeReadTx); /** * We commit third transaction * */ assertThreePhaseCommit(thirdDeleteTxCohort); } @Test @Ignore public void testTransactionConflict() throws InterruptedException, ExecutionException { DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction(); DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction(); assertTestContainerWrite(txOne); assertTestContainerWrite(txTwo); /** * Commits transaction */ assertThreePhaseCommit(txOne.ready()); /** * Asserts that txTwo could not be commited */ assertFalse(txTwo.ready().canCommit().get()); } private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort) throws InterruptedException, ExecutionException { assertTrue(cohort.canCommit().get().booleanValue()); cohort.preCommit().get(); cohort.commit().get(); } private static Optional> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx) throws InterruptedException, ExecutionException { /** * * Writes /test in writeTx * */ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)); return assertTestContainerExists(writeTx); } /** * Reads /test from readTx Read should return container. */ private static Optional> assertTestContainerExists(final DOMStoreReadTransaction readTx) throws InterruptedException, ExecutionException { ListenableFuture>> writeTxContainer = readTx.read(TestModel.TEST_PATH); assertTrue(writeTxContainer.get().isPresent()); return writeTxContainer.get(); } }