From 51d0c3b83ed2cb0877f2eb43cd5e14ceae5c08fd Mon Sep 17 00:00:00 2001 From: Andrej Mak Date: Tue, 14 Mar 2017 09:26:15 +0100 Subject: [PATCH] Add AbstractDataStoreClientBehavior unit tests Change-Id: I84f83c14353480c2aee54b5fc077c5c275c26f71 Signed-off-by: Andrej Mak --- .../access/client/AccessClientUtil.java | 24 +++ .../AbstractDataStoreClientBehaviorTest.java | 181 ++++++++++++++++++ ...istributedDataStoreClientBehaviorTest.java | 30 +++ .../SimpleDataStoreClientBehaviorTest.java | 21 ++ 4 files changed, 256 insertions(+) create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/access/client/AccessClientUtil.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/AbstractDataStoreClientBehaviorTest.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/DistributedDataStoreClientBehaviorTest.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/SimpleDataStoreClientBehaviorTest.java diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/access/client/AccessClientUtil.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/access/client/AccessClientUtil.java new file mode 100644 index 0000000000..999aad8637 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/access/client/AccessClientUtil.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Pantheon Technologies 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.access.client; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier; + +/** + * Util class to access package private members in cds-access-client for test purposes. + */ +public class AccessClientUtil { + + public static ClientActorContext createClientActorContext(final ActorSystem system, final ActorRef actor, + final ClientIdentifier id, final String persistenceId) { + return new ClientActorContext(actor, system.scheduler(), system.dispatcher(), persistenceId, id); + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/AbstractDataStoreClientBehaviorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/AbstractDataStoreClientBehaviorTest.java new file mode 100644 index 0000000000..7ababb8ca8 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/AbstractDataStoreClientBehaviorTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 Pantheon Technologies 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.databroker.actors.dds; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.ActorSystem; +import akka.actor.Status; +import akka.testkit.JavaTestKit; +import akka.testkit.TestProbe; +import java.util.Collections; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.cluster.access.client.AbstractClientConnection; +import org.opendaylight.controller.cluster.access.client.AccessClientUtil; +import org.opendaylight.controller.cluster.access.client.ClientActorContext; +import org.opendaylight.controller.cluster.access.client.InternalCommand; +import org.opendaylight.controller.cluster.access.commands.ConnectClientRequest; +import org.opendaylight.controller.cluster.access.commands.ConnectClientSuccess; +import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier; +import org.opendaylight.controller.cluster.access.concepts.FrontendIdentifier; +import org.opendaylight.controller.cluster.access.concepts.FrontendType; +import org.opendaylight.controller.cluster.access.concepts.MemberName; +import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo; +import org.opendaylight.controller.cluster.datastore.utils.ActorContext; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; +import scala.concurrent.Promise; + +public abstract class AbstractDataStoreClientBehaviorTest { + + protected static final String SHARD = "default"; + private static final MemberName MEMBER_NAME = MemberName.forName("member-1"); + private static final FrontendType FRONTEND_TYPE = FrontendType.forName("type-1"); + private static final FrontendIdentifier FRONTEND_ID = FrontendIdentifier.create(MEMBER_NAME, FRONTEND_TYPE); + private static final ClientIdentifier CLIENT_ID = ClientIdentifier.create(FRONTEND_ID, 0); + private static final String PERSISTENCE_ID = "per-1"; + + private ActorSystem system; + private ClientActorContext clientContext; + private TestProbe clientActorProbe; + private TestProbe actorContextProbe; + private AbstractDataStoreClientBehavior behavior; + + @Before + public void setUp() throws Exception { + system = ActorSystem.apply(); + clientActorProbe = new TestProbe(system, "client"); + actorContextProbe = new TestProbe(system, "actor-context"); + final ActorContext context = createActorContextMock(system, actorContextProbe.ref()); + clientContext = + AccessClientUtil.createClientActorContext(system, clientActorProbe.ref(), CLIENT_ID, PERSISTENCE_ID); + behavior = createBehavior(clientContext, context); + } + + protected abstract AbstractDataStoreClientBehavior createBehavior(ClientActorContext clientContext, + ActorContext context); + + @After + public void tearDown() throws Exception { + JavaTestKit.shutdownActorSystem(system); + } + + @Test + public void testResolveShardForPath() throws Exception { + Assert.assertEquals(0L, behavior.resolveShardForPath(YangInstanceIdentifier.EMPTY).longValue()); + } + + @Test + public void testHaltClient() throws Exception { + behavior.haltClient(new RuntimeException()); + } + + @Test + public void testOnCommand() throws Exception { + final TestProbe probe = new TestProbe(system); + final GetClientRequest request = new GetClientRequest(probe.ref()); + final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand(request); + final Status.Success success = probe.expectMsgClass(Status.Success.class); + Assert.assertEquals(behavior, success.status()); + Assert.assertSame(behavior, nextBehavior); + } + + @Test + public void testOnCommandUnhandled() throws Exception { + final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand("unhandled"); + Assert.assertSame(behavior, nextBehavior); + } + + @Test + public void testCreateLocalHistory() throws Exception { + final ClientLocalHistory history = behavior.createLocalHistory(); + Assert.assertEquals(behavior.getIdentifier(), history.getIdentifier().getClientId()); + } + + @Test + public void testCreateTransaction() throws Exception { + final ClientTransaction transaction = behavior.createTransaction(); + Assert.assertEquals(behavior.getIdentifier(), transaction.getIdentifier().getHistoryId().getClientId()); + } + + @Test + public void testCreateSnapshot() throws Exception { + final ClientSnapshot snapshot = behavior.createSnapshot(); + Assert.assertEquals(behavior.getIdentifier(), snapshot.getIdentifier().getHistoryId().getClientId()); + } + + @Test + public void testClose() throws Exception { + behavior.close(); + final InternalCommand internalCommand = + clientActorProbe.expectMsgClass(InternalCommand.class); + internalCommand.execute(behavior); + try { + behavior.createLocalHistory(); + Assert.fail("Behavior is closed and shouldn't allow to create new history."); + } catch (final IllegalStateException e) { + //ok + } + } + + @Test + public void testGetIdentifier() throws Exception { + Assert.assertEquals(CLIENT_ID, behavior.getIdentifier()); + } + + @Test + public void testGetConnection() throws Exception { + //set up data tree mock + final CursorAwareDataTreeModification modification = mock(CursorAwareDataTreeModification.class); + when(modification.readNode(YangInstanceIdentifier.EMPTY)).thenReturn(com.google.common.base.Optional.absent()); + final DataTreeSnapshot snapshot = mock(DataTreeSnapshot.class); + when(snapshot.newModification()).thenReturn(modification); + final DataTree dataTree = mock(DataTree.class); + when(dataTree.takeSnapshot()).thenReturn(snapshot); + + final TestProbe backendProbe = new TestProbe(system, "backend"); + final long shard = 0L; + behavior.createTransaction().read(YangInstanceIdentifier.EMPTY); + final AbstractClientConnection connection = behavior.getConnection(shard); + //check cached connection for same shard + Assert.assertSame(connection, behavior.getConnection(shard)); + + final ConnectClientRequest connectClientRequest = actorContextProbe.expectMsgClass(ConnectClientRequest.class); + Assert.assertEquals(CLIENT_ID, connectClientRequest.getTarget()); + final long sequence = 0L; + Assert.assertEquals(sequence, connectClientRequest.getSequence()); + actorContextProbe.reply(new ConnectClientSuccess(CLIENT_ID, sequence, backendProbe.ref(), + Collections.emptyList(), dataTree, 3)); + Assert.assertEquals(clientActorProbe.ref(), connection.localActor()); + //capture and execute command passed to client context + final InternalCommand command = clientActorProbe.expectMsgClass(InternalCommand.class); + command.execute(behavior); + //check, whether command was reaplayed + verify(modification).readNode(YangInstanceIdentifier.EMPTY); + } + + private static ActorContext createActorContextMock(final ActorSystem system, final ActorRef actor) { + final ActorContext mock = mock(ActorContext.class); + final Promise promise = new scala.concurrent.impl.Promise.DefaultPromise<>(); + final ActorSelection selection = system.actorSelection(actor.path()); + final PrimaryShardInfo shardInfo = new PrimaryShardInfo(selection, (short) 0); + promise.success(shardInfo); + when(mock.findPrimaryShardAsync(SHARD)).thenReturn(promise.future()); + return mock; + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/DistributedDataStoreClientBehaviorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/DistributedDataStoreClientBehaviorTest.java new file mode 100644 index 0000000000..47fcc55df5 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/DistributedDataStoreClientBehaviorTest.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Pantheon Technologies 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.databroker.actors.dds; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.opendaylight.controller.cluster.access.client.ClientActorContext; +import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategy; +import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory; +import org.opendaylight.controller.cluster.datastore.utils.ActorContext; + +public class DistributedDataStoreClientBehaviorTest extends AbstractDataStoreClientBehaviorTest { + @Override + protected AbstractDataStoreClientBehavior createBehavior(final ClientActorContext clientContext, + final ActorContext context) { + final ShardStrategyFactory factory = mock(ShardStrategyFactory.class); + final ShardStrategy strategy = mock(ShardStrategy.class); + when(strategy.findShard(any())).thenReturn(SHARD); + when(factory.getStrategy(any())).thenReturn(strategy); + when(context.getShardStrategyFactory()).thenReturn(factory); + return new DistributedDataStoreClientBehavior(clientContext, context); + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/SimpleDataStoreClientBehaviorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/SimpleDataStoreClientBehaviorTest.java new file mode 100644 index 0000000000..0e67276f31 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/actors/dds/SimpleDataStoreClientBehaviorTest.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 Pantheon Technologies 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.databroker.actors.dds; + +import org.opendaylight.controller.cluster.access.client.ClientActorContext; +import org.opendaylight.controller.cluster.datastore.utils.ActorContext; + +public class SimpleDataStoreClientBehaviorTest extends AbstractDataStoreClientBehaviorTest { + + @Override + protected AbstractDataStoreClientBehavior createBehavior(final ClientActorContext clientContext, + final ActorContext context) { + return new SimpleDataStoreClientBehavior(clientContext, context, SHARD); + } + +} \ No newline at end of file -- 2.36.6