import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import javax.annotation.Nonnull;
import org.junit.Test;
+import org.mockito.Mock;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
-import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor;
+import org.opendaylight.mdsal.dom.store.inmemory.DOMDataTreeShardProducer;
+import org.opendaylight.mdsal.dom.store.inmemory.DOMDataTreeShardWriteTransaction;
+import org.opendaylight.mdsal.dom.store.inmemory.WriteableDOMDataTreeShard;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
public class ShardedDOMDataWriteTransactionTest {
private static final Map<YangInstanceIdentifier, List<NormalizedNode<?, ?>>> TEST_MAP = new HashMap<>();
+ private static final DOMDataTreeIdentifier ROOT_ID =
+ new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.EMPTY);
+
+ @Mock
+ private WriteableDOMDataTreeShard rootShard;
+
+ @Mock
+ private DOMDataTreeShardProducer mockedProducer;
+
@Test
public void basicTests() throws Exception {
+
+ initMocks(this);
+
+ doReturn(new TestDOMShardWriteTransaction()).when(mockedProducer).createTransaction();
+ doReturn(mockedProducer).when(rootShard).createProducer(any(Collection.class));
+
final ShardedDOMDataTree shardedDOMDataTree =
new ShardedDOMDataTree();
- final ShardedDOMDataTreeProducer shardedDOMDataTreeProducer =
- new ShardedDOMDataTreeProducer(shardedDOMDataTree, new HashMap<>(), new HashSet<>());
- final TestDOMStoreWriteTransaction testDOMStoreWriteTransaction =
- new TestDOMStoreWriteTransaction();
- final Map<DOMDataTreeIdentifier, DOMStoreWriteTransaction> idToTransaction =
- new HashMap<>();
+ shardedDOMDataTree.registerDataTreeShard(ROOT_ID, rootShard);
final YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.of(QName.create("test"));
- idToTransaction.put(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, yangInstanceIdentifier),
- testDOMStoreWriteTransaction);
- final ShardedDOMDataWriteTransaction shardedDOMDataWriteTransaction =
- new ShardedDOMDataWriteTransaction(shardedDOMDataTreeProducer, idToTransaction);
- final ShardedDOMDataWriteTransaction otherShardedDOMDataWriteTransaction =
- new ShardedDOMDataWriteTransaction(shardedDOMDataTreeProducer, idToTransaction);
+ final DOMDataTreeProducer producer = shardedDOMDataTree.createProducer(Collections.singletonList(ROOT_ID));
+ final DOMDataTreeCursorAwareTransaction transaction = producer.createTransaction(false);
+ final DOMDataTreeWriteCursor cursor = transaction.createCursor(ROOT_ID);
+ assertNotNull(cursor);
assertFalse(TEST_MAP.containsKey(yangInstanceIdentifier));
- shardedDOMDataWriteTransaction.put(
- LogicalDatastoreType.OPERATIONAL, yangInstanceIdentifier, TestUtils.TEST_CONTAINER);
+ cursor.write(yangInstanceIdentifier.getLastPathArgument(), TestUtils.TEST_CONTAINER);
assertTrue(TEST_MAP.containsKey(yangInstanceIdentifier));
- shardedDOMDataWriteTransaction.delete(
- LogicalDatastoreType.OPERATIONAL, yangInstanceIdentifier);
+
+ cursor.delete(yangInstanceIdentifier.getLastPathArgument());
assertFalse(TEST_MAP.containsKey(yangInstanceIdentifier));
- shardedDOMDataWriteTransaction.merge(
- LogicalDatastoreType.OPERATIONAL, yangInstanceIdentifier, TestUtils.TEST_CONTAINER);
+
+ cursor.merge(yangInstanceIdentifier.getLastPathArgument(), TestUtils.TEST_CONTAINER);
assertTrue(TEST_MAP.get(yangInstanceIdentifier).contains(TestUtils.TEST_CONTAINER));
try {
- shardedDOMDataWriteTransaction.put(
- LogicalDatastoreType.CONFIGURATION, yangInstanceIdentifier, TestUtils.TEST_CONTAINER);
- fail("Expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- assertTrue(e.getMessage().contains(LogicalDatastoreType.CONFIGURATION.toString()));
+ producer.createTransaction(false);
+ fail("Should have failed, there's still a tx open");
+ } catch (final IllegalStateException e) {
+ assertTrue(e.getMessage().contains("open"));
+ }
+
+ cursor.close();
+ try {
+ transaction.createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY));
+ fail("Should have failed, config ds not available to this tx");
+ } catch (final IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("not accessible"));
}
- shardedDOMDataTreeProducer.createTransaction(true);
- assertTrue(shardedDOMDataWriteTransaction.cancel());
- assertFalse(shardedDOMDataWriteTransaction.cancel());
+ assertTrue(transaction.cancel());
+ assertFalse(transaction.cancel());
- assertTrue(shardedDOMDataWriteTransaction.getIdentifier().matches("^SHARDED-DOM-\\d$"));
- assertNotEquals(shardedDOMDataWriteTransaction.getIdentifier(),
- otherShardedDOMDataWriteTransaction.getIdentifier());
+ final DOMDataTreeCursorAwareTransaction newTx = producer.createTransaction(false);
+ assertTrue("Transaction identifier incorrect " + transaction.getIdentifier(), ((String) transaction.getIdentifier()).contains("SHARDED-DOM-"));
+ assertNotEquals(transaction.getIdentifier(),
+ newTx.getIdentifier());
}
- private final class TestDOMStoreWriteTransaction implements DOMStoreWriteTransaction {
+ private final class TestDOMShardWriteTransaction implements DOMDataTreeShardWriteTransaction {
+
+ @Nonnull
+ @Override
+ public DOMDataTreeWriteCursor createCursor(@Nonnull final DOMDataTreeIdentifier prefix) {
+ return new TestCursor();
+ }
@Override
- public void write(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
- List<NormalizedNode<?, ?>> dataList = TEST_MAP.get(path);
- if(dataList == null) dataList = new ArrayList<>();
- dataList.add(data);
- TEST_MAP.put(path, dataList);
+ public void ready() {
+
}
@Override
- public void merge(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
- List<NormalizedNode<?, ?>> dataList = TEST_MAP.get(path);
- if(dataList == null) dataList = new ArrayList<>();
- dataList.add(data);
- TEST_MAP.put(path, dataList);
+ public void close() {
+
}
@Override
- public void delete(YangInstanceIdentifier path) {
- TEST_MAP.remove(path);
+ public ListenableFuture<Void> submit() {
+ return null;
}
@Override
- public DOMStoreThreePhaseCommitCohort ready() {
+ public ListenableFuture<Boolean> validate() {
return null;
}
@Override
- public Object getIdentifier() {
+ public ListenableFuture<Void> prepare() {
return null;
}
+ @Override
+ public ListenableFuture<Void> commit() {
+ return null;
+ }
+ }
+
+ private final class TestCursor implements DOMDataTreeWriteCursor {
+
+ private final Deque<PathArgument> stack = new ArrayDeque<>();
+
+ @Override
+ public void delete(final PathArgument child) {
+ final ArrayDeque<PathArgument> newPath = new ArrayDeque<>(stack);
+ newPath.push(child);
+ TEST_MAP.remove(YangInstanceIdentifier.create(newPath));
+ }
+
+ @Override
+ public void merge(final PathArgument child, final NormalizedNode<?, ?> data) {
+ final ArrayDeque<PathArgument> newPath = new ArrayDeque<>(stack);
+ newPath.push(child);
+ final List<NormalizedNode<?, ?>> dataList = TEST_MAP.get(YangInstanceIdentifier.create(newPath));
+ if (dataList != null) {
+ dataList.add(data);
+ } else {
+ TEST_MAP.put(YangInstanceIdentifier.create(newPath), Lists.newArrayList(data));
+ }
+ }
+
+ @Override
+ public void write(final PathArgument child, final NormalizedNode<?, ?> data) {
+ final ArrayDeque<PathArgument> newPath = new ArrayDeque<>(stack);
+ newPath.push(child);
+ TEST_MAP.put(YangInstanceIdentifier.create(newPath), Lists.newArrayList(data));
+ }
+
+ @Override
+ public void enter(@Nonnull final PathArgument child) {
+ stack.push(child);
+ }
+
+ @Override
+ public void enter(@Nonnull final PathArgument... path) {
+ for (final PathArgument pathArgument : path) {
+ stack.push(pathArgument);
+ }
+ }
+
+ @Override
+ public void enter(@Nonnull final Iterable<PathArgument> path) {
+ path.forEach(stack::push);
+ }
+
+ @Override
+ public void exit() {
+ stack.pop();
+ }
+
+ @Override
+ public void exit(final int depth) {
+ stack.pop();
+ }
+
@Override
public void close() {
- // NOOP
+
}
}
}
\ No newline at end of file