Bump upstream SNAPSHOTS
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / databroker / actors / dds / AbstractDataStoreClientBehaviorTest.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertSame;
12 import static org.junit.Assert.assertThrows;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.verify;
15 import static org.mockito.Mockito.when;
16 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.CLIENT_ID;
17
18 import akka.actor.ActorRef;
19 import akka.actor.ActorSelection;
20 import akka.actor.ActorSystem;
21 import akka.actor.Status;
22 import akka.testkit.TestProbe;
23 import akka.testkit.javadsl.TestKit;
24 import java.util.List;
25 import java.util.Optional;
26 import org.junit.After;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.opendaylight.controller.cluster.access.client.AbstractClientConnection;
30 import org.opendaylight.controller.cluster.access.client.AccessClientUtil;
31 import org.opendaylight.controller.cluster.access.client.ClientActorContext;
32 import org.opendaylight.controller.cluster.access.client.InternalCommand;
33 import org.opendaylight.controller.cluster.access.commands.ConnectClientRequest;
34 import org.opendaylight.controller.cluster.access.commands.ConnectClientSuccess;
35 import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
36 import org.opendaylight.controller.cluster.datastore.utils.ActorUtils;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification;
39 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
40 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
41 import scala.concurrent.Promise;
42
43 public abstract class AbstractDataStoreClientBehaviorTest {
44
45     protected static final String SHARD = "default";
46     private static final String PERSISTENCE_ID = "per-1";
47
48     private ActorSystem system;
49     private ClientActorContext clientContext;
50     private TestProbe clientActorProbe;
51     private TestProbe actorContextProbe;
52     private AbstractDataStoreClientBehavior behavior;
53
54     @Before
55     public void setUp() {
56         system = ActorSystem.apply();
57         clientActorProbe = new TestProbe(system, "client");
58         actorContextProbe = new TestProbe(system, "actor-context");
59         final ActorUtils context = createActorContextMock(system, actorContextProbe.ref());
60         clientContext =
61                 AccessClientUtil.createClientActorContext(system, clientActorProbe.ref(), CLIENT_ID, PERSISTENCE_ID);
62         behavior = createBehavior(clientContext, context);
63     }
64
65     @SuppressWarnings("checkstyle:hiddenField")
66     protected abstract AbstractDataStoreClientBehavior createBehavior(ClientActorContext clientContext,
67                                                                       ActorUtils context);
68
69     @After
70     public void tearDown() {
71         TestKit.shutdownActorSystem(system);
72     }
73
74     @Test
75     public void testResolveShardForPath() {
76         assertEquals(0L, behavior.resolveShardForPath(YangInstanceIdentifier.empty()).longValue());
77     }
78
79     @Test
80     public void testHaltClient() {
81         behavior.haltClient(new RuntimeException());
82     }
83
84     @Test
85     public void testOnCommand() {
86         final TestProbe probe = new TestProbe(system);
87         final GetClientRequest request = new GetClientRequest(probe.ref());
88         final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand(request);
89         final Status.Success success = probe.expectMsgClass(Status.Success.class);
90         assertEquals(behavior, success.status());
91         assertSame(behavior, nextBehavior);
92     }
93
94     @Test
95     public void testOnCommandUnhandled() {
96         final AbstractDataStoreClientBehavior nextBehavior = behavior.onCommand("unhandled");
97         assertSame(behavior, nextBehavior);
98     }
99
100     @Test
101     public void testCreateLocalHistory() {
102         final ClientLocalHistory history = behavior.createLocalHistory();
103         assertEquals(behavior.getIdentifier(), history.getIdentifier().getClientId());
104     }
105
106     @Test
107     public void testCreateTransaction() {
108         final ClientTransaction transaction = behavior.createTransaction();
109         assertEquals(behavior.getIdentifier(), transaction.getIdentifier().getHistoryId().getClientId());
110     }
111
112     @Test
113     public void testCreateSnapshot() {
114         final ClientSnapshot snapshot = behavior.createSnapshot();
115         assertEquals(behavior.getIdentifier(), snapshot.getIdentifier().getHistoryId().getClientId());
116     }
117
118     @Test
119     public void testClose() {
120         behavior.close();
121         final InternalCommand<ShardBackendInfo> internalCommand =
122                 clientActorProbe.expectMsgClass(InternalCommand.class);
123         internalCommand.execute(behavior);
124
125         assertThrows(IllegalStateException.class, () -> behavior.createLocalHistory());
126     }
127
128     @Test
129     public void testGetIdentifier() {
130         assertEquals(CLIENT_ID, behavior.getIdentifier());
131     }
132
133     @Test
134     public void testGetConnection() {
135         //set up data tree mock
136         final CursorAwareDataTreeModification modification = mock(CursorAwareDataTreeModification.class);
137         when(modification.readNode(YangInstanceIdentifier.empty())).thenReturn(Optional.empty());
138         final DataTreeSnapshot snapshot = mock(DataTreeSnapshot.class);
139         when(snapshot.newModification()).thenReturn(modification);
140         final DataTree dataTree = mock(DataTree.class);
141         when(dataTree.takeSnapshot()).thenReturn(snapshot);
142
143         final TestProbe backendProbe = new TestProbe(system, "backend");
144         final long shard = 0L;
145         behavior.createTransaction().read(YangInstanceIdentifier.empty());
146         final AbstractClientConnection<ShardBackendInfo> connection = behavior.getConnection(shard);
147         //check cached connection for same shard
148         assertSame(connection, behavior.getConnection(shard));
149
150         final ConnectClientRequest connectClientRequest = actorContextProbe.expectMsgClass(ConnectClientRequest.class);
151         assertEquals(CLIENT_ID, connectClientRequest.getTarget());
152         final long sequence = 0L;
153         assertEquals(sequence, connectClientRequest.getSequence());
154         actorContextProbe.reply(new ConnectClientSuccess(CLIENT_ID, sequence, backendProbe.ref(), List.of(), dataTree,
155                 3));
156         assertEquals(clientActorProbe.ref(), connection.localActor());
157         //capture and execute command passed to client context
158         final InternalCommand<ShardBackendInfo> command = clientActorProbe.expectMsgClass(InternalCommand.class);
159         command.execute(behavior);
160         //check, whether command was reaplayed
161         verify(modification).readNode(YangInstanceIdentifier.empty());
162     }
163
164     private static ActorUtils createActorContextMock(final ActorSystem system, final ActorRef actor) {
165         final ActorUtils mock = mock(ActorUtils.class);
166         final Promise<PrimaryShardInfo> promise = new scala.concurrent.impl.Promise.DefaultPromise<>();
167         final ActorSelection selection = system.actorSelection(actor.path());
168         final PrimaryShardInfo shardInfo = new PrimaryShardInfo(selection, (short) 0);
169         promise.success(shardInfo);
170         when(mock.findPrimaryShardAsync(SHARD)).thenReturn(promise.future());
171         return mock;
172     }
173
174 }