b581188cb1f60d86292f791c7284173c3ccde90d
[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 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 ClusterSingletonServiceGroupImpl}.
46  */
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);
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     public ClusterSingletonServiceGroupImpl singletonServiceGroup;
69
70     public ServiceRegistration firstReg;
71     public ServiceRegistration secondReg;
72
73     /**
74      * Initialization functionality for every Tests in this suite.
75      *
76      * @throws CandidateAlreadyRegisteredException unexpected exception.
77      */
78     @Before
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();
86
87         doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonService).getIdentifier();
88         doReturn(SERVICE_GROUP_IDENT).when(mockClusterSingletonServiceSecond).getIdentifier();
89
90         firstReg = new ServiceRegistration(mockClusterSingletonService) {
91             @Override
92             protected void removeRegistration() {
93                 // No-op
94             }
95         };
96         secondReg = new ServiceRegistration(mockClusterSingletonServiceSecond) {
97             @Override
98             protected void removeRegistration() {
99                 // No-op
100             }
101         };
102
103         singletonServiceGroup = new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY,
104             mockEosService);
105     }
106
107     /**
108      * Test NULL ServiceIdent input for new ServiceGroup instance.
109      */
110     @Test
111     public void instantiationClusterSingletonServiceGroupNullIdentTest() {
112         assertThrows(NullPointerException.class,
113             () -> new ClusterSingletonServiceGroupImpl(null, MAIN_ENTITY, CLOSE_ENTITY, mockEosService));
114     }
115
116     /**
117      * Test empty ServiceIdent input for new ServiceGroup instance.
118      */
119     @Test
120     public void instantiationClusterSingletonServiceGroupEmptyIdentTest() {
121         assertThrows(IllegalArgumentException.class,
122             () -> new ClusterSingletonServiceGroupImpl("", MAIN_ENTITY, CLOSE_ENTITY, mockEosService));
123     }
124
125     /**
126      * Test NULL MainEntity input for new ServiceGroup instance.
127      */
128     @Test
129     public void instantiationClusterSingletonServiceGroupNullMainEntityTest() {
130         assertThrows(NullPointerException.class,
131             () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, null, CLOSE_ENTITY, mockEosService));
132     }
133
134     /**
135      * Test NULL CloseEntity input for new ServiceGroup instance.
136      */
137     @Test
138     public void instantiationClusterSingletonServiceGroupNullCloseEntityTest() {
139         assertThrows(NullPointerException.class,
140             () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, null, mockEosService));
141     }
142
143     /**
144      * Test NULL EntityOwnershipService input for new ServiceGroup instance.
145      */
146     @Test
147     public void instantiationClusterSingletonServiceGroupNullEOS_Test() {
148         assertThrows(NullPointerException.class,
149             () -> new ClusterSingletonServiceGroupImpl(SERVICE_IDENTIFIER, MAIN_ENTITY, CLOSE_ENTITY, null));
150     }
151
152     /**
153      * Test GoldPath for initialization ServiceGroup.
154      */
155     @Test
156     public void initializationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
157         singletonServiceGroup.initialize();
158         verify(mockEosService).registerCandidate(MAIN_ENTITY);
159     }
160
161     /**
162      * Test GoldPath for NO-TO-SLAVE entity Candidate role change.
163      *
164      * @throws CandidateAlreadyRegisteredException - unexpected exception
165      */
166     @Test
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);
174     }
175
176     /**
177      * Test GoldPath for NO-TO-SLAVE but without MASTER entity Candidate role change.
178      *
179      * @throws CandidateAlreadyRegisteredException - unexpected exception
180      */
181     @Test
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);
189     }
190
191     /**
192      * Test GoldPath for InJeopardy entity Candidate role change.
193      *
194      * @throws CandidateAlreadyRegisteredException - unexpected exception
195      */
196     @Test
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);
204     }
205
206     /**
207      * Test GoldPath for registration SingletonService.
208      *
209      * @throws CandidateAlreadyRegisteredException - unexpected exception
210      */
211     @Test
212     public void serviceRegistrationClusterSingletonServiceGroupTest() throws CandidateAlreadyRegisteredException {
213         singletonServiceGroup.initialize();
214         verify(mockEosService).registerCandidate(MAIN_ENTITY);
215         singletonServiceGroup.registerService(firstReg);
216     }
217
218     /**
219      * Test GoldPath for registration SingletonService.
220      *
221      * @throws CandidateAlreadyRegisteredException - unexpected exception
222      */
223     @Test
224     public void serviceRegistrationClusterSingletonServiceGroupTwoServiceTest()
225             throws CandidateAlreadyRegisteredException {
226         singletonServiceGroup.initialize();
227         verify(mockEosService).registerCandidate(MAIN_ENTITY);
228         singletonServiceGroup.registerService(firstReg);
229         singletonServiceGroup.registerService(secondReg);
230     }
231
232     /**
233      * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
234      * without mastership and don't remove ServiceGroup from map.
235      *
236      * @throws CandidateAlreadyRegisteredException - unexpected exception
237      */
238     @Test
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();
245     }
246
247     /**
248      * Test GoldPath for unregistration SingletonService don't call closeServiceInstance
249      *     without mastership and don't remove ServiceGroup from map.
250      *
251      * @throws CandidateAlreadyRegisteredException - unexpected exception
252      */
253     @Test
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();
262     }
263
264     /**
265      * Test GoldPath get Slave role for registered main entity.
266      *
267      * @throws CandidateAlreadyRegisteredException - unexpected exception
268      */
269     @Test
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();
276     }
277
278     /**
279      * Test GoldPath get Master role for registered main entity.
280      *
281      * @throws CandidateAlreadyRegisteredException - unexpected exception
282      */
283     @Test
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);
291     }
292
293     /**
294      * Test GoldPath get Master role for registered close entity.
295      *
296      * @throws CandidateAlreadyRegisteredException - unexpected exception
297      */
298     @Test
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();
308     }
309
310     /**
311      * Test GoldPath get Master role for registered entity but initial Slave
312      *     role for closeEntity.
313      *
314      * @throws CandidateAlreadyRegisteredException - unexpected exception
315      */
316     @Test
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();
327     }
328
329     /**
330      * Test inJeopardy validation during wait phase for Master role for closeEntity.
331      *
332      * @throws CandidateAlreadyRegisteredException - unexpected exception
333      */
334     @Test
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();
345     }
346
347     /**
348      * Test inJeopardy validation during wait phase for Master role for closeEntity.
349      *
350      * @throws CandidateAlreadyRegisteredException - unexpected exception
351      */
352     @Test
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();
365     }
366
367     /**
368      * Test inJeopardy validation for holding leadership.
369      *
370      * @throws CandidateAlreadyRegisteredException - unexpected exception
371      */
372     @Test
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();
382
383         // Base entity in jeopardy should not matter...
384         singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_GRANTED, true);
385         verify(mockClusterSingletonService, never()).closeServiceInstance();
386
387         // ... application state is actually guarded by cleanup
388         singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, REMOTE_OWNERSHIP_LOST_NO_OWNER, true);
389         verify(mockClusterSingletonService).closeServiceInstance();
390     }
391
392     /**
393      * Test GoldPath for SLAVE-TO-MASTER entity Candidate role change.
394      *
395      * @throws CandidateAlreadyRegisteredException - unexpected exception
396      */
397     @Test
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();
409     }
410
411     /**
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.
415      */
416     @Test(expected = IllegalStateException.class)
417     public void tryToTakeLeaderForNotInitializedGroupTest() {
418         singletonServiceGroup.registerService(firstReg);
419     }
420
421     /**
422      * Test checks closing processing for close {@link ServiceRegistration}.
423      *
424      * @throws CandidateAlreadyRegisteredException - unexpected exception
425      */
426     @Test
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();
440     }
441
442     /**
443      * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change.
444      *
445      * @throws CandidateAlreadyRegisteredException - unexpected exception
446      */
447     @Test
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();
460     }
461
462     /**
463      * Test checks validation Error processing for MASTER-TO-SLAVE closeEntity Candidate role change
464      *     without closeEntity registration.
465      *
466      * @throws CandidateAlreadyRegisteredException - unexpected exception
467      */
468     @Test
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();
479     }
480
481     @Test
482     public void testRegisterCloseShutdown() throws CandidateAlreadyRegisteredException, InterruptedException,
483             ExecutionException {
484         initializeGroupAndStartService();
485
486         assertNotNull(singletonServiceGroup.unregisterService(firstReg));
487         verify(mockClusterSingletonService, never()).closeServiceInstance();
488         verify(mockEntityCandReg).close();
489
490         final ListenableFuture<?> future = singletonServiceGroup.closeClusterSingletonGroup();
491         assertNotNull(future);
492         assertFalse(future.isDone());
493         verify(mockClusterSingletonService).closeServiceInstance();
494
495         singletonServiceGroup.ownershipChanged(MAIN_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
496         verify(mockCloseEntityCandReg).close();
497
498         singletonServiceGroup.ownershipChanged(CLOSE_ENTITY, LOCAL_OWNERSHIP_LOST_NEW_OWNER, false);
499         assertTrue(future.isDone());
500         assertNull(future.get());
501     }
502
503     private void initialize() throws CandidateAlreadyRegisteredException {
504         singletonServiceGroup.initialize();
505         verify(mockEosService).registerCandidate(MAIN_ENTITY);
506     }
507
508     private void initializeGroupAndStartService() throws CandidateAlreadyRegisteredException {
509         initialize();
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();
515     }
516 }