BUG-9145: rework singleton service group state tracking
[mdsal.git] / singleton-service / mdsal-singleton-dom-impl / src / test / java / org / opendaylight / mdsal / singleton / dom / impl / ClusterSingletonServiceGroupImplTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.mdsal.singleton.dom.impl;
10
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
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.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.CLOSE_SERVICE_ENTITY_TYPE;
20 import static org.opendaylight.mdsal.singleton.dom.impl.AbstractClusterSingletonServiceProviderImpl.SERVICE_ENTITY_TYPE;
21
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import java.util.concurrent.ExecutionException;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.mockito.Mock;
28 import org.mockito.MockitoAnnotations;
29 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
30 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
31 import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipCandidateRegistration;
32 import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipChange;
33 import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipListener;
34 import org.opendaylight.mdsal.eos.common.api.GenericEntityOwnershipService;
35 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
36 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
37 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
38 import org.opendaylight.mdsal.singleton.dom.impl.util.TestEntity;
39 import org.opendaylight.mdsal.singleton.dom.impl.util.TestInstanceIdentifier;
40
41 /**
42  * Testing {@link ClusterSingletonServiceGroupImpl}.
43  */
44 public class ClusterSingletonServiceGroupImplTest {
45     private static final String SERVICE_IDENTIFIER = "TestServiceIdent";
46     private static final ServiceGroupIdentifier SERVICE_GROUP_IDENT = ServiceGroupIdentifier.create(SERVICE_IDENTIFIER);
47
48     private static final TestEntity MAIN_ENTITY = new TestEntity(SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);
49     private static final TestEntity CLOSE_ENTITY = new TestEntity(CLOSE_SERVICE_ENTITY_TYPE, SERVICE_IDENTIFIER);
50
51     @Mock
52     private ClusterSingletonService mockClusterSingletonService;
53     @Mock
54     private ClusterSingletonService mockClusterSingletonServiceSecond;
55     @Mock
56     private GenericEntityOwnershipCandidateRegistration<?, ?> mockEntityCandReg;
57     @Mock
58     private GenericEntityOwnershipCandidateRegistration<?, ?> mockCloseEntityCandReg;
59     @Mock
60     private GenericEntityOwnershipListener<TestInstanceIdentifier,
61         GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity>> mockEosListener;
62
63     @Mock
64     private GenericEntityOwnershipService<TestInstanceIdentifier,TestEntity,
65         GenericEntityOwnershipListener<TestInstanceIdentifier,
66             GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity>>> mockEosService;
67
68     private ClusterSingletonServiceGroupImpl<TestInstanceIdentifier,TestEntity,
69         GenericEntityOwnershipChange<TestInstanceIdentifier,TestEntity>,
70             GenericEntityOwnershipListener<TestInstanceIdentifier,
71                 GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity>>,
72                     GenericEntityOwnershipService<TestInstanceIdentifier, TestEntity,
73                         GenericEntityOwnershipListener<TestInstanceIdentifier,
74                             GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity>>>> singletonServiceGroup;
75
76     /**
77      * Initialization functionality for every Tests in this suite.
78      *
79      * @throws CandidateAlreadyRegisteredException unexpected exception.
80      */
81     @Before
82     public void setup() throws CandidateAlreadyRegisteredException {
83         MockitoAnnotations.initMocks(this);
84
85         doReturn(mockEntityCandReg).when(mockEosService).registerCandidate(MAIN_ENTITY);
86         doReturn(mockCloseEntityCandReg).when(mockEosService).registerCandidate(CLOSE_ENTITY);
87         doNothing().when(mockEntityCandReg).close();
88         doNothing().when(mockCloseEntityCandReg).close();
89         doNothing().when(mockClusterSingletonService).instantiateServiceInstance();
90         doReturn(Futures.immediateFuture(null)).when(mockClusterSingletonService).closeServiceInstance();
91
92         doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonService).getIdentifier();
93         doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonServiceSecond).getIdentifier();
94
95         singletonServiceGroup = new ClusterSingletonServiceGroupImpl<>(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY,
96             mockEosService);
97     }
98
99     /**
100      * Test NULL ServiceIdent input for new ServiceGroup instance.
101      */
102     @Test(expected = NullPointerException.class)
103     public void instantiationClusterSingletonServiceGroupNullIdentTest() {
104         new ClusterSingletonServiceGroupImpl<>(null, MAIN_ENTITY, CLOSE_ENTITY, mockEosService);
105     }
106
107     /**
108      * Test empty ServiceIdent input for new ServiceGroup instance.
109      */
110     @Test(expected = IllegalArgumentException.class)
111     public void instantiationClusterSingletonServiceGroupEmptyIdentTest() {
112         new ClusterSingletonServiceGroupImpl<>("", MAIN_ENTITY, CLOSE_ENTITY, mockEosService);
113     }
114
115     /**
116      * Test NULL MainEntity input for new ServiceGroup instance.
117      */
118     @Test(expected = NullPointerException.class)
119     public void instantiationClusterSingletonServiceGroupNullMainEntityTest() {
120         new ClusterSingletonServiceGroupImpl<>(SERVICE_IDENTIFIER, null, CLOSE_ENTITY, mockEosService);
121     }
122
123     /**
124      * Test NULL CloseEntity input for new ServiceGroup instance.
125      */
126     @Test(expected = NullPointerException.class)
127     public void instantiationClusterSingletonServiceGroupNullCloseEntityTest() {
128         new ClusterSingletonServiceGroupImpl<>(SERVICE_IDENTIFIER, MAIN_ENTITY, null, mockEosService);
129     }
130
131     /**
132      * Test NULL EntityOwnershipService input for new ServiceGroup instance.
133      */
134     @Test(expected = NullPointerException.class)
135     public void instantiationClusterSingletonServiceGroupNullEOS_Test() {
136         new ClusterSingletonServiceGroupImpl<>(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY, null);
137     }
138
139     /**
140      * Test GoldPath for initialization ServiceGroup.
141      */
142     @Test
143     public void initializationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
144         singletonServiceGroup.initialize();
145         verify(mockEosService).registerCandidate(MAIN_ENTITY);
146     }
147
148     /**
149      * Test GoldPath for NO-TO-SLAVE entity Candidate role change.
150      *
151      * @throws CandidateAlreadyRegisteredException - unexpected exception
152      */
153     @Test
154     public void initializationSlaveTest() throws CandidateAlreadyRegisteredException {
155         singletonServiceGroup.initialize();
156         verify(mockEosService).registerCandidate(MAIN_ENTITY);
157         singletonServiceGroup.registerService(mockClusterSingletonService);
158         singletonServiceGroup.ownershipChanged(getEntityToSlave());
159         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
160         verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
161     }
162
163     /**
164      * Test GoldPath for NO-TO-SLAVE but without MASTER entity Candidate role change.
165      *
166      * @throws CandidateAlreadyRegisteredException - unexpected exception
167      */
168     @Test
169     public void initializationNoMasterTest() throws CandidateAlreadyRegisteredException {
170         singletonServiceGroup.initialize();
171         verify(mockEosService).registerCandidate(MAIN_ENTITY);
172         singletonServiceGroup.registerService(mockClusterSingletonService);
173         singletonServiceGroup.ownershipChanged(getEntityToSlaveNoMaster());
174         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
175         verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
176     }
177
178     /**
179      * Test GoldPath for InJeopardy entity Candidate role change.
180      *
181      * @throws CandidateAlreadyRegisteredException - unexpected exception
182      */
183     @Test
184     public void initializationInJeopardyTest() throws CandidateAlreadyRegisteredException {
185         singletonServiceGroup.initialize();
186         verify(mockEosService).registerCandidate(MAIN_ENTITY);
187         singletonServiceGroup.registerService(mockClusterSingletonService);
188         singletonServiceGroup.ownershipChanged(getEntityToJeopardy());
189         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
190         verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
191     }
192
193     /**
194      * Test GoldPath for registration SingletonService.
195      *
196      * @throws CandidateAlreadyRegisteredException - unexpected exception
197      */
198     @Test
199     public void serviceRegistrationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
200         singletonServiceGroup.initialize();
201         verify(mockEosService).registerCandidate(MAIN_ENTITY);
202         singletonServiceGroup.registerService(mockClusterSingletonService);
203     }
204
205     /**
206      * Test GoldPath for registration SingletonService.
207      *
208      * @throws CandidateAlreadyRegisteredException - unexpected exception
209      */
210     @Test
211     public void serviceRegistrationClusterSingletonServiceGroupTwoServiceTest()
212             throws CandidateAlreadyRegisteredException {
213         singletonServiceGroup.initialize();
214         verify(mockEosService).registerCandidate(MAIN_ENTITY);
215         singletonServiceGroup.registerService(mockClusterSingletonService);
216         singletonServiceGroup.registerService(mockClusterSingletonServiceSecond);
217     }
218
219     /**
220      * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
221      * without mastership and don't remove ServiceGroup from map.
222      *
223      * @throws CandidateAlreadyRegisteredException - unexpected exception
224      */
225     @Test
226     public void serviceUnregistrationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
227         singletonServiceGroup.initialize();
228         verify(mockEosService).registerCandidate(MAIN_ENTITY);
229         singletonServiceGroup.registerService(mockClusterSingletonService);
230         assertTrue(singletonServiceGroup.unregisterService(mockClusterSingletonService));
231         verify(mockClusterSingletonService, never()).closeServiceInstance();
232     }
233
234     /**
235      * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
236      *     without mastership and don't remove ServiceGroup from map.
237      *
238      * @throws CandidateAlreadyRegisteredException - unexpected exception
239      */
240     @Test
241     public void serviceUnregistrationClusterSingletonServiceGroupTwoServicesTest()
242             throws CandidateAlreadyRegisteredException {
243         singletonServiceGroup.initialize();
244         verify(mockEosService).registerCandidate(MAIN_ENTITY);
245         singletonServiceGroup.registerService(mockClusterSingletonService);
246         singletonServiceGroup.registerService(mockClusterSingletonServiceSecond);
247         assertFalse(singletonServiceGroup.unregisterService(mockClusterSingletonService));
248         verify(mockClusterSingletonService, never()).closeServiceInstance();
249     }
250
251     /**
252      * Test GoldPath get Slave role for registered main entity.
253      *
254      * @throws CandidateAlreadyRegisteredException - unexpected exception
255      */
256     @Test
257     public void getSlaveClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
258         singletonServiceGroup.initialize();
259         verify(mockEosService).registerCandidate(MAIN_ENTITY);
260         singletonServiceGroup.registerService(mockClusterSingletonService);
261         singletonServiceGroup.ownershipChanged(getEntityToSlave());
262         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
263     }
264
265     /**
266      * Test GoldPath get Master role for registered main entity.
267      *
268      * @throws CandidateAlreadyRegisteredException - unexpected exception
269      */
270     @Test
271     public void tryToTakeLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
272         singletonServiceGroup.initialize();
273         verify(mockEosService).registerCandidate(MAIN_ENTITY);
274         singletonServiceGroup.registerService(mockClusterSingletonService);
275         singletonServiceGroup.ownershipChanged(getEntityToMaster());
276         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
277         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
278     }
279
280     /**
281      * Test GoldPath get Master role for registered close entity.
282      *
283      * @throws CandidateAlreadyRegisteredException - unexpected exception
284      */
285     @Test
286     public void takeMasterClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
287         singletonServiceGroup.initialize();
288         verify(mockEosService).registerCandidate(MAIN_ENTITY);
289         singletonServiceGroup.registerService(mockClusterSingletonService);
290         singletonServiceGroup.ownershipChanged(getEntityToMaster());
291         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
292         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
293         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
294         verify(mockClusterSingletonService).instantiateServiceInstance();
295     }
296
297     /**
298      * Test GoldPath get Master role for registered entity but initial Slave
299      *     role for closeEntity.
300      *
301      * @throws CandidateAlreadyRegisteredException - unexpected exception
302      */
303     @Test
304     public void waitToTakeMasterClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
305         singletonServiceGroup.initialize();
306         verify(mockEosService).registerCandidate(MAIN_ENTITY);
307         singletonServiceGroup.registerService(mockClusterSingletonService);
308         singletonServiceGroup.ownershipChanged(getEntityToMaster());
309         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
310         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
311         singletonServiceGroup.ownershipChanged(getInitDoubleEntityToSlave());
312         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
313         verify(mockClusterSingletonService, never()).closeServiceInstance();
314     }
315
316     /**
317      * Test inJeopardy validation during wait phase for Master role for closeEntity.
318      *
319      * @throws CandidateAlreadyRegisteredException - unexpected exception
320      */
321     @Test
322     public void inJeopardyInWaitPhaseClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
323         singletonServiceGroup.initialize();
324         verify(mockEosService).registerCandidate(MAIN_ENTITY);
325         singletonServiceGroup.registerService(mockClusterSingletonService);
326         singletonServiceGroup.ownershipChanged(getEntityToMaster());
327         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
328         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
329         singletonServiceGroup.ownershipChanged(getEntityToJeopardy());
330         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
331         verify(mockClusterSingletonService, never()).closeServiceInstance();
332     }
333
334     /**
335      * Test inJeopardy validation during wait phase for Master role for closeEntity.
336      *
337      * @throws CandidateAlreadyRegisteredException - unexpected exception
338      */
339     @Test
340     public void inJeopardyInWaitPhaseClusterSingletonServiceGroupTwoServiceTest()
341             throws CandidateAlreadyRegisteredException {
342         singletonServiceGroup.initialize();
343         verify(mockEosService).registerCandidate(MAIN_ENTITY);
344         singletonServiceGroup.registerService(mockClusterSingletonService);
345         singletonServiceGroup.registerService(mockClusterSingletonServiceSecond);
346         singletonServiceGroup.ownershipChanged(getEntityToMaster());
347         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
348         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
349         singletonServiceGroup.ownershipChanged(getEntityToJeopardy());
350         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
351         verify(mockClusterSingletonService, never()).closeServiceInstance();
352     }
353
354     /**
355      * Test inJeopardy validation for holding leadership.
356      *
357      * @throws CandidateAlreadyRegisteredException - unexpected exception
358      */
359     @Test
360     public void inJeopardyLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
361         singletonServiceGroup.initialize();
362         verify(mockEosService).registerCandidate(MAIN_ENTITY);
363         singletonServiceGroup.registerService(mockClusterSingletonService);
364         singletonServiceGroup.ownershipChanged(getEntityToMaster());
365         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
366         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
367         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
368         verify(mockClusterSingletonService).instantiateServiceInstance();
369
370         // Base entity in jeopardy should not matter...
371         singletonServiceGroup.ownershipChanged(getEntityToJeopardy());
372         verify(mockClusterSingletonService, never()).closeServiceInstance();
373
374         // ... application state is actually guarded by cleanup
375         singletonServiceGroup.ownershipChanged(getDoubleEntityToJeopardy());
376         verify(mockClusterSingletonService).closeServiceInstance();
377     }
378
379     /**
380      * Test GoldPath for SLAVE-TO-MASTER entity Candidate role change.
381      *
382      * @throws CandidateAlreadyRegisteredException - unexpected exception
383      */
384     @Test
385     public void lostLeaderClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
386         singletonServiceGroup.initialize();
387         verify(mockEosService).registerCandidate(MAIN_ENTITY);
388         singletonServiceGroup.registerService(mockClusterSingletonService);
389         singletonServiceGroup.ownershipChanged(getEntityToMaster());
390         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
391         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
392         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
393         verify(mockClusterSingletonService).instantiateServiceInstance();
394         singletonServiceGroup.ownershipChanged(getEntityToSlave());
395         verify(mockClusterSingletonService).closeServiceInstance();
396     }
397
398     /**
399      * Test checks validation Error processing for SLAVE-TO-MASTER entity Candidate role change.
400      *     Not initialized provider has to close and remove all singletonServices from Group and
401      *     Group itself remove too.
402      */
403     @Test(expected = RuntimeException.class)
404     public void tryToTakeLeaderForNotInitializedGroupTest() {
405         singletonServiceGroup.registerService(mockClusterSingletonService);
406     }
407
408     /**
409      * Test checks closing processing for close {@link ClusterSingletonServiceRegistration}.
410      *
411      * @throws CandidateAlreadyRegisteredException - unexpected exception
412      */
413     @Test
414     public void checkClosingRegistrationTest() throws CandidateAlreadyRegisteredException {
415         singletonServiceGroup.initialize();
416         verify(mockEosService).registerCandidate(MAIN_ENTITY);
417         singletonServiceGroup.registerService(mockClusterSingletonService);
418         singletonServiceGroup.ownershipChanged(getEntityToMaster());
419         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
420         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
421         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
422         verify(mockClusterSingletonService).instantiateServiceInstance();
423         assertTrue(singletonServiceGroup.unregisterService(mockClusterSingletonService));
424         verify(mockClusterSingletonService, never()).closeServiceInstance();
425         singletonServiceGroup.ownershipChanged(getEntityToSlaveNoMaster());
426         verify(mockClusterSingletonService).closeServiceInstance();
427     }
428
429     /**
430      * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change.
431      *
432      * @throws CandidateAlreadyRegisteredException - unexpected exception
433      */
434     @Test
435     public void checkClosingUnexpectedDoubleEntityForMasterOwnershipChangeRegistrationTest()
436             throws CandidateAlreadyRegisteredException {
437         singletonServiceGroup.initialize();
438         verify(mockEosService).registerCandidate(MAIN_ENTITY);
439         singletonServiceGroup.registerService(mockClusterSingletonService);
440         singletonServiceGroup.ownershipChanged(getEntityToMaster());
441         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
442         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
443         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
444         verify(mockClusterSingletonService).instantiateServiceInstance();
445         singletonServiceGroup.ownershipChanged(getDoubleEntityToSlave());
446         verify(mockClusterSingletonService).closeServiceInstance();
447     }
448
449     /**
450      * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change
451      *     without closeEntity registration.
452      *
453      * @throws CandidateAlreadyRegisteredException - unexpected exception
454      */
455     @Test
456     public void checkClosingUnexpectedDoubleEntityForSlaveOwnershipChangeRegistrationTest()
457             throws CandidateAlreadyRegisteredException {
458         singletonServiceGroup.initialize();
459         verify(mockEosService).registerCandidate(MAIN_ENTITY);
460         singletonServiceGroup.registerService(mockClusterSingletonService);
461         singletonServiceGroup.ownershipChanged(getEntityToSlave());
462         verify(mockClusterSingletonService, never()).instantiateServiceInstance();
463         verify(mockEosService, never()).registerCandidate(CLOSE_ENTITY);
464         singletonServiceGroup.ownershipChanged(getDoubleEntityToSlave());
465         verify(mockClusterSingletonService, never()).closeServiceInstance();
466     }
467
468     @Test
469     public void testRegisterCloseShutdown() throws CandidateAlreadyRegisteredException, InterruptedException,
470             ExecutionException {
471         initializeGroupAndStartService();
472
473         assertTrue(singletonServiceGroup.unregisterService(mockClusterSingletonService));
474         verify(mockClusterSingletonService, never()).closeServiceInstance();
475         verify(mockEntityCandReg, never()).close();
476
477         final ListenableFuture<?> future = singletonServiceGroup.closeClusterSingletonGroup();
478         assertNotNull(future);
479         assertFalse(future.isDone());
480         verify(mockClusterSingletonService, never()).closeServiceInstance();
481         verify(mockEntityCandReg).close();
482
483         singletonServiceGroup.ownershipChanged(getEntityToSlave());
484         verify(mockClusterSingletonService).closeServiceInstance();
485         verify(mockCloseEntityCandReg).close();
486
487         singletonServiceGroup.ownershipChanged(getDoubleEntityToSlave());
488         assertTrue(future.isDone());
489         assertNull(future.get());
490     }
491
492     private void initialize() throws CandidateAlreadyRegisteredException {
493         singletonServiceGroup.initialize();
494         verify(mockEosService).registerCandidate(MAIN_ENTITY);
495     }
496
497     private void initializeGroupAndStartService() throws CandidateAlreadyRegisteredException {
498         initialize();
499         singletonServiceGroup.registerService(mockClusterSingletonService);
500         singletonServiceGroup.ownershipChanged(getEntityToMaster());
501         verify(mockEosService).registerCandidate(CLOSE_ENTITY);
502         singletonServiceGroup.ownershipChanged(getDoubleEntityToMaster());
503         verify(mockClusterSingletonService).instantiateServiceInstance();
504     }
505
506     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getEntityToMaster() {
507         return new GenericEntityOwnershipChange<>(MAIN_ENTITY, EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED);
508     }
509
510     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getEntityToSlave() {
511         return new GenericEntityOwnershipChange<>(MAIN_ENTITY,
512                 EntityOwnershipChangeState.LOCAL_OWNERSHIP_LOST_NEW_OWNER);
513     }
514
515     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getEntityToSlaveNoMaster() {
516         return new GenericEntityOwnershipChange<>(MAIN_ENTITY,
517                 EntityOwnershipChangeState.LOCAL_OWNERSHIP_LOST_NO_OWNER);
518     }
519
520     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getEntityToJeopardy() {
521         return new GenericEntityOwnershipChange<>(MAIN_ENTITY,
522                 EntityOwnershipChangeState.REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
523     }
524
525     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getDoubleEntityToMaster() {
526         return new GenericEntityOwnershipChange<>(CLOSE_ENTITY, EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED);
527     }
528
529     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getDoubleEntityToSlave() {
530         return new GenericEntityOwnershipChange<>(CLOSE_ENTITY,
531                 EntityOwnershipChangeState.LOCAL_OWNERSHIP_LOST_NEW_OWNER);
532     }
533
534     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getInitDoubleEntityToSlave() {
535         return new GenericEntityOwnershipChange<>(CLOSE_ENTITY, EntityOwnershipChangeState.REMOTE_OWNERSHIP_CHANGED);
536     }
537
538     private static GenericEntityOwnershipChange<TestInstanceIdentifier, TestEntity> getDoubleEntityToJeopardy() {
539         return new GenericEntityOwnershipChange<>(CLOSE_ENTITY,
540                 EntityOwnershipChangeState.REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
541     }
542 }