diff options
author | Jim Hahn <jrh3@att.com> | 2018-06-21 16:23:19 -0400 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2018-06-21 17:17:10 -0400 |
commit | 9afa523e5147c971a0d8d0405361f3c3e8faa6ce (patch) | |
tree | 05566af1d59b8da6338435384a0fed481c76b179 /integrity-audit/src/test/java/org | |
parent | ec62d8d34ae4724b81d29f6314951c277f423ba4 (diff) |
IntegrityAuditor: remove sleep from junit tests
Modified the code to use a CurrentTime object for its "time" operations
(e.g., sleep(), currentTimeInMillis()). Modified junit tests to replace
the CurrentTime object with TestTime objects so they don't actually
do any sleeping.
Reformat "commit" message.
Remove TODO from junit test.
Init testTime in junit setUp().
Add AuditorTime and test classes.
Change "latch" to "semaphore" in comments.
Change time units in junit test from SECONDS to MILLISECONDS.
Add sleep() method to auditor test class.
Reorder field qualifiers.
Change utils scope to "compile" in pom.
Change-Id: I8aa8b642b315156c00422192e4aa8e47b4503c2f
Issue-ID: POLICY-908
Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'integrity-audit/src/test/java/org')
6 files changed, 155 insertions, 112 deletions
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(); |