summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java80
-rw-r--r--integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java49
-rw-r--r--integrity-audit/src/test/java/org/onap/policy/common/ia/IntegrityAuditTestBase.java103
-rw-r--r--integrity-monitor/src/main/java/org/onap/policy/common/im/IntegrityMonitor.java100
-rw-r--r--integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTest.java47
-rw-r--r--integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTestBase.java13
-rw-r--r--utils-test/pom.xml5
-rw-r--r--utils-test/src/main/java/org/onap/policy/common/utils/time/TestTime.java59
-rw-r--r--utils-test/src/main/java/org/onap/policy/common/utils/time/TestTimeMulti.java200
-rw-r--r--utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeMultiTest.java116
-rw-r--r--utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeTest.java66
-rw-r--r--utils/pom.xml5
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java61
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java117
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java233
-rw-r--r--utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java61
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java568
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertiesTest.java224
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertyConfigurationTest.java331
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/time/CurrentTimeTest.java59
20 files changed, 1569 insertions, 928 deletions
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 f1839b12..58ed8b99 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,10 +25,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
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;
@@ -108,18 +105,6 @@ public class AuditThread extends Thread {
private IntegrityAudit integrityAudit;
/**
- * A latch is taken from this queue before starting an audit. May be {@code null}. Used by JUnit
- * tests.
- */
- private BlockingQueue<CountDownLatch> auditLatchQueue;
-
- /**
- * Latch to be decremented when the next audit completes. May be {@code null}. Used by JUnit
- * tests to wait for an audit to complete.
- */
- private CountDownLatch auditCompletionLatch = null;
-
- /**
* AuditThread constructor.
*
* @param resourceName the resource name
@@ -133,7 +118,7 @@ public class AuditThread extends Thread {
int integrityAuditPeriodSeconds, IntegrityAudit integrityAudit) throws IntegrityAuditException {
this(resourceName, persistenceUnit, properties, TimeUnit.SECONDS.toMillis(integrityAuditPeriodSeconds),
- integrityAudit, null);
+ integrityAudit);
}
/**
@@ -148,13 +133,12 @@ public class AuditThread extends Thread {
* @throws IntegrityAuditException if an error occurs
*/
public AuditThread(String resourceName, String persistenceUnit, Properties properties, long integrityAuditMillis,
- IntegrityAudit integrityAudit, BlockingQueue<CountDownLatch> queue) throws IntegrityAuditException {
+ IntegrityAudit integrityAudit) throws IntegrityAuditException {
this.resourceName = resourceName;
this.persistenceUnit = persistenceUnit;
this.properties = properties;
this.integrityAuditPeriodMillis = integrityAuditMillis;
this.integrityAudit = integrityAudit;
- this.auditLatchQueue = queue;
/*
* The DbDAO Constructor registers this node in the IntegrityAuditEntity table. Each
@@ -174,14 +158,8 @@ public class AuditThread extends Thread {
logger.info("AuditThread.run: Entering");
try {
- /*
- * For JUnit testing: wait for the first latch, decrement it to indicate that the thread
- * has started, and then wait for the next latch, before we actually start doing
- * anything. These simply return if there is no latch queue defined.
- */
- getNextLatch();
- decrementLatch();
- getNextLatch();
+ // for junit testing
+ runStarted();
/*
* Triggers change in designation, unless no other viable candidate.
@@ -284,11 +262,8 @@ public class AuditThread extends Thread {
* property, otherwise just sleep the normal interval.
*/
if (auditCompleted) {
- // indicate that an audit has completed
- decrementLatch();
-
- // don't start the next audit cycle until a latch has been provided
- getNextLatch();
+ // for junit testing: indicate that an audit has completed
+ auditCompleted();
if (logger.isDebugEnabled()) {
logger.debug("AuditThread.run: Audit completed; resourceName=" + this.resourceName
@@ -342,29 +317,6 @@ public class AuditThread extends Thread {
}
/**
- * Gets the next audit-completion latch from the queue. Blocks, if the queue is empty.
- *
- * @throws InterruptedException if interrupted while waiting
- */
- private void getNextLatch() throws InterruptedException {
- BlockingQueue<CountDownLatch> queue = this.auditLatchQueue;
- if (queue != null) {
- this.auditCompletionLatch = queue.take();
- }
- }
-
- /**
- * Decrements the current audit-completion latch, if any.
- */
- private void decrementLatch() {
- CountDownLatch latch = this.auditCompletionLatch;
- if (latch != null) {
- this.auditCompletionLatch = null;
- latch.countDown();
- }
- }
-
- /**
* Determines if an exception is an InterruptedException or was caused by an
* InterruptedException.
*
@@ -788,6 +740,26 @@ public class AuditThread extends Thread {
}
/**
+ * Indicates that the {@link #run()} method has started. This method simply returns,
+ * and may overridden by junit tests.
+ *
+ * @throws InterruptedException
+ */
+ public void runStarted() throws InterruptedException {
+ // does nothing
+ }
+
+ /**
+ * Indicates that an audit has completed. This method simply returns, and may
+ * overridden by junit tests.
+ *
+ * @throws InterruptedException
+ */
+ 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.
*
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 9abdbe52..b3330faf 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
@@ -21,9 +21,6 @@
package org.onap.policy.common.ia;
import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-
import org.onap.policy.common.ia.IntegrityAuditProperties.NodeTypeEnum;
import org.onap.policy.common.logging.flexlogger.FlexLogger;
import org.onap.policy.common.logging.flexlogger.Logger;
@@ -217,37 +214,20 @@ public class IntegrityAudit {
* @throws IntegrityAuditException if an error occurs
*/
public void startAuditThread() throws IntegrityAuditException {
- startAuditThread(null);
- }
-
- /**
- * Starts the audit thread.
- *
- * @param queue the queue
- * @return {@code true} if the thread was started, {@code false} otherwise
- * @throws IntegrityAuditException if an error occurs
- */
- protected boolean startAuditThread(BlockingQueue<CountDownLatch> queue) throws IntegrityAuditException {
-
logger.info("startAuditThread: Entering");
- boolean success = false;
-
if (integrityAuditPeriodMillis >= 0) {
- this.auditThread = new AuditThread(this.resourceName, this.persistenceUnit, this.properties,
- integrityAuditPeriodMillis, this, queue);
+ this.auditThread = makeAuditThread(this.resourceName, this.persistenceUnit, this.properties, integrityAuditPeriodMillis);
logger.info("startAuditThread: Audit started and will run every " + integrityAuditPeriodMillis / 1000
+ " seconds");
this.auditThread.start();
- success = true;
+
} else {
logger.info("startAuditThread: Suppressing integrity audit, integrityAuditPeriodSeconds="
+ integrityAuditPeriodMillis / 1000);
}
logger.info("startAuditThread: Exiting");
-
- return success;
}
/**
@@ -299,4 +279,29 @@ public class IntegrityAudit {
return !this.auditThread.isAlive();
}
}
+
+ /**
+ *
+ * @return {@code true} if an audit thread exists, {@code false} otherwise
+ */
+ protected boolean haveAuditThread() {
+ return (this.auditThread != null);
+ }
+
+ /**
+ * Creates an audit thread. May be overridden by junit tests.
+ *
+ * @param resourceName2
+ * @param persistenceUnit2
+ * @param properties2
+ * @param integrityAuditPeriodMillis2
+ *
+ * @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);
+ }
}
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 afbcc452..c9179908 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
@@ -22,10 +22,6 @@ package org.onap.policy.common.ia;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -34,21 +30,19 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
-
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.slf4j.LoggerFactory;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
/**
* All JUnits are designed to run in the local development environment where they have write
@@ -464,26 +458,26 @@ public class IntegrityAuditTestBase {
protected void runAudit(MyIntegrityAudit... auditors) throws InterruptedException {
// start an audit cycle on each auditor
- List<CountDownLatch> latches = new ArrayList<>(auditors.length);
+ List<Semaphore> semaphores = new ArrayList<>(auditors.length);
for (MyIntegrityAudit p : auditors) {
- latches.add(p.startAudit());
+ semaphores.add(p.startAudit());
}
// wait for each auditor to complete its cycle
- for (CountDownLatch latch : latches) {
- waitLatch(latch);
+ for (Semaphore sem : semaphores) {
+ waitSem(sem);
}
}
/**
- * Waits for a latch to reach zero.
+ * Waits for a semaphore to be released.
*
- * @param latch the latch to wait for
+ * @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
*/
- protected void waitLatch(CountDownLatch latch) throws InterruptedException {
- assertTrue(latch.await(WAIT_MS, TimeUnit.SECONDS));
+ protected void waitSem(Semaphore sem) throws InterruptedException {
+ assertTrue(sem.tryAcquire(WAIT_MS, TimeUnit.SECONDS));
}
/**
@@ -520,11 +514,16 @@ public class IntegrityAuditTestBase {
* Manages audits by inserting latches into a queue for the AuditThread to count.
*/
protected class MyIntegrityAudit extends IntegrityAudit {
-
+
+ /**
+ * Semaphore on which the audit thread should wait.
+ */
+ private Semaphore auditSem = null;
+
/**
- * Queue from which the AuditThread will take latches.
+ * Semaphore on which the junit management thread should wait.
*/
- private BlockingQueue<CountDownLatch> queue = null;
+ private Semaphore junitSem = null;
/**
* Constructs an auditor and starts the AuditThread.
@@ -550,16 +549,14 @@ public class IntegrityAuditTestBase {
}
/**
- * Triggers an audit by adding a latch to the queue.
+ * Triggers an audit by releasing the audit thread's semaphore.
*
- * @return the latch that was added
+ * @return the semaphore on which to wait
* @throws InterruptedException if the thread is interrupted
*/
- public CountDownLatch startAudit() throws InterruptedException {
- CountDownLatch latch = new CountDownLatch(1);
- queue.add(latch);
-
- return latch;
+ public Semaphore startAudit() throws InterruptedException {
+ auditSem.release();
+ return junitSem;
}
/**
@@ -567,25 +564,23 @@ public class IntegrityAuditTestBase {
*/
@Override
public final void startAuditThread() throws IntegrityAuditException {
- if (queue != null) {
- // queue up a bogus latch, in case a thread is still running
- queue.add(new CountDownLatch(1) {
- @Override
- public void countDown() {
- throw new RuntimeException("auditor has multiple threads");
- }
- });
+ if (auditSem != null) {
+ // release a bunch of semaphores, in case a thread is still running
+ auditSem.release(1000);
}
+
+ auditSem = new Semaphore(0);
+ junitSem = new Semaphore(0);
+
+ super.startAuditThread();
- queue = new LinkedBlockingQueue<>();
+ if (haveAuditThread()) {
+ // tell the thread it can run
+ auditSem.release();
- if (super.startAuditThread(queue)) {
// wait for the thread to start
- CountDownLatch latch = new CountDownLatch(1);
- queue.add(latch);
-
try {
- waitLatch(latch);
+ waitSem(junitSem);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
@@ -605,5 +600,31 @@ public class IntegrityAuditTestBase {
assertTrue(waitThread(this));
}
+
+ @Override
+ protected AuditThread makeAuditThread(String resourceName2, String persistenceUnit2, Properties properties2,
+ long integrityAuditPeriodMillis2) throws IntegrityAuditException {
+
+ return new AuditThread(resourceName2, persistenceUnit2, properties2, integrityAuditPeriodMillis2, this) {
+
+ private Semaphore auditSem = MyIntegrityAudit.this.auditSem;
+ private Semaphore junitSem = MyIntegrityAudit.this.junitSem;
+
+ @Override
+ public void runStarted() throws InterruptedException {
+ auditSem.acquire();
+
+ junitSem.release();
+ auditSem.acquire();
+ }
+
+ @Override
+ public void auditCompleted() throws InterruptedException {
+ junitSem.release();
+ auditSem.acquire();
+ }
+
+ };
+ }
}
}
diff --git a/integrity-monitor/src/main/java/org/onap/policy/common/im/IntegrityMonitor.java b/integrity-monitor/src/main/java/org/onap/policy/common/im/IntegrityMonitor.java
index c32a2213..38dc20dc 100644
--- a/integrity-monitor/src/main/java/org/onap/policy/common/im/IntegrityMonitor.java
+++ b/integrity-monitor/src/main/java/org/onap/policy/common/im/IntegrityMonitor.java
@@ -29,10 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.persistence.EntityManager;
@@ -43,7 +40,6 @@ import javax.persistence.LockModeType;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.validation.constraints.NotNull;
-
import org.onap.policy.common.im.jmx.ComponentAdmin;
import org.onap.policy.common.im.jmx.ComponentAdminMBean;
import org.onap.policy.common.im.jmx.JmxAgentConnection;
@@ -196,7 +192,7 @@ public class IntegrityMonitor {
*/
protected IntegrityMonitor(String resourceName, Properties properties) throws IntegrityMonitorException {
- this(resourceName, properties, null);
+ this(resourceName, properties, new Factory());
}
/**
@@ -207,10 +203,10 @@ public class IntegrityMonitor {
*
* @param resourceName The resource name of the resource
* @param properties a set of properties passed in from the resource
- * @param queue queue to use to control the FPManager thread, or {@code null}
+ * @param factory Factory to use to control the FPManager thread
* @throws IntegrityMonitorException if any errors are encountered in the constructor
*/
- protected IntegrityMonitor(String resourceName, Properties properties, BlockingQueue<CountDownLatch> queue)
+ protected IntegrityMonitor(String resourceName, Properties properties, Factory factory)
throws IntegrityMonitorException {
// singleton check since this constructor can be called from a child or
@@ -357,7 +353,8 @@ public class IntegrityMonitor {
logger.error("ComponentAdmin constructor exception: {}", e.toString(), e);
}
- fpManager = new FpManager(queue);
+ fpManager = new FpManager(factory);
+ fpManager.start();
}
@@ -373,7 +370,7 @@ public class IntegrityMonitor {
*/
public static IntegrityMonitor getInstance(String resourceName, Properties properties)
throws IntegrityMonitorException {
- return getInstance(resourceName, properties, null);
+ return getInstance(resourceName, properties, new Factory());
}
/**
@@ -382,13 +379,13 @@ public class IntegrityMonitor {
*
* @param resourceName The resource name of the resource
* @param properties a set of properties passed in from the resource
- * @param queue queue to use to control the FPManager thread, or {@code null}
+ * @param factory Factory to use to control the FPManager thread
* @return The new instance of IntegrityMonitor
* @throws IntegrityMonitorException if unable to create jmx url or the constructor returns an
* exception
*/
protected static IntegrityMonitor getInstance(String resourceName, Properties properties,
- BlockingQueue<CountDownLatch> queue) throws IntegrityMonitorException {
+ Factory factory) throws IntegrityMonitorException {
synchronized (getInstanceLock) {
logger.debug("getInstance() called - resourceName= {}", resourceName);
@@ -399,7 +396,7 @@ public class IntegrityMonitor {
if (instance == null) {
logger.debug("Creating new instance of IntegrityMonitor");
- instance = new IntegrityMonitor(resourceName, properties, queue);
+ instance = new IntegrityMonitor(resourceName, properties, factory);
}
return instance;
}
@@ -1740,18 +1737,15 @@ public class IntegrityMonitor {
* dependencies, does a refresh state audit and runs the stateAudit.
*/
class FpManager extends Thread {
- private final CountDownLatch stopper = new CountDownLatch(1);
+ private boolean stopRequested = false;
- private BlockingQueue<CountDownLatch> queue;
- private CountDownLatch progressLatch = null;
+ private final Factory factory;
// Constructor - start FP manager thread
- FpManager(BlockingQueue<CountDownLatch> queue) {
- this.queue = queue;
+ FpManager(Factory factory) {
+ this.factory = factory;
// set now as the last time the refreshStateAudit ran
IntegrityMonitor.this.refreshStateAuditLastRunDate = new Date();
- // start thread
- this.start();
}
@Override
@@ -1759,13 +1753,13 @@ public class IntegrityMonitor {
logger.debug("FPManager thread running");
try {
- getLatch();
- decrementLatch();
+ factory.runStarted();
- while (!stopper.await(cycleIntervalMillis, TimeUnit.MILLISECONDS)) {
- getLatch();
+ while(!stopRequested) {
+ factory.doSleep(cycleIntervalMillis);
+
IntegrityMonitor.this.runOnce();
- decrementLatch();
+ factory.monitorCompleted();
}
} catch (InterruptedException e) {
@@ -1775,31 +1769,9 @@ public class IntegrityMonitor {
}
public void stopAndExit() {
- stopper.countDown();
+ stopRequested = true;
this.interrupt();
}
-
- /**
- * Gets the next latch from the queue.
- *
- * @throws InterruptedException
- *
- */
- private void getLatch() throws InterruptedException {
- if (queue != null) {
- progressLatch = queue.take();
- }
- }
-
- /**
- * Decrements the current latch.
- */
- private void decrementLatch() {
- if (progressLatch != null) {
- progressLatch.countDown();
- }
- }
-
}
private void runOnce() {
@@ -1934,6 +1906,40 @@ public class IntegrityMonitor {
return allNotWellMap;
}
+ /**
+ * Used to access various objects. Overridden by junit tests.
+ */
+ public static class Factory {
+
+ /**
+ * Indicates that the {@link FpManager#run()} method has started. This method
+ * simply returns.
+ *
+ * @throws InterruptedException
+ */
+ public void runStarted() throws InterruptedException {
+ // does nothing
+ }
+
+ /**
+ * Sleeps for a period of time.
+ * @param sleepMs amount of time to sleep, in milliseconds
+ * @throws InterruptedException
+ */
+ public void doSleep(long sleepMs) throws InterruptedException {
+ Thread.sleep(sleepMs);
+ }
+
+ /**
+ * Indicates that a monitor activity has completed. This method simply returns.
+ *
+ * @throws InterruptedException
+ */
+ public void monitorCompleted() throws InterruptedException {
+ // does nothing
+ }
+ }
+
/*
* The remaining methods are used by JUnit tests.
*/
diff --git a/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTest.java b/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTest.java
index 7f1e5516..091dcc91 100644
--- a/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTest.java
+++ b/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTest.java
@@ -22,23 +22,19 @@ package org.onap.policy.common.im;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-
import java.util.Date;
import java.util.List;
import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-
+import java.util.concurrent.Semaphore;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import javax.persistence.TemporalType;
-
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.im.IntegrityMonitor.Factory;
import org.onap.policy.common.im.jpa.ForwardProgressEntity;
import org.onap.policy.common.im.jpa.ResourceRegistrationEntity;
import org.onap.policy.common.im.jpa.StateManagementEntity;
@@ -57,7 +53,8 @@ public class IntegrityMonitorTest extends IntegrityMonitorTestBase {
private static EntityTransaction et;
private static String resourceName;
- private BlockingQueue<CountDownLatch> queue;
+ private Semaphore monitorSem;
+ private Semaphore junitSem;
/**
* Set up for test class.
@@ -900,9 +897,36 @@ public class IntegrityMonitorTest extends IntegrityMonitorTestBase {
private IntegrityMonitor makeMonitor(String resourceName, Properties myProp) throws Exception {
IntegrityMonitor.deleteInstance();
- queue = new LinkedBlockingQueue<>();
+ monitorSem = new Semaphore(0);
+ junitSem = new Semaphore(0);
+
+ Factory factory = new IntegrityMonitor.Factory() {
+
+ @Override
+ public void doSleep(long sleepMs) throws InterruptedException {
+ /*
+ * No need to sleep, as the thread won't progress until the
+ * semaphore is released.
+ */
+ }
+
+ @Override
+ public void runStarted() throws InterruptedException {
+ monitorSem.acquire();
+
+ junitSem.release();
+ monitorSem.acquire();
+ }
+
+ @Override
+ public void monitorCompleted() throws InterruptedException {
+ junitSem.release();
+ monitorSem.acquire();
+ }
+
+ };
- IntegrityMonitor im = IntegrityMonitor.getInstance(resourceName, myProp, queue);
+ IntegrityMonitor im = IntegrityMonitor.getInstance(resourceName, myProp, factory);
// wait for the monitor thread to start
waitStep();
@@ -916,8 +940,7 @@ public class IntegrityMonitorTest extends IntegrityMonitorTestBase {
* @throws InterruptedException if the thread is interrupted
*/
private void waitStep() throws InterruptedException {
- CountDownLatch latch = new CountDownLatch(1);
- queue.offer(latch);
- waitLatch(latch);
+ monitorSem.release();
+ waitSem(junitSem);
}
}
diff --git a/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTestBase.java b/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTestBase.java
index 0c8259b7..e5562306 100644
--- a/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTestBase.java
+++ b/integrity-monitor/src/test/java/org/onap/policy/common/im/IntegrityMonitorTestBase.java
@@ -22,17 +22,14 @@ package org.onap.policy.common.im;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
-
import org.onap.policy.common.utils.jpa.EntityTransCloser;
import org.onap.policy.common.utils.test.log.logback.ExtractAppender;
import org.slf4j.Logger;
@@ -243,14 +240,14 @@ public class IntegrityMonitorTestBase {
}
/**
- * Waits for a latch to reach zero.
+ * Waits for a semaphore to be acquired
*
- * @param latch the latch
+ * @param sem the latch
* @throws InterruptedException if the thread is interrupted
* @throws AssertionError if the latch did not reach zero in the allotted time
*/
- protected void waitLatch(CountDownLatch latch) throws InterruptedException {
- assertTrue(latch.await(WAIT_MS, TimeUnit.SECONDS));
+ protected void waitSem(Semaphore sem) throws InterruptedException {
+ assertTrue(sem.tryAcquire(WAIT_MS, TimeUnit.MILLISECONDS));
}
/**
diff --git a/utils-test/pom.xml b/utils-test/pom.xml
index a7c2eaee..933104b0 100644
--- a/utils-test/pom.xml
+++ b/utils-test/pom.xml
@@ -42,6 +42,11 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTime.java b/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTime.java
new file mode 100644
index 00000000..3dfed4bd
--- /dev/null
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTime.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils-Test
+ * ================================================================================
+ * 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.utils.time;
+
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * "Current" time, when running junit tests. This is intended to be injected into classes
+ * under test, to replace their {@link CurrentTime} objects. When {@link #sleep(long)} is
+ * invoked, it simply advances the notion of "current" time and returns immediately.
+ */
+public class TestTime extends CurrentTime {
+
+ /**
+ * "Current" time, in milliseconds, used by tests.
+ */
+ private AtomicLong tcur = new AtomicLong(System.currentTimeMillis());
+
+ /**
+ *
+ */
+ public TestTime() {
+ super();
+ }
+
+ @Override
+ public long getMillis() {
+ return tcur.get();
+ }
+
+ @Override
+ public Date getDate() {
+ return new Date(tcur.get());
+ }
+
+ @Override
+ public void sleep(long sleepMs) throws InterruptedException {
+ tcur.addAndGet(sleepMs);
+ }
+}
diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTimeMulti.java b/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTimeMulti.java
new file mode 100644
index 00000000..7a8277c7
--- /dev/null
+++ b/utils-test/src/main/java/org/onap/policy/common/utils/time/TestTimeMulti.java
@@ -0,0 +1,200 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils-Test
+ * ================================================================================
+ * 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.utils.time;
+
+import java.util.Date;
+import java.util.PriorityQueue;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * "Current" time, when running junit tests in multiple threads. This is intended to be
+ * injected into classes under test, to replace their {@link CurrentTime} objects. The
+ * {@link #sleep(long)} method blocks until all threads enter and then it moves the notion
+ * of "current" time forward, allowing threads to resume, as the end of their sleep time
+ * is reached. Additional threads do not resume until all threads have once again entered
+ * {@link #sleep(long)} or when {@link #threadCompleted()} is invoked to indicate that a
+ * thread will not re-enter {@link #sleep(long)}.
+ */
+public class TestTimeMulti extends CurrentTime {
+
+ /**
+ * Number of threads that will be sleeping simultaneously.
+ */
+ private int nthreads;
+
+ /**
+ * "Current" time, in milliseconds, used by tests.
+ */
+ private long tcur = System.currentTimeMillis();
+
+ /**
+ * Queue of sleeping threads waiting to be awakened.
+ */
+ private final PriorityQueue<Info> queue = new PriorityQueue<>();
+
+ /**
+ * Used to synchronize updates.
+ */
+ private final Object locker = new Object();
+
+ /**
+ *
+ * @param nthreads number of threads that will be sleeping simultaneously
+ */
+ public TestTimeMulti(int nthreads) {
+ this.nthreads = nthreads;
+ }
+
+ @Override
+ public long getMillis() {
+ return tcur;
+ }
+
+ @Override
+ public Date getDate() {
+ return new Date(tcur);
+ }
+
+ @Override
+ public void sleep(long sleepMs) throws InterruptedException {
+ if (sleepMs <= 0) {
+ return;
+ }
+
+ Info info = new Info(tcur + sleepMs);
+
+ synchronized (locker) {
+ queue.add(info);
+
+ if (queue.size() == nthreads) {
+ // all threads are now sleeping - wake one up
+ wakeThreads();
+ }
+ }
+
+ // this MUST happen outside of the "synchronized" block
+ info.await();
+ }
+
+ /**
+ * Indicates that a thread has terminated or that it will no longer be invoking
+ * {@link #sleep(long)}. Awakens the next sleeping thread, if the queue is full after
+ * removing the terminated thread.
+ *
+ * @throws IllegalStateException if the queue is already full
+ */
+ public void threadCompleted() {
+ synchronized (locker) {
+ int sz = queue.size();
+ if (sz >= nthreads) {
+ throw new IllegalStateException("too many threads still sleeping");
+ }
+
+ --nthreads;
+
+ if (sz == nthreads) {
+ // after removing terminated thread - queue is now full; awaken something
+ wakeThreads();
+ }
+ }
+ }
+
+ /**
+ * Advances the "current" time and awakens any threads sleeping until that time.
+ */
+ private void wakeThreads() {
+ Info info = queue.poll();
+ if(info == null) {
+ return;
+ }
+
+ tcur = info.getAwakenAtMs();
+ info.wake();
+
+ while ((info = queue.poll()) != null) {
+ if (tcur == info.getAwakenAtMs()) {
+ info.wake();
+
+ } else {
+ // not ready to wake this thread - put it back in the queue
+ queue.add(info);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Info about a sleeping thread.
+ */
+ private static class Info implements Comparable<Info> {
+
+ /**
+ * Time, in milliseconds, at which the associated thread should awaken.
+ */
+ private final long awakenAtMs;
+
+ /**
+ * This is triggered when the associated thread should awaken.
+ */
+ private final CountDownLatch latch = new CountDownLatch(1);
+
+ /**
+ * @param awakenAtMs time, in milliseconds, at which the associated thread should
+ * awaken
+ */
+ public Info(long awakenAtMs) {
+ this.awakenAtMs = awakenAtMs;
+ }
+
+ public long getAwakenAtMs() {
+ return awakenAtMs;
+ }
+
+ /**
+ * Awakens the associated thread by decrementing its latch.
+ */
+ public void wake() {
+ latch.countDown();
+ }
+
+ /**
+ * Blocks the current thread until awakened (i.e., until its latch is
+ * decremented).
+ *
+ * @throws InterruptedException
+ */
+ public void await() throws InterruptedException {
+ latch.await();
+ }
+
+ @Override
+ public int compareTo(Info o) {
+ int diff = Long.compare(awakenAtMs, o.awakenAtMs);
+
+ // this assumes that Object.toString() is unique for each Info object
+ if (diff == 0)
+ diff = this.toString().compareTo(o.toString());
+
+ return diff;
+ }
+
+ }
+}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeMultiTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeMultiTest.java
new file mode 100644
index 00000000..206ab5f1
--- /dev/null
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeMultiTest.java
@@ -0,0 +1,116 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils-Test
+ * ================================================================================
+ * 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.utils.time;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class TestTimeMultiTest {
+
+ private static final int NTHREADS = 10;
+ private static final int NTIMES = 100;
+ private static final long WAIT_SEC = 5L;
+ private static final long MIN_SLEEP_MS = 5L;
+
+ private TestTimeMulti ttm;
+ private Semaphore done;
+
+ @Test
+ public void test() throws Exception {
+ ttm = new TestTimeMulti(NTHREADS);
+ done = new Semaphore(0);
+
+ long tbeg = ttm.getMillis();
+
+ // create threads
+ List<MyThread> threads = new ArrayList<>(NTHREADS);
+ for (int x = 0; x < NTHREADS; ++x) {
+ threads.add(new MyThread(x + MIN_SLEEP_MS));
+ }
+
+ // launch threads
+ for (MyThread thr : threads) {
+ thr.start();
+ }
+
+ // wait for each one to complete
+ for (MyThread thr : threads) {
+ assertTrue("complete " + thr.getSleepMs(), done.tryAcquire(WAIT_SEC, TimeUnit.SECONDS));
+ ttm.threadCompleted();
+ }
+
+ // check results
+ for (MyThread thr : threads) {
+ assertEquals("time " + thr.getSleepMs(), thr.texpected, thr.tactual);
+ }
+
+ assertTrue(ttm.getMillis() >= tbeg + NTIMES * MIN_SLEEP_MS);
+ }
+
+ private class MyThread extends Thread {
+
+ private final long sleepMs;
+
+ private volatile long texpected;
+ private volatile long tactual;
+
+ public MyThread(long sleepMs) {
+ this.sleepMs = sleepMs;
+
+ this.setDaemon(true);
+ }
+
+ public long getSleepMs() {
+ return sleepMs;
+ }
+
+ @Override
+ public void run() {
+ try {
+ for (int x = 0; x < NTIMES; ++x) {
+ texpected = ttm.getMillis() + sleepMs;
+ ttm.sleep(sleepMs);
+
+ if ((tactual = ttm.getMillis()) != texpected) {
+ break;
+ }
+
+ if ((tactual = ttm.getDate().getTime()) != texpected) {
+ break;
+ }
+ }
+
+ } catch (InterruptedException expected) {
+ Thread.currentThread().interrupt();
+ }
+
+ done.release();
+ }
+ }
+}
diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeTest.java
new file mode 100644
index 00000000..c1e15b38
--- /dev/null
+++ b/utils-test/src/test/java/org/onap/policy/common/utils/time/TestTimeTest.java
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils-Test
+ * ================================================================================
+ * 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.utils.time;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class TestTimeTest {
+
+ @Test
+ public void test() throws Exception {
+ TestTime tm = new TestTime();
+ TestTime tm2 = new TestTime();
+
+ long treal = System.currentTimeMillis();
+
+ long tcur = tm.getMillis();
+ assertEquals(tcur, tm.getDate().getTime());
+
+ long tsleep = 10000L;
+ long tcur2 = tcur;
+
+ // sleep a bit and then check values
+ tcur2 += tsleep;
+ tm2.sleep(tsleep);
+ assertEquals(tcur2, tm2.getMillis());
+ assertEquals(tcur2, tm2.getDate().getTime());
+
+ // sleep some more and then check values
+ tcur2 += tsleep;
+ tm2.sleep(tsleep);
+ assertEquals(tcur2, tm2.getMillis());
+ assertEquals(tcur2, tm2.getDate().getTime());
+
+ // check again - to ensure unchanged
+ assertEquals(tcur2, tm2.getMillis());
+ assertEquals(tcur2, tm2.getDate().getTime());
+
+ // original should also be unchanged
+ assertEquals(tcur, tm.getMillis());
+ assertEquals(tcur, tm.getDate().getTime());
+
+ // ensure that no real time has elapsed
+ assertTrue(System.currentTimeMillis() < treal + tsleep / 2);
+ }
+
+}
diff --git a/utils/pom.xml b/utils/pom.xml
index cf34bd7c..8375408e 100644
--- a/utils/pom.xml
+++ b/utils/pom.xml
@@ -38,6 +38,11 @@
<dependencies>
<dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.4</version>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java
index 7253c746..e72ebaba 100644
--- a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java
+++ b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java
@@ -25,8 +25,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
import org.onap.policy.common.utils.properties.exception.PropertyAccessException;
import org.onap.policy.common.utils.properties.exception.PropertyException;
import org.onap.policy.common.utils.properties.exception.PropertyInvalidException;
@@ -35,7 +38,9 @@ import org.onap.policy.common.utils.properties.exception.PropertyMissingExceptio
/**
* Configuration whose fields are initialized by reading from a set of {@link Properties},
* as directed by the {@link Property} annotations that appear on fields within the
- * subclass.
+ * subclass. The values of the fields are set via <i>setXxx()</i> methods. As a result, if
+ * a field is annotated and there is no corresponding <i>setXxx()</i> method, then an
+ * exception will be thrown.
* <p>
* It is possible that an invalid <i>defaultValue</i> is specified via the
* {@link Property} annotation. This could remain undetected until an optional property is
@@ -104,7 +109,10 @@ public class PropertyConfiguration {
checkModifiable(field, prop);
- if (setValue(field, props, prop)) {
+ Method setter = getSetter(field, prop);
+ checkSetter(setter, prop);
+
+ if (setValue(setter, field, props, prop)) {
return true;
}
@@ -112,15 +120,33 @@ public class PropertyConfiguration {
}
/**
+ * @param field field whose value is to be set
+ * @param prop property of interest
+ * @return the method to be used to set the field's value
+ * @throws PropertyAccessException if a "set" method cannot be identified
+ */
+ private Method getSetter(Field field, Property prop) throws PropertyAccessException {
+ String nm = "set" + StringUtils.capitalize(field.getName());
+
+ try {
+ return this.getClass().getMethod(nm, field.getType());
+
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new PropertyAccessException(prop.name(), nm, e);
+ }
+ }
+
+ /**
* Sets a field's value from a particular property.
*
+ * @param setter method to be used to set the field's value
* @param field field whose value is to be set
* @param props properties from which to get the value
* @param prop property of interest
* @return {@code true} if the property's value was set, {@code false} otherwise
* @throws PropertyException if an error occurs
*/
- protected boolean setValue(Field field, Properties props, Property prop) throws PropertyException {
+ protected boolean setValue(Method setter, Field field, Properties props, Property prop) throws PropertyException {
try {
Object val = getValue(field, props, prop);
@@ -128,23 +154,15 @@ public class PropertyConfiguration {
return false;
} else {
-
- /*
- * According to java docs & blogs, "field" is our own copy, so we're free
- * to change the flags without impacting the real permissions of the field
- * within the real class.
- */
- field.setAccessible(true);
-
- field.set(this, val);
+ setter.invoke(this, val);
return true;
}
} catch (IllegalArgumentException e) {
throw new PropertyInvalidException(prop.name(), field.getName(), e);
- } catch (IllegalAccessException e) {
- throw new PropertyAccessException(prop.name(), field.getName(), e);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new PropertyAccessException(prop.name(), setter.getName(), e);
}
}
@@ -203,6 +221,21 @@ public class PropertyConfiguration {
}
/**
+ * Verifies that the setter method is not <i>static</i>.
+ *
+ * @param setter method to be checked
+ * @param prop property of interest
+ * @throws PropertyAccessException if the method is static
+ */
+ private void checkSetter(Method setter, Property prop) throws PropertyAccessException {
+ int mod = setter.getModifiers();
+
+ if (Modifier.isStatic(mod)) {
+ throw new PropertyAccessException(prop.name(), setter.getName(), "method is 'static'");
+ }
+ }
+
+ /**
* Gets a property value, coercing it to a String.
*
* @param fieldName field whose value is to be set
diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java
new file mode 100644
index 00000000..0f416c3a
--- /dev/null
+++ b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java
@@ -0,0 +1,117 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * 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.utils.properties;
+
+import java.util.Properties;
+
+/**
+ * Properties with an optional specialization (e.g., session name, controller name).
+ */
+public class SpecProperties extends Properties {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The property prefix, ending with ".".
+ */
+ private final String prefix;
+
+ /**
+ * The specialized property prefix, ending with ".".
+ */
+ private final String specPrefix;
+
+ /**
+ *
+ * @param prefix the property name prefix that appears before any specialization, may
+ * be ""
+ * @param specialization the property name specialization (e.g., session name)
+ */
+ public SpecProperties(String prefix, String specialization) {
+ this.prefix = withTrailingDot(prefix);
+ this.specPrefix = withTrailingDot(this.prefix + specialization);
+ }
+
+ /**
+ *
+ * @param prefix the property name prefix that appears before any specialization, may
+ * be ""
+ * @param specialization the property name specialization (e.g., session name)
+ * @param props the default properties
+ */
+ public SpecProperties(String prefix, String specialization, Properties props) {
+ super(props);
+
+ this.prefix = withTrailingDot(prefix);
+ this.specPrefix = withTrailingDot(this.prefix + specialization);
+ }
+
+ /**
+ * Adds a trailing "." to a String, if it doesn't already have one.
+ *
+ * @param text text to which the "." should be added
+ * @return the text, with a trailing "."
+ */
+ private static String withTrailingDot(String text) {
+ return text.isEmpty() || text.endsWith(".") ? text : text + ".";
+ }
+
+ /**
+ * Gets the property whose value has the given key, looking first for the specialized
+ * property name, and then for the generalized property name.
+ *
+ * @param key property name, without the specialization
+ * @return the value from the property set, or {@code null} if the property set does
+ * not contain the value
+ */
+ @Override
+ public String getProperty(String key) {
+ if (!key.startsWith(prefix)) {
+ return super.getProperty(key);
+ }
+
+ String suffix = key.substring(prefix.length());
+
+ String val = super.getProperty(specPrefix + suffix);
+ if (val != null) {
+ return val;
+ }
+
+ return super.getProperty(key);
+ }
+
+ protected String getPrefix() {
+ return prefix;
+ }
+
+ protected String getSpecPrefix() {
+ return specPrefix;
+ }
+
+ @Override
+ public final int hashCode() {
+ throw new UnsupportedOperationException("SpecProperties cannot be hashed");
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ throw new UnsupportedOperationException("cannot compare SpecProperties");
+ }
+}
diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java
deleted file mode 100644
index 9e3767c1..00000000
--- a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * 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.utils.properties;
-
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-
-/**
- * PropertyConfiguration whose property names are specialized, using a specialization. A
- * property name can take one of the following forms:
- * <dl>
- * <dt>aaa{$}Ddd</dt>
- * <dd>if the specialization is "Xxx", then it looks for the value associated with the
- * property named "aaaXxxDdd"</dd>
- * <dt>aaa{Bbb?Ccc}Ddd</dt>
- * <dd>if the specialization is "Xxx", then it looks for the value associated with the
- * property named "aaaBbbXxxCccDdd". If the property does not exist, then it looks for the
- * value associated with the property named "aaaDdd" (i.e., without the
- * specialization)</dd>
- * <dt>aaa</dt>
- * <dd>simply looks for the value associated with the property named "aaa", without using
- * the specialization</dd>
- * </dl>
- * <p>
- * In the above examples, any of the components (e.g., "aaa") may be empty.
- */
-public class SpecPropertyConfiguration extends PropertyConfiguration {
-
- /**
- * Pattern to extract the specializer from a property name. Group 1 matches the form,
- * "{$}", while groups 2 and 3 match the prefix and suffix, respectively, of the form,
- * "{prefix?suffix}".
- */
- private static final Pattern SPEC_PAT = Pattern.compile(""
- // start of specialization info
- + "\\{(?:"
- // specialization type 1
- + "(\\$)"
- // alternative
- + "|"
- // specialization type 2
- + "(?:"
- // specialization type 2 prefix, may be empty
- + "([^}?]*)"
- // place-holder for the specialization, itself
- + "\\?"
- // specialization type 2 suffix, may be empty
- + "([^}]*)"
- // end of specialization type 2
- + ")"
- // end of specialization info
- + ")\\}");
-
- /**
- * The specialization to be used within property names.
- */
- private final String specialization;
-
- /**
- * Constructs a configuration, without populating any fields; fields should be
- * populated later by invoking {@link #setAllFields(Properties)}.
- *
- * @param specialization specialization to be substituted within property names
- */
- public SpecPropertyConfiguration(String specialization) {
- super();
-
- this.specialization = specialization;
- }
-
- /**
- *
- * Initializes each "@Property" field with its value, as found in the properties.
- *
- * @param specialization specialization to be substituted within property names
- * @param props properties from which to extract the values
- * @throws PropertyException if an error occurs
- */
- public SpecPropertyConfiguration(String specialization, Properties props) throws PropertyException {
- super();
-
- this.specialization = specialization;
-
- setAllFields(props);
- }
-
- /**
- * Gets a property's value, examining the property name for each of the types of
- * specialization.
- */
- @Override
- protected String getRawPropertyValue(Properties props, String propnm) {
- Matcher mat = SPEC_PAT.matcher(propnm);
-
- if (!mat.find()) {
- // property name isn't specialized - use it as is
- return super.getRawPropertyValue(props, propnm);
-
- } else if (mat.group(1) != null) {
- // replace "{$}" with the specialization name
- return super.getRawPropertyValue(props, specializeType1(propnm, specialization, mat));
-
- } else {
- // first try to get the property using the specialization info
- String val = super.getRawPropertyValue(props, specializeType2(propnm, specialization, mat));
- if (val != null) {
- return val;
- }
-
- // wasn't found - try again, without any specialization info
- return super.getRawPropertyValue(props, generalizeType2(propnm, mat));
- }
- }
-
- /**
- * Generalizes a property name by stripping any specialization info from it. This is
- * typically used to construct property names for junit testing.
- *
- * @param propnm property name to be stripped of specialization info
- * @return the generalized property name
- * @throws IllegalArgumentException if the property name requires specialization
- * (i.e., contains "{$}")
- */
- public static String generalize(String propnm) {
- Matcher mat = SPEC_PAT.matcher(propnm);
-
- if (!mat.find()) {
- // property name has no specialization info
- return propnm;
-
- } else if (mat.group(1) != null) {
- // the "{$}" form requires specialization
- throw new IllegalArgumentException("property requires specialization");
-
- } else {
- // property name has specialization info - strip it out
- return generalizeType2(propnm, mat);
- }
- }
-
- /**
- *
- * Generalizes a property name of specialization type 2 (i.e., "{xxx?yyy}" form).
- *
- * @param propnm property name to be stripped of specialization info
- * @param matcher the matcher that matched the "{xxx?yyy}"
- * @return the generalized property name
- */
- private static String generalizeType2(String propnm, Matcher mat) {
- String prefix = propnm.substring(0, mat.start());
- String suffix = propnm.substring(mat.end());
-
- return prefix + suffix;
- }
-
- /**
- * Specializes a property name by applying the specialization. This is typically used
- * to construct property names for junit testing.
- *
- * @param propnm property name to be stripped of specialization info
- * @param spec specialization to apply
- * @return the specialized property name
- */
- public static String specialize(String propnm, String spec) {
- Matcher mat = SPEC_PAT.matcher(propnm);
-
- if (!mat.find()) {
- // property name has no specialization info - leave it as is
- return propnm;
-
- } else if (mat.group(1) != null) {
- // the "{$}" form requires specialization
- return specializeType1(propnm, spec, mat);
-
- } else {
- // the "{xxx?yyy}" form requires specialization
- return specializeType2(propnm, spec, mat);
- }
- }
-
- /**
- * Specializes a property name of specialization type 1 (i.e., "{$}" form).
- *
- * @param propnm property name to be stripped of specialization info
- * @param spec specialization to apply
- * @param matcher the matcher that matched the "{$}"
- * @return the specialized property name
- */
- private static String specializeType1(String propnm, String spec, Matcher mat) {
- String prefix = propnm.substring(0, mat.start());
- String suffix = propnm.substring(mat.end());
-
- return prefix + spec + suffix;
- }
-
- /**
- * Specializes a property name of specialization type 2 (i.e., "{xxx?yyy}" form).
- *
- * @param propnm property name to be stripped of specialization info
- * @param spec specialization to apply
- * @param matcher the matcher that matched the "{xxx?yyy}"
- * @return the specialized property name
- */
- private static String specializeType2(String propnm, String spec, Matcher matcher) {
- String prefix = propnm.substring(0, matcher.start());
- String suffix = propnm.substring(matcher.end());
-
- String specPrefix = matcher.group(2);
- String specSuffix = matcher.group(3);
-
- return (prefix + specPrefix + spec + specSuffix + suffix);
- }
-}
diff --git a/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java b/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java
new file mode 100644
index 00000000..cab469e5
--- /dev/null
+++ b/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils
+ * ================================================================================
+ * 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.utils.time;
+
+import java.util.Date;
+
+/**
+ * Methods to access the current time. Classes can use objects of this type to get current
+ * time information, while allowing the objects to be overridden by junit tests.
+ */
+public class CurrentTime {
+
+ /**
+ *
+ */
+ public CurrentTime() {
+ super();
+ }
+
+ /**
+ * @return the current time, in milliseconds
+ */
+ public long getMillis() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * @return the current Date
+ */
+ public Date getDate() {
+ return new Date();
+ }
+
+ /**
+ * Sleeps for a period of time.
+ *
+ * @param sleepMs amount of time to sleep, in milliseconds
+ * @throws InterruptedException
+ */
+ public void sleep(long sleepMs) throws InterruptedException {
+ Thread.sleep(sleepMs);
+ }
+}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java b/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
index cf823b5d..121ae384 100644
--- a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
+++ b/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
@@ -68,15 +68,9 @@ public class PropertyConfigurationTest {
@Test
public void testPropertyConfiguration() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
- };
-
props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config();
+ PlainStringConfig cfg = new PlainStringConfig();
assertEquals(null, cfg.value);
cfg.setAllFields(props);
@@ -85,18 +79,8 @@ public class PropertyConfigurationTest {
@Test
public void testPropertyConfigurationProperties() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
+ PlainStringConfig cfg = new PlainStringConfig(props);
assertEquals(STRING_VALUE, cfg.value);
}
@@ -111,6 +95,11 @@ public class PropertyConfigurationTest {
@Property(name = "grandparent.value")
protected boolean grandparentValue;
+
+ @SuppressWarnings("unused")
+ public void setGrandparentValue(boolean grandparentValue) {
+ this.grandparentValue = grandparentValue;
+ }
};
/*
@@ -120,12 +109,22 @@ public class PropertyConfigurationTest {
@Property(name = "parent.value")
protected long parentValue;
+
+ @SuppressWarnings("unused")
+ public void setParentValue(long parentValue) {
+ this.parentValue = parentValue;
+ }
};
class Config extends ParentConfig {
@Property(name = THE_VALUE)
private String value;
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
@@ -158,6 +157,11 @@ public class PropertyConfigurationTest {
class Config extends PropertyConfiguration {
private String value;
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
@@ -171,18 +175,8 @@ public class PropertyConfigurationTest {
@Test
public void testSetValueFieldProperties_FieldSet() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
+ PlainStringConfig cfg = new PlainStringConfig(props);
assertEquals(STRING_VALUE, cfg.value);
}
@@ -196,6 +190,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, STRING_VALUE);
@@ -215,14 +214,19 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Exception value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, STRING_VALUE);
new Config(props);
}
- @Test(expected = PropertyMissingException.class)
- public void testSetValueFieldPropertyProperties_NoProperty_NoDefault() throws PropertyException {
+ @Test(expected = PropertyAccessException.class)
+ public void testGetSetter_NoSetter() throws PropertyException {
class Config extends PropertyConfiguration {
@Property(name = THE_VALUE)
@@ -233,15 +237,18 @@ public class PropertyConfigurationTest {
}
};
+ props.setProperty(THE_VALUE, STRING_VALUE);
new Config(props);
}
- @Test(expected = PropertyInvalidException.class)
- public void testSetValueFieldPropertyProperties_InvalidValue() throws PropertyException {
- class Config extends PropertyConfiguration {
+ @Test(expected = PropertyMissingException.class)
+ public void testSetValueMethodFieldPropertiesProperty_NoProperty_NoDefault() throws PropertyException {
+ new PlainStringConfig(props);
+ }
- @Property(name = THE_VALUE)
- private int value;
+ @Test(expected = PropertyInvalidException.class)
+ public void testSetValueMethodFieldPropertiesProperty_InvalidValue() throws PropertyException {
+ class Config extends PlainPrimIntConfig {
public Config(Properties props) throws PropertyException {
super(props);
@@ -260,6 +267,24 @@ public class PropertyConfigurationTest {
new Config(props);
}
+ @Test(expected = PropertyAccessException.class)
+ public void testSetValueMethodFieldPropertiesProperty_MethodEx() throws PropertyException {
+ class Config extends PlainStringConfig {
+
+ public Config(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ @Override
+ public void setValue(String value) {
+ throw new IllegalArgumentException("expected exception");
+ }
+ };
+
+ props.setProperty(THE_VALUE, STRING_VALUE);
+ new Config(props);
+ }
+
@Test
public void testGetValue() throws PropertyException {
// this class contains all of the supported field types
@@ -295,6 +320,96 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setStringValue(String stringValue) {
+ this.stringValue = stringValue;
+ }
+
+ @SuppressWarnings("unused")
+ public Boolean getBoolTrueValue() {
+ return boolTrueValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setBoolTrueValue(Boolean boolTrueValue) {
+ this.boolTrueValue = boolTrueValue;
+ }
+
+ @SuppressWarnings("unused")
+ public Boolean getBoolFalseValue() {
+ return boolFalseValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setBoolFalseValue(Boolean boolFalseValue) {
+ this.boolFalseValue = boolFalseValue;
+ }
+
+ @SuppressWarnings("unused")
+ public boolean isPrimBoolTrueValue() {
+ return primBoolTrueValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPrimBoolTrueValue(boolean primBoolTrueValue) {
+ this.primBoolTrueValue = primBoolTrueValue;
+ }
+
+ @SuppressWarnings("unused")
+ public boolean isPrimBoolFalseValue() {
+ return primBoolFalseValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPrimBoolFalseValue(boolean primBoolFalseValue) {
+ this.primBoolFalseValue = primBoolFalseValue;
+ }
+
+ @SuppressWarnings("unused")
+ public Integer getIntValue() {
+ return intValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setIntValue(Integer intValue) {
+ this.intValue = intValue;
+ }
+
+ @SuppressWarnings("unused")
+ public int getPrimIntValue() {
+ return primIntValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPrimIntValue(int primIntValue) {
+ this.primIntValue = primIntValue;
+ }
+
+ @SuppressWarnings("unused")
+ public Long getLongValue() {
+ return longValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setLongValue(Long longValue) {
+ this.longValue = longValue;
+ }
+
+ @SuppressWarnings("unused")
+ public long getPrimLongValue() {
+ return primLongValue;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPrimLongValue(long primLongValue) {
+ this.primLongValue = primLongValue;
+ }
};
props.setProperty("string", "a string");
@@ -331,6 +446,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Exception value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, STRING_VALUE);
@@ -354,6 +474,21 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setPublicString(String publicString) {
+ this.publicString = publicString;
+ }
+
+ @SuppressWarnings("unused")
+ public void setPrivateString(String privateString) {
+ this.privateString = privateString;
+ }
+
+ @SuppressWarnings("unused")
+ public void setProtectedString(String protectedString) {
+ this.protectedString = protectedString;
+ }
};
props.setProperty("public", "a public string");
@@ -370,7 +505,7 @@ public class PropertyConfigurationTest {
@Test(expected = PropertyAccessException.class)
public void testCheckModifiable_Static() throws PropertyException {
props.setProperty(THE_VALUE, STRING_VALUE);
- new StaticConfig(props);
+ new StaticPropConfig(props);
}
@Test(expected = PropertyAccessException.class)
@@ -390,38 +525,24 @@ public class PropertyConfigurationTest {
new Config(props);
}
+ @Test(expected = PropertyAccessException.class)
+ public void testCheckSetter_Static() throws PropertyException {
+ props.setProperty(THE_VALUE, STRING_VALUE);
+ new StaticMethodConfig(props);
+ }
+
@Test
public void testGetStringValue() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
+ PlainStringConfig cfg = new PlainStringConfig(props);
assertEquals(STRING_VALUE, cfg.value);
}
@Test
public void testGetBooleanValue_NoDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, "true");
- Config cfg = new Config(props);
+ PlainBooleanConfig cfg = new PlainBooleanConfig(props);
assertEquals(true, cfg.value);
}
@@ -436,6 +557,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Boolean value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "true");
@@ -452,6 +578,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Boolean value) {
+ this.value = value;
+ }
};
// property not defined
@@ -479,6 +610,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Boolean value) {
+ this.value = value;
+ }
};
// property not defined
@@ -506,6 +642,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Integer value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "200");
@@ -524,6 +665,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Integer value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "200");
@@ -540,6 +686,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Integer value) {
+ this.value = value;
+ }
};
// property not defined
@@ -562,6 +713,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Long value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "20000");
@@ -580,6 +736,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Long value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "20000");
@@ -596,6 +757,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(Long value) {
+ this.value = value;
+ }
};
// property not defined
@@ -610,18 +776,8 @@ public class PropertyConfigurationTest {
@Test
public void testGetPropValue_Prop_NoDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
+ PlainStringConfig cfg = new PlainStringConfig(props);
assertEquals(STRING_VALUE, cfg.value);
}
@@ -636,6 +792,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, STRING_VALUE);
@@ -654,6 +815,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
props.setProperty(THE_VALUE, "");
@@ -672,6 +838,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
Config cfg = new Config(props);
@@ -689,6 +860,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
Config cfg = new Config(props);
@@ -706,6 +882,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
new Config(props);
@@ -721,6 +902,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
Config cfg = new Config(props);
@@ -730,10 +916,7 @@ public class PropertyConfigurationTest {
@Test
public void testGetRawPropertyValue() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
+ class Config extends PlainStringConfig {
public Config(Properties props) throws PropertyException {
super(props);
@@ -747,144 +930,64 @@ public class PropertyConfigurationTest {
Config cfg = new Config(props);
- assertEquals(STRING_VALUE, cfg.value);
+ assertEquals(STRING_VALUE, cfg.getValue());
}
@Test
public void testMakeBoolean_True() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, "true");
- Config cfg = new Config(props);
+ PlainBooleanConfig cfg = new PlainBooleanConfig(props);
assertEquals(true, cfg.value);
}
@Test
public void testMakeBoolean_False() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, "false");
- Config cfg = new Config(props);
+ PlainBooleanConfig cfg = new PlainBooleanConfig(props);
assertEquals(false, cfg.value);
}
@Test(expected = PropertyInvalidException.class)
public void testMakeBoolean_Invalid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, INVALID_VALUE);
- new Config(props);
+ new PlainBooleanConfig(props);
}
@Test
public void testMakeInteger_Valid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private int value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, "300");
- Config cfg = new Config(props);
+ PlainPrimIntConfig cfg = new PlainPrimIntConfig(props);
assertEquals(300, cfg.value);
}
@Test(expected = PropertyInvalidException.class)
public void testMakeInteger_Invalid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private int value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, INVALID_VALUE);
- new Config(props);
+ new PlainPrimIntConfig(props);
}
@Test(expected = PropertyInvalidException.class)
public void testMakeInteger_TooBig() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private int value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, String.valueOf(Integer.MAX_VALUE + 10L));
- new Config(props);
+ new PlainPrimIntConfig(props);
}
@Test
public void testMakeLong_Valid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, "30000");
- Config cfg = new Config(props);
+ PlainPrimLongConfig cfg = new PlainPrimLongConfig(props);
assertEquals(30000L, cfg.value);
}
@Test(expected = PropertyInvalidException.class)
public void testMakeLong_Invalid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- };
-
props.setProperty(THE_VALUE, INVALID_VALUE);
- new Config(props);
+ new PlainPrimLongConfig(props);
}
@Test
@@ -897,6 +1000,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(long value) {
+ this.value = value;
+ }
};
Config cfg = new Config(props);
@@ -914,6 +1022,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(long value) {
+ this.value = value;
+ }
};
new Config(props);
@@ -929,6 +1042,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(long value) {
+ this.value = value;
+ }
};
new Config(props);
@@ -944,6 +1062,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
// missing property - should default to ""
@@ -971,6 +1094,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(long value) {
+ this.value = value;
+ }
};
new Config(props);
@@ -986,6 +1114,11 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(String value) {
+ this.value = value;
+ }
};
Config cfg = new Config(props);
@@ -1003,23 +1136,126 @@ public class PropertyConfigurationTest {
public Config(Properties props) throws PropertyException {
super(props);
}
+
+ @SuppressWarnings("unused")
+ public void setValue(long value) {
+ this.value = value;
+ }
};
new Config(props);
}
/**
- * A config whose annotated property is "static".
+ * Config with a String value having no qualifiers.
*/
- public static class StaticConfig extends PropertyConfiguration {
+ public class PlainStringConfig extends PropertyConfiguration {
+
+ @Property(name = THE_VALUE)
+ private String value;
+
+ public PlainStringConfig() {
+
+ }
+
+ public PlainStringConfig(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ };
+
+ /**
+ * Config with a Boolean value having no qualifiers.
+ */
+ public class PlainBooleanConfig extends PropertyConfiguration {
+
+ @Property(name = THE_VALUE)
+ private Boolean value;
+
+ public PlainBooleanConfig(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ public void setValue(Boolean value) {
+ this.value = value;
+ }
+ };
+
+ /**
+ * Config with an int value having no qualifiers.
+ */
+ public class PlainPrimIntConfig extends PropertyConfiguration {
+
+ @Property(name = THE_VALUE)
+ private int value;
+
+ public PlainPrimIntConfig(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+ };
+
+ /**
+ * Config with a long value having no qualifiers.
+ */
+ public class PlainPrimLongConfig extends PropertyConfiguration {
+
+ @Property(name = THE_VALUE)
+ private long value;
+
+ public PlainPrimLongConfig(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ public void setValue(long value) {
+ this.value = value;
+ }
+ };
+
+ /**
+ * A config whose field is "static".
+ */
+ public static class StaticPropConfig extends PropertyConfiguration {
// "static" field cannot be set
@Property(name = THE_VALUE)
private static String value;
- public StaticConfig(Properties props) throws PropertyException {
+ public StaticPropConfig(Properties props) throws PropertyException {
super(props);
}
+
+ public static void setValue(String value) {
+ StaticPropConfig.value = value;
+ }
+ };
+
+ /**
+ * A config whose method is "static".
+ */
+ public static class StaticMethodConfig extends PropertyConfiguration {
+
+ // "static" field cannot be set
+ @Property(name = THE_VALUE)
+ private String value;
+
+ public StaticMethodConfig(Properties props) throws PropertyException {
+ super(props);
+ }
+
+ public static void setValue(String value) {
+
+ }
};
/**
diff --git a/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertiesTest.java b/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertiesTest.java
new file mode 100644
index 00000000..01f096d1
--- /dev/null
+++ b/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertiesTest.java
@@ -0,0 +1,224 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * 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.utils.properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import java.util.Properties;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SpecPropertiesTest {
+
+ /**
+ * Property prefix of interest.
+ */
+ private static final String MY_PREFIX = "my.prefix";
+
+ /**
+ * Specialization, which follows the prefix.
+ */
+ private static final String MY_SPEC = "my.spec";
+
+ /**
+ * Generalized prefix (i.e., without the spec).
+ */
+ private static final String PREFIX_GEN = MY_PREFIX + ".";
+
+ /**
+ * Specialized prefix (i.e., with the spec).
+ */
+ private static final String PREFIX_SPEC = PREFIX_GEN + MY_SPEC + ".";
+
+ /**
+ * Suffix to add to property names to generate names of properties that are not
+ * populated.
+ */
+ private static final String SUFFIX = ".suffix";
+
+ /**
+ * Property name without a prefix.
+ */
+ private static final String PROP_NO_PREFIX = "other";
+
+ /**
+ * Generalized property name (i.e., without the spec).
+ */
+ private static final String PROP_GEN = PREFIX_GEN + "generalized";
+
+ // property names that include the spec
+ private static final String PROP_SPEC = PREFIX_SPEC + "specialized";
+ private static final String PROP_UNKNOWN = PREFIX_SPEC + "unknown";
+
+ // property values
+ private static final String VAL_NO_PREFIX = "no-prefix";
+ private static final String VAL_GEN = "gen";
+ private static final String VAL_SPEC = "spec";
+
+ private static final String VAL_DEFAULT = "default value";
+
+ private Properties supportingProps;
+ private SpecProperties props;
+
+ @Before
+ public void setUp() {
+ supportingProps = new Properties();
+
+ supportingProps.setProperty(PROP_NO_PREFIX, VAL_NO_PREFIX);
+ supportingProps.setProperty(PROP_GEN, VAL_GEN);
+ supportingProps.setProperty(PROP_SPEC, VAL_SPEC);
+
+ props = new SpecProperties(MY_PREFIX, MY_SPEC);
+
+ props.putAll(supportingProps);
+ }
+
+ @Test
+ public void testSpecPropertiesStringString() {
+
+ // no supporting properties
+ props = new SpecProperties(MY_PREFIX, MY_SPEC);
+
+ assertEquals(PREFIX_GEN, props.getPrefix());
+ assertEquals(PREFIX_SPEC, props.getSpecPrefix());
+
+ // everything is null
+ assertNull(props.getProperty(gen(PROP_NO_PREFIX)));
+ assertNull(props.getProperty(gen(PROP_GEN)));
+ assertNull(props.getProperty(gen(PROP_SPEC)));
+ assertNull(props.getProperty(gen(PROP_UNKNOWN)));
+ }
+
+ @Test
+ public void testSpecPropertiesStringStringProperties() {
+
+ // use supportingProps as default properties
+ props = new SpecProperties(MY_PREFIX, MY_SPEC, supportingProps);
+
+ assertEquals(PREFIX_GEN, props.getPrefix());
+ assertEquals(PREFIX_SPEC, props.getSpecPrefix());
+
+ assertEquals(VAL_NO_PREFIX, props.getProperty(gen(PROP_NO_PREFIX)));
+ assertEquals(VAL_GEN, props.getProperty(gen(PROP_GEN)));
+ assertEquals(VAL_SPEC, props.getProperty(gen(PROP_SPEC)));
+ assertNull(props.getProperty(gen(PROP_UNKNOWN)));
+ }
+
+ @Test
+ public void testSpecPropertiesStringStringProperties_EmptyPrefix() {
+ supportingProps = new Properties();
+
+ supportingProps.setProperty(PROP_NO_PREFIX, VAL_NO_PREFIX);
+ supportingProps.setProperty("a.value", VAL_GEN);
+ supportingProps.setProperty("b.value", VAL_GEN);
+ supportingProps.setProperty(MY_SPEC + ".b.value", VAL_SPEC);
+
+ // no supporting properties
+ props = new SpecProperties("", MY_SPEC, supportingProps);
+
+ assertEquals(VAL_NO_PREFIX, props.getProperty(gen(PROP_NO_PREFIX)));
+ assertEquals(VAL_GEN, props.getProperty(gen("a.value")));
+ assertEquals(VAL_SPEC, props.getProperty(MY_SPEC + ".b.value"));
+ assertNull(props.getProperty(gen(PROP_UNKNOWN)));
+ }
+
+ @Test
+ public void testWithTrailingDot() {
+ // neither has trailing dot
+ assertEquals(PREFIX_GEN, props.getPrefix());
+ assertEquals(PREFIX_SPEC, props.getSpecPrefix());
+
+ // both have trailing dot
+ props = new SpecProperties(PREFIX_GEN, MY_SPEC + ".");
+ assertEquals(PREFIX_GEN, props.getPrefix());
+ assertEquals(PREFIX_SPEC, props.getSpecPrefix());
+
+ // first is empty
+ props = new SpecProperties("", MY_SPEC);
+ assertEquals("", props.getPrefix());
+ assertEquals(MY_SPEC + ".", props.getSpecPrefix());
+
+ // second is empty
+ props = new SpecProperties(PREFIX_GEN, "");
+ assertEquals(PREFIX_GEN, props.getPrefix());
+ assertEquals(PREFIX_GEN, props.getSpecPrefix());
+ }
+
+ @Test
+ public void testGetPropertyString() {
+ // the key does contain the prefix
+ assertEquals(VAL_NO_PREFIX, props.getProperty(gen(PROP_NO_PREFIX)));
+ assertNull(props.getProperty(gen(PROP_NO_PREFIX + SUFFIX)));
+
+ // specialized value exists
+ assertEquals(VAL_GEN, props.getProperty(gen(PROP_GEN)));
+ assertNull(props.getProperty(gen(PROP_GEN + SUFFIX)));
+
+ // generalized value exists
+ assertEquals(VAL_SPEC, props.getProperty(gen(PROP_SPEC)));
+ assertNull(props.getProperty(gen(PROP_SPEC + SUFFIX)));
+
+ // not found
+ assertNull(props.getProperty(gen(PROP_UNKNOWN)));
+ assertNull(props.getProperty(gen(PROP_UNKNOWN + SUFFIX)));
+ }
+
+ @Test
+ public void testGetPropertyStringString() {
+ // the key does contain the prefix
+ assertEquals(VAL_NO_PREFIX, props.getProperty(gen(PROP_NO_PREFIX), VAL_DEFAULT));
+ assertEquals(VAL_DEFAULT, props.getProperty(gen(PROP_NO_PREFIX + SUFFIX), VAL_DEFAULT));
+
+ // specialized value exists
+ assertEquals(VAL_GEN, props.getProperty(gen(PROP_GEN), VAL_DEFAULT));
+ assertEquals(VAL_DEFAULT, props.getProperty(gen(PROP_GEN + SUFFIX), VAL_DEFAULT));
+
+ // generalized value exists
+ assertEquals(VAL_SPEC, props.getProperty(gen(PROP_SPEC), VAL_DEFAULT));
+ assertEquals(VAL_DEFAULT, props.getProperty(gen(PROP_SPEC + SUFFIX), VAL_DEFAULT));
+
+ // not found
+ assertEquals(VAL_DEFAULT, props.getProperty(gen(PROP_UNKNOWN), VAL_DEFAULT));
+ assertEquals(VAL_DEFAULT, props.getProperty(gen(PROP_UNKNOWN + SUFFIX), VAL_DEFAULT));
+
+ // can return null
+ assertNull(props.getProperty(gen(PROP_UNKNOWN), null));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testHashCode() {
+ props.hashCode();
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testEquals() {
+ props.equals(props);
+ }
+
+ private String gen(String propnm) {
+ if (propnm.startsWith(PREFIX_SPEC)) {
+ return PREFIX_GEN + propnm.substring(PREFIX_SPEC.length());
+ }
+
+ return propnm;
+ }
+
+}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertyConfigurationTest.java b/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertyConfigurationTest.java
deleted file mode 100644
index 39c8f01a..00000000
--- a/utils/src/test/java/org/onap/policy/common/utils/properties/SpecPropertyConfigurationTest.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * 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.utils.properties;
-
-import static org.junit.Assert.*;
-import java.util.Properties;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-import org.onap.policy.common.utils.properties.exception.PropertyMissingException;
-import static org.onap.policy.common.utils.properties.SpecPropertyConfiguration.*;
-
-/**
- *
- */
-public class SpecPropertyConfigurationTest {
-
- /**
- * The specializer.
- */
- private static final String SPEC = "my.name";
-
- /**
- * Properties used when invoking constructors.
- */
- private Properties props;
-
- /**
- * @throws java.lang.Exception
- */
- @Before
- public void setUp() throws Exception {
- props = new Properties();
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#getRawPropertyValue(java.util.Properties, java.lang.String)}.
- * @throws PropertyException
- */
- @Test
- public void testGetRawPropertyValue() throws PropertyException {
- class Config extends SpecPropertyConfiguration {
-
- // no spec
- @Property(name = "prefix.suffix")
- private String noSpec;
-
- // no spec, other type
- @Property(name = "no.spec.bool")
- private boolean noSpecBool;
-
- // type 1, no prefix
- @Property(name = "{$}.suffix")
- private String type1NoPrefix;
-
- // type 1, no suffix
- @Property(name = "prefix.{$}")
- private String type1NoSuffix;
-
- // type 1, both prefix and suffix
- @Property(name = "prefix.{$}.suffix")
- private String type1Both;
-
- // type 1, other type
- @Property(name = "an.{$}.int")
- private int type1Int;
-
- // type 2, no prefix
- @Property(name = "{abc.?.def}.suffix")
- private String type2NoPrefix;
-
- // type 2, no suffix
- @Property(name = "prefix.{abc.?.def}")
- private String type2NoSuffix;
-
- // type 2, no spec prefix
- @Property(name = "prefix.{?.def}.suffix")
- private String type2NoSpecPrefix;
-
- // type 2, no spec suffix
- @Property(name = "prefix{.abc.?}.suffix")
- private String type2NoSpecSuffix;
-
- // type 2, all components
- @Property(name = "prefix.{abc.?.def.}suffix")
- private String type2Both;
-
- // type 2, other type
- @Property(name = "a.{abc.?.def.}long")
- private long type2Long;
-
- public Config(String specialization, Properties props) throws PropertyException {
- super(specialization, props);
- }
- };
-
- props.setProperty("prefix.suffix", "no.spec");
- props.setProperty("no.spec.bool", "true");
- props.setProperty("world.suffix", "type1.no.prefix");
- props.setProperty("prefix.world", "type1.no.suffix");
- props.setProperty("prefix.world.suffix", "type1.both");
- props.setProperty("an.world.int", "200");
- props.setProperty("abc.world.def.suffix", "type2.no.prefix");
- props.setProperty("prefix.abc.world.def", "type2.no.suffix");
- props.setProperty("prefix.world.def.suffix", "type2.no.spec.prefix");
- props.setProperty("prefix.abc.world.suffix", "type2.no.spec.suffix");
- props.setProperty("prefix.abc.world.def.suffix", "type2.both");
- props.setProperty("a.abc.world.def.long", "3000");
-
- Config cfg = new Config("world", props);
-
- assertEquals("no.spec", cfg.noSpec);
- assertEquals(true, cfg.noSpecBool);
- assertEquals("type1.no.prefix", cfg.type1NoPrefix);
- assertEquals("type1.no.suffix", cfg.type1NoSuffix);
- assertEquals("type1.both", cfg.type1Both);
- assertEquals(200, cfg.type1Int);
- assertEquals("type2.no.prefix", cfg.type2NoPrefix);
- assertEquals("type2.no.suffix", cfg.type2NoSuffix);
- assertEquals("type2.no.spec.prefix", cfg.type2NoSpecPrefix);
- assertEquals("type2.no.spec.suffix", cfg.type2NoSpecSuffix);
- assertEquals("type2.both", cfg.type2Both);
- assertEquals(3000L, cfg.type2Long);
- }
- @Test
- public void testGetRawPropertyValue_Type2_Generalized() throws PropertyException {
- class Config extends SpecPropertyConfiguration {
-
- // type 2, all components
- @Property(name = "prefix.{abc.?.def.}suffix")
- private String value;
-
- public Config(String specialization, Properties props) throws PropertyException {
- super(specialization, props);
- }
- };
-
- props.setProperty("prefix.suffix", "no.spec");
-
- Config cfg = new Config("world", props);
-
- assertEquals("no.spec", cfg.value);
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#getRawPropertyValue(java.util.Properties, java.lang.String)}.
- * @throws PropertyException
- */
- @Test(expected = PropertyMissingException.class)
- public void testGetRawPropertyValue_NotFound() throws PropertyException {
- class Config extends SpecPropertyConfiguration {
-
- @Property(name = "not.found")
- private String notFound;
-
- public Config(String specialization, Properties props) throws PropertyException {
- super(specialization, props);
- }
- };
-
- new Config("not found", props);
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#SpecPropertyConfiguration(java.lang.String)}.
- * @throws PropertyException
- */
- @Test
- public void testSpecPropertyConfigurationString() throws PropertyException {
- final String propnm = "string.{$}.prop";
- final String propval = "hello";
-
- class Config extends SpecPropertyConfiguration {
-
- @Property(name = propnm)
- private String value;
-
- public Config(String specialization) {
- super(specialization);
- }
- };
-
- props.setProperty(specialize(propnm, SPEC), propval);
-
- Config cfg = new Config(SPEC);
- assertEquals(null, cfg.value);
-
- cfg.setAllFields(props);
- assertEquals(propval, cfg.value);
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#SpecPropertyConfiguration(java.lang.String, java.util.Properties)}.
- * @throws PropertyException
- */
- @Test
- public void testSpecPropertyConfigurationStringProperties() throws PropertyException {
- final String propnm = "int.{$}.prop";
- final int propval = 10;
-
- class Config extends SpecPropertyConfiguration {
-
- @Property(name = propnm)
- private int value;
-
- public Config(String specialization, Properties props) throws PropertyException {
- super(specialization, props);
- }
- };
-
- props.setProperty(specialize(propnm, SPEC), String.valueOf(propval));
-
- Config cfg = new Config(SPEC, props);
-
- assertEquals(propval, cfg.value);
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#generalize(java.lang.String)}.
- */
- @Test
- public void testGeneralize_NoSpec() {
- final String xyzPdq = "xyz.pdq";
-
- // no spec
- assertEquals(xyzPdq, generalize(xyzPdq));
-
- // spec type 1 throws an exception - we'll test it separately
-
- // spec type 2
- assertEquals(xyzPdq, generalize("xyz.{xxx.?.yyy.}pdq"));
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#generalize(java.lang.String)}.
- */
- @Test(expected = IllegalArgumentException.class)
- public void testGeneralize_Spec1() {
- generalize("abc.{$}.def");
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#generalizeType2(java.lang.String, java.util.regex.Matcher)}.
- */
- @Test
- public void testGeneralizeType2() {
- assertEquals("abc.def", generalize("abc.{xyz?pdq}def"));
-
- assertEquals("", generalize("{xyz?pdq}"));
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#specialize(java.lang.String, java.lang.String)}.
- */
- @Test
- public void testSpecialize() {
- final String spec = "get.spec";
- final String abcDef = "abc.def";
-
- // no spec
- assertEquals(abcDef, specialize(abcDef, spec));
-
- // spec type 1
- assertEquals("abc.get.spec.def", specialize("abc.{$}.def", spec));
-
- // spec type 2
- assertEquals("abc.xxx.get.spec.yyy.def", specialize("abc.{xxx.?.yyy.}def", spec));
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#specializeType1(java.lang.String, java.lang.String, java.util.regex.Matcher)}.
- */
- @Test
- public void testSpecializeType1() {
- final String spec = "spec1";
-
- // no prefix
- assertEquals("spec1.def", specialize("{$}.def", spec));
-
- // no suffix
- assertEquals("abc.spec1", specialize("abc.{$}", spec));
-
- // with both prefix and suffix
- assertEquals("abc.spec1.def", specialize("abc.{$}.def", spec));
- }
-
- /**
- * Test method for {@link org.onap.policy.common.utils.properties.SpecPropertyConfiguration#specializeType2(java.lang.String, java.lang.String, java.util.regex.Matcher)}.
- */
- @Test
- public void testSpecializeType2() {
- final String spec = "spec2";
-
- // no prefix
- assertEquals("xxx.spec2.yyy.def", specialize("{xxx.?.yyy.}def", spec));
-
- // no suffix
- assertEquals("abc.xxx.spec2.yyy", specialize("abc{.xxx.?.yyy}", spec));
-
- // no spec prefix
- assertEquals("abc.spec2.yyy.def", specialize("abc.{?.yyy.}def", spec));
-
- // no spec suffix
- assertEquals("abc.xxx.spec2.def", specialize("abc.{xxx.?}.def", spec));
-
- // no components
- assertEquals(spec, specialize("{?}", spec));
-
- // all components
- assertEquals("abc.xxx.spec2.yyy.def", specialize("abc.{xxx.?.yyy.}def", spec));
- }
-
-}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/time/CurrentTimeTest.java b/utils/src/test/java/org/onap/policy/common/utils/time/CurrentTimeTest.java
new file mode 100644
index 00000000..694a3d21
--- /dev/null
+++ b/utils/src/test/java/org/onap/policy/common/utils/time/CurrentTimeTest.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Common Utils
+ * ================================================================================
+ * 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.utils.time;
+
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class CurrentTimeTest {
+
+ @Test
+ public void testGetMillis() {
+ long tcur = System.currentTimeMillis();
+ long tval = new CurrentTime().getMillis();
+ long tval2 = new CurrentTime().getMillis();
+ long tend = System.currentTimeMillis();
+
+ assertTrue(tval >= tcur && tval <= tend);
+ assertTrue(tval2 >= tcur && tval2 <= tend);
+ }
+
+ @Test
+ public void testGetDate() {
+ long tcur = System.currentTimeMillis();
+ long tval = new CurrentTime().getDate().getTime();
+ long tval2 = new CurrentTime().getDate().getTime();
+ long tend = System.currentTimeMillis();
+
+ assertTrue(tval >= tcur && tval <= tend);
+ assertTrue(tval2 >= tcur && tval2 <= tend);
+ }
+
+ @Test
+ public void testSleep() throws Exception {
+ long tcur = System.currentTimeMillis();
+ new CurrentTime().sleep(10);
+ long tend = System.currentTimeMillis();
+
+ assertTrue(tend >= tcur + 10 - 1);
+ }
+
+}