2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
10 import static org.mockito.Mockito.mock;
11 import static org.mockito.Mockito.verify;
12 import static org.mockito.Mockito.when;
13 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.CLIENT_ID;
15 import akka.actor.ActorRef;
16 import akka.actor.ActorSelection;
17 import akka.actor.ActorSystem;
18 import akka.actor.Status;
19 import akka.testkit.TestProbe;
20 import akka.testkit.javadsl.TestKit;
21 import java.util.Collections;
22 import java.util.Optional;
23 import org.junit.After;
24 import org.junit.Assert;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.opendaylight.controller.cluster.access.client.AbstractClientConnection;
28 import org.opendaylight.controller.cluster.access.client.AccessClientUtil;
29 import org.opendaylight.controller.cluster.access.client.ClientActorContext;
30 import org.opendaylight.controller.cluster.access.client.InternalCommand;
31 import org.opendaylight.controller.cluster.access.commands.ConnectClientRequest;
32 import org.opendaylight.controller.cluster.access.commands.ConnectClientSuccess;
33 import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
34 import org.opendaylight.controller.cluster.datastore.utils.ActorUtils;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeModification;
37 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
38 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
39 import scala.concurrent.Promise;
41 public abstract class AbstractDataStoreClientBehaviorTest {
43 protected static final String SHARD = "default";
44 private static final String PERSISTENCE_ID = "per-1";
46 private ActorSystem system;
47 private ClientActorContext clientContext;
48 private TestProbe clientActorProbe;
49 private TestProbe actorContextProbe;
50 private AbstractDataStoreClientBehavior behavior;
54 system = ActorSystem.apply();
55 clientActorProbe = new TestProbe(system, "client");
56 actorContextProbe = new TestProbe(system, "actor-context");
57 final ActorUtils context = createActorContextMock(system, actorContextProbe.ref());
59 AccessClientUtil.createClientActorContext(system, clientActorProbe.ref(), CLIENT_ID, PERSISTENCE_ID);
60 behavior = createBehavior(clientContext, context);
63 @SuppressWarnings("checkstyle:hiddenField")
64 protected abstract AbstractDataStoreClientBehavior createBehavior(ClientActorContext clientContext,
68 public void tearDown() {
69 TestKit.shutdownActorSystem(system);
73 public void testResolveShardForPath() {
74 Assert.assertEquals(0L, behavior.resolveShardForPath(YangInstanceIdentifier.empty()).longValue());
78 public void testHaltClient() {
79 behavior.haltClient(new RuntimeException());
83 public void testOnCommand() {
84 final TestProbe probe = new TestProbe(system);
85 final GetClientRequest request = new GetClientRequest(probe.ref());
86 final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand(request);
87 final Status.Success success = probe.expectMsgClass(Status.Success.class);
88 Assert.assertEquals(behavior, success.status());
89 Assert.assertSame(behavior, nextBehavior);
93 public void testOnCommandUnhandled() {
94 final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand("unhandled");
95 Assert.assertSame(behavior, nextBehavior);
99 public void testCreateLocalHistory() {
100 final ClientLocalHistory history = behavior.createLocalHistory();
101 Assert.assertEquals(behavior.getIdentifier(), history.getIdentifier().getClientId());
105 public void testCreateTransaction() {
106 final ClientTransaction transaction = behavior.createTransaction();
107 Assert.assertEquals(behavior.getIdentifier(), transaction.getIdentifier().getHistoryId().getClientId());
111 public void testCreateSnapshot() {
112 final ClientSnapshot snapshot = behavior.createSnapshot();
113 Assert.assertEquals(behavior.getIdentifier(), snapshot.getIdentifier().getHistoryId().getClientId());
117 public void testClose() {
119 final InternalCommand<ShardBackendInfo> internalCommand =
120 clientActorProbe.expectMsgClass(InternalCommand.class);
121 internalCommand.execute(behavior);
123 behavior.createLocalHistory();
124 Assert.fail("Behavior is closed and shouldn't allow to create new history.");
125 } catch (final IllegalStateException e) {
131 public void testGetIdentifier() {
132 Assert.assertEquals(CLIENT_ID, behavior.getIdentifier());
136 public void testGetConnection() {
137 //set up data tree mock
138 final CursorAwareDataTreeModification modification = mock(CursorAwareDataTreeModification.class);
139 when(modification.readNode(YangInstanceIdentifier.empty())).thenReturn(Optional.empty());
140 final DataTreeSnapshot snapshot = mock(DataTreeSnapshot.class);
141 when(snapshot.newModification()).thenReturn(modification);
142 final DataTree dataTree = mock(DataTree.class);
143 when(dataTree.takeSnapshot()).thenReturn(snapshot);
145 final TestProbe backendProbe = new TestProbe(system, "backend");
146 final long shard = 0L;
147 behavior.createTransaction().read(YangInstanceIdentifier.empty());
148 final AbstractClientConnection<ShardBackendInfo> connection = behavior.getConnection(shard);
149 //check cached connection for same shard
150 Assert.assertSame(connection, behavior.getConnection(shard));
152 final ConnectClientRequest connectClientRequest = actorContextProbe.expectMsgClass(ConnectClientRequest.class);
153 Assert.assertEquals(CLIENT_ID, connectClientRequest.getTarget());
154 final long sequence = 0L;
155 Assert.assertEquals(sequence, connectClientRequest.getSequence());
156 actorContextProbe.reply(new ConnectClientSuccess(CLIENT_ID, sequence, backendProbe.ref(),
157 Collections.emptyList(), dataTree, 3));
158 Assert.assertEquals(clientActorProbe.ref(), connection.localActor());
159 //capture and execute command passed to client context
160 final InternalCommand<ShardBackendInfo> command = clientActorProbe.expectMsgClass(InternalCommand.class);
161 command.execute(behavior);
162 //check, whether command was reaplayed
163 verify(modification).readNode(YangInstanceIdentifier.empty());
166 private static ActorUtils createActorContextMock(final ActorSystem system, final ActorRef actor) {
167 final ActorUtils mock = mock(ActorUtils.class);
168 final Promise<PrimaryShardInfo> promise = new scala.concurrent.impl.Promise.DefaultPromise<>();
169 final ActorSelection selection = system.actorSelection(actor.path());
170 final PrimaryShardInfo shardInfo = new PrimaryShardInfo(selection, (short) 0);
171 promise.success(shardInfo);
172 when(mock.findPrimaryShardAsync(SHARD)).thenReturn(promise.future());