2 * Copyright (c) 2017 Cisco Systems, Inc. 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.sharding;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.ArgumentMatchers.eq;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.doThrow;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.verifyNoMoreInteractions;
22 import akka.actor.ActorRef;
23 import akka.dispatch.Futures;
24 import java.util.Optional;
25 import java.util.concurrent.TimeUnit;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
29 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
30 import org.opendaylight.controller.cluster.datastore.exceptions.LocalShardNotFoundException;
31 import org.opendaylight.controller.cluster.datastore.utils.ActorUtils;
32 import org.opendaylight.controller.cluster.dom.api.LeaderLocation;
33 import org.opendaylight.controller.cluster.dom.api.LeaderLocationListener;
34 import org.opendaylight.controller.cluster.dom.api.LeaderLocationListenerRegistration;
35 import org.opendaylight.controller.cluster.raft.LeadershipTransferFailedException;
36 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
37 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
38 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
39 import scala.concurrent.Future;
40 import scala.concurrent.duration.FiniteDuration;
42 @Deprecated(forRemoval = true)
43 public class CDSShardAccessImplTest extends AbstractActorTest {
45 private static final DOMDataTreeIdentifier TEST_ID =
46 new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, TestModel.TEST_PATH);
48 private CDSShardAccessImpl shardAccess;
49 private ActorUtils context;
53 context = mock(ActorUtils.class);
54 final DatastoreContext datastoreContext = DatastoreContext.newBuilder().build();
55 doReturn(Optional.of(getSystem().deadLetters())).when(context).findLocalShard(any());
56 doReturn(datastoreContext).when(context).getDatastoreContext();
57 doReturn(getSystem()).when(context).getActorSystem();
58 shardAccess = new CDSShardAccessImpl(TEST_ID, context);
62 @SuppressWarnings("checkstyle:IllegalCatch")
63 public void testRegisterLeaderLocationListener() {
64 final LeaderLocationListener listener1 = mock(LeaderLocationListener.class);
66 // first registration should be OK
67 shardAccess.registerLeaderLocationListener(listener1);
69 // second registration should fail with IllegalArgumentEx
71 shardAccess.registerLeaderLocationListener(listener1);
72 fail("Should throw exception");
73 } catch (final Exception e) {
74 assertTrue(e instanceof IllegalArgumentException);
77 // null listener registration should fail with NPE
79 shardAccess.registerLeaderLocationListener(null);
80 fail("Should throw exception");
81 } catch (final Exception e) {
82 assertTrue(e instanceof NullPointerException);
85 // registering listener on closed shard access should fail with IllegalStateEx
86 final LeaderLocationListener listener2 = mock(LeaderLocationListener.class);
89 shardAccess.registerLeaderLocationListener(listener2);
90 fail("Should throw exception");
91 } catch (final Exception ex) {
92 assertTrue(ex instanceof IllegalStateException);
97 @SuppressWarnings("checkstyle:IllegalCatch")
98 public void testOnLeaderLocationChanged() {
99 final LeaderLocationListener listener1 = mock(LeaderLocationListener.class);
100 doThrow(new RuntimeException("Failed")).when(listener1).onLeaderLocationChanged(any());
101 final LeaderLocationListener listener2 = mock(LeaderLocationListener.class);
102 doNothing().when(listener2).onLeaderLocationChanged(any());
103 final LeaderLocationListener listener3 = mock(LeaderLocationListener.class);
104 doNothing().when(listener3).onLeaderLocationChanged(any());
106 final LeaderLocationListenerRegistration<?> reg1 = shardAccess.registerLeaderLocationListener(listener1);
107 final LeaderLocationListenerRegistration<?> reg2 = shardAccess.registerLeaderLocationListener(listener2);
108 final LeaderLocationListenerRegistration<?> reg3 = shardAccess.registerLeaderLocationListener(listener3);
110 // Error in listener1 should not affect dispatching change to other listeners
111 shardAccess.onLeaderLocationChanged(LeaderLocation.LOCAL);
112 verify(listener1).onLeaderLocationChanged(eq(LeaderLocation.LOCAL));
113 verify(listener2).onLeaderLocationChanged(eq(LeaderLocation.LOCAL));
114 verify(listener3).onLeaderLocationChanged(eq(LeaderLocation.LOCAL));
116 // Closed listeners shouldn't see new leader location changes
119 shardAccess.onLeaderLocationChanged(LeaderLocation.REMOTE);
120 verify(listener3).onLeaderLocationChanged(eq(LeaderLocation.REMOTE));
121 verifyNoMoreInteractions(listener1);
122 verifyNoMoreInteractions(listener2);
124 // Closed shard access should not dispatch any new events
126 shardAccess.onLeaderLocationChanged(LeaderLocation.UNKNOWN);
127 verifyNoMoreInteractions(listener1);
128 verifyNoMoreInteractions(listener2);
129 verifyNoMoreInteractions(listener3);
135 @SuppressWarnings("checkstyle:IllegalCatch")
136 public void testGetShardIdentifier() {
137 assertEquals(shardAccess.getShardIdentifier(), TEST_ID);
139 // closed shard access should throw illegal state
142 shardAccess.getShardIdentifier();
143 fail("Exception expected");
144 } catch (final Exception e) {
145 assertTrue(e instanceof IllegalStateException);
150 @SuppressWarnings("checkstyle:IllegalCatch")
151 public void testGetLeaderLocation() {
152 // new shard access does not know anything about leader location
153 assertEquals(shardAccess.getLeaderLocation(), LeaderLocation.UNKNOWN);
155 // we start getting leader location changes notifications
156 shardAccess.onLeaderLocationChanged(LeaderLocation.LOCAL);
157 assertEquals(shardAccess.getLeaderLocation(), LeaderLocation.LOCAL);
159 shardAccess.onLeaderLocationChanged(LeaderLocation.REMOTE);
160 shardAccess.onLeaderLocationChanged(LeaderLocation.UNKNOWN);
161 assertEquals(shardAccess.getLeaderLocation(), LeaderLocation.UNKNOWN);
163 // closed shard access throws illegal state
166 shardAccess.getLeaderLocation();
167 fail("Should have failed with IllegalStateEx");
168 } catch (Exception e) {
169 assertTrue(e instanceof IllegalStateException);
174 @SuppressWarnings("checkstyle:IllegalCatch")
175 public void testMakeLeaderLocal() throws Exception {
176 final FiniteDuration timeout = new FiniteDuration(5, TimeUnit.SECONDS);
177 final ActorRef localShardRef = mock(ActorRef.class);
178 final Future<ActorRef> localShardRefFuture = Futures.successful(localShardRef);
179 doReturn(localShardRefFuture).when(context).findLocalShardAsync(any());
181 // MakeLeaderLocal will reply with success
182 doReturn(Futures.successful(null)).when(context).executeOperationAsync((ActorRef) any(), any(), any());
183 doReturn(getSystem().dispatcher()).when(context).getClientDispatcher();
184 assertEquals(waitOnAsyncTask(shardAccess.makeLeaderLocal(), timeout), null);
186 // MakeLeaderLocal will reply with failure
187 doReturn(Futures.failed(new LeadershipTransferFailedException("Failure")))
188 .when(context).executeOperationAsync((ActorRef) any(), any(), any());
191 waitOnAsyncTask(shardAccess.makeLeaderLocal(), timeout);
192 fail("makeLeaderLocal operation should not be successful");
193 } catch (final Exception e) {
194 assertTrue(e instanceof LeadershipTransferFailedException);
197 // we don't even find local shard
198 doReturn(Futures.failed(new LocalShardNotFoundException("Local shard not found")))
199 .when(context).findLocalShardAsync(any());
202 waitOnAsyncTask(shardAccess.makeLeaderLocal(), timeout);
203 fail("makeLeaderLocal operation should not be successful");
204 } catch (final Exception e) {
205 assertTrue(e instanceof LeadershipTransferFailedException);
206 assertTrue(e.getCause() instanceof LocalShardNotFoundException);
209 // closed shard access should throw IllegalStateEx
212 shardAccess.makeLeaderLocal();
213 fail("Should have thrown IllegalStateEx. ShardAccess is closed");
214 } catch (final Exception e) {
215 assertTrue(e instanceof IllegalStateException);