BUG-8858: rework singleton group locking
[mdsal.git] / singleton-service / mdsal-singleton-dom-impl / src / test / java / org / opendaylight / mdsal / singleton / dom / impl / DOMClusterSingletonServiceProviderAsyncImplTest.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.verify;
16
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.SettableFuture;
19 import java.util.Timer;
20 import java.util.TimerTask;
21 import org.junit.AfterClass;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
25 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
26
27 /*
28  * Testing {@link DOMClusterSingletonServiceProviderImpl} implementation
29  */
30 public final class DOMClusterSingletonServiceProviderAsyncImplTest extends AbstractDOMClusterServiceProviderTest {
31     /*
32      * Test implementation of {@link ClusterSingletonService}
33      */
34     static class TestClusterSingletonAsyncServiceInstance extends TestClusterSingletonService {
35         @Override
36         public ListenableFuture<Void> closeServiceInstance() {
37             super.closeServiceInstance();
38
39             final SettableFuture<Void> future = SettableFuture.create();
40             TIMER.schedule(new TimerTask() {
41                 @Override
42                 public void run() {
43                     future.set(null);
44                 }
45             }, ASYNC_TIME_DELAY_MILLIS);
46             return future;
47         }
48     }
49
50     protected static final long ASYNC_TIME_DELAY_MILLIS = 100L;
51     protected static Timer TIMER;
52
53     @BeforeClass
54     public static void asyncInitTest() {
55         TIMER = new Timer();
56     }
57
58     @AfterClass
59     public static void cleanTest() {
60         TIMER.cancel();
61     }
62
63     @Override
64     TestClusterSingletonService instantiateService() {
65         return new TestClusterSingletonAsyncServiceInstance();
66     }
67
68     /**
69      * Test GoldPath for takeLeadership with ownership result MASTER {@link ClusterSingletonService}.
70      *
71      * @throws Exception if the condition does not meet
72      */
73     @Test
74     public void takeDoubleLeadershipClusterSingletonServiceTest() 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(getDoubleEntityToMaster());
83         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
84         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
85         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
86         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
87         verify(mockDoubleEntityCandReg).close();
88         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
89         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
90         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
91         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
92         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
93         verify(mockEosDoubleEntityListReg, never()).close();
94         verify(mockEosEntityListReg, never()).close();
95         verify(mockEntityCandReg, never()).close();
96     }
97
98     /**
99      * Test checks unexpected change for MASTER-TO-SLAVE double Candidate role change.
100      *
101      * @throws Exception if the condition does not meet
102      */
103     @Test
104     public void unexpectedLostLeadershipDoubleCandidateTest() throws Exception {
105         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
106                 .registerClusterSingletonService(clusterSingletonService);
107         assertNotNull(reg);
108         verify(mockEos).registerCandidate(ENTITY);
109         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
110         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
111         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
112         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
113         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
114         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
115         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
116         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToSlave());
117         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
118         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
119         verify(mockEosDoubleEntityListReg, never()).close();
120         verify(mockEntityCandReg, never()).close();
121         verify(mockDoubleEntityCandReg, never()).close();
122         reg.close();
123         verify(mockEosDoubleEntityListReg, never()).close();
124         verify(mockEntityCandReg, atLeastOnce()).close();
125         verify(mockDoubleEntityCandReg, never()).close();
126         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
127         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
128         verify(mockEntityCandReg, atLeastOnce()).close();
129         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
130         verify(mockEosDoubleEntityListReg, never()).close();
131         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
132     }
133
134     /**
135      * Test checks inJeopardy Cluster Node state for Master Instance.
136      *
137      * @throws Exception if the condition does not meet
138      */
139     @Test
140     public void inJeopardyMasterTest() throws Exception {
141         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
142                 .registerClusterSingletonService(clusterSingletonService);
143         assertNotNull(reg);
144         verify(mockEos).registerCandidate(ENTITY);
145         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
146         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
147         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
148         clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave());
149         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
150         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
151         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
152         clusterSingletonServiceProvider.ownershipChanged(getEntityToJeopardy());
153         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
154         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
155         verify(mockEosEntityListReg, never()).close();
156         verify(mockEosDoubleEntityListReg, never()).close();
157         verify(mockEntityCandReg, never()).close();
158         verify(mockDoubleEntityCandReg).close();
159     }
160
161     /**
162      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
163      *
164      * @throws Exception if the condition does not meet
165      */
166     @Test
167     public void closeClusterSingletonServiceRegistrationMasterTest() throws Exception {
168         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
169                 .registerClusterSingletonService(clusterSingletonService);
170         assertNotNull(reg);
171         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
172         verify(mockEos).registerCandidate(ENTITY);
173         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
174         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
175         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
176         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
177         reg.close();
178         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
179         verify(mockEosEntityListReg, never()).close();
180         verify(mockEosDoubleEntityListReg, never()).close();
181         verify(mockEntityCandReg, atLeastOnce()).close();
182         verify(mockDoubleEntityCandReg, never()).close();
183         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
184         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
185         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
186         verify(mockEntityCandReg, atLeastOnce()).close();
187         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
188         verify(mockEosDoubleEntityListReg, never()).close();
189         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
190     }
191
192     /**
193      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
194      *
195      * @throws Exception if the condition does not meet
196      */
197     @Test
198     public void closeClusterSingletonServiceRegistrationMasterCloseWithNotificationTimesTest() throws Exception {
199         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
200                 .registerClusterSingletonService(clusterSingletonService);
201         assertNotNull(reg);
202         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
203         verify(mockEos).registerCandidate(ENTITY);
204         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
205         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
206         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
207         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
208         reg.close();
209         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
210         verify(mockEosEntityListReg, never()).close();
211         verify(mockEosDoubleEntityListReg, never()).close();
212         verify(mockEntityCandReg, atLeastOnce()).close();
213         verify(mockDoubleEntityCandReg, never()).close();
214         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
215         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
216         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
217         verify(mockEntityCandReg, atLeastOnce()).close();
218         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
219         verify(mockEosDoubleEntityListReg, never()).close();
220         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
221     }
222
223     /**
224      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
225      *
226      * @throws Exception if the condition does not meet
227      */
228     @Test
229     public void closeClusterSingletonServiceRegistrationMasterCloseCoupleTimesTest() throws Exception {
230         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
231                 .registerClusterSingletonService(clusterSingletonService);
232         assertNotNull(reg);
233         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
234         verify(mockEos).registerCandidate(ENTITY);
235         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
236         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
237         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
238         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
239         reg.close();
240         reg.close();
241         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
242         verify(mockEosEntityListReg, never()).close();
243         verify(mockEosDoubleEntityListReg, never()).close();
244         verify(mockEntityCandReg, atLeastOnce()).close();
245         verify(mockDoubleEntityCandReg, never()).close();
246         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
247         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
248         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
249         verify(mockEntityCandReg, atLeastOnce()).close();
250         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
251         verify(mockEosDoubleEntityListReg, never()).close();
252         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
253     }
254 }