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 / 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.DESTROYED, 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(getEntityMasterJeopardy());
153         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
154         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityMasterJeopardy());
155         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
156         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
157         verify(mockEosEntityListReg, never()).close();
158         verify(mockEosDoubleEntityListReg, never()).close();
159         verify(mockEntityCandReg, never()).close();
160         verify(mockDoubleEntityCandReg, never()).close();
161     }
162
163     /**
164      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
165      *
166      * @throws Exception if the condition does not meet
167      */
168     @Test
169     public void closeClusterSingletonServiceRegistrationMasterTest() throws Exception {
170         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
171                 .registerClusterSingletonService(clusterSingletonService);
172         assertNotNull(reg);
173         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
174         verify(mockEos).registerCandidate(ENTITY);
175         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
176         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
177         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
178         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
179         reg.close();
180         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
181         verify(mockEosEntityListReg, never()).close();
182         verify(mockEosDoubleEntityListReg, never()).close();
183         verify(mockEntityCandReg, atLeastOnce()).close();
184         verify(mockDoubleEntityCandReg, never()).close();
185         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
186         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
187         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
188         verify(mockEntityCandReg, atLeastOnce()).close();
189         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
190         verify(mockEosDoubleEntityListReg, never()).close();
191         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
192     }
193
194     /**
195      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
196      *
197      * @throws Exception if the condition does not meet
198      */
199     @Test
200     public void closeClusterSingletonServiceRegistrationMasterCloseWithNotificationTimesTest() throws Exception {
201         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
202                 .registerClusterSingletonService(clusterSingletonService);
203         assertNotNull(reg);
204         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
205         verify(mockEos).registerCandidate(ENTITY);
206         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
207         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
208         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
209         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
210         reg.close();
211         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
212         verify(mockEosEntityListReg, never()).close();
213         verify(mockEosDoubleEntityListReg, never()).close();
214         verify(mockEntityCandReg, atLeastOnce()).close();
215         verify(mockDoubleEntityCandReg, never()).close();
216         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
217         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
218         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
219         verify(mockEntityCandReg, atLeastOnce()).close();
220         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
221         verify(mockEosDoubleEntityListReg, never()).close();
222         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
223     }
224
225     /**
226      * Test checks close processing for {@link ClusterSingletonServiceRegistration}.
227      *
228      * @throws Exception if the condition does not meet
229      */
230     @Test
231     public void closeClusterSingletonServiceRegistrationMasterCloseCoupleTimesTest() throws Exception {
232         final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider
233                 .registerClusterSingletonService(clusterSingletonService);
234         assertNotNull(reg);
235         assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState());
236         verify(mockEos).registerCandidate(ENTITY);
237         clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster());
238         verify(mockEos).registerCandidate(DOUBLE_ENTITY);
239         clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster());
240         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
241         reg.close();
242         reg.close();
243         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
244         verify(mockEosEntityListReg, never()).close();
245         verify(mockEosDoubleEntityListReg, never()).close();
246         verify(mockEntityCandReg, atLeastOnce()).close();
247         verify(mockDoubleEntityCandReg, never()).close();
248         assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState());
249         clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave());
250         Thread.sleep(ASYNC_TIME_DELAY_MILLIS * 2);
251         verify(mockEntityCandReg, atLeastOnce()).close();
252         verify(mockDoubleEntityCandReg, atLeastOnce()).close();
253         verify(mockEosDoubleEntityListReg, never()).close();
254         assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState());
255     }
256 }