diff options
17 files changed, 349 insertions, 361 deletions
diff --git a/common-logging/pom.xml b/common-logging/pom.xml index 82849b93..747e4b2a 100644 --- a/common-logging/pom.xml +++ b/common-logging/pom.xml @@ -2,7 +2,7 @@ ============LICENSE_START======================================================= ONAP Policy Engine - Common Modules ================================================================================ - Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31,6 +31,10 @@ <artifactId>ONAP-Logging</artifactId> <description>ONAP Logging Framework</description> <packaging>jar</packaging> + + <properties> + <powermock.version>1.6.6</powermock.version> + </properties> <dependencies> <dependency> @@ -54,6 +58,12 @@ <artifactId>eelf-core</artifactId> <version>1.0.1-oss</version> </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/common-logging/src/main/java/org/onap/policy/common/logging/flexlogger/PropertyUtil.java b/common-logging/src/main/java/org/onap/policy/common/logging/flexlogger/PropertyUtil.java index 54e06411..566362c9 100644 --- a/common-logging/src/main/java/org/onap/policy/common/logging/flexlogger/PropertyUtil.java +++ b/common-logging/src/main/java/org/onap/policy/common/logging/flexlogger/PropertyUtil.java @@ -36,9 +36,14 @@ import java.util.TimerTask; * notifications of future changes. */ public class PropertyUtil { - - // timer thread used for polling for property file changes - private static Timer timer = null; + + protected static class LazyHolder { + /** + * Timer thread. Will not be allocated by the JVM until it is first referenced. + * This may be overridden by junit tests. + */ + private static Timer timer = new Timer("PropertyUtil-Timer", true); + } // this table maps canonical file into a 'ListenerRegistration' instance private static HashMap<File, ListenerRegistration> registrations = new HashMap<>(); @@ -138,17 +143,6 @@ public class PropertyUtil { // add to static table, so this instance can be shared registrations.put(file, this); - if (timer == null) { - // still need to create a timer thread - synchronized (PropertyUtil.class) { - // an additional check is added inside the 'synchronized' block, - // just in case someone beat us to it - if (timer == null) { - timer = new Timer("PropertyUtil-Timer", true); - } - } - } - // create and schedule the timer task, so this is periodically polled timerTask = new TimerTask() { @Override @@ -160,7 +154,7 @@ public class PropertyUtil { } } }; - timer.schedule(timerTask, 10000L, 10000L); + LazyHolder.timer.schedule(timerTask, 10000L, 10000L); } /** diff --git a/common-logging/src/test/java/org/onap/policy/common/logging/flexlogger/PropertyUtilTest.java b/common-logging/src/test/java/org/onap/policy/common/logging/flexlogger/PropertyUtilTest.java index d97df4ce..b4fcfc18 100644 --- a/common-logging/src/test/java/org/onap/policy/common/logging/flexlogger/PropertyUtilTest.java +++ b/common-logging/src/test/java/org/onap/policy/common/logging/flexlogger/PropertyUtilTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP-Logging * ================================================================================ - * Copyright (C) 2018 Ericsson. All rights reserved. + * Copyright (C) 2018 Ericsson, AT&T. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,29 +21,70 @@ package org.onap.policy.common.logging.flexlogger; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; - +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; import java.util.Set; - +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.onap.policy.common.logging.flexlogger.PropertyUtil.Listener; +import org.powermock.reflect.Whitebox; public class PropertyUtilTest { + /** + * + */ + private static final String TIMER_FIELD = "timer"; private static final File FILE = new File("target/test.properties"); - private TestListener testListener = new TestListener(); + private static Timer saveTimer; + + private TimerTask task; + private Timer timer; + private TestListener testListener; + + @BeforeClass + public static void setUpBeforeClass() { + saveTimer = Whitebox.getInternalState(PropertyUtil.LazyHolder.class, TIMER_FIELD); + + } + + @AfterClass + public static void tearDownAfterClass() { + Whitebox.setInternalState(PropertyUtil.LazyHolder.class, TIMER_FIELD, saveTimer); + + } /** * Perform test case set up. */ @Before public void setUp() throws IOException { + task = null; + timer = mock(Timer.class); + Whitebox.setInternalState(PropertyUtil.LazyHolder.class, TIMER_FIELD, timer); + + doAnswer(args -> { + task = args.getArgumentAt(0, TimerTask.class); + return null; + }).when(timer).schedule(any(TimerTask.class), anyLong(), anyLong()); + + testListener = new TestListener(); + FileOutputStream fileOutputStream = new FileOutputStream(FILE); Properties properties = new Properties(); properties.put("testProperty", "testValue"); @@ -56,6 +97,11 @@ public class PropertyUtilTest { PropertyUtil.stopListening(FILE, testListener); FILE.delete(); } + + @Test + public void testTimer() { + assertNotNull(saveTimer); + } @Test public void testGetProperties() throws IOException { @@ -78,6 +124,8 @@ public class PropertyUtilTest { newProperties.put("testProperty", "testValueNew"); newProperties.store(fileOutputStream, ""); + // fire task and verify that it notifies the listener + task.run(); assertTrue(testListener.isPropertiesChangedInvoked()); } @@ -104,23 +152,21 @@ public class PropertyUtilTest { assertEquals("testValueNew", readProperties.getProperty("testProperty")); } + /** + * The {@link #propertiesChanged(Properties, Set)} method is invoked via a background + * thread, thus we have to use a latch to wait for it to be invoked. + */ private class TestListener implements Listener { - boolean propertiesChangedInvoked = false; + private CountDownLatch latch = new CountDownLatch(1); @Override public void propertiesChanged(Properties properties, Set<String> changedKeys) { - propertiesChangedInvoked = true; + latch.countDown(); } public boolean isPropertiesChangedInvoked() throws InterruptedException { - for (int i = 0; i < 20; i++) { - if (propertiesChangedInvoked) { - return true; - } - Thread.sleep(1000); - } - return false; + return latch.await(5, TimeUnit.SECONDS); } } diff --git a/integrity-audit/pom.xml b/integrity-audit/pom.xml index 107b13a7..241a9a88 100644 --- a/integrity-audit/pom.xml +++ b/integrity-audit/pom.xml @@ -61,7 +61,6 @@ <groupId>org.onap.policy.common</groupId> <artifactId>utils</artifactId> <version>${project.version}</version> - <scope>test</scope> </dependency> <dependency> <groupId>org.onap.policy.common</groupId> diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java index 58ed8b99..dc396a07 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java @@ -25,7 +25,6 @@ import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Properties; -import java.util.concurrent.TimeUnit; import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; import org.onap.policy.common.logging.eelf.MessageCodes; import org.onap.policy.common.logging.flexlogger.FlexLogger; @@ -43,31 +42,19 @@ public class AuditThread extends Thread { * Number of milliseconds that must elapse for audit to be considered complete. It's public for * access by JUnit test logic. */ - public static final long AUDIT_COMPLETION_INTERVAL = 30000; + public static final long AUDIT_COMPLETION_INTERVAL = 30000L; - /* - * Number of iterations for audit simulation. - */ - public static final long AUDIT_SIMULATION_ITERATIONS = 3; - - /* - * Number of milliseconds to sleep between audit simulation iterations. It's public for access - * by JUnit test logic. + /** + * Number of audit cycles before the completion flag is reset. */ - public static final long AUDIT_SIMULATION_SLEEP_INTERVAL = 5000; + public static final int AUDIT_RESET_CYCLES = 2; /* * Unless audit has already been run on this entity, number of milliseconds to sleep between * audit thread iterations. If audit has already been run, we sleep integrityAuditPeriodMillis. * May be modified by JUnit tests. */ - private static long auditThreadSleepIntervalMillis = 5000; - - /* - * Number of milliseconds that must elapse for audit to be considered complete. May be modified - * by JUnit tests. - */ - private static long auditCompletionIntervalMillis = AUDIT_COMPLETION_INTERVAL; + private static final long AUDIT_THREAD_SLEEP_INTERVAL_MS = 5000L; /* * DB access class. @@ -97,7 +84,7 @@ public class AuditThread extends Thread { /* * See IntegrityAudit class for usage. */ - private long integrityAuditPeriodMillis; + private int integrityAuditPeriodSeconds; /* * The containing IntegrityAudit instance @@ -116,28 +103,11 @@ public class AuditThread extends Thread { */ public AuditThread(String resourceName, String persistenceUnit, Properties properties, int integrityAuditPeriodSeconds, IntegrityAudit integrityAudit) throws IntegrityAuditException { - - this(resourceName, persistenceUnit, properties, TimeUnit.SECONDS.toMillis(integrityAuditPeriodSeconds), - integrityAudit); - } - - /** - * AuditThread constructor. - * - * @param resourceName the resource name - * @param persistenceUnit the persistence unit - * @param properties the properties - * @param integrityAuditMillis the integrity audit period in milliseconds - * @param integrityAudit the integrity audit - * @param queue the queue - * @throws IntegrityAuditException if an error occurs - */ - public AuditThread(String resourceName, String persistenceUnit, Properties properties, long integrityAuditMillis, - IntegrityAudit integrityAudit) throws IntegrityAuditException { + this.resourceName = resourceName; this.persistenceUnit = persistenceUnit; this.properties = properties; - this.integrityAuditPeriodMillis = integrityAuditMillis; + this.integrityAuditPeriodSeconds = integrityAuditPeriodSeconds; this.integrityAudit = integrityAudit; /* @@ -267,24 +237,24 @@ public class AuditThread extends Thread { if (logger.isDebugEnabled()) { logger.debug("AuditThread.run: Audit completed; resourceName=" + this.resourceName - + " sleeping " + integrityAuditPeriodMillis + "ms"); + + " sleeping " + integrityAuditPeriodSeconds + "s"); } - Thread.sleep(integrityAuditPeriodMillis); + AuditorTime.getInstance().sleep(integrityAuditPeriodSeconds * 1000L); if (logger.isDebugEnabled()) { logger.debug("AuditThread.run: resourceName=" + this.resourceName + " awaking from " - + integrityAuditPeriodMillis + "ms sleep"); + + integrityAuditPeriodSeconds + "s sleep"); } } else { if (logger.isDebugEnabled()) { logger.debug("AuditThread.run: resourceName=" + this.resourceName + ": Sleeping " - + AuditThread.auditThreadSleepIntervalMillis + "ms"); + + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL_MS + "ms"); } - Thread.sleep(AuditThread.auditThreadSleepIntervalMillis); + AuditorTime.getInstance().sleep(AuditThread.AUDIT_THREAD_SLEEP_INTERVAL_MS); if (logger.isDebugEnabled()) { logger.debug("AuditThread.run: resourceName=" + this.resourceName + ": Awaking from " - + AuditThread.auditThreadSleepIntervalMillis + "ms sleep"); + + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL_MS + "ms sleep"); } } @@ -297,10 +267,10 @@ public class AuditThread extends Thread { } String msg = "AuditThread.run loop - Exception thrown: " + e.getMessage() - + "; Will try audit again in " + (integrityAuditPeriodMillis / 1000) + " seconds"; + + "; Will try audit again in " + integrityAuditPeriodSeconds + " seconds"; logger.error(MessageCodes.EXCEPTION_ERROR, e, msg); // Sleep and try again later - Thread.sleep(integrityAuditPeriodMillis); + AuditorTime.getInstance().sleep(integrityAuditPeriodSeconds * 1000L); } } @@ -630,7 +600,7 @@ public class AuditThread extends Thread { boolean stale = false; - Date currentTime = new Date(); + Date currentTime = AuditorTime.getInstance().getDate(); Date lastUpdated = integrityAuditEntity.getLastUpdated(); /* @@ -641,7 +611,7 @@ public class AuditThread extends Thread { lastUpdatedTime = lastUpdated.getTime(); } long timeDifference = currentTime.getTime() - lastUpdatedTime; - if (timeDifference > auditCompletionIntervalMillis) { + if (timeDifference > AUDIT_COMPLETION_INTERVAL) { stale = true; } @@ -684,13 +654,13 @@ public class AuditThread extends Thread { long timeDifference; - Date currentTime = new Date(); + Date currentTime = AuditorTime.getInstance().getDate(); Date lastUpdated = thisEntity.getLastUpdated(); long lastUpdatedTime = lastUpdated.getTime(); timeDifference = currentTime.getTime() - lastUpdatedTime; - if (timeDifference > (auditCompletionIntervalMillis * 2)) { + if (timeDifference > (AUDIT_COMPLETION_INTERVAL * AUDIT_RESET_CYCLES)) { if (logger.isDebugEnabled()) { logger.debug("resetAuditCompleted: Resetting auditCompleted for resourceName=" + this.resourceName); } @@ -726,12 +696,8 @@ public class AuditThread extends Thread { logger.debug("runAudit: Running audit for persistenceUnit=" + this.persistenceUnit + " on resourceName=" + this.resourceName); } - if (IntegrityAudit.isUnitTesting()) { - dbAudit.dbAuditSimulate(this.resourceName, this.persistenceUnit, AuditThread.AUDIT_SIMULATION_ITERATIONS, - AuditThread.auditThreadSleepIntervalMillis); - } else { - dbAudit.dbAudit(this.resourceName, this.persistenceUnit, this.nodeType); - } + + dbAudit.dbAudit(this.resourceName, this.persistenceUnit, this.nodeType); if (logger.isDebugEnabled()) { logger.debug("runAudit: Exiting"); @@ -758,43 +724,4 @@ public class AuditThread extends Thread { public void auditCompleted() throws InterruptedException { // does nothing } - - /** - * Adjusts the thread-sleep-interval to be used when an audit has <i>not</i> been completed. - * Used by JUnit tests. - * - * @param auditThreadSleepIntervalMillis the interval to use in milliseconds - */ - protected static void setAuditThreadSleepIntervalMillis(long auditThreadSleepIntervalMillis) { - AuditThread.auditThreadSleepIntervalMillis = auditThreadSleepIntervalMillis; - } - - /** - * Gets the current thread-sleep-interval to be used when an audit has <i>not</i> been - * completed. Used by JUnit tests. - * - * @return the current sleep interval, in milli-seconds - */ - protected static long getAuditThreadSleepIntervalMillis() { - return auditThreadSleepIntervalMillis; - } - - /** - * Adjusts the audit-completion-interval. Used by JUnit tests. - * - * @param auditThreadSleepIntervalMillis the interval to use in milliseconds - */ - protected static void setAuditCompletionIntervalMillis(long auditThreadSleepIntervalMillis) { - AuditThread.auditCompletionIntervalMillis = auditThreadSleepIntervalMillis; - } - - /** - * Gets the audit-completion-interval. Used by JUnit tests. - * - * @return the current audit-completion interval, in milli-seconds - */ - protected static long getAuditCompletionIntervalMillis() { - return auditCompletionIntervalMillis; - } - } diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditorTime.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditorTime.java new file mode 100644 index 00000000..9cff742c --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditorTime.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import java.util.function.Supplier; +import org.onap.policy.common.utils.time.CurrentTime; + +/** + * "Current" time used by IntegrityMonitor classes. + */ +public class AuditorTime { + + /** + * Instance to be used. + */ + private static final CurrentTime currentTime = new CurrentTime(); + + /** + * Supplies the instance to be used for accessing the current time. This may be + * overridden by junit tests to provide a different time instance for each thread when + * multiple threads are run in parallel. + */ + private static Supplier<CurrentTime> supplier = () -> currentTime; + + /** + * + */ + private AuditorTime() { + super(); + } + + /** + * @return the CurrentTime singleton + */ + public static CurrentTime getInstance() { + return supplier.get(); + } +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java index 4c4104f6..d7fbd749 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java @@ -1,4 +1,4 @@ -/*- +/* * ============LICENSE_START======================================================= * Integrity Audit * ================================================================================ @@ -29,9 +29,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; - import javax.persistence.Table; - import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.builder.RecursiveToStringStyle; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; @@ -48,8 +46,8 @@ public class DbAudit { private static final Logger logger = FlexLogger.getLogger(DbAudit.class); - private static long dbAuditUpdateMillis = 5000L; - private static long dbAuditSleepMillis = 2000L; + private static final long DB_AUDIT_UPDATE_MS = 5000L; + private static final long DB_AUDIT_SLEEP_MS = 2000L; DbDAO dbDao = null; @@ -145,7 +143,7 @@ public class DbAudit { Map<String, Set<Object>> misMatchedMap = new HashMap<>(); // We need to keep track of how long the audit is taking - long startTime = System.currentTimeMillis(); + long startTime = AuditorTime.getInstance().getMillis(); // Retrieve all instances of the class for each node if (logger.isDebugEnabled()) { @@ -209,15 +207,15 @@ public class DbAudit { } // end for (IntegrityAuditEntity iae : iaeList) // Time check - if ((System.currentTimeMillis() - startTime) >= dbAuditUpdateMillis) { + if ((AuditorTime.getInstance().getMillis() - startTime) >= DB_AUDIT_UPDATE_MS) { // update the timestamp dbDao.setLastUpdated(); // reset the startTime - startTime = System.currentTimeMillis(); + startTime = AuditorTime.getInstance().getMillis(); } else { // sleep a couple seconds to break up the activity if (logger.isDebugEnabled()) { - logger.debug("dbAudit: Sleeping " + dbAuditSleepMillis + "ms"); + logger.debug("dbAudit: Sleeping " + DB_AUDIT_SLEEP_MS + "ms"); } sleep(); if (logger.isDebugEnabled()) { @@ -244,7 +242,7 @@ public class DbAudit { // again classNameSet = new HashSet<>(misMatchedMap.keySet()); // We need to keep track of how long the audit is taking - startTime = System.currentTimeMillis(); + startTime = AuditorTime.getInstance().getMillis(); // Retrieve all instances of the class for each node if (logger.isDebugEnabled()) { @@ -315,15 +313,15 @@ public class DbAudit { } } // Time check - if ((System.currentTimeMillis() - startTime) >= dbAuditUpdateMillis) { + if ((AuditorTime.getInstance().getMillis() - startTime) >= DB_AUDIT_UPDATE_MS) { // update the timestamp dbDao.setLastUpdated(); // reset the startTime - startTime = System.currentTimeMillis(); + startTime = AuditorTime.getInstance().getMillis(); } else { // sleep a couple seconds to break up the activity if (logger.isDebugEnabled()) { - logger.debug("dbAudit: Second comparison; sleeping " + dbAuditSleepMillis + "ms"); + logger.debug("dbAudit: Second comparison; sleeping " + DB_AUDIT_SLEEP_MS + "ms"); } sleep(); if (logger.isDebugEnabled()) { @@ -352,7 +350,7 @@ public class DbAudit { */ private void sleep() throws IntegrityAuditException { try { - Thread.sleep(dbAuditSleepMillis); + AuditorTime.getInstance().sleep(DB_AUDIT_SLEEP_MS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -361,40 +359,6 @@ public class DbAudit { } /** - * dbAuditSimulate simulates the DB audit. - * - * @param resourceName the resouce name - * @param persistenceUnit the persistence unit - * @param simulationIterations the simulations iterations - * @param simulationIntervalMs the simulation interval in milliseconds - * @throws DbAuditException if an error occurs - */ - public void dbAuditSimulate(String resourceName, String persistenceUnit, long simulationIterations, - long simulationIntervalMs) throws DbAuditException { - - try { - logger.info("dbAuditSimulate: Starting audit simulation for resourceName=" + resourceName - + ", persistenceUnit=" + persistenceUnit); - - for (int i = 0; i < simulationIterations; i++) { - dbDao.setLastUpdated(); - logger.info("dbAuditSimulate: i=" + i + ", sleeping " + simulationIntervalMs + "ms"); - Thread.sleep(simulationIntervalMs); - } - - logger.info("dbAuditSimulate: Finished audit simulation for resourceName=" + resourceName - + ", persistenceUnit=" + persistenceUnit); - - } catch (DbDaoTransactionException e) { - throw new DbAuditException(e); - - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new DbAuditException(e); - } - } - - /** * compareEntries() will compare the lists of entries from the DB. * * @param myEntries the entries @@ -496,41 +460,4 @@ public class DbAudit { throw new IntegrityAuditException(e); } } - - /** - * Gets the audit-update time. - * - * @return the audit-update time, in milliseconds - */ - protected static long getDbAuditUpdateMillis() { - return dbAuditUpdateMillis; - } - - /** - * Sets the audit-update time. - * - * @param dbAuditUpdateMillis the new audit update time, in milliseconds - */ - protected static void setDbAuditUpdateMillis(long dbAuditUpdateMillis) { - DbAudit.dbAuditUpdateMillis = dbAuditUpdateMillis; - } - - /** - * Gets the audit-sleep time. - * - * @return the audit-sleep time, in milliseconds - */ - protected static long getDbAuditSleepMillis() { - return dbAuditSleepMillis; - } - - /** - * Sets the audit-sleep time. - * - * @param dbAuditSleepMillis the new audit sleep time, in milliseconds - */ - protected static void setDbAuditSleepMillis(long dbAuditSleepMillis) { - DbAudit.dbAuditSleepMillis = dbAuditSleepMillis; - } - } diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java index 864adacb..ef765f36 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java @@ -1,4 +1,4 @@ -/*- +/* * ============LICENSE_START======================================================= * Integrity Audit * ================================================================================ @@ -20,14 +20,12 @@ package org.onap.policy.common.ia; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; @@ -41,7 +39,6 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; - import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; import org.onap.policy.common.logging.flexlogger.FlexLogger; import org.onap.policy.common.logging.flexlogger.Logger; @@ -52,6 +49,7 @@ import org.onap.policy.common.logging.flexlogger.Logger; */ public class DbDAO { private static final Logger logger = FlexLogger.getLogger(DbDAO.class.getName()); + private String resourceName; private String persistenceUnit; private String dbDriver; @@ -579,7 +577,7 @@ public class DbDAO { em.refresh(iae); logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit + " exists and lastUpdated be updated"); - iae.setLastUpdated(new Date()); + iae.setLastUpdated(AuditorTime.getInstance().getDate()); em.persist(iae); // flush to the DB @@ -672,7 +670,7 @@ public class DbDAO { + persistenceUnit + ", nodeType=" + nodeType); } - long startTime = System.currentTimeMillis(); + long startTime = AuditorTime.getInstance().getMillis(); synchronized (lock) { @@ -759,10 +757,10 @@ public class DbDAO { } // end synchronized block if (logger.isDebugEnabled()) { - logger.debug("changeDesignated: Exiting; time expended=" + (System.currentTimeMillis() - startTime) + "ms"); + logger.debug("changeDesignated: Exiting; time expended=" + + (AuditorTime.getInstance().getMillis() - startTime) + "ms"); } } - } diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java index b3330faf..4d15205a 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java @@ -47,13 +47,13 @@ public class IntegrityAudit { * This is the audit period in milliseconds. For example, if it had a value of 3600000, the * audit can only run once per hour. If it has a value of 6000, it can run once per minute. * - * Values: integrityAuditPeriodMillis < 0 (negative number) indicates the audit is off - * integrityAuditPeriodMillis == 0 indicates the audit is to run continuously - * integrityAuditPeriodMillis > 0 indicates the audit is to run at most once during the + * Values: integrityAuditPeriodSeconds < 0 (negative number) indicates the audit is off + * integrityAuditPeriodSeconds == 0 indicates the audit is to run continuously + * integrityAuditPeriodSeconds > 0 indicates the audit is to run at most once during the * indicated period * */ - private int integrityAuditPeriodMillis; + private int integrityAuditPeriodSeconds; /** * IntegrityAudit constructor. @@ -82,14 +82,11 @@ public class IntegrityAudit { // IntegrityAuditProperties.AUDIT_PERIOD_SECONDS and // IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS are allowed to be null if (properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS) != null) { - this.integrityAuditPeriodMillis = 1000 - * Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); - } else if (properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS) != null) { - this.integrityAuditPeriodMillis = - Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS).trim()); + this.integrityAuditPeriodSeconds = + Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); } else { // If it is null, set it to the default value - this.integrityAuditPeriodMillis = 1000 * IntegrityAuditProperties.DEFAULT_AUDIT_PERIOD_SECONDS; + this.integrityAuditPeriodSeconds = IntegrityAuditProperties.DEFAULT_AUDIT_PERIOD_SECONDS; } logger.info("Constructor: Exiting"); @@ -99,7 +96,7 @@ public class IntegrityAudit { * Used during JUnit testing by AuditPeriodTest.java */ public int getIntegrityAuditPeriodSeconds() { - return (integrityAuditPeriodMillis / 1000); + return integrityAuditPeriodSeconds; } /** @@ -192,14 +189,6 @@ public class IntegrityAudit { + properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); parmsAreBad = true; } - } else if (properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS) != null) { - try { - Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS).trim()); - } catch (NumberFormatException nfe) { - badparams.append(", auditPeriodMilliSeconds=" - + properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS).trim()); - parmsAreBad = true; - } } } // End else logger.debug("parmsAreBad: exit:" + "\nresourceName: " + resourceName + "\npersistenceUnit: " + persistenceUnit @@ -216,15 +205,14 @@ public class IntegrityAudit { public void startAuditThread() throws IntegrityAuditException { logger.info("startAuditThread: Entering"); - if (integrityAuditPeriodMillis >= 0) { - this.auditThread = makeAuditThread(this.resourceName, this.persistenceUnit, this.properties, integrityAuditPeriodMillis); - logger.info("startAuditThread: Audit started and will run every " + integrityAuditPeriodMillis / 1000 - + " seconds"); + if (integrityAuditPeriodSeconds >= 0) { + this.auditThread = makeAuditThread(this.resourceName, this.persistenceUnit, this.properties, integrityAuditPeriodSeconds); + logger.info("startAuditThread: Audit started and will run every " + integrityAuditPeriodSeconds + " seconds"); this.auditThread.start(); } else { logger.info("startAuditThread: Suppressing integrity audit, integrityAuditPeriodSeconds=" - + integrityAuditPeriodMillis / 1000); + + integrityAuditPeriodSeconds); } logger.info("startAuditThread: Exiting"); @@ -294,14 +282,14 @@ public class IntegrityAudit { * @param resourceName2 * @param persistenceUnit2 * @param properties2 - * @param integrityAuditPeriodMillis2 + * @param integrityAuditPeriodSeconds2 * * @return a new audit thread * @throws IntegrityAuditException */ protected AuditThread makeAuditThread(String resourceName2, String persistenceUnit2, Properties properties2, - long integrityAuditPeriodMillis2) throws IntegrityAuditException { - - return new AuditThread(resourceName2, persistenceUnit2, properties2, integrityAuditPeriodMillis2, this); + int integrityAuditPeriodSeconds2) throws IntegrityAuditException { + + return new AuditThread(resourceName2, persistenceUnit2, properties2, integrityAuditPeriodSeconds2, this); } } diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java index 2708c090..3afab61f 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java @@ -29,7 +29,6 @@ public class IntegrityAuditProperties { public static final String DB_USER = "javax.persistence.jdbc.user"; public static final String DB_PWD = "javax.persistence.jdbc.password"; public static final String AUDIT_PERIOD_SECONDS = "integrity_audit_period_seconds"; - public static final String AUDIT_PERIOD_MILLISECONDS = "integrity_audit_period_milliseconds"; public static final String SITE_NAME = "site_name"; diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java index 23b90efc..c1046828 100644 --- a/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java @@ -40,6 +40,7 @@ import javax.persistence.TemporalType; /* * The Entity class to for management of IntegrityAudits */ +import org.onap.policy.common.ia.AuditorTime; @Entity @Table(name = "IntegrityAuditEntity") @@ -101,14 +102,14 @@ public class IntegrityAuditEntity implements Serializable { */ @PrePersist public void prePersist() { - Date date = new Date(); + Date date = AuditorTime.getInstance().getDate(); this.createdDate = date; this.lastUpdated = date; } @PreUpdate public void preUpdate() { - this.lastUpdated = new Date(); + this.lastUpdated = AuditorTime.getInstance().getDate(); } public long getId() { diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditPeriodTest.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditPeriodTest.java index 232468d6..5baf21ad 100644 --- a/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditPeriodTest.java +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditPeriodTest.java @@ -123,7 +123,7 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { properties.put(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS, "0"); - final ExtractAppender logA = watch(debugLogger, "[Aa]waking from (0ms) sleep"); + final ExtractAppender logA = watch(debugLogger, "[Aa]waking from (0s) sleep"); MyIntegrityAudit integrityAudit = makeAuditor("pdp1", A_SEQ_PU); @@ -134,7 +134,7 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { */ String[] awakings = new String[10]; for (int x = 0; x < awakings.length; ++x) { - awakings[x] = "0ms"; + awakings[x] = "0s"; runAudit(integrityAudit); } @@ -171,13 +171,13 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { * Verifies that audits actually take as long as expected, even with multiple auditors running * simultaneously. * - * @param periodms audit period, in milliseconds + * @param periodSec audit period, in seconds * @throws Exception if an error occurs * @throws InterruptedException if the thread is interrupted */ - private void testAuditPeriod(long periodms) throws Exception, InterruptedException { + private void testAuditPeriod(long periodSec) throws Exception, InterruptedException { - properties.put(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS, String.valueOf(periodms)); + properties.put(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS, String.valueOf(periodSec)); /* * Start several auditors. @@ -196,13 +196,13 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { * Now run again and ensure it waited long enough between runs. */ long tmin = minAuditTime(ia); - assertTrue(tmin >= periodms + AUDIT_SIMULATION_MS); + assertTrue(tmin >= periodSec + AuditThread.AUDIT_COMPLETION_INTERVAL * AuditThread.AUDIT_RESET_CYCLES); /* * Now run again and ensure it waited long enough between runs. */ tmin = minAuditTime(ia); - assertTrue(tmin >= periodms + AUDIT_SIMULATION_MS); + assertTrue(tmin >= periodSec + AuditThread.AUDIT_COMPLETION_INTERVAL * AuditThread.AUDIT_RESET_CYCLES); } /** @@ -214,8 +214,7 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { */ private long minAuditTime(MyIntegrityAudit... auditors) throws InterruptedException { List<Thread> threads = new ArrayList<>(auditors.length); - AtomicLong tfirst = new AtomicLong(Long.MAX_VALUE); - final long tbeg = System.currentTimeMillis(); + AtomicLong tmin = new AtomicLong(Long.MAX_VALUE); // create the threads for (MyIntegrityAudit p : auditors) { @@ -224,8 +223,13 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { @Override public void run() { try { + long tbegin = p.getTimeInMillis(); runAudit(p); - setMinTime(tfirst); + long elapsed = p.getTimeInMillis() - tbegin; + + synchronized(tmin) { + tmin.set(Math.min(tmin.get(), elapsed)); + } } catch (InterruptedException e) { ; @@ -247,19 +251,6 @@ public class AuditPeriodTest extends IntegrityAuditTestBase { t.join(); } - return (tfirst.get() - tbeg); - } - - /** - * Sets a value to the minimum between the current value and the current time. - * - * @param tmin current minimum value/value to be set - */ - private static void setMinTime(AtomicLong tmin) { - long tcur = System.currentTimeMillis(); - long time; - while ((time = tmin.get()) > tcur) { - tmin.compareAndSet(time, tcur); - } + return tmin.get(); } } diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditorTimeTest.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditorTimeTest.java new file mode 100644 index 00000000..6ee10102 --- /dev/null +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/AuditorTimeTest.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.onap.policy.common.utils.time.CurrentTime; + +/** + * + */ +public class AuditorTimeTest { + + @Test + public void testGetInstance() { + CurrentTime inst = AuditorTime.getInstance(); + assertNotNull(inst); + + assertEquals(inst, AuditorTime.getInstance()); + } + +} diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/DbAuditTest.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/DbAuditTest.java index cfbf90cb..e7ea47e0 100644 --- a/integrity-audit/src/test/java/org/onap/policy/common/ia/DbAuditTest.java +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/DbAuditTest.java @@ -1,4 +1,4 @@ -/*- +/* * ============LICENSE_START======================================================= * Integrity Audit * ================================================================================ @@ -23,14 +23,11 @@ package org.onap.policy.common.ia; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; - import java.util.List; import java.util.Properties; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; - //import org.apache.commons.logging.Log; //import org.apache.commons.logging.LogFactory; import org.junit.After; diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/DbDAOTest.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/DbDAOTest.java index 01e2f2b0..6e93529c 100644 --- a/integrity-audit/src/test/java/org/onap/policy/common/ia/DbDAOTest.java +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/DbDAOTest.java @@ -52,6 +52,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; import org.onap.policy.common.utils.jpa.EntityTransCloser; +import org.onap.policy.common.utils.time.TestTime; /* * All JUnits are designed to run in the local development environment @@ -273,6 +274,8 @@ public class DbDAOTest extends IntegrityAuditTestBase { Properties properties = makeProperties(); try (EntityTransCloser et = new EntityTransCloser(em.getTransaction())) { + TestTime testTime = getTestTime(); + // Create an entry dbDao = new DbDAO(resourceName, A_SEQ_PU, properties); @@ -296,10 +299,10 @@ public class DbDAOTest extends IntegrityAuditTestBase { final Date oldDate = iae.getLastUpdated(); // ensure dates are different by sleeping for a bit - Thread.sleep(1); + testTime.sleep(1); iae.setSite("SiteB"); - iae.setLastUpdated(new Date()); + iae.setLastUpdated(testTime.getDate()); final Date newDate = iae.getLastUpdated(); em.persist(iae); diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditDesignationTest.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditDesignationTest.java index 69f37da5..bd3baf49 100644 --- a/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditDesignationTest.java +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditDesignationTest.java @@ -53,7 +53,7 @@ public class IntegrityAuditDesignationTest extends IntegrityAuditTestBase { * </code> * </pre> */ - private static final String START_AUDIT_RE_PREFIX = "Starting audit simulation for resourceName=("; + private static final String START_AUDIT_RE_PREFIX = "Running audit for persistenceUnit=\\w+ on resourceName=("; @BeforeClass public static void setUpBeforeClass() throws Exception { @@ -152,17 +152,7 @@ public class IntegrityAuditDesignationTest extends IntegrityAuditTestBase { * Tests designation logic when two functioning resources are in play. Designation should * alternate between resources. * - * Note: console.log must be examined to ascertain whether or not this test was successful. A - * quick way of examining the log is to search for the string "audit simulation": - * - * As you can see from the "dbAuditSimulate" method, when it executes, it logs the - * "Starting audit simulation..." message and when it finishes, it logs the - * "Finished audit simulation..." message. By looking for these messages, you can verify that - * the audits are run by the proper resource. For example, when testFourResourcesOneDead is run, - * you should see a Starting.../Finished... sequence for "pdp1", followed by a - * Starting.../Finished... sequence for pdp2, followed by a Starting.../Finished... sequence for - * pdp4 (pdp3 is skipped as it's dead/hung), followed by a Starting.../Finished... sequence for - * "pdp1", etc. + * Note: console.log must be examined to ascertain whether or not this test was successful. */ @Test public void testTwoResources() throws Exception { diff --git a/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditTestBase.java b/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditTestBase.java index c9179908..94ee0297 100644 --- a/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditTestBase.java +++ b/integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditTestBase.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Properties; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; @@ -40,6 +41,9 @@ import org.onap.policy.common.utils.jpa.EntityMgrCloser; import org.onap.policy.common.utils.jpa.EntityMgrFactoryCloser; import org.onap.policy.common.utils.jpa.EntityTransCloser; import org.onap.policy.common.utils.test.log.logback.ExtractAppender; +import org.onap.policy.common.utils.time.CurrentTime; +import org.onap.policy.common.utils.time.TestTime; +import org.powermock.reflect.Whitebox; import org.slf4j.LoggerFactory; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -72,41 +76,22 @@ public class IntegrityAuditTestBase { */ private static final String LOG_DIR = "testingLogs/common-modules/integrity-audit"; + /** - * Max time, in milliseconds, to wait for a latch to be triggered. + * Name of the field within the AuditorTime class that supplies the time. */ - protected static final long WAIT_MS = 5000L; - - /** - * Milliseconds that auditor should sleep between audit steps. - */ - protected static final long SLEEP_INTERVAL_MS = 2L; - - /** - * Milliseconds that auditor should sleep when an audit completes. - */ - protected static final long COMPLETION_INTERVAL_MS = 5L; + public static final String TIME_SUPPLY_FIELD = "supplier"; - /** - * Milliseconds that an entire audit-simulation cycles takes. - */ - protected static final long AUDIT_SIMULATION_MS = SLEEP_INTERVAL_MS * AuditThread.AUDIT_SIMULATION_ITERATIONS; /** - * Milliseconds that it takes for an auditor's last update to become stale. Includes a 1ms fudge - * factor. + * Max time, in milliseconds, to wait for a semaphore. */ - protected static final long STALE_MS = 1 + 2 * Math.max(COMPLETION_INTERVAL_MS, AUDIT_SIMULATION_MS); - - /** - * Milliseconds that the db-audit should wait between makings updates. - */ - private static final long DB_AUDIT_UPDATE_MS = 10L; - + protected static final long WAIT_MS = 5000L; + /** - * Milliseconds that the db-audit should sleep between cycles. + * Number of seconds in an audit period. */ - private static final long DB_AUDIT_SLEEP_MS = 3L; + public static final int AUDIT_PERIOD_SEC = 5; public static final String DEFAULT_DB_URL_PREFIX = "jdbc:h2:mem:"; @@ -132,7 +117,7 @@ public class IntegrityAuditTestBase { /** * Matches the start of an audit for arbitrary PDPs in the debug log. */ - protected static final String START_AUDIT_RE = "Starting audit simulation for resourceName=([^,]*)"; + protected static final String START_AUDIT_RE = "Running audit for persistenceUnit=\\w+ on resourceName=([^,]*)"; /** * Properties to be used in all tests. @@ -150,34 +135,30 @@ public class IntegrityAuditTestBase { protected static EntityManager em; /** - * Saved debug logger level, to be restored once all tests complete. + * Current time used by given test. */ - private static Level savedDebugLevel; - - /** - * Saved error logger level, to be restored once all tests complete. - */ - private static Level savedErrorLevel; + private static ThreadLocal<TestTime> testTime = ThreadLocal.withInitial(() -> null); /** - * Saved audit sleep interval, to be restored once all tests complete. + * Supplies the test time so that each thread maintains its own notion of "current" + * time. */ - private static long savedSleepIntervalMs; + private static Supplier<TestTime> timeSupplier = () -> testTime.get(); /** - * Saved audit completion interval, to be restored once all tests complete. + * Saved debug logger level, to be restored once all tests complete. */ - private static long savedCompletionIntervalMs; + private static Level savedDebugLevel; /** - * Saved db audit update time, to be restored once all tests complete. + * Saved error logger level, to be restored once all tests complete. */ - private static long savedDbAuditUpdateMs; + private static Level savedErrorLevel; /** - * Saved db audit sleep time, to be restored once all tests complete. + * Saved time, to be restored once all tests complete. */ - private static long savedDbAuditSleepMs; + private static Supplier<CurrentTime> savedTime; /** * List of auditors whose threads must be stopped when a given test case ends. @@ -207,18 +188,9 @@ public class IntegrityAuditTestBase { IntegrityAuditTestBase.dbUrl = dbUrl; // save data that we have to restore at the end of the test + savedTime = Whitebox.getInternalState(AuditorTime.class, TIME_SUPPLY_FIELD); savedDebugLevel = debugLogger.getLevel(); savedErrorLevel = errorLogger.getLevel(); - savedSleepIntervalMs = AuditThread.getAuditThreadSleepIntervalMillis(); - savedCompletionIntervalMs = AuditThread.getAuditCompletionIntervalMillis(); - savedDbAuditUpdateMs = DbAudit.getDbAuditUpdateMillis(); - savedDbAuditSleepMs = DbAudit.getDbAuditSleepMillis(); - - AuditThread.setAuditThreadSleepIntervalMillis(SLEEP_INTERVAL_MS); - AuditThread.setAuditCompletionIntervalMillis(COMPLETION_INTERVAL_MS); - - DbAudit.setDbAuditUpdateMillis(DB_AUDIT_UPDATE_MS); - DbAudit.setDbAuditSleepMillis(DB_AUDIT_SLEEP_MS); IntegrityAudit.setUnitTesting(true); @@ -236,6 +208,7 @@ public class IntegrityAuditTestBase { // done em = emf.createEntityManager(); + Whitebox.setInternalState(AuditorTime.class, TIME_SUPPLY_FIELD, timeSupplier); debugLogger.setLevel(Level.DEBUG); errorLogger.setLevel(Level.ERROR); } @@ -244,14 +217,10 @@ public class IntegrityAuditTestBase { * Restores the configuration to what it was before the test. */ protected static void tearDownAfterClass() { - AuditThread.setAuditThreadSleepIntervalMillis(savedSleepIntervalMs); - AuditThread.setAuditCompletionIntervalMillis(savedCompletionIntervalMs); - - DbAudit.setDbAuditUpdateMillis(savedDbAuditUpdateMs); - DbAudit.setDbAuditSleepMillis(savedDbAuditSleepMs); - + IntegrityAudit.setUnitTesting(false); + Whitebox.setInternalState(AuditorTime.class, TIME_SUPPLY_FIELD, savedTime); debugLogger.setLevel(savedDebugLevel); errorLogger.setLevel(savedErrorLevel); @@ -267,7 +236,10 @@ public class IntegrityAuditTestBase { auditors = new LinkedList<>(); appenders = new LinkedList<>(); - properties.put(IntegrityAuditProperties.AUDIT_PERIOD_MILLISECONDS, String.valueOf(SLEEP_INTERVAL_MS)); + properties.put(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS, String.valueOf(AUDIT_PERIOD_SEC)); + + TestTime time = new TestTime(); + testTime.set(time); // Clean up the DB try (EntityTransCloser etc = new EntityTransCloser(em.getTransaction())) { @@ -295,6 +267,13 @@ public class IntegrityAuditTestBase { } /** + * @return the {@link TestTime} in use by this thread + */ + public static TestTime getTestTime() { + return testTime.get(); + } + + /** * Truncate the table. * * @param properties the properties @@ -410,7 +389,13 @@ public class IntegrityAuditTestBase { * @throws Exception if an error occurs */ protected MyIntegrityAudit makeAuditor(String resourceName2, String persistenceUnit2) throws Exception { - return new MyIntegrityAudit(resourceName2, persistenceUnit2, makeProperties()); + // each auditor gets its own notion of time + TestTime time = new TestTime(); + + // use the auditor-specific time while this thread constructs things + testTime.set(time); + + return new MyIntegrityAudit(resourceName2, persistenceUnit2, makeProperties(), time); } /** @@ -474,19 +459,22 @@ public class IntegrityAuditTestBase { * * @param sem the semaphore for which to wait * @throws InterruptedException if the thread is interrupted - * @throws AssertionError if the latch did not reach zero in the allotted time + * @throws AssertionError if the semaphore did not reach zero in the allotted time */ protected void waitSem(Semaphore sem) throws InterruptedException { - assertTrue(sem.tryAcquire(WAIT_MS, TimeUnit.SECONDS)); + assertTrue(sem.tryAcquire(WAIT_MS, TimeUnit.MILLISECONDS)); } - + /** * Sleep a bit so that the currently designated pdp becomes stale. * * @throws InterruptedException if the thread is interrupted */ protected void waitStale() throws InterruptedException { - Thread.sleep(STALE_MS); + // waits for ALL auditors to become stale, as each has its own timer + for (MyIntegrityAudit auditor : auditors) { + auditor.sleep(AuditThread.AUDIT_COMPLETION_INTERVAL * AuditThread.AUDIT_RESET_CYCLES + 1); + } } /** @@ -511,10 +499,12 @@ public class IntegrityAuditTestBase { } /** - * Manages audits by inserting latches into a queue for the AuditThread to count. + * Manages audits by inserting semaphores into a queue for the AuditThread to count. */ protected class MyIntegrityAudit extends IntegrityAudit { + private final TestTime myTime; + /** * Semaphore on which the audit thread should wait. */ @@ -531,15 +521,36 @@ public class IntegrityAuditTestBase { * @param resourceName the resource name * @param persistenceUnit the persistence unit * @param properties the properties + * @param time * @throws Exception if an error occurs */ - public MyIntegrityAudit(String resourceName, String persistenceUnit, Properties properties) throws Exception { + public MyIntegrityAudit(String resourceName, String persistenceUnit, Properties properties, TestTime time) throws Exception { super(resourceName, persistenceUnit, properties); + + myTime = time; + testTime.set(myTime); auditors.add(this); startAuditThread(); } + + /** + * @return the "current" time for the auditor + */ + public long getTimeInMillis() { + return myTime.getMillis(); + } + + /** + * Sleeps for a period of time. + * + * @param sleepMs + * @throws InterruptedException + */ + public void sleep(long sleepMs) throws InterruptedException { + myTime.sleep(sleepMs); + } /** * Interrupts the AuditThread. @@ -560,7 +571,8 @@ public class IntegrityAuditTestBase { } /** - * Starts a new AuditThread. Creates a new latch queue and associates it with the thread. + * Starts a new AuditThread. Creates a new pair of semaphores and associates them + * with the thread. */ @Override public final void startAuditThread() throws IntegrityAuditException { @@ -603,14 +615,24 @@ public class IntegrityAuditTestBase { @Override protected AuditThread makeAuditThread(String resourceName2, String persistenceUnit2, Properties properties2, - long integrityAuditPeriodMillis2) throws IntegrityAuditException { + int integrityAuditPeriodSeconds2) throws IntegrityAuditException { + + // make sure we're still using the auditor's time while we construct things + testTime.set(myTime); - return new AuditThread(resourceName2, persistenceUnit2, properties2, integrityAuditPeriodMillis2, this) { + return new AuditThread(resourceName2, persistenceUnit2, properties2, integrityAuditPeriodSeconds2, this) { private Semaphore auditSem = MyIntegrityAudit.this.auditSem; private Semaphore junitSem = MyIntegrityAudit.this.junitSem; @Override + public void run() { + // make sure our thread uses this auditor's time + testTime.set(myTime); + super.run(); + } + + @Override public void runStarted() throws InterruptedException { auditSem.acquire(); |