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.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.verify;
19 import akka.actor.ActorRef;
20 import akka.actor.ActorSelection;
21 import akka.actor.ActorSystem;
22 import com.google.common.primitives.UnsignedLong;
23 import java.util.Optional;
24 import org.junit.Test;
25 import org.mockito.Mock;
26 import org.opendaylight.controller.cluster.access.ABIVersion;
27 import org.opendaylight.controller.cluster.access.client.AccessClientUtil;
28 import org.opendaylight.controller.cluster.access.client.ClientActorContext;
29 import org.opendaylight.controller.cluster.access.client.ConnectedClientConnection;
30 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
31 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
32 import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
33 import org.opendaylight.controller.cluster.datastore.utils.ActorUtils;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
36 import scala.concurrent.Promise;
37 import scala.concurrent.impl.Promise.DefaultPromise;
39 public abstract class AbstractClientHistoryTest<T extends AbstractClientHistory> {
40 protected static final String SHARD_NAME = "default";
41 protected static final String PERSISTENCE_ID = "per-1";
42 protected static final LocalHistoryIdentifier HISTORY_ID = new LocalHistoryIdentifier(TestUtils.CLIENT_ID, 1L);
45 private DataTree tree;
47 private DatastoreContext datastoreContext;
49 protected abstract T object();
51 protected abstract ClientActorContext clientActorContext();
54 public abstract void testDoCreateSnapshot();
57 public abstract void testDoCreateTransaction();
60 public abstract void testCreateHistoryProxy();
63 public abstract void testOnTransactionComplete();
66 public abstract void testOnTransactionAbort();
69 public abstract void testOnTransactionReady();
72 public abstract void testOnTransactionReadyDuplicate();
75 public void testCreateSnapshotProxy() {
76 final AbstractProxyTransaction snapshotProxy = object().createSnapshotProxy(TestUtils.TRANSACTION_ID, 0L);
77 assertNotNull(snapshotProxy);
78 assertNotEquals(TestUtils.TRANSACTION_ID, snapshotProxy.getIdentifier());
82 public void testCreateTransactionProxy() {
83 AbstractProxyTransaction transactionProxy = object().createTransactionProxy(TestUtils.TRANSACTION_ID, 0L);
84 assertNotNull(transactionProxy);
85 assertNotEquals(TestUtils.TRANSACTION_ID, transactionProxy.getIdentifier());
89 public void testState() {
90 assertEquals(AbstractClientHistory.State.IDLE, object().state());
94 public void testUpdateState() {
95 object().updateState(AbstractClientHistory.State.IDLE, AbstractClientHistory.State.CLOSED);
96 assertEquals(AbstractClientHistory.State.CLOSED, object().state());
100 public void testDoClose() {
101 object().createTransactionProxy(TestUtils.TRANSACTION_ID, 0L);
103 assertEquals(AbstractClientHistory.State.CLOSED, object().state());
107 public void testGetIdentifier() {
108 assertEquals(HISTORY_ID, object().getIdentifier());
112 public void testNextTx() {
113 assertEquals(object().nextTx() + 1, object().nextTx());
117 public void testResolveShardForPath() {
118 final Long shardForPath = object().resolveShardForPath(YangInstanceIdentifier.of());
119 assertNotNull(shardForPath);
120 assertEquals(0L, (long) shardForPath);
124 public void testLocalAbort() {
125 object().localAbort(new Throwable());
126 assertEquals(AbstractClientHistory.State.CLOSED, object().state());
130 public void testOnProxyDestroyed() {
131 final ProxyHistory proxyHistory = mock(ProxyHistory.class);
132 doReturn(HISTORY_ID).when(proxyHistory).getIdentifier();
134 object().onProxyDestroyed(proxyHistory);
135 verify(proxyHistory).getIdentifier();
139 public void testCreateTransaction() {
140 final ClientTransaction transaction = object().createTransaction();
141 assertNotNull(transaction);
145 public void testTakeSnapshot() {
146 final ClientSnapshot clientSnapshot = object().takeSnapshot();
147 assertEquals(object().getIdentifier(), clientSnapshot.getIdentifier().getHistoryId());
151 public void testStartReconnect() {
152 // cookie and shard are the same
153 final Long cookie = 0L;
154 final Long shard = cookie;
156 final ShardBackendInfo info = new ShardBackendInfo(clientActorContext().self(), 0L, ABIVersion.current(),
157 SHARD_NAME, UnsignedLong.ZERO, Optional.of(tree), 10);
158 final ConnectedClientConnection<ShardBackendInfo> newConn = AccessClientUtil.createConnectedConnection(
159 clientActorContext(), cookie, info);
160 object().createSnapshotProxy(TestUtils.TRANSACTION_ID, shard);
162 final HistoryReconnectCohort reconnectCohort = object().startReconnect(newConn);
163 assertNotNull(reconnectCohort);
167 public void testStartReconnectMissingOldProxy() {
168 // cookie and shard are different
169 final Long cookie = 1L;
170 final Long shard = 0L;
172 final ShardBackendInfo info = new ShardBackendInfo(clientActorContext().self(), 0L, ABIVersion.current(),
173 SHARD_NAME, UnsignedLong.ZERO, Optional.of(tree), 10);
174 final ConnectedClientConnection<ShardBackendInfo> newConn = AccessClientUtil.createConnectedConnection(
175 clientActorContext(), cookie, info);
176 object().createSnapshotProxy(TestUtils.TRANSACTION_ID, shard);
178 final HistoryReconnectCohort reconnectCohort = object().startReconnect(newConn);
179 assertNull(reconnectCohort);
182 protected final ActorUtils createActorUtilsMock(final ActorSystem system, final ActorRef actor) {
183 final ActorUtils mock = mock(ActorUtils.class);
184 final Promise<PrimaryShardInfo> promise = new DefaultPromise<>();
185 final ActorSelection selection = system.actorSelection(actor.path());
186 final PrimaryShardInfo shardInfo = new PrimaryShardInfo(selection, (short) 0);
187 promise.success(shardInfo);
188 doReturn(promise.future()).when(mock).findPrimaryShardAsync(any());
189 doReturn(1000).when(datastoreContext).getShardBatchedModificationCount();
190 doReturn(datastoreContext).when(mock).getDatastoreContext();