From: Tibor Král Date: Thu, 21 May 2020 16:27:08 +0000 (+0200) Subject: Add tests for new RootDataTreeChangeListenerProxy and Actor X-Git-Tag: v2.0.1~13 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=4152b84fbf3d8d5436467f96076c6fb6a0f2ae4a Add tests for new RootDataTreeChangeListenerProxy and Actor Listening on root with multiple shards is not tested anywhere, add some test coverage. JIRA: CONTROLLER-1932 Change-Id: Ie0d94f2d9b90869a140b73d85f1696df712fad25 Signed-off-by: Tibor Král Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerActor.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerActor.java index 963dea98af..8a826ef67a 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerActor.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerActor.java @@ -133,6 +133,6 @@ final class RootDataTreeChangeListenerActor extends DataTreeChangeListenerActor } static Props props(final DOMDataTreeChangeListener instance, final int shardCount) { - return Props.create(RootDataTreeChangeListenerActor.class, shardCount); + return Props.create(RootDataTreeChangeListenerActor.class, instance, shardCount); } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerProxyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerProxyTest.java new file mode 100644 index 0000000000..7fea757d39 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/RootDataTreeChangeListenerProxyTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.cluster.datastore; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import akka.actor.ActorRef; +import akka.testkit.javadsl.TestKit; +import com.google.common.collect.ImmutableList; +import java.time.Duration; +import java.util.List; +import java.util.Set; +import org.junit.Test; +import org.opendaylight.controller.cluster.datastore.config.Configuration; +import org.opendaylight.controller.cluster.datastore.exceptions.NotInitializedException; +import org.opendaylight.controller.cluster.datastore.messages.DataTreeChanged; +import org.opendaylight.controller.cluster.datastore.messages.EnableNotification; +import org.opendaylight.controller.cluster.datastore.messages.FindLocalShard; +import org.opendaylight.controller.cluster.datastore.messages.LocalShardFound; +import org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeChangeListener; +import org.opendaylight.controller.cluster.datastore.messages.RegisterDataTreeNotificationListenerReply; +import org.opendaylight.controller.cluster.datastore.utils.ActorUtils; +import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel; +import org.opendaylight.mdsal.dom.api.ClusteredDOMDataTreeChangeListener; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates; + +public class RootDataTreeChangeListenerProxyTest extends AbstractActorTest { + + @Test(timeout = 10000) + public void testSuccessfulRegistrationOnTwoShards() { + final TestKit kit = new TestKit(getSystem()); + ActorUtils actorUtils = new ActorUtils(getSystem(), kit.getRef(), mock(ClusterWrapper.class), + mock(Configuration.class)); + + ClusteredDOMDataTreeChangeListener mockClusteredListener = mock( + ClusteredDOMDataTreeChangeListener.class); + + final YangInstanceIdentifier path = YangInstanceIdentifier.empty(); + final RootDataTreeChangeListenerProxy rootListenerProxy = + new RootDataTreeChangeListenerProxy<>(actorUtils, mockClusteredListener, + Set.of("shard-1", "shard-2")); + + final Duration timeout = Duration.ofSeconds(5); + FindLocalShard findLocalShard1 = kit.expectMsgClass(FindLocalShard.class); + kit.reply(new LocalShardFound(kit.getRef())); + FindLocalShard findLocalShard2 = kit.expectMsgClass(FindLocalShard.class); + kit.reply(new LocalShardFound(kit.getRef())); + assertTrue(List.of(findLocalShard1.getShardName(), findLocalShard2.getShardName()) + .containsAll(List.of("shard-2", "shard-1"))); + + RegisterDataTreeChangeListener registerForShard1 = kit.expectMsgClass(timeout, + RegisterDataTreeChangeListener.class); + assertEquals("getPath", path, registerForShard1.getPath()); + assertTrue("isRegisterOnAllInstances", registerForShard1.isRegisterOnAllInstances()); + + kit.reply(new RegisterDataTreeNotificationListenerReply(kit.getRef())); + + RegisterDataTreeChangeListener registerForShard2 = kit.expectMsgClass(timeout, + RegisterDataTreeChangeListener.class); + assertEquals("getPath", path, registerForShard2.getPath()); + assertTrue("isRegisterOnAllInstances", registerForShard2.isRegisterOnAllInstances()); + + kit.reply(new RegisterDataTreeNotificationListenerReply(kit.getRef())); + + assertEquals(registerForShard1.getListenerActorPath(), registerForShard2.getListenerActorPath()); + + final TestKit kit2 = new TestKit(getSystem()); + final ActorRef rootListenerActor = getSystem().actorFor(registerForShard1.getListenerActorPath()); + rootListenerActor.tell(new EnableNotification(true, "test"), kit.getRef()); + final DataTreeCandidate peopleCandidate = DataTreeCandidates.fromNormalizedNode(YangInstanceIdentifier.empty(), + PeopleModel.create()); + rootListenerActor.tell(new DataTreeChanged(ImmutableList.of(peopleCandidate)), kit.getRef()); + rootListenerActor.tell(new DataTreeChanged(ImmutableList.of(peopleCandidate)), kit2.getRef()); + //verify the 2 candidates were processed into 1 initial candidate + verify(mockClusteredListener, timeout(100).times(1)).onDataTreeChanged(any()); + + rootListenerProxy.close(); + } + + @Test(timeout = 10000, expected = java.lang.AssertionError.class) + public void testNotAllShardsFound() { + final TestKit kit = new TestKit(getSystem()); + ActorUtils actorUtils = new ActorUtils(getSystem(), kit.getRef(), mock(ClusterWrapper.class), + mock(Configuration.class)); + + ClusteredDOMDataTreeChangeListener mockClusteredListener = mock( + ClusteredDOMDataTreeChangeListener.class); + + final RootDataTreeChangeListenerProxy rootListenerProxy = + new RootDataTreeChangeListenerProxy<>(actorUtils, mockClusteredListener, Set.of("shard-1", "shard-2")); + + Duration timeout = Duration.ofSeconds(5); + kit.expectMsgClass(FindLocalShard.class); + kit.reply(new LocalShardFound(kit.getRef())); + kit.expectMsgClass(FindLocalShard.class); + // don't send second reply + kit.expectMsgClass(timeout, RegisterDataTreeChangeListener.class); + + rootListenerProxy.close(); + } + + @Test(timeout = 10000, expected = java.lang.AssertionError.class) + public void testLocalShardNotInitialized() { + final TestKit kit = new TestKit(getSystem()); + ActorUtils actorUtils = new ActorUtils(getSystem(), kit.getRef(), mock(ClusterWrapper.class), + mock(Configuration.class)); + + ClusteredDOMDataTreeChangeListener mockClusteredListener = mock( + ClusteredDOMDataTreeChangeListener.class); + + final RootDataTreeChangeListenerProxy rootListenerProxy = + new RootDataTreeChangeListenerProxy<>(actorUtils, mockClusteredListener, Set.of("shard-1")); + + Duration timeout = Duration.ofSeconds(5); + kit.expectMsgClass(FindLocalShard.class); + kit.reply(new NotInitializedException("not initialized")); + // don't send second reply + kit.expectMsgClass(timeout, RegisterDataTreeChangeListener.class); + + rootListenerProxy.close(); + } +}