2 * ============LICENSE_START=======================================================
3 * feature-active-standby-management
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.drools.activestandby;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.when;
30 import java.io.FileInputStream;
31 import java.io.IOException;
32 import java.util.Date;
33 import java.util.Properties;
34 import java.util.concurrent.Callable;
35 import javax.persistence.EntityManager;
36 import javax.persistence.EntityManagerFactory;
37 import javax.persistence.EntityTransaction;
38 import javax.persistence.Persistence;
39 import org.apache.commons.lang3.time.DateUtils;
40 import org.junit.AfterClass;
41 import org.junit.Before;
42 import org.junit.BeforeClass;
43 import org.junit.Test;
44 import org.onap.policy.common.im.IntegrityMonitor;
45 import org.onap.policy.common.im.IntegrityMonitorException;
46 import org.onap.policy.common.im.MonitorTime;
47 import org.onap.policy.common.im.StateManagement;
48 import org.onap.policy.common.utils.time.CurrentTime;
49 import org.onap.policy.common.utils.time.PseudoTimer;
50 import org.onap.policy.common.utils.time.TestTimeMulti;
51 import org.onap.policy.drools.core.PolicySessionFeatureApi;
52 import org.onap.policy.drools.statemanagement.StateManagementFeatureApi;
53 import org.onap.policy.drools.statemanagement.StateManagementFeatureApiConstants;
54 import org.powermock.reflect.Whitebox;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 * Testing the allSeemsWell interface to verify that it correctly affects the
63 public class AllSeemsWellTest {
64 private static final Logger logger = LoggerFactory.getLogger(AllSeemsWellTest.class);
66 private static final String MONITOR_FIELD_NAME = "instance";
67 private static final String HANDLER_INSTANCE_FIELD = "electionHandler";
70 * Currently, the DroolsPdpsElectionHandler.DesignationWaiter is invoked every 1 seconds, starting
71 * at the start of the next multiple of pdpUpdateInterval, but with a minimum of 5 sec cushion
72 * to ensure that we wait for the DesignationWaiter to do its job, before
73 * checking the results. Add a few seconds for safety
76 private static final int SLEEP_TIME_SEC = 10;
79 * DroolsPdpsElectionHandler runs every 1 seconds, so it takes 10 seconds for the
80 * checkWaitTimer() method to time out and call allSeemsWell which then requires
81 * the forward progress counter to go stale which should add an additional 5 sec.
84 private static final int STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC = 15;
87 * As soon as the election hander successfully runs, it will resume the forward progress.
88 * If the election handler runs ever 1 sec and test transaction is run every 1 sec and
89 * then fpc is written every 1 sec and then the fpc is checked every 2 sec, that could
90 * take a total of 5 sec to recognize the resumption of progress. So, add 1 for safety.
92 private static final int RESUMED_ELECTION_HANDLER_SLEEP_TIME_SEC = 6;
94 private static EntityManagerFactory emfx;
95 private static EntityManagerFactory emfd;
96 private static EntityManager emx;
97 private static EntityManager emd;
98 private static EntityTransaction et;
100 private static final String CONFIG_DIR = "src/test/resources/asw";
102 private static CurrentTime saveTime;
103 private static Factory saveFactory;
105 private TestTimeMulti testTime;
108 * See the IntegrityMonitor.getJmxUrl() method for the rationale behind this jmx related processing.
114 * @throws Exception exception
117 public static void setUpClass() throws Exception {
119 String userDir = System.getProperty("user.dir");
120 logger.debug("setUpClass: userDir={}", userDir);
121 System.setProperty("com.sun.management.jmxremote.port", "9980");
122 System.setProperty("com.sun.management.jmxremote.authenticate", "false");
124 DroolsPdpsElectionHandler.setIsUnitTesting(true);
126 saveTime = Whitebox.getInternalState(MonitorTime.class, MONITOR_FIELD_NAME);
127 saveFactory = Factory.getInstance();
129 resetInstanceObjects();
131 //Create the data access for xacml db
132 Properties stateManagementProperties = loadStateManagementProperties();
134 emfx = Persistence.createEntityManagerFactory("junitXacmlPU", stateManagementProperties);
136 // Create an entity manager to use the DB
137 emx = emfx.createEntityManager();
139 //Create the data access for drools db
140 Properties activeStandbyProperties = loadActiveStandbyProperties();
142 emfd = Persistence.createEntityManagerFactory("junitDroolsPU", activeStandbyProperties);
144 // Create an entity manager to use the DB
145 emd = emfd.createEntityManager();
149 * Restores the system state.
151 * @throws IntegrityMonitorException if the integrity monitor cannot be shut down
154 public static void tearDownClass() throws IntegrityMonitorException {
155 resetInstanceObjects();
157 Whitebox.setInternalState(MonitorTime.class, MONITOR_FIELD_NAME, saveTime);
158 Factory.setInstance(saveFactory);
160 DroolsPdpsElectionHandler.setIsUnitTesting(false);
172 * @throws Exception exception
175 public void setUp() throws Exception {
176 resetInstanceObjects();
179 testTime = new TestTimeMulti();
180 Whitebox.setInternalState(MonitorTime.class, MONITOR_FIELD_NAME, testTime);
182 Factory factory = mock(Factory.class);
183 when(factory.makeTimer()).thenAnswer(ans -> new PseudoTimer(testTime));
184 Factory.setInstance(factory);
187 private static void resetInstanceObjects() throws IntegrityMonitorException {
188 IntegrityMonitor.setUnitTesting(true);
189 IntegrityMonitor.deleteInstance();
190 IntegrityMonitor.setUnitTesting(false);
192 Whitebox.setInternalState(ActiveStandbyFeature.class, HANDLER_INSTANCE_FIELD, (Object) null);
197 * Clean the xacml database.
199 public void cleanXacmlDb() {
200 et = emx.getTransaction();
203 // Make sure we leave the DB clean
204 emx.createQuery("DELETE FROM StateManagementEntity").executeUpdate();
205 emx.createQuery("DELETE FROM ResourceRegistrationEntity").executeUpdate();
206 emx.createQuery("DELETE FROM ForwardProgressEntity").executeUpdate();
212 * Clean the drools database.
214 public void cleanDroolsDb() {
215 et = emd.getTransaction();
218 // Make sure we leave the DB clean
219 emd.createQuery("DELETE FROM DroolsPdpEntity").executeUpdate();
225 // Tests hot standby when there is only one PDP.
229 public void testAllSeemsWell() throws Exception {
231 logger.debug("\n\ntestAllSeemsWell: Entering\n\n");
235 Properties stateManagementProperties = loadStateManagementProperties();
237 logger.debug("testAllSeemsWell: Creating emfXacml");
238 final EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory(
239 "junitXacmlPU", stateManagementProperties);
241 Properties activeStandbyProperties = loadActiveStandbyProperties();
242 final String thisPdpId = activeStandbyProperties
243 .getProperty(ActiveStandbyProperties.NODE_NAME);
245 logger.debug("testAllSeemsWell: Creating emfDrools");
246 EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory(
247 "junitDroolsPU", activeStandbyProperties);
249 DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools);
251 logger.debug("testAllSeemsWell: Cleaning up tables");
252 conn.deleteAllPdps();
255 * Insert this PDP as not designated. Initial standby state will be
256 * either null or cold standby. Demoting should transit state to
260 logger.debug("testAllSeemsWell: Inserting PDP={} as not designated", thisPdpId);
261 Date yesterday = DateUtils.addDays(testTime.getDate(), -1);
262 DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday);
264 DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId);
265 logger.debug("testAllSeemsWell: After insertion, PDP={} has DESIGNATED={}",
266 thisPdpId, droolsPdpEntity.isDesignated());
267 assertFalse(droolsPdpEntity.isDesignated());
269 logger.debug("testAllSeemsWell: Instantiating stateManagement object");
270 StateManagement sm = new StateManagement(emfXacml, "dummy");
271 sm.deleteAllStateManagementEntities();
274 // Now we want to create a StateManagementFeature and initialize it. It will be
275 // discovered by the ActiveStandbyFeature when the election handler initializes.
277 StateManagementFeatureApi stateManagementFeatureApi = null;
278 for (StateManagementFeatureApi feature : StateManagementFeatureApiConstants.getImpl().getList()) {
279 ((PolicySessionFeatureApi) feature).globalInit(null, CONFIG_DIR);
280 stateManagementFeatureApi = feature;
281 logger.debug("testAllSeemsWell stateManagementFeature.getResourceName(): {}",
282 stateManagementFeatureApi.getResourceName());
285 assertNotNull(stateManagementFeatureApi);
287 final StateManagementFeatureApi smf = stateManagementFeatureApi;
289 // Create an ActiveStandbyFeature and initialize it. It will discover the StateManagementFeature
290 // that has been created.
291 ActiveStandbyFeatureApi activeStandbyFeature = null;
292 for (ActiveStandbyFeatureApi feature : ActiveStandbyFeatureApiConstants.getImpl().getList()) {
293 ((PolicySessionFeatureApi) feature).globalInit(null, CONFIG_DIR);
294 activeStandbyFeature = feature;
295 logger.debug("testAllSeemsWell activeStandbyFeature.getResourceName(): {}",
296 activeStandbyFeature.getResourceName());
299 assertNotNull(activeStandbyFeature);
302 logger.debug("testAllSeemsWell: Demoting PDP={}", thisPdpId);
303 // demoting should cause state to transit to hotstandby
307 logger.debug("testAllSeemsWell: Sleeping {} s, to allow JpaDroolsPdpsConnector "
308 + "time to check droolspdpentity table", SLEEP_TIME_SEC);
309 waitForCondition(() -> conn.getPdp(thisPdpId).isDesignated(), SLEEP_TIME_SEC);
311 // Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service.
313 droolsPdpEntity = conn.getPdp(thisPdpId);
314 logger.debug("testAllSeemsWell: After sm.demote() invoked, DESIGNATED= {} "
315 + "for PDP= {}", droolsPdpEntity.isDesignated(), thisPdpId);
316 assertTrue(droolsPdpEntity.isDesignated());
317 String standbyStatus = smf.getStandbyStatus(thisPdpId);
318 logger.debug("testAllSeemsWell: After demotion, PDP= {} "
319 + "has standbyStatus= {}", thisPdpId, standbyStatus);
320 assertTrue(standbyStatus != null && standbyStatus.equals(StateManagement.PROVIDING_SERVICE));
322 //Now we want to stall the election handler and see the if AllSeemsWell will make the
323 //standbystatus = coldstandby
325 DroolsPdpsElectionHandler.setIsStalled(true);
327 logger.debug("testAllSeemsWell: Sleeping {} s, to allow checkWaitTimer to recognize "
328 + "the election handler has stalled and for the testTransaction to fail to "
329 + "increment forward progress and for the lack of forward progress to be recognized.",
330 STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC);
333 //It takes 10x the update interval (1 sec) before the watcher will declare the election handler dead
334 //and that just stops forward progress counter. So, the fp monitor must then run to determine
335 // if the fpc has stalled. That will take about another 5 sec.
336 waitForCondition(() -> smf.getStandbyStatus().equals(StateManagement.COLD_STANDBY),
337 STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC);
339 logger.debug("testAllSeemsWell: After isStalled=true, PDP= {} "
340 + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId));
341 assertEquals(StateManagement.COLD_STANDBY, smf.getStandbyStatus());
343 //Now lets resume the election handler
344 DroolsPdpsElectionHandler.setIsStalled(false);
346 waitForCondition(() -> smf.getStandbyStatus().equals(StateManagement.PROVIDING_SERVICE),
347 RESUMED_ELECTION_HANDLER_SLEEP_TIME_SEC);
349 logger.debug("testAllSeemsWell: After isStalled=false, PDP= {} "
350 + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId));
352 assertEquals(StateManagement.PROVIDING_SERVICE, smf.getStandbyStatus());
354 //resumedElectionHandlerSleepTime = 5000;
355 logger.debug("\n\ntestAllSeemsWell: Exiting\n\n");
359 private static Properties loadStateManagementProperties() throws IOException {
360 try (FileInputStream input = new FileInputStream(CONFIG_DIR + "/feature-state-management.properties")) {
361 Properties props = new Properties();
367 private static Properties loadActiveStandbyProperties() throws IOException {
368 try (FileInputStream input =
369 new FileInputStream(CONFIG_DIR + "/feature-active-standby-management.properties")) {
370 Properties props = new Properties();
376 private void waitForCondition(Callable<Boolean> testCondition, int timeoutInSeconds) throws InterruptedException {
377 testTime.waitUntil(testCondition);