2 * Copyright (c) 2016 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.mdsal.singleton.dom.impl;
10 import static org.junit.Assert.assertFalse;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertThrows;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.never;
18 import static org.mockito.Mockito.verify;
19 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.LOCAL_OWNERSHIP_GRANTED;
20 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.LOCAL_OWNERSHIP_LOST_NEW_OWNER;
21 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.LOCAL_OWNERSHIP_LOST_NO_OWNER;
22 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_CHANGED;
23 import static org.opendaylight.mdsal.eos.common.api.EntityOwnershipStateChange.REMOTE_OWNERSHIP_LOST_NO_OWNER;
24 import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.CLOSE_SERVICE_ENTITY_TYPE;
25 import static org.opendaylight.mdsal.singleton.dom.impl.EOSClusterSingletonServiceProvider.SERVICE_ENTITY_TYPE;
27 import com.google.common.util.concurrent.Futures;
28 import com.google.common.util.concurrent.ListenableFuture;
29 import java.util.concurrent.ExecutionException;
30 import org.eclipse.jdt.annotation.NonNull;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.Mock;
35 import org.mockito.junit.MockitoJUnitRunner;
36 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
37 import org.opendaylight.mdsal.eos.dom.api.DOMEntity;
38 import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipListener;
39 import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService;
40 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
41 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
42 import org.opendaylight.yangtools.concepts.Registration;
45 * Testing {@link ClusterSingletonServiceGroupImpl}.
47 @RunWith(MockitoJUnitRunner.StrictStubs.class)
48 public class ClusterSingletonServiceGroupImplTest {
49 public static final String SERVICE_IDENTIFIER = "TestServiceIdent";
50 public static final ServiceGroupIdentifier SERVICE_GROUP_IDENT = ServiceGroupIdentifier.create(SERVICE_IDENTIFIER);
52 public static final @NonNull DOMEntity MAIN_ENTITY = new DOMEntity(SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);
53 public static final @NonNull DOMEntity CLOSE_ENTITY = new DOMEntity(CLOSE_SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);
56 public ClusterSingletonService mockClusterSingletonService;
58 public ClusterSingletonService mockClusterSingletonServiceSecond;
60 public Registration mockEntityCandReg;
62 public Registration mockCloseEntityCandReg;
64 public DOMEntityOwnershipListener mockEosListener;
66 public DOMEntityOwnershipService mockEosService;
68 public ClusterSingletonServiceGroupImpl singletonServiceGroup;
70 public ServiceRegistration firstReg;
71 public ServiceRegistration secondReg;
74 * Initialization functionality for every Tests in this suite.
76 * @throws CandidateAlreadyRegisteredException unexpected exception.
79 public void setup() throws CandidateAlreadyRegisteredException {
80 doReturn(mockEntityCandReg).when(mockEosService).registerCandidate(MAIN_ENTITY);
81 doReturn(mockCloseEntityCandReg).when(mockEosService).registerCandidate(CLOSE_ENTITY);
82 doNothing().when(mockEntityCandReg).close();
83 doNothing().when(mockCloseEntityCandReg).close();
84 doNothing().when(mockClusterSingletonService).instantiateServiceInstance();
85 doReturn(Futures.immediateFuture(null)).when(mockClusterSingletonService).closeServiceInstance();
87 doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonService).getIdentifier();
88 doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonServiceSecond).getIdentifier();
90 firstReg = new ServiceRegistration(mockClusterSingletonService) {
92 protected void removeRegistration() {
96 secondReg = new ServiceRegistration(mockClusterSingletonServiceSecond) {
98 protected void removeRegistration() {
103 singletonServiceGroup = new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY,
108 * Test NULL ServiceIdent input for new ServiceGroup instance.
111 public void instantiationClusterSingletonServiceGroupNullIdentTest() {
112 assertThrows(NullPointerException.class,
113 () -> new ClusterSingletonServiceGroupImpl(null, MAIN_ENTITY, CLOSE_ENTITY, mockEosService));
117 * Test empty ServiceIdent input for new ServiceGroup instance.
120 public void instantiationClusterSingletonServiceGroupEmptyIdentTest() {
121 assertThrows(IllegalArgumentException.class,
122 () -> new ClusterSingletonServiceGroupImpl("", MAIN_ENTITY, CLOSE_ENTITY, mockEosService));
126 * Test NULL MainEntity input for new ServiceGroup instance.
129 public void instantiationClusterSingletonServiceGroupNullMainEntityTest() {
130 assertThrows(NullPointerException.class,
131 () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, null, CLOSE_ENTITY, mockEosService));
135 * Test NULL CloseEntity input for new ServiceGroup instance.
138 public void instantiationClusterSingletonServiceGroupNullCloseEntityTest() {
139 assertThrows(NullPointerException.class,
140 () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, null, mockEosService));
144 * Test NULL EntityOwnershipService input for new ServiceGroup instance.
147 public void instantiationClusterSingletonServiceGroupNullEOS_Test() {
148 assertThrows(NullPointerException.class,
149 () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY, null));
153 * Test GoldPath for initialization ServiceGroup.
156 public void initializationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
157 singletonServiceGroup.initialize();
158 verify(mockEosService).registerCandidate(MAIN_ENTITY);
162 * Test GoldPath for NO-TO-SLAVE entity Candidate role change.
164 * @throws CandidateAlreadyRegisteredException - unexpected exception
167 public void initializationSlaveTest() throws CandidateAlreadyRegisteredException {
168 singletonServiceGroup.initialize();
169 verify(mockEosService).registerCandidate(MAIN_ENTITY);
170 singletonServiceGroup.registerService(firstReg);
171 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
172 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
173 verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
177 * Test GoldPath for NO-TO-SLAVE but without MASTER entity Candidate role change.
179 * @throws CandidateAlreadyRegisteredException - unexpected exception
182 public void initializationNoMasterTest() throws CandidateAlreadyRegisteredException {
183 singletonServiceGroup.initialize();
184 verify(mockEosService).registerCandidate(MAIN_ENTITY);
185 singletonServiceGroup.registerService(firstReg);
186 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NO_OWNER, false);
187 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
188 verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
192 * Test GoldPath for InJeopardy entity Candidate role change.
194 * @throws CandidateAlreadyRegisteredException - unexpected exception
197 public void initializationInJeopardyTest() throws CandidateAlreadyRegisteredException {
198 singletonServiceGroup.initialize();
199 verify(mockEosService).registerCandidate(MAIN_ENTITY);
200 singletonServiceGroup.registerService(firstReg);
201 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
202 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
203 verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
207 * Test GoldPath for registration SingletonService.
209 * @throws CandidateAlreadyRegisteredException - unexpected exception
212 public void serviceRegistrationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
213 singletonServiceGroup.initialize();
214 verify(mockEosService).registerCandidate(MAIN_ENTITY);
215 singletonServiceGroup.registerService(firstReg);
219 * Test GoldPath for registration SingletonService.
221 * @throws CandidateAlreadyRegisteredException - unexpected exception
224 public void serviceRegistrationClusterSingletonServiceGroupTwoServiceTest()
225 throws CandidateAlreadyRegisteredException {
226 singletonServiceGroup.initialize();
227 verify(mockEosService).registerCandidate(MAIN_ENTITY);
228 singletonServiceGroup.registerService(firstReg);
229 singletonServiceGroup.registerService(secondReg);
233 * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
234 * without mastership and don't remove ServiceGroup from map.
236 * @throws CandidateAlreadyRegisteredException - unexpected exception
239 public void serviceUnregistrationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
240 singletonServiceGroup.initialize();
241 verify(mockEosService).registerCandidate(MAIN_ENTITY);
242 singletonServiceGroup.registerService(firstReg);
243 assertNotNull(singletonServiceGroup.unregisterService(firstReg));
244 verify(mockClusterSingletonService, never()).closeServiceInstance();
248 * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
249 * without mastership and don't remove ServiceGroup from map.
251 * @throws CandidateAlreadyRegisteredException - unexpected exception
254 public void serviceUnregistrationClusterSingletonServiceGroupTwoServicesTest()
255 throws CandidateAlreadyRegisteredException {
256 singletonServiceGroup.initialize();
257 verify(mockEosService).registerCandidate(MAIN_ENTITY);
258 singletonServiceGroup.registerService(firstReg);
259 singletonServiceGroup.registerService(secondReg);
260 assertNull(singletonServiceGroup.unregisterService(firstReg));
261 verify(mockClusterSingletonService, never()).closeServiceInstance();
265 * Test GoldPath get Slave role for registered main entity.
267 * @throws CandidateAlreadyRegisteredException - unexpected exception
270 public void getSlaveClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
271 singletonServiceGroup.initialize();
272 verify(mockEosService).registerCandidate(MAIN_ENTITY);
273 singletonServiceGroup.registerService(firstReg);
274 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
275 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
279 * Test GoldPath get Master role for registered main entity.
281 * @throws CandidateAlreadyRegisteredException - unexpected exception
284 public void tryToTakeLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
285 singletonServiceGroup.initialize();
286 verify(mockEosService).registerCandidate(MAIN_ENTITY);
287 singletonServiceGroup.registerService(firstReg);
288 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
289 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
290 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
294 * Test GoldPath get Master role for registered close entity.
296 * @throws CandidateAlreadyRegisteredException - unexpected exception
299 public void takeMasterClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
300 singletonServiceGroup.initialize();
301 verify(mockEosService).registerCandidate(MAIN_ENTITY);
302 singletonServiceGroup.registerService(firstReg);
303 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
304 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
305 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
306 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
307 verify(mockClusterSingletonService).instantiateServiceInstance();
311 * Test GoldPath get Master role for registered entity but initial Slave
312 * role for closeEntity.
314 * @throws CandidateAlreadyRegisteredException - unexpected exception
317 public void waitToTakeMasterClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
318 singletonServiceGroup.initialize();
319 verify(mockEosService).registerCandidate(MAIN_ENTITY);
320 singletonServiceGroup.registerService(firstReg);
321 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
322 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
323 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
324 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, REMOTE_OWNERSHIP_CHANGED, false);
325 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
326 verify(mockClusterSingletonService, never()).closeServiceInstance();
330 * Test inJeopardy validation during wait phase for Master role for closeEntity.
332 * @throws CandidateAlreadyRegisteredException - unexpected exception
335 public void inJeopardyInWaitPhaseClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
336 singletonServiceGroup.initialize();
337 verify(mockEosService).registerCandidate(MAIN_ENTITY);
338 singletonServiceGroup.registerService(firstReg);
339 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
340 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
341 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
342 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
343 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
344 verify(mockClusterSingletonService, never()).closeServiceInstance();
348 * Test inJeopardy validation during wait phase for Master role for closeEntity.
350 * @throws CandidateAlreadyRegisteredException - unexpected exception
353 public void inJeopardyInWaitPhaseClusterSingletonServiceGroupTwoServiceTest()
354 throws CandidateAlreadyRegisteredException {
355 singletonServiceGroup.initialize();
356 verify(mockEosService).registerCandidate(MAIN_ENTITY);
357 singletonServiceGroup.registerService(firstReg);
358 singletonServiceGroup.registerService(secondReg);
359 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
360 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
361 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
362 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
363 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
364 verify(mockClusterSingletonService, never()).closeServiceInstance();
368 * Test inJeopardy validation for holding leadership.
370 * @throws CandidateAlreadyRegisteredException - unexpected exception
373 public void inJeopardyLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
374 singletonServiceGroup.initialize();
375 verify(mockEosService).registerCandidate(MAIN_ENTITY);
376 singletonServiceGroup.registerService(firstReg);
377 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
378 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
379 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
380 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
381 verify(mockClusterSingletonService).instantiateServiceInstance();
383 // Base entity in jeopardy should not matter...
384 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, true);
385 verify(mockClusterSingletonService, never()).closeServiceInstance();
387 // ... application state is actually guarded by cleanup
388 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
389 verify(mockClusterSingletonService).closeServiceInstance();
393 * Test GoldPath for SLAVE-TO-MASTER entity Candidate role change.
395 * @throws CandidateAlreadyRegisteredException - unexpected exception
398 public void lostLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
399 singletonServiceGroup.initialize();
400 verify(mockEosService).registerCandidate(MAIN_ENTITY);
401 singletonServiceGroup.registerService(firstReg);
402 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
403 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
404 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
405 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
406 verify(mockClusterSingletonService).instantiateServiceInstance();
407 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
408 verify(mockClusterSingletonService).closeServiceInstance();
412 * Test checks validation Error processing for SLAVE-TO-MASTER entity Candidate role change.
413 * Not initialized provider has to close and remove all singletonServices from Group and
414 * Group itself remove too.
416 @Test(expected = IllegalStateException.class)
417 public void tryToTakeLeaderForNotInitializedGroupTest() {
418 singletonServiceGroup.registerService(firstReg);
422 * Test checks closing processing for close {@link ServiceRegistration}.
424 * @throws CandidateAlreadyRegisteredException - unexpected exception
427 public void checkClosingRegistrationTest() throws CandidateAlreadyRegisteredException {
428 singletonServiceGroup.initialize();
429 verify(mockEosService).registerCandidate(MAIN_ENTITY);
430 singletonServiceGroup.registerService(firstReg);
431 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
432 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
433 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
434 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
435 verify(mockClusterSingletonService).instantiateServiceInstance();
436 assertNotNull(singletonServiceGroup.unregisterService(firstReg));
437 verify(mockClusterSingletonService, never()).closeServiceInstance();
438 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NO_OWNER, false);
439 verify(mockClusterSingletonService).closeServiceInstance();
443 * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change.
445 * @throws CandidateAlreadyRegisteredException - unexpected exception
448 public void checkClosingUnexpectedDoubleEntityForMasterOwnershipChangeRegistrationTest()
449 throws CandidateAlreadyRegisteredException {
450 singletonServiceGroup.initialize();
451 verify(mockEosService).registerCandidate(MAIN_ENTITY);
452 singletonServiceGroup.registerService(firstReg);
453 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
454 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
455 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
456 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
457 verify(mockClusterSingletonService).instantiateServiceInstance();
458 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
459 verify(mockClusterSingletonService).closeServiceInstance();
463 * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change
464 * without closeEntity registration.
466 * @throws CandidateAlreadyRegisteredException - unexpected exception
469 public void checkClosingUnexpectedDoubleEntityForSlaveOwnershipChangeRegistrationTest()
470 throws CandidateAlreadyRegisteredException {
471 singletonServiceGroup.initialize();
472 verify(mockEosService).registerCandidate(MAIN_ENTITY);
473 singletonServiceGroup.registerService(firstReg);
474 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
475 verify(mockClusterSingletonService, never()).instantiateServiceInstance();
476 verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
477 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
478 verify(mockClusterSingletonService, never()).closeServiceInstance();
482 public void testRegisterCloseShutdown() throws CandidateAlreadyRegisteredException, InterruptedException,
484 initializeGroupAndStartService();
486 assertNotNull(singletonServiceGroup.unregisterService(firstReg));
487 verify(mockClusterSingletonService, never()).closeServiceInstance();
488 verify(mockEntityCandReg).close();
490 final ListenableFuture<?> future = singletonServiceGroup.closeClusterSingletonGroup();
491 assertNotNull(future);
492 assertFalse(future.isDone());
493 verify(mockClusterSingletonService).closeServiceInstance();
495 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
496 verify(mockCloseEntityCandReg).close();
498 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
499 assertTrue(future.isDone());
500 assertNull(future.get());
503 private void initialize() throws CandidateAlreadyRegisteredException {
504 singletonServiceGroup.initialize();
505 verify(mockEosService).registerCandidate(MAIN_ENTITY);
508 private void initializeGroupAndStartService() throws CandidateAlreadyRegisteredException {
510 singletonServiceGroup.registerService(firstReg);
511 singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
512 verify(mockEosService).registerCandidate(CLOSE_ENTITY);
513 singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_GRANTED, false);
514 verify(mockClusterSingletonService).instantiateServiceInstance();