X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fsharding%2FDistributedShardedDOMDataTreeTest.java;h=91435bed5c1efd8076ee52b59ff91ffc3f506049;hp=9841ca01250f27ef1ca0ede6fa5a28e5dd12e351;hb=20f8f30f4bbf1e982672c1f883a6a18b0e4539de;hpb=13a15f0230ccc28a2ed7212b59dc785accf97b9f diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTreeTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTreeTest.java index 9841ca0125..91435bed5c 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTreeTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/sharding/DistributedShardedDOMDataTreeTest.java @@ -36,6 +36,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletionStage; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -46,6 +48,7 @@ import org.mockito.Captor; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.opendaylight.controller.cluster.ActorSystemProvider; +import org.opendaylight.controller.cluster.access.concepts.MemberName; import org.opendaylight.controller.cluster.datastore.AbstractTest; import org.opendaylight.controller.cluster.datastore.DatastoreContext; import org.opendaylight.controller.cluster.datastore.DatastoreContext.Builder; @@ -94,6 +97,7 @@ public class DistributedShardedDOMDataTreeTest extends AbstractTest { new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(getOuterListIdFor(0).getPathArguments()) .node(TestModel.INNER_LIST_QNAME)); + private static final Set SINGLE_MEMBER = Collections.singleton(AbstractTest.MEMBER_NAME); private ActorSystem leaderSystem; @@ -307,18 +311,87 @@ public class DistributedShardedDOMDataTreeTest extends AbstractTest { } - private static Collection createInnerListMapEntries(final int amount, final String valuePrefix) { - final Collection ret = new ArrayList<>(); - for (int i = 0; i < amount; i++) { - ret.add(ImmutableNodes.mapEntryBuilder() - .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.INNER_LIST_QNAME, - QName.create(TestModel.INNER_LIST_QNAME, "name"), Integer.toString(i))) - .withChild(ImmutableNodes - .leafNode(QName.create(TestModel.INNER_LIST_QNAME, "value"), valuePrefix + "-" + i)) - .build()); + // top level shard at TEST element, with subshards on each outer-list map entry + @Test + public void testMultipleShardLevels() throws Exception { + initEmptyDatastore("config"); + + final DistributedShardRegistration testShardId = waitOnAsyncTask( + leaderShardFactory.createDistributedShard(TEST_ID, SINGLE_MEMBER), + DistributedShardedDOMDataTree.SHARD_FUTURE_TIMEOUT_DURATION); + + final ArrayList registrations = new ArrayList<>(); + final int listSize = 5; + for (int i = 0; i < listSize; i++) { + final YangInstanceIdentifier entryYID = getOuterListIdFor(i); + final CompletionStage future = leaderShardFactory.createDistributedShard( + new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, entryYID), SINGLE_MEMBER); + + registrations.add(waitOnAsyncTask(future, DistributedShardedDOMDataTree.SHARD_FUTURE_TIMEOUT_DURATION)); } - return ret; + final DOMDataTreeIdentifier rootId = + new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY); + final DOMDataTreeProducer producer = leaderShardFactory.createProducer(Collections.singletonList( + rootId)); + + DOMDataTreeCursorAwareTransaction transaction = producer.createTransaction(false); + + DOMDataTreeWriteCursor cursor = transaction.createCursor(rootId); + assertNotNull(cursor); + + final MapNode outerList = + ImmutableMapNodeBuilder.create() + .withNodeIdentifier(new NodeIdentifier(TestModel.OUTER_LIST_QNAME)).build(); + + final ContainerNode testNode = + ImmutableContainerNodeBuilder.create() + .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)) + .withChild(outerList) + .build(); + + cursor.write(testNode.getIdentifier(), testNode); + + cursor.close(); + transaction.submit().checkedGet(); + + final DOMDataTreeListener mockedDataTreeListener = mock(DOMDataTreeListener.class); + doNothing().when(mockedDataTreeListener).onDataTreeChanged(anyCollection(), anyMap()); + + final MapNode wholeList = ImmutableMapNodeBuilder.create(outerList) + .withValue(createOuterEntries(listSize, "testing-values")).build(); + + transaction = producer.createTransaction(false); + cursor = transaction.createCursor(TEST_ID); + assertNotNull(cursor); + + cursor.write(wholeList.getIdentifier(), wholeList); + cursor.close(); + + transaction.submit().checkedGet(); + + leaderShardFactory.registerListener(mockedDataTreeListener, Collections.singletonList(TEST_ID), + true, Collections.emptyList()); + + // need 6 invocations, first initial thats from the parent shard, and then each individual subshard + verify(mockedDataTreeListener, timeout(10000).times(6)).onDataTreeChanged(captorForChanges.capture(), + captorForSubtrees.capture()); + verifyNoMoreInteractions(mockedDataTreeListener); + final List>> allSubtrees = captorForSubtrees.getAllValues(); + + final Map> lastSubtree = allSubtrees.get(allSubtrees.size() - 1); + + final NormalizedNode actual = lastSubtree.get(TEST_ID); + assertNotNull(actual); + + final NormalizedNode expected = + ImmutableContainerNodeBuilder.create() + .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME)) + .withChild(ImmutableMapNodeBuilder.create(outerList) + .withValue(createOuterEntries(listSize, "testing-values")).build()) + .build(); + + assertEquals(expected, actual); } @Test @@ -381,6 +454,40 @@ public class DistributedShardedDOMDataTreeTest extends AbstractTest { } } + private static Collection createOuterEntries(final int amount, final String valuePrefix) { + final Collection ret = new ArrayList<>(); + for (int i = 0; i < amount; i++) { + ret.add(ImmutableNodes.mapEntryBuilder() + .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.OUTER_LIST_QNAME, + QName.create(TestModel.OUTER_LIST_QNAME, "id"), i)) + .withChild(ImmutableNodes + .leafNode(QName.create(TestModel.OUTER_LIST_QNAME, "id"), i)) + .withChild(createWholeInnerList(amount, "outer id: " + i + " " + valuePrefix)) + .build()); + } + + return ret; + } + + private static MapNode createWholeInnerList(final int amount, final String valuePrefix) { + return ImmutableMapNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(TestModel.INNER_LIST_QNAME)) + .withValue(createInnerListMapEntries(amount, valuePrefix)).build(); + } + + private static Collection createInnerListMapEntries(final int amount, final String valuePrefix) { + final Collection ret = new ArrayList<>(); + for (int i = 0; i < amount; i++) { + ret.add(ImmutableNodes.mapEntryBuilder() + .withNodeIdentifier(new NodeIdentifierWithPredicates(TestModel.INNER_LIST_QNAME, + QName.create(TestModel.INNER_LIST_QNAME, "name"), Integer.toString(i))) + .withChild(ImmutableNodes + .leafNode(QName.create(TestModel.INNER_LIST_QNAME, "value"), valuePrefix + "-" + i)) + .build()); + } + + return ret; + } + private static YangInstanceIdentifier getOuterListIdFor(final int id) { return TestModel.OUTER_LIST_PATH.node(new NodeIdentifierWithPredicates( TestModel.OUTER_LIST_QNAME, QName.create(TestModel.OUTER_LIST_QNAME, "id"), id));