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