aboutsummaryrefslogtreecommitdiffstats
path: root/controlloop/common/database/src
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-06-26 11:00:18 -0400
committerJim Hahn <jrh3@att.com>2019-06-26 18:59:18 -0400
commitd8118c6638bb2440f89eae9d3f979bdfb0e013c3 (patch)
tree6f4122198b21438a9d41a47910381df17ef92d36 /controlloop/common/database/src
parentd2ec3b974f116d87c6bd84dee13ea7fc2739f54e (diff)
Fix sonar issues in drools-applications database
Refactored to eliminate duplicate code blocks. Added coverage tests. Change-Id: I99d2b6f68fee38a1dbbf038ad29d1dfe87fb4ae7 Issue-ID: POLICY-1791 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'controlloop/common/database/src')
-rw-r--r--controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/CountRecentOperationsPip.java61
-rw-r--r--controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/GetOperationOutcomePip.java53
-rw-r--r--controlloop/common/database/src/main/java/org/onap/policy/database/std/StdOnapPip.java100
-rw-r--r--controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/CountRecentOperationsPipTest.java216
-rw-r--r--controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/GetOperationOutcomePipTest.java189
-rw-r--r--controlloop/common/database/src/test/java/org/onap/policy/database/std/DbaoTest.java70
-rw-r--r--controlloop/common/database/src/test/java/org/onap/policy/database/std/StdOnapPipTest.java268
-rw-r--r--controlloop/common/database/src/test/resources/META-INF/persistence.xml9
8 files changed, 775 insertions, 191 deletions
diff --git a/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/CountRecentOperationsPip.java b/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/CountRecentOperationsPip.java
index 1f73ed3ce..7b6f13611 100644
--- a/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/CountRecentOperationsPip.java
+++ b/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/CountRecentOperationsPip.java
@@ -27,11 +27,12 @@ import com.att.research.xacml.api.pip.PIPRequest;
import com.att.research.xacml.api.pip.PIPResponse;
import com.att.research.xacml.std.pip.StdMutablePIPResponse;
import com.att.research.xacml.std.pip.StdPIPResponse;
-import com.google.common.base.Strings;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Properties;
-import javax.persistence.Persistence;
+import java.util.Set;
import org.onap.policy.database.ToscaDictionary;
import org.onap.policy.database.std.StdOnapPip;
import org.slf4j.Logger;
@@ -42,6 +43,9 @@ public class CountRecentOperationsPip extends StdOnapPip {
public static final String ISSUER_NAME = "count-recent-operations";
private static Logger logger = LoggerFactory.getLogger(CountRecentOperationsPip.class);
+ private static final Set<String> TIME_WINDOW_SCALES = Collections
+ .unmodifiableSet(new HashSet<>(Arrays.asList("minute", "hour", "day", "week", "month", "year")));
+
public CountRecentOperationsPip() {
super();
}
@@ -53,25 +57,7 @@ public class CountRecentOperationsPip extends StdOnapPip {
@Override
public void configure(String id, Properties properties) throws PIPException {
- super.configure(id, properties);
- //
- // Create our entity manager
- //
- em = null;
- try {
- //
- // In case there are any overloaded properties for the JPA
- //
- Properties emProperties = new Properties(properties);
- //
- // Create the entity manager factory
- //
- em = Persistence.createEntityManagerFactory(
- properties.getProperty(ISSUER_NAME + ".persistenceunit"),
- emProperties).createEntityManager();
- } catch (Exception e) {
- logger.error("Persistence failed {} operations history db {}", e.getLocalizedMessage(), e);
- }
+ super.configure(id, properties, ISSUER_NAME);
}
/**
@@ -85,23 +71,11 @@ public class CountRecentOperationsPip extends StdOnapPip {
public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
logger.debug("getAttributes requesting attribute {} of type {} for issuer {}",
pipRequest.getAttributeId(), pipRequest.getDataTypeId(), pipRequest.getIssuer());
- //
- // Determine if the issuer is correct
- //
- if (Strings.isNullOrEmpty(pipRequest.getIssuer())) {
- logger.debug("issuer is null - returning empty response");
- //
- // We only respond to ourself as the issuer
- //
- return StdPIPResponse.PIP_RESPONSE_EMPTY;
- }
- if (! pipRequest.getIssuer().startsWith(ToscaDictionary.GUARD_ISSUER_PREFIX)) {
- logger.debug("Issuer does not start with guard");
- //
- // We only respond to ourself as the issuer
- //
+
+ if (isRequestInvalid(pipRequest)) {
return StdPIPResponse.PIP_RESPONSE_EMPTY;
}
+
//
// Parse out the issuer which denotes the time window
// Eg: any-prefix:tw:10:minute
@@ -156,12 +130,7 @@ public class CountRecentOperationsPip extends StdOnapPip {
//
// Compute the time window
//
- if (! "minute".equalsIgnoreCase(timeWindowScale)
- && ! "hour".equalsIgnoreCase(timeWindowScale)
- && ! "day".equalsIgnoreCase(timeWindowScale)
- && ! "week".equalsIgnoreCase(timeWindowScale)
- && ! "month".equalsIgnoreCase(timeWindowScale)
- && ! "year".equalsIgnoreCase(timeWindowScale)) {
+ if (! TIME_WINDOW_SCALES.contains(timeWindowScale.toLowerCase())) {
//
// Unsupported
//
@@ -197,7 +166,7 @@ public class CountRecentOperationsPip extends StdOnapPip {
.setParameter(4, timeWindowScale)
.setParameter(5, timeWindowVal * -1)
.getSingleResult();
- } catch (Exception e) {
+ } catch (RuntimeException e) {
logger.error("Named query failed ", e);
}
//
@@ -209,10 +178,10 @@ public class CountRecentOperationsPip extends StdOnapPip {
//
logger.info("operations query returned {}", result);
//
- // Should get back a long
+ // Should get back a number
//
- if (result instanceof Long) {
- return ((Long) result).intValue();
+ if (result instanceof Number) {
+ return ((Number) result).intValue();
}
//
// We shouldn't really get this result, but just
diff --git a/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/GetOperationOutcomePip.java b/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/GetOperationOutcomePip.java
index 20c8f028a..5a0db0501 100644
--- a/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/GetOperationOutcomePip.java
+++ b/controlloop/common/database/src/main/java/org/onap/policy/database/operationshistory/GetOperationOutcomePip.java
@@ -25,12 +25,10 @@ import com.att.research.xacml.api.pip.PIPRequest;
import com.att.research.xacml.api.pip.PIPResponse;
import com.att.research.xacml.std.pip.StdMutablePIPResponse;
import com.att.research.xacml.std.pip.StdPIPResponse;
-import com.google.common.base.Strings;
import java.util.Arrays;
import java.util.Collection;
import java.util.Properties;
import javax.persistence.NoResultException;
-import javax.persistence.Persistence;
import org.onap.policy.database.ToscaDictionary;
import org.onap.policy.database.std.StdOnapPip;
import org.slf4j.Logger;
@@ -52,25 +50,7 @@ public class GetOperationOutcomePip extends StdOnapPip {
@Override
public void configure(String id, Properties properties) throws PIPException {
- super.configure(id, properties);
- //
- // Create our entity manager
- //
- em = null;
- try {
- //
- // In case there are any overloaded properties for the JPA
- //
- Properties emProperties = new Properties(properties);
- //
- // Create the entity manager factory
- //
- em = Persistence.createEntityManagerFactory(
- properties.getProperty(ISSUER_NAME + ".persistenceunit"),
- emProperties).createEntityManager();
- } catch (Exception e) {
- logger.error("Persistence failed {} operations history db {}", e.getLocalizedMessage(), e);
- }
+ super.configure(id, properties, ISSUER_NAME);
}
/**
@@ -84,31 +64,28 @@ public class GetOperationOutcomePip extends StdOnapPip {
public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
logger.debug("getAttributes requesting attribute {} of type {} for issuer {}",
pipRequest.getAttributeId(), pipRequest.getDataTypeId(), pipRequest.getIssuer());
- //
- // Determine if the issuer is correct
- //
- if (Strings.isNullOrEmpty(pipRequest.getIssuer())) {
- logger.debug("issuer is null - returning empty response");
- //
- // We only respond to ourself as the issuer
- //
- return StdPIPResponse.PIP_RESPONSE_EMPTY;
- }
- if (! pipRequest.getIssuer().startsWith(ToscaDictionary.GUARD_ISSUER_PREFIX)) {
- logger.debug("Issuer does not start with guard");
- //
- // We only respond to ourself as the issuer
- //
+
+ if (isRequestInvalid(pipRequest)) {
return StdPIPResponse.PIP_RESPONSE_EMPTY;
}
+
//
// Parse out the issuer which denotes the time window
// Eg: any-prefix:clname:some-controlloop-name
//
String[] s1 = pipRequest.getIssuer().split("clname:");
String clname = s1[1];
- String target = null;
- target = getTarget(pipFinder);
+ String target = getTarget(pipFinder);
+ //
+ // Sanity check
+ //
+ if (target == null) {
+ //
+ // See if we have all the values
+ //
+ logger.error("missing attributes return empty");
+ return StdPIPResponse.PIP_RESPONSE_EMPTY;
+ }
logger.debug("Going to query DB about: clname={}, target={}", clname, target);
String outcome = doDatabaseQuery(clname, target);
diff --git a/controlloop/common/database/src/main/java/org/onap/policy/database/std/StdOnapPip.java b/controlloop/common/database/src/main/java/org/onap/policy/database/std/StdOnapPip.java
index a94727371..1416b3ef9 100644
--- a/controlloop/common/database/src/main/java/org/onap/policy/database/std/StdOnapPip.java
+++ b/controlloop/common/database/src/main/java/org/onap/policy/database/std/StdOnapPip.java
@@ -39,6 +39,8 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.Properties;
import javax.persistence.EntityManager;
+import javax.persistence.Persistence;
+import org.apache.commons.lang3.StringUtils;
import org.onap.policy.database.ToscaDictionary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -74,11 +76,65 @@ public abstract class StdOnapPip extends StdConfigurableEngine {
return Collections.emptyList();
}
- @Override
- public void configure(String id, Properties properties) throws PIPException {
+ /**
+ * Configures this object and initializes {@link #em}.
+ *
+ * @param id name of this engine
+ * @param properties configuration properties
+ * @param issuerName name of this issuer, used to identify the persistence unit
+ * @throws PIPException if an error occurs
+ */
+ protected void configure(String id, Properties properties, String issuerName) throws PIPException {
super.configure(id, properties);
logger.debug("Configuring historyDb PIP {}", properties);
this.properties = properties;
+
+ //
+ // Create our entity manager
+ //
+ em = null;
+ try {
+ //
+ // In case there are any overloaded properties for the JPA
+ //
+ Properties emProperties = new Properties(properties);
+ //
+ // Create the entity manager factory
+ //
+ em = Persistence.createEntityManagerFactory(
+ properties.getProperty(issuerName + ".persistenceunit"),
+ emProperties).createEntityManager();
+ } catch (Exception e) {
+ logger.error("Persistence failed {} operations history db {}", e.getLocalizedMessage(), e);
+ }
+ }
+
+ /**
+ * Determines if a request is valid.
+ *
+ * @param pipRequest request to validate
+ * @return {@code true} if the request is <i>NOT</i> valid, {@code false} if it is
+ */
+ protected boolean isRequestInvalid(PIPRequest pipRequest) {
+ //
+ // Determine if the issuer is correct
+ //
+ if (StringUtils.isBlank(pipRequest.getIssuer())) {
+ logger.debug("issuer is null - returning empty response");
+ //
+ // We only respond to ourself as the issuer
+ //
+ return true;
+ }
+ if (! pipRequest.getIssuer().startsWith(ToscaDictionary.GUARD_ISSUER_PREFIX)) {
+ logger.debug("Issuer does not start with guard");
+ //
+ // We only respond to ourself as the issuer
+ //
+ return true;
+ }
+
+ return false;
}
protected String getActor(PIPFinder pipFinder) {
@@ -150,14 +206,16 @@ public abstract class StdOnapPip extends StdConfigurableEngine {
}
protected String findFirstAttributeValue(PIPResponse pipResponse) {
- for (Attribute attribute: pipResponse.getAttributes()) {
- Iterator<AttributeValue<String>> iterAttributeValues = attribute.findValues(DataTypes.DT_STRING);
- if (iterAttributeValues != null) {
- while (iterAttributeValues.hasNext()) {
- String value = iterAttributeValues.next().getValue();
- if (value != null) {
- return value;
- }
+ for (Attribute attribute : pipResponse.getAttributes()) {
+ Iterator<AttributeValue<String>> iterAttributeValues = attribute.findValues(DataTypes.DT_STRING);
+ if (iterAttributeValues == null) {
+ continue;
+ }
+
+ while (iterAttributeValues.hasNext()) {
+ String value = iterAttributeValues.next().getValue();
+ if (value != null) {
+ return value;
}
}
}
@@ -165,31 +223,25 @@ public abstract class StdOnapPip extends StdConfigurableEngine {
}
protected void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category,
- Identifier attributeId, int value, PIPRequest pipRequest) {
- AttributeValue<BigInteger> attributeValue = null;
+ Identifier attributeId, int value, PIPRequest pipRequest) {
try {
- attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value);
+ AttributeValue<BigInteger> attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value);
+ stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
+ pipRequest.getIssuer(), false));
} catch (Exception e) {
logger.error("Failed to convert {} to integer {}", value, e);
}
- if (attributeValue != null) {
- stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
- pipRequest.getIssuer(), false));
- }
}
protected void addStringAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId,
- String value, PIPRequest pipRequest) {
- AttributeValue<String> attributeValue = null;
+ String value, PIPRequest pipRequest) {
try {
- attributeValue = DataTypes.DT_STRING.createAttributeValue(value);
+ AttributeValue<String> attributeValue = DataTypes.DT_STRING.createAttributeValue(value);
+ stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
+ pipRequest.getIssuer(), false));
} catch (Exception ex) {
logger.error("Failed to convert {} to an AttributeValue<String>", value, ex);
}
- if (attributeValue != null) {
- stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
- pipRequest.getIssuer(), false));
- }
}
}
diff --git a/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/CountRecentOperationsPipTest.java b/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/CountRecentOperationsPipTest.java
index e3cb17fd5..66b412028 100644
--- a/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/CountRecentOperationsPipTest.java
+++ b/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/CountRecentOperationsPipTest.java
@@ -19,31 +19,54 @@
package org.onap.policy.database.operationshistory;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import com.att.research.xacml.api.Attribute;
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.api.pip.PIPException;
+import com.att.research.xacml.api.pip.PIPFinder;
+import com.att.research.xacml.api.pip.PIPRequest;
+import com.att.research.xacml.api.pip.PIPResponse;
+import com.att.research.xacml.std.pip.StdPIPResponse;
import java.io.FileInputStream;
-import java.lang.reflect.Method;
import java.sql.Date;
import java.time.Instant;
-
+import java.util.Collection;
import java.util.Properties;
import java.util.UUID;
-
import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
-
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.onap.policy.database.ToscaDictionary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CountRecentOperationsPipTest {
+ private static final String ID = "issuer";
private static final Logger LOGGER = LoggerFactory.getLogger(CountRecentOperationsPipTest.class);
- private static CountRecentOperationsPip pipEngine;
+ private static final String ISSUER = ToscaDictionary.GUARD_ISSUER_PREFIX + "-my-issuer:tw:1:HOUR";
+ private static final String ACTOR = "Controller";
+ private static final String RECIPE = "operationA";
+ private static final String TARGET = "vnf-1";
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+
+ private static MyPip pipEngine;
+ private static Properties properties;
+ private static EntityManagerFactory emf;
private static EntityManager em;
+ private PIPRequest req;
+
/**
* Create an instance of our engine and also the persistence
* factory.
@@ -51,23 +74,23 @@ public class CountRecentOperationsPipTest {
* @throws Exception connectivity issues
*/
@BeforeClass
- public static void setup() throws Exception {
+ public static void setUpBeforeClass() throws Exception {
LOGGER.info("Setting up PIP Testing");
//
// Create instance
//
- pipEngine = new CountRecentOperationsPip();
+ pipEngine = new MyPip();
//
// Load our test properties to use
//
- Properties properties = new Properties();
+ properties = new Properties();
try (FileInputStream is = new FileInputStream("src/test/resources/test.properties")) {
properties.load(is);
}
//
// Configure it using properties
//
- pipEngine.configure("issuer", properties);
+ pipEngine.configure(ID, properties);
LOGGER.info("PIP configured now creating our entity manager");
LOGGER.info("properties {}", properties);
//
@@ -75,12 +98,18 @@ public class CountRecentOperationsPipTest {
//
String persistenceUnit = CountRecentOperationsPip.ISSUER_NAME + ".persistenceunit";
LOGGER.info("persistenceunit {}", persistenceUnit);
- em = Persistence.createEntityManagerFactory(properties.getProperty(persistenceUnit), properties)
- .createEntityManager();
+ emf = Persistence.createEntityManagerFactory(properties.getProperty(persistenceUnit), properties);
+ em = emf.createEntityManager();
//
//
//
- LOGGER.info("Configured own entity manager", em.toString());
+ LOGGER.info("Configured own entity manager");
+ }
+
+ @Before
+ public void setUp() {
+ req = mock(PIPRequest.class);
+ when(req.getIssuer()).thenReturn(ISSUER);
}
private Dbao createEntry(String cl, String target, String outcome) {
@@ -91,8 +120,8 @@ public class CountRecentOperationsPipTest {
newEntry.setClosedLoopName(cl);
newEntry.setTarget(target);
newEntry.setOutcome(outcome);
- newEntry.setActor("Controller");
- newEntry.setOperation("operationA");
+ newEntry.setActor(ACTOR);
+ newEntry.setOperation(RECIPE);
newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
newEntry.setEndtime(Date.from(Instant.now()));
newEntry.setRequestId(UUID.randomUUID().toString());
@@ -100,35 +129,64 @@ public class CountRecentOperationsPipTest {
}
@Test
- public void testGetCountFromDb() throws Exception {
- //
- // Use reflection to run getCountFromDB
- //
- Method method = CountRecentOperationsPip.class.getDeclaredMethod("doDatabaseQuery",
- String.class,
- String.class,
- String.class,
- int.class,
- String.class);
- method.setAccessible(true);
- //
- // create entry
- //
- Dbao newEntry = createEntry("cl-foobar-1", "vnf-1", "SUCCESS");
- //
- // Test pipEngine
- //
- int count = (int) method.invoke(pipEngine, newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget(),
- 1, "HOUR");
+ public void testAttributesRequired() {
+ assertEquals(3, pipEngine.attributesRequired().size());
+ }
+
+ @Test
+ public void testGetAttributes_InvalidRequestInfo() throws PIPException {
+ // invalid request - null issuer
+ when(req.getIssuer()).thenReturn(null);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(req, null));
+
+ /*
+ * Make a valid issuer in the request, for subsequent tests.
+ */
+ when(req.getIssuer()).thenReturn(ISSUER);
+
+ // null actor
+ MyPip pip = new MyPip() {
+ @Override
+ protected String getActor(PIPFinder pipFinder) {
+ return null;
+ }
+ };
+ pip.configure(ID, properties);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pip.getAttributes(req, null));
+
+ // null recipe
+ pip = new MyPip() {
+ @Override
+ protected String getRecipe(PIPFinder pipFinder) {
+ return null;
+ }
+ };
+ pip.configure(ID, properties);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pip.getAttributes(req, null));
+
+ // null target
+ pip = new MyPip() {
+ @Override
+ protected String getTarget(PIPFinder pipFinder) {
+ return null;
+ }
+ };
+ pip.configure(ID, properties);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pip.getAttributes(req, null));
+ }
+
+ @Test
+ public void testDoDatabaseQuery() throws Exception {
+
//
// No entries yet
//
- assertEquals(0, count);
+ assertEquals(0, getCount(pipEngine.getAttributes(req, null)));
//
// Add entry
//
em.getTransaction().begin();
- em.persist(newEntry);
+ em.persist(createEntry("cl-foobar-1", TARGET, "SUCCESS"));
em.getTransaction().commit();
//
// Directly check ground truth
@@ -137,14 +195,67 @@ public class CountRecentOperationsPipTest {
.setParameter(1, 1);
LOGGER.info("{} entries", queryCount.getSingleResult());
//
- // Test pipEngine
- //
- count = (int) method.invoke(pipEngine, newEntry.getActor(), newEntry.getOperation(), newEntry.getTarget(),
- 1, "HOUR");
- //
// Should count 1 entry now
//
- assertEquals(1, count);
+ assertEquals(1, getCount(pipEngine.getAttributes(req, null)));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_InvalidTimeWindow() throws Exception {
+ when(req.getIssuer()).thenReturn(ISSUER + "invalid time window");
+
+ assertEquals(-1, getCount(pipEngine.getAttributes(req, null)));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_NullEm() throws Exception {
+ assertEquals(-1, getCount(new MyPip().getAttributes(req, null)));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_EmException() throws Exception {
+ MyPip pip = new MyPip() {
+ @Override
+ public void configure(String id, Properties properties) throws PIPException {
+ em = mock(EntityManager.class);
+ when(em.createNativeQuery(any())).thenThrow(new RuntimeException(EXPECTED_EXCEPTION));
+ }
+ };
+ pip.configure(ID, properties);
+
+ assertEquals(-1, getCount(pip.getAttributes(req, null)));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_NonNumeric() throws Exception {
+ MyPip pip = new MyPip() {
+ @Override
+ public void configure(String id, Properties properties) throws PIPException {
+ em = mock(EntityManager.class);
+ Query query = mock(Query.class);
+ when(em.createNativeQuery(any())).thenReturn(query);
+ when(query.setParameter(anyInt(), any())).thenReturn(query);
+ when(query.getSingleResult()).thenReturn("200");
+ }
+ };
+ pip.configure(ID, properties);
+
+ assertEquals(200, getCount(pip.getAttributes(req, null)));
+ }
+
+ private int getCount(PIPResponse resp) {
+ Collection<Attribute> attrs = resp.getAttributes();
+ assertEquals(1, attrs.size());
+
+ Attribute attr = attrs.iterator().next();
+ assertEquals(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, attr.getCategory());
+ assertEquals(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT, attr.getAttributeId());
+
+ Collection<AttributeValue<?>> values = attr.getValues();
+ assertEquals(1, values.size());
+
+ AttributeValue<?> value = values.iterator().next();
+ return ((Number) value.getValue()).intValue();
}
/**
@@ -152,9 +263,26 @@ public class CountRecentOperationsPipTest {
*/
@AfterClass
public static void cleanup() {
- if (em != null) {
- em.close();
+ if (emf != null) {
+ emf.close();
}
}
+ private static class MyPip extends CountRecentOperationsPip {
+
+ @Override
+ protected String getActor(PIPFinder pipFinder) {
+ return ACTOR;
+ }
+
+ @Override
+ protected String getRecipe(PIPFinder pipFinder) {
+ return RECIPE;
+ }
+
+ @Override
+ protected String getTarget(PIPFinder pipFinder) {
+ return TARGET;
+ }
+ }
}
diff --git a/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/GetOperationOutcomePipTest.java b/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/GetOperationOutcomePipTest.java
index 7e7258c5f..5ab850722 100644
--- a/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/GetOperationOutcomePipTest.java
+++ b/controlloop/common/database/src/test/java/org/onap/policy/database/operationshistory/GetOperationOutcomePipTest.java
@@ -19,27 +19,57 @@
package org.onap.policy.database.operationshistory;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import com.att.research.xacml.api.Attribute;
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.XACML3;
+import com.att.research.xacml.api.pip.PIPException;
+import com.att.research.xacml.api.pip.PIPFinder;
+import com.att.research.xacml.api.pip.PIPRequest;
+import com.att.research.xacml.api.pip.PIPResponse;
+import com.att.research.xacml.std.pip.StdPIPResponse;
import java.io.FileInputStream;
-import java.lang.reflect.Method;
import java.sql.Date;
import java.time.Instant;
+import java.util.Collection;
import java.util.Properties;
import java.util.UUID;
import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.onap.policy.database.ToscaDictionary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GetOperationOutcomePipTest {
+ private static final String ID = "issuer";
+ private static final String TEST_CL1 = "testcl1";
+ private static final String TEST_TARGET1 = "testtarget1";
+ private static final String TEST_TARGET2 = "testtarget2";
+ private static final String ACTOR = "Controller";
+ private static final String RECIPE = "operationA";
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final String ISSUER_PREFIX = ToscaDictionary.GUARD_ISSUER_PREFIX + "-my-issuer:clname:";
+ private static final String ISSUER = ISSUER_PREFIX + TEST_CL1;
private static final Logger LOGGER = LoggerFactory.getLogger(GetOperationOutcomePipTest.class);
- private static GetOperationOutcomePip pipEngine;
+ private static MyPip pipEngine;
+ private static Properties properties;
+
+ private static EntityManagerFactory emf;
private static EntityManager em;
+ private PIPRequest req;
+
/**
* Create an instance of our engine and also the persistence
* factory.
@@ -47,23 +77,23 @@ public class GetOperationOutcomePipTest {
* @throws Exception connectivity issues
*/
@BeforeClass
- public static void setup() throws Exception {
+ public static void setUpBeforeClass() throws Exception {
LOGGER.info("Setting up PIP Testing");
//
// Create instance
//
- pipEngine = new GetOperationOutcomePip();
+ pipEngine = new MyPip(TEST_TARGET1);
//
// Load our test properties to use
//
- Properties properties = new Properties();
+ properties = new Properties();
try (FileInputStream is = new FileInputStream("src/test/resources/test.properties")) {
properties.load(is);
}
//
// Configure it using properties
//
- pipEngine.configure("issuer", properties);
+ pipEngine.configure(ID, properties);
LOGGER.info("PIP configured now creating our entity manager");
LOGGER.info("properties {}", properties);
//
@@ -71,14 +101,20 @@ public class GetOperationOutcomePipTest {
//
String persistenceUnit = GetOperationOutcomePip.ISSUER_NAME + ".persistenceunit";
LOGGER.info("persistenceunit {}", persistenceUnit);
- em = Persistence.createEntityManagerFactory(properties.getProperty(persistenceUnit), properties)
- .createEntityManager();
+ emf = Persistence.createEntityManagerFactory(properties.getProperty(persistenceUnit), properties);
+ em = emf.createEntityManager();
//
//
//
LOGGER.info("Configured own entity manager", em.toString());
}
+ @Before
+ public void setUp() {
+ req = mock(PIPRequest.class);
+ when(req.getIssuer()).thenReturn(ISSUER);
+ }
+
private void insertEntry(String cl, String target, String outcome) {
//
// Create entry
@@ -87,8 +123,8 @@ public class GetOperationOutcomePipTest {
newEntry.setClosedLoopName(cl);
newEntry.setTarget(target);
newEntry.setOutcome(outcome);
- newEntry.setActor("Controller");
- newEntry.setOperation("operationA");
+ newEntry.setActor(ACTOR);
+ newEntry.setOperation(RECIPE);
newEntry.setStarttime(Date.from(Instant.now().minusMillis(20000)));
newEntry.setEndtime(Date.from(Instant.now()));
newEntry.setRequestId(UUID.randomUUID().toString());
@@ -102,43 +138,104 @@ public class GetOperationOutcomePipTest {
@Test
- public void testGetOutcomeFromDb() throws Exception {
- //
- // Use reflection to run getCountFromDB
- //
- Method method = GetOperationOutcomePip.class.getDeclaredMethod("doDatabaseQuery",
- String.class,
- String.class);
- method.setAccessible(true);
+ public void testAttributesRequired() {
+ assertEquals(1, pipEngine.attributesRequired().size());
+ }
+
+ @Test
+ public void testGetAttributes_InvalidRequestInfo() throws PIPException {
+ // invalid request - null issuer
+ when(req.getIssuer()).thenReturn(null);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pipEngine.getAttributes(req, null));
+
+ /*
+ * Make a valid issuer in the request, for subsequent tests.
+ */
+ when(req.getIssuer()).thenReturn(ISSUER);
+
+ // null target
+ MyPip pip = new MyPip(null);
+ pip.configure(ID, properties);
+ assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pip.getAttributes(req, null));
+ }
+
+ @Test
+ public void testDoDatabaseQuery() throws Exception {
//
// Insert entry
//
- insertEntry("testcl1", "testtarget1", "1");
- //
- // Test pipEngine
- //
- String outcome = (String) method.invoke(pipEngine, "testcl1", "testtarget1");
+ insertEntry(TEST_CL1, TEST_TARGET1, "1");
//
// outcome should be "1"
//
- assertEquals("1", outcome);
+ assertEquals("1", getOutcome(pipEngine.getAttributes(req, null)));
//
// Insert more entries
//
- insertEntry("testcl1", "testtarget1", "2");
- insertEntry("testcl2", "testtarget2", "3");
- insertEntry("testcl1", "testtarget2", "4");
+ insertEntry(TEST_CL1, TEST_TARGET1, "2");
+ insertEntry("testcl2", TEST_TARGET2, "3");
+ insertEntry(TEST_CL1, TEST_TARGET2, "4");
//
// Test pipEngine
//
- outcome = (String) method.invoke(pipEngine, "testcl1", "testtarget1");
- assertEquals("2", outcome);
+ assertEquals("2", getOutcome(TEST_CL1, TEST_TARGET1));
- outcome = (String) method.invoke(pipEngine, "testcl2", "testtarget2");
- assertEquals("3", outcome);
+ assertEquals("3", getOutcome("testcl2", TEST_TARGET2));
- outcome = (String) method.invoke(pipEngine, "testcl1", "testtarget2");
- assertEquals("4", outcome);
+ assertEquals("4", getOutcome(TEST_CL1, TEST_TARGET2));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_NoResult() throws Exception {
+ MyPip pip = new MyPip(TEST_TARGET1) {
+ @Override
+ public void configure(String id, Properties properties) throws PIPException {
+ em = mock(EntityManager.class);
+ when(em.createQuery(anyString())).thenThrow(new NoResultException());
+ }
+ };
+ pip.configure(ID, properties);
+
+ assertNull(getOutcome(pip.getAttributes(req, null)));
+ }
+
+ @Test
+ public void testDoDatabaseQuery_EmException() throws Exception {
+ MyPip pip = new MyPip(TEST_TARGET1) {
+ @Override
+ public void configure(String id, Properties properties) throws PIPException {
+ em = mock(EntityManager.class);
+ when(em.createQuery(anyString())).thenThrow(new RuntimeException(EXPECTED_EXCEPTION));
+ }
+ };
+ pip.configure(ID, properties);
+
+ assertEquals(null, getOutcome(pip.getAttributes(req, null)));
+ }
+
+ private String getOutcome(String clname, String target) throws PIPException {
+ req = mock(PIPRequest.class);
+ when(req.getIssuer()).thenReturn(ISSUER_PREFIX + clname);
+
+ MyPip pip = new MyPip(target);
+ pip.configure(ID, properties);
+
+ return getOutcome(pip.getAttributes(req, null));
+ }
+
+ private String getOutcome(PIPResponse resp) {
+ Collection<Attribute> attrs = resp.getAttributes();
+ assertEquals(1, attrs.size());
+
+ Attribute attr = attrs.iterator().next();
+ assertEquals(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, attr.getCategory());
+ assertEquals(ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONOUTCOME, attr.getAttributeId());
+
+ Collection<AttributeValue<?>> values = attr.getValues();
+ assertEquals(1, values.size());
+
+ AttributeValue<?> value = values.iterator().next();
+ return (String) value.getValue();
}
/**
@@ -146,9 +243,31 @@ public class GetOperationOutcomePipTest {
*/
@AfterClass
public static void cleanup() {
- if (em != null) {
- em.close();
+ if (emf != null) {
+ emf.close();
}
}
+ private static class MyPip extends GetOperationOutcomePip {
+ private String target;
+
+ public MyPip(String target) {
+ this.target = target;
+ }
+
+ @Override
+ protected String getActor(PIPFinder pipFinder) {
+ return ACTOR;
+ }
+
+ @Override
+ protected String getRecipe(PIPFinder pipFinder) {
+ return RECIPE;
+ }
+
+ @Override
+ protected String getTarget(PIPFinder pipFinder) {
+ return target;
+ }
+ }
}
diff --git a/controlloop/common/database/src/test/java/org/onap/policy/database/std/DbaoTest.java b/controlloop/common/database/src/test/java/org/onap/policy/database/std/DbaoTest.java
new file mode 100644
index 000000000..43c6157cf
--- /dev/null
+++ b/controlloop/common/database/src/test/java/org/onap/policy/database/std/DbaoTest.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 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.database.std;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+import org.junit.Test;
+import org.onap.policy.database.operationshistory.Dbao;
+
+public class DbaoTest {
+
+ @Test
+ public void test() {
+ Dbao dao = new Dbao();
+
+ dao.setActor("my-actor");
+ dao.setClosedLoopName("cl-name");
+ Date endDate = new Date();
+ dao.setEndtime(endDate);
+ dao.setId(100L);
+ dao.setMessage("my-message");
+ dao.setOperation("my-operation");
+ dao.setOutcome("my-outcome");
+ dao.setRequestId("my-request");
+ Date startDate = new Date(endDate.getTime() - 1);
+ dao.setStarttime(startDate);
+ dao.setSubrequestId("my-sub");
+ dao.setTarget("my-target");
+
+ assertEquals("my-actor", dao.getActor());
+ assertEquals("cl-name", dao.getClosedLoopName());
+ assertEquals(endDate, dao.getEndtime());
+ assertEquals(100L, dao.getId().longValue());
+ assertEquals("my-message", dao.getMessage());
+ assertEquals("my-operation", dao.getOperation());
+ assertEquals("my-outcome", dao.getOutcome());
+ assertEquals("my-request", dao.getRequestId());
+ assertEquals(startDate, dao.getStarttime());
+ assertEquals("my-sub", dao.getSubrequestId());
+ assertEquals("my-target", dao.getTarget());
+
+ assertTrue(dao.toString().startsWith("Dbao"));
+
+ int hc = dao.hashCode();
+ dao.setId(101L);
+ assertTrue(hc != dao.hashCode());
+
+ assertTrue(dao.equals(dao));
+ assertFalse(dao.equals(new Dbao()));
+ }
+}
diff --git a/controlloop/common/database/src/test/java/org/onap/policy/database/std/StdOnapPipTest.java b/controlloop/common/database/src/test/java/org/onap/policy/database/std/StdOnapPipTest.java
new file mode 100644
index 000000000..de186c41d
--- /dev/null
+++ b/controlloop/common/database/src/test/java/org/onap/policy/database/std/StdOnapPipTest.java
@@ -0,0 +1,268 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 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.database.std;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.att.research.xacml.api.Attribute;
+import com.att.research.xacml.api.AttributeValue;
+import com.att.research.xacml.api.Identifier;
+import com.att.research.xacml.api.Status;
+import com.att.research.xacml.api.pip.PIPException;
+import com.att.research.xacml.api.pip.PIPFinder;
+import com.att.research.xacml.api.pip.PIPRequest;
+import com.att.research.xacml.api.pip.PIPResponse;
+import com.att.research.xacml.std.datatypes.DataTypes;
+import com.att.research.xacml.std.pip.StdMutablePIPResponse;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.database.ToscaDictionary;
+
+public class StdOnapPipTest {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final String A_VALUE = "a-value";
+ private static final String ISSUER = ToscaDictionary.GUARD_ISSUER_PREFIX + "-my-issuer";
+
+ private MyPip pip;
+ private PIPRequest req;
+ private PIPFinder finder;
+ private StdMutablePIPResponse resp;
+
+ /**
+ * Initializes mocks and populates {@link #pip}.
+ */
+ @Before
+ public void setUp() {
+ req = mock(PIPRequest.class);
+ finder = mock(PIPFinder.class);
+ resp = new StdMutablePIPResponse();
+
+ when(req.getIssuer()).thenReturn(ISSUER);
+
+ pip = new MyPip();
+ }
+
+ @Test
+ public void testAttributesProvided() {
+ assertTrue(pip.attributesProvided().isEmpty());
+ }
+
+ @Test
+ public void testIsRequestInvalid() {
+ // valid issuer
+ when(req.getIssuer()).thenReturn(ISSUER);
+ assertFalse(pip.isRequestInvalid(req));
+
+ // invalid issuer
+ when(req.getIssuer()).thenReturn("bogus-issuer");
+ assertTrue(pip.isRequestInvalid(req));
+
+ // null issuer
+ when(req.getIssuer()).thenReturn(null);
+ assertTrue(pip.isRequestInvalid(req));
+ }
+
+ @Test
+ public void testGetActor() {
+ testGetArbitraryAttribute(StdOnapPip.PIP_REQUEST_ACTOR, pip2 -> pip2.getActor(finder));
+ }
+
+ @Test
+ public void testGetRecipe() {
+ testGetArbitraryAttribute(StdOnapPip.PIP_REQUEST_RECIPE, pip2 -> pip2.getRecipe(finder));
+ }
+
+ @Test
+ public void testGetTarget() {
+ testGetArbitraryAttribute(StdOnapPip.PIP_REQUEST_TARGET, pip2 -> pip2.getTarget(finder));
+ }
+
+ private void testGetArbitraryAttribute(PIPRequest request, Function<StdOnapPip, String> getter) {
+ // target found
+ pip = new MyPip() {
+ @Override
+ protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
+ return resp;
+ }
+
+ @Override
+ protected String findFirstAttributeValue(PIPResponse pipResponse) {
+ return A_VALUE;
+ }
+ };
+
+ pip = spy(pip);
+
+ assertEquals(A_VALUE, getter.apply(pip));
+ verify(pip).getAttribute(request, finder);
+ verify(pip).findFirstAttributeValue(resp);
+
+
+ // not found
+ pip = new MyPip() {
+ @Override
+ protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
+ return null;
+ }
+
+ @Override
+ protected String findFirstAttributeValue(PIPResponse pipResponse) {
+ return A_VALUE;
+ }
+ };
+
+ pip = spy(pip);
+
+ assertNull(getter.apply(pip));
+ verify(pip).getAttribute(request, finder);
+ verify(pip, never()).findFirstAttributeValue(resp);
+ }
+
+ @Test
+ public void testGetAttribute() throws PIPException {
+ when(finder.getMatchingAttributes(req, pip)).thenReturn(resp);
+
+ Status status = mock(Status.class);
+ Identifier ident = mock(Identifier.class);
+
+ when(ident.stringValue()).thenReturn("my-attr-id");
+ when(req.getAttributeId()).thenReturn(ident);
+
+ // status != OK
+ resp.setStatus(status);
+ when(status.isOk()).thenReturn(false);
+ assertNull(pip.getAttribute(req, finder));
+
+ // status OK, empty attributes
+ resp.setStatus(status);
+ when(status.isOk()).thenReturn(true);
+ assertNull(pip.getAttribute(req, finder));
+
+ // status OK, has attributes
+ resp.setStatus(status);
+ when(status.isOk()).thenReturn(true);
+ resp.setAttributes(Arrays.asList(mock(Attribute.class)));
+ assertSame(resp, pip.getAttribute(req, finder));
+
+ // null status, has attributes
+ resp.setStatus(null);
+ resp.setAttributes(Arrays.asList(mock(Attribute.class)));
+ assertSame(resp, pip.getAttribute(req, finder));
+
+ // with exception
+ when(finder.getMatchingAttributes(req, pip)).thenThrow(new PIPException());
+ assertNull(pip.getAttribute(req, finder));
+ }
+
+ @Test
+ public void testFindFirstAttributeValue() {
+
+ // no attributes
+ resp.setAttributes(Collections.emptyList());
+ assertNull(pip.findFirstAttributeValue(resp));
+
+ // attribute that returns null
+ Attribute attr = mock(Attribute.class);
+ resp.setAttributes(Arrays.asList(attr, attr));
+ assertNull(pip.findFirstAttributeValue(resp));
+
+ // attribute that returns a list of null values
+ Attribute attr2 = mock(Attribute.class);
+ resp.setAttributes(Arrays.asList(attr, attr2));
+ List<AttributeValue<String>> lst = Arrays.asList(makeAttr(null), makeAttr(null));
+ when(attr.findValues(DataTypes.DT_STRING)).thenReturn(lst.iterator());
+ assertNull(pip.findFirstAttributeValue(resp));
+
+ // non-null value in the middle of the list
+ lst = Arrays.asList(makeAttr(null), makeAttr(A_VALUE), makeAttr(null));
+ when(attr.findValues(DataTypes.DT_STRING)).thenReturn(lst.iterator());
+ assertEquals(A_VALUE, pip.findFirstAttributeValue(resp));
+ }
+
+ private AttributeValue<String> makeAttr(String value) {
+ @SuppressWarnings("unchecked")
+ AttributeValue<String> attrval = mock(AttributeValue.class);
+
+ when(attrval.getValue()).thenReturn(value);
+
+ return attrval;
+ }
+
+ @Test
+ public void testAddIntegerAttribute() {
+ resp = spy(resp);
+
+ Identifier cat = mock(Identifier.class);
+ Identifier attrid = mock(Identifier.class);
+
+ pip.addIntegerAttribute(resp, cat, attrid, 100, req);
+
+ verify(resp).addAttribute(any());
+
+ // try with exception
+ doThrow(new RuntimeException(EXPECTED_EXCEPTION)).when(resp).addAttribute(any());
+ pip.addIntegerAttribute(resp, cat, attrid, 100, req);
+ }
+
+ @Test
+ public void testAddStringAttribute() {
+ resp = spy(resp);
+
+ Identifier cat = mock(Identifier.class);
+ Identifier attrid = mock(Identifier.class);
+
+ pip.addStringAttribute(resp, cat, attrid, A_VALUE, req);
+
+ verify(resp).addAttribute(any());
+
+ // try with exception
+ doThrow(new RuntimeException(EXPECTED_EXCEPTION)).when(resp).addAttribute(any());
+ pip.addStringAttribute(resp, cat, attrid, A_VALUE, req);
+ }
+
+ private class MyPip extends StdOnapPip {
+
+ @Override
+ public Collection<PIPRequest> attributesRequired() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
+ return null;
+ }
+
+ }
+}
diff --git a/controlloop/common/database/src/test/resources/META-INF/persistence.xml b/controlloop/common/database/src/test/resources/META-INF/persistence.xml
index 0c49d94e2..202850d96 100644
--- a/controlloop/common/database/src/test/resources/META-INF/persistence.xml
+++ b/controlloop/common/database/src/test/resources/META-INF/persistence.xml
@@ -19,7 +19,8 @@
============LICENSE_END=========================================================
-->
-<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
<persistence-unit name="PipEngineTest" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
@@ -29,13 +30,13 @@
<properties>
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.logging.level" value="FINE" />
- <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:testdb;DATABASE_TO_UPPER=FALSE" />
<property name="javax.persistence.jdbc.user" value="policy" />
<property name="javax.persistence.jdbc.password" value="P01icY" />
- <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
- <property name="javax.persistence.schema-generation.create-source" value="metadata"/>
+ <property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
+ <property name="javax.persistence.schema-generation.create-source" value="metadata" />
</properties>
</persistence-unit>