Rework ClusterSingletonServiceGroupImpl locking
[mdsal.git] / singleton-service / mdsal-singleton-dom-impl / src / test / java / org / opendaylight / mdsal / singleton / dom / impl / DOMClusterSingletonServiceProviderImplTest.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.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.mockito.Mockito.atLeastOnce;
14 import static org.mockito.Mockito.never;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
21 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
22 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
23
24 /**
25  * Synchronous test suite.
26  */
27 public class DOMClusterSingletonServiceProviderImplTest extends AbstractDOMClusterServiceProviderTest {
28     /**
29      * Initialization functionality for every Tests in this suite.
30      *
31      * @throws CandidateAlreadyRegisteredException if the condition does not meet
32      */
33     @Override
34     @Before
35     public void setup() throws CandidateAlreadyRegisteredException {
36         super.setup();
37     }
38
39     /**
40      * Test GoldPath for takeLeadership with ownership result MASTER {@link ClusterSingletonService}.
41      *
42      * @throws Exception if the condition does not meet
43      */
44     @Test
45     public void takeDoubleLeadershipClusterSingletonServiceTest() throws Exception {
46         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
47                 .registerClusterSingletonService(clusterSingletonService);
48         assertNotNull(reg);
49         verify(mockEos).registerCandidate(ENTITY);
50         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
51         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
52         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
53         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
54         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
55         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
56         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
57         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
58         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
59         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
60         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
61         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
62         verify(mockEosDoubleEntityListReg, never()).close();
63         verify(mockEosEntityListReg, never()).close();
64         verify(mockEntityCandReg, never()).close();
65         verify(mockDoubleEntityCandReg).close();
66     }
67
68     /**
69      * Test checks unexpected change for MASTER-TO-SLAVE double Candidate role change.
70      *
71      * @throws Exception if the condition does not meet
72      */
73     @Test
74     public void unexpectedLostLeadershipDoubleCandidateTest() throws Exception {
75         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
76                 .registerClusterSingletonService(clusterSingletonService);
77         assertNotNull(reg);
78         verify(mockEos).registerCandidate(ENTITY);
79         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
80         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
81         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
82         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
83         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
84         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
85         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
86         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToSlave());
87         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
88         verify(mockEosDoubleEntityListReg, never()).close();
89         verify(mockEntityCandReg, never()).close();
90         verify(mockDoubleEntityCandReg, never()).close();
91         reg.close();
92         verify(mockEosEntityListReg, never()).close();
93         verify(mockEosDoubleEntityListReg, never()).close();
94         verify(mockEntityCandReg, atLeastOnce()).close();
95         verify(mockDoubleEntityCandReg).close();
96         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
97         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
98         verify(mockEntityCandReg).close();
99         verify(mockEosDoubleEntityListReg, never()).close();
100     }
101
102     /**
103      * Test checks inJeopardy Cluster Node state for Master Instance.
104      *
105      * @throws Exception if the condition does not meet
106      */
107     @Test
108     public void inJeopardyMasterTest() throws Exception {
109         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
110                 .registerClusterSingletonService(clusterSingletonService);
111         assertNotNull(reg);
112         verify(mockEos).registerCandidate(ENTITY);
113         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
114         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
115         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
116         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
117         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
118         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
119         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
120         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToJeopardy());
121         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
122         verify(mockEosEntityListReg, never()).close();
123         verify(mockEosDoubleEntityListReg, never()).close();
124         verify(mockEntityCandReg, never()).close();
125         verify(mockDoubleEntityCandReg, never()).close();
126     }
127
128     /**
129      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
130      *
131      * @throws Exception if the condition does not meet
132      */
133     @Test
134     public void closeClusterSingletonServiceRegistrationMasterTest() throws Exception {
135         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
136                 .registerClusterSingletonService(clusterSingletonService);
137         assertNotNull(reg);
138         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
139         verify(mockEos).registerCandidate(ENTITY);
140         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
141         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
142         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
143         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
144         reg.close();
145         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
146         verify(mockEosEntityListReg, never()).close();
147         verify(mockEosDoubleEntityListReg, never()).close();
148         verify(mockEntityCandReg).close();
149         verify(mockDoubleEntityCandReg).close();
150         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
151     }
152
153     /**
154      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
155      *
156      * @throws Exception if the condition does not meet
157      */
158     @Test
159     public void closeClusterSingletonServiceRegistrationMasterCloseWithNotificationTimesTest() throws Exception {
160         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
161                 .registerClusterSingletonService(clusterSingletonService);
162         assertNotNull(reg);
163         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
164         verify(mockEos).registerCandidate(ENTITY);
165         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
166         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
167         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
168         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
169         reg.close();
170         verify(mockEosEntityListReg, never()).close();
171         verify(mockEosDoubleEntityListReg, never()).close();
172         verify(mockEntityCandReg, atLeastOnce()).close();
173         verify(mockDoubleEntityCandReg).close();
174         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
175     }
176
177     /**
178      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
179      *
180      * @throws Exception if the condition does not meet
181      */
182     @Test
183     public void closeClusterSingletonServiceRegistrationMasterCloseCoupleTimesTest() throws Exception {
184         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
185                 .registerClusterSingletonService(clusterSingletonService);
186         assertNotNull(reg);
187         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
188         verify(mockEos).registerCandidate(ENTITY);
189         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
190         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
191         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
192         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
193         reg.close();
194         reg.close();
195         verify(mockEosEntityListReg, never()).close();
196         verify(mockEosDoubleEntityListReg, never()).close();
197         verify(mockEntityCandReg).close();
198         verify(mockDoubleEntityCandReg).close();
199         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
200         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
201         verify(mockEosDoubleEntityListReg, never()).close();
202     }
203
204     /**
205      * Verify that closing a group does not prevent next incarnation of it to be registered and the next incarnation
206      * will become active once the old incarnation finishes cleaning up.
207      */
208     @Test
209     public void testTwoIncarnations() throws Exception {
210         ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
211                 .registerClusterSingletonService(clusterSingletonService);
212         assertNotNull(reg);
213         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
214         verify(mockEos).registerCandidate(ENTITY);
215         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
216         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
217         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
218         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
219
220         // Close, triggers unregistration, but we will not continue with it.
221         reg.close();
222         verify(mockEosEntityListReg, never()).close();
223         verify(mockEosDoubleEntityListReg, never()).close();
224         verify(mockEntityCandReg).close();
225         verify(mockDoubleEntityCandReg).close();
226         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
227
228         // Instantiate the next incarnation
229         reg = clusterSingletonServiceProvider.registerClusterSingletonService(clusterSingletonService2);
230         verify(mockEos).registerCandidate(ENTITY);
231         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService2.getServiceState());
232
233         // Drive the old incarnation to closure, resetting mocks as needed
234         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
235         verify(mockEosDoubleEntityListReg, never()).close();
236
237         // Reset mocks for reuse. The next change should see the previous group terminate and the next incarnation
238         // to start coming up
239         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToSlave());
240         verify(mockEos, times(2)).registerCandidate(ENTITY);
241         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
242         verify(mockEos, times(2)).registerCandidate(DOUBLE_ENTITY);
243         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
244         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService2.getServiceState());
245
246         // Check for potential service mixup
247         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
248
249         verify(mockEosEntityListReg, never()).close();
250         verify(mockEosDoubleEntityListReg, never()).close();
251     }
252 }