summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-04-05 09:52:35 -0400
committerJim Hahn <jrh3@att.com>2019-04-05 11:51:26 -0400
commit287e9d464e487ed5ae5fe5250ab960194f179c01 (patch)
tree4e1d9295b308f4328c894bafe2190c0728089f46
parent457c9b19c058877ca59c9b0826d22f3f97392daf (diff)
Flesh out policy deployment REST API
Also moved the controller, the provider, and supporting classes to their own dep_undep package. Change-Id: Ifea1c4dd2ecbf93a8f4d45e130830cf9271103d3 Issue-ID: POLICY-1542 Signed-off-by: Jim Hahn <jrh3@att.com>
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateData.java28
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/PapRestServer.java1
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java84
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java (renamed from main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployControllerV1.java)8
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java156
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java369
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java214
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java26
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateDataTest.java37
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/internal/TestModels.java46
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java225
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployControllerV1.java (renamed from main/src/test/java/org/onap/policy/pap/main/rest/TestPdpGroupDeployControllerV1.java)45
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java214
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java421
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java258
-rw-r--r--main/src/test/resources/simpleDeploy/daoPolicyList.json10
-rw-r--r--main/src/test/resources/simpleDeploy/emptyGroups.json3
-rw-r--r--main/src/test/resources/simpleDeploy/emptyRequest.json3
-rw-r--r--main/src/test/resources/simpleDeploy/emptyRequestBase.json2
-rw-r--r--main/src/test/resources/simpleDeploy/getGroupDao.json84
-rw-r--r--main/src/test/resources/simpleDeploy/getPolicyReqNullVersion.json7
-rw-r--r--main/src/test/resources/simpleDeploy/groups.json25
-rw-r--r--main/src/test/resources/simpleDeploy/policy.json6
-rw-r--r--main/src/test/resources/simpleDeploy/request.json8
-rw-r--r--main/src/test/resources/simpleDeploy/requestBase.json4
-rw-r--r--main/src/test/resources/simpleDeploy/updateGroupReqMultiple.json20
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupDao.json72
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupGroup1.json40
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupGroup2.json25
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupPolicy2.json10
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupPolicy3.json10
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroupPolicy4.json10
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroup_NoPdpsDao.json21
-rw-r--r--main/src/test/resources/simpleDeploy/upgradeGroup_NothingUpdatedDao.json25
34 files changed, 2295 insertions, 222 deletions
diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateData.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateData.java
index 0d861e21..eca0b384 100644
--- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateData.java
+++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateData.java
@@ -20,8 +20,8 @@
package org.onap.policy.pap.main.comm.msgdata;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import org.onap.policy.models.pdp.concepts.PdpStatus;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
@@ -62,32 +62,16 @@ public abstract class UpdateData extends MessageData {
}
// see if the other has any policies that this does not have
- ArrayList<ToscaPolicyIdentifier> lst = new ArrayList<>(response.getPolicies());
- List<ToscaPolicy> mypolicies = update.getPolicies();
+ Set<ToscaPolicyIdentifier> set = new HashSet<>(response.getPolicies());
- if (mypolicies.size() != lst.size()) {
- return "policies do not match";
+ for (ToscaPolicy policy : update.getPolicies()) {
+ set.remove(policy.getIdentifier());
}
- lst.removeAll(convertToscaPolicyToToscaPolicyIndentifier(update.getPolicies()));
- if (!lst.isEmpty()) {
+ if (!set.isEmpty()) {
return "policies do not match";
}
return null;
}
-
- /**
- * Converts a ToscaPolicy list to ToscaPolicyIdentifier list.
- *
- * @param toscaPolicies the list of ToscaPolicy
- * @return the ToscaPolicyIdentifier list
- */
- private List<ToscaPolicyIdentifier> convertToscaPolicyToToscaPolicyIndentifier(List<ToscaPolicy> toscaPolicies) {
- final List<ToscaPolicyIdentifier> toscaPolicyIdentifiers = new ArrayList<>();
- for (final ToscaPolicy toscaPolicy : toscaPolicies) {
- toscaPolicyIdentifiers.add(new ToscaPolicyIdentifier(toscaPolicy.getName(), toscaPolicy.getVersion()));
- }
- return toscaPolicyIdentifiers;
- }
}
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PapRestServer.java b/main/src/main/java/org/onap/policy/pap/main/rest/PapRestServer.java
index 28587077..05ba2901 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/PapRestServer.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/PapRestServer.java
@@ -30,6 +30,7 @@ import org.onap.policy.common.endpoints.http.server.HttpServletServer;
import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
import org.onap.policy.common.gson.GsonMessageBodyHandler;
import org.onap.policy.pap.main.parameters.RestServerParameters;
+import org.onap.policy.pap.main.rest.depundep.PdpGroupDeployControllerV1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java
deleted file mode 100644
index f0636fc6..00000000
--- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP PAP
- * ================================================================================
- * 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.pap.main.rest;
-
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
-import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse;
-import org.onap.policy.models.pdp.concepts.PdpGroups;
-
-/**
- * Provider for PAP component to deploy PDP groups.
- */
-public class PdpGroupDeployProvider {
-
- /**
- * Deploys or updates a PDP group.
- *
- * @param groups PDP group configuration
- * @return a pair containing the status and the response
- */
- public Pair<Response.Status, PdpGroupDeployResponse> deployGroup(PdpGroups groups) {
-
- /*
- * TODO Lock for updates - return error if already locked.
- */
-
- /*
- * TODO Make updates - sending initial messages to PDPs and arranging for
- * listeners to complete the deployment actions (in the background). The final
- * step for the listener is to unlock.
- */
-
- /*
- * TODO Return error if unable to send updates to all PDPs.
- */
-
- return Pair.of(Response.Status.OK, new PdpGroupDeployResponse());
- }
-
- /**
- * Deploys or updates PDP policies.
- *
- * @param policies PDP policies
- * @return a pair containing the status and the response
- */
- public Pair<Response.Status, PdpGroupDeployResponse> deployPolicies(PdpDeployPolicies policies) {
-
- /*
- * TODO Lock for updates - return error if already locked.
- */
-
- /*
- * TODO Make updates - sending initial messages to PDPs and arranging for
- * listeners to complete the deployment actions (in the background). The final
- * step for the listener is to unlock.
- */
-
- /*
- * TODO Return error if unable to send updates to all PDPs.
- */
-
- return Pair.of(Response.Status.OK, new PdpGroupDeployResponse());
- }
-}
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployControllerV1.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java
index d67974dd..6d4dc7ed 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployControllerV1.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.policy.pap.main.rest;
+package org.onap.policy.pap.main.rest.depundep;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@@ -28,19 +28,17 @@ import io.swagger.annotations.Authorization;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.ResponseHeader;
-
import java.util.UUID;
-
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
-
import org.apache.commons.lang3.tuple.Pair;
import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse;
import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.pap.main.rest.PapRestControllerV1;
/**
* Class to provide REST end points for PAP component to deploy a PDP group.
@@ -123,7 +121,7 @@ public class PdpGroupDeployControllerV1 extends PapRestControllerV1 {
// @formatter:on
public Response deployPolicies(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "PDP Policies; only the name and policyVersion are required",
+ @ApiParam(value = "PDP Policies; only the name is required",
required = true) PdpDeployPolicies policies) {
Pair<Status, PdpGroupDeployResponse> pair = provider.deployPolicies(policies);
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java
new file mode 100644
index 00000000..eef14388
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java
@@ -0,0 +1,156 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
+import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provider for PAP component to deploy PDP groups. The following items must be in the
+ * {@link Registry}:
+ * <ul>
+ * <li>PDP Modification Lock</li>
+ * <li>PDP Modify Request Map</li>
+ * <li>PAP DAO Factory</li>
+ * </ul>
+ */
+public class PdpGroupDeployProvider extends ProviderBase<PdpGroupDeployResponse> {
+ private static final Logger logger = LoggerFactory.getLogger(PdpGroupDeployProvider.class);
+
+
+ /**
+ * Constructs the object.
+ */
+ public PdpGroupDeployProvider() {
+ super();
+ }
+
+ /**
+ * Deploys or updates PDP groups.
+ *
+ * @param groups PDP group configurations
+ * @return a pair containing the status and the response
+ */
+ public Pair<Response.Status, PdpGroupDeployResponse> deployGroup(PdpGroups groups) {
+ return process(groups, this::deployGroups);
+ }
+
+ /**
+ * Deploys or updates PDP groups.
+ *
+ * @param data session data
+ * @param groups PDP group configurations
+ * @return a list of requests that should be sent to configure the PDPs
+ */
+ private List<PdpUpdate> deployGroups(SessionData data, PdpGroups groups) {
+ throw new PolicyPapRuntimeException("not implemented yet");
+ }
+
+ /**
+ * Deploys or updates PDP policies.
+ *
+ * @param policies PDP policies
+ * @return a pair containing the status and the response
+ */
+ public Pair<Response.Status, PdpGroupDeployResponse> deployPolicies(PdpDeployPolicies policies) {
+ return process(policies, this::deploySimplePolicies);
+ }
+
+ /**
+ * Deploys or updates PDP policies using the simple API.
+ *
+ * @param data session data
+ * @param extPolicies external PDP policies
+ * @return a list of requests that should be sent to configure the PDPs
+ */
+ private void deploySimplePolicies(SessionData data, PdpDeployPolicies policies) {
+
+ for (ToscaPolicyIdentifierOptVersion desiredPolicy : policies.getPolicies()) {
+
+ try {
+ processPolicy(data, desiredPolicy);
+
+ } catch (PfModelException e) {
+ // no need to log the error here, as it will be logged by the invoker
+ logger.warn("failed to deploy policy: {}", desiredPolicy);
+ throw new PolicyPapRuntimeException(DB_ERROR_MSG, e);
+
+ } catch (RuntimeException e) {
+ // no need to log the error here, as it will be logged by the invoker
+ logger.warn("failed to deploy policy: {}", desiredPolicy);
+ throw e;
+ }
+ }
+ }
+
+ @Override
+ protected BiFunction<PdpGroup, PdpSubGroup, Boolean> makeUpdater(ToscaPolicy policy) {
+ ToscaPolicyIdentifier desiredIdent = policy.getIdentifier();
+ ToscaPolicyTypeIdentifier desiredType = policy.getTypeIdentifier();
+
+ return (group, subgroup) -> {
+
+ if (!subgroup.getSupportedPolicyTypes().contains(desiredType)) {
+ // doesn't support the desired policy type
+ return false;
+ }
+
+ if (subgroup.getPolicies().contains(desiredIdent)) {
+ // already has the desired policy
+ return false;
+ }
+
+ if (subgroup.getPdpInstances().isEmpty()) {
+ throw new PolicyPapRuntimeException("group " + group.getName() + " subgroup " + subgroup.getPdpType()
+ + " has no active PDPs");
+ }
+
+
+ // add the policy to the subgroup
+ subgroup.getPolicies().add(desiredIdent);
+ return true;
+ };
+ }
+
+ @Override
+ public PdpGroupDeployResponse makeResponse(String errorMsg) {
+ PdpGroupDeployResponse resp = new PdpGroupDeployResponse();
+ resp.setErrorDetails(errorMsg);
+ return resp;
+ }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java
new file mode 100644
index 00000000..29d3b3ca
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java
@@ -0,0 +1,369 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.common.utils.validation.Version;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pap.concepts.SimpleResponse;
+import org.onap.policy.models.pdp.concepts.Pdp;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+import org.onap.policy.pap.main.PapConstants;
+import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
+import org.onap.policy.pap.main.comm.PdpModifyRequestMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Super class of providers that deploy and undeploy PDP groups. The following items must
+ * be in the {@link Registry}:
+ * <ul>
+ * <li>PDP Modification Lock</li>
+ * <li>PDP Modify Request Map</li>
+ * <li>PAP DAO Factory</li>
+ * </ul>
+ *
+ * @param <R> the response type
+ */
+public abstract class ProviderBase<R extends SimpleResponse> {
+ private static final String DEPLOY_FAILED = "failed to deploy/undeploy policies";
+
+ public static final String DB_ERROR_MSG = "DB error";
+
+ private static final Logger logger = LoggerFactory.getLogger(ProviderBase.class);
+
+ /**
+ * Lock used when updating PDPs.
+ */
+ private final Object updateLock;
+
+ /**
+ * Used to send UPDATE and STATE-CHANGE requests to the PDPs.
+ */
+ private final PdpModifyRequestMap requestMap;
+
+ /**
+ * Factory for PAP DAO.
+ */
+ private final PolicyModelsProviderFactoryWrapper daoFactory;
+
+
+ /**
+ * Constructs the object.
+ */
+ public ProviderBase() {
+ this.updateLock = Registry.get(PapConstants.REG_PDP_MODIFY_LOCK, Object.class);
+ this.requestMap = Registry.get(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class);
+ this.daoFactory = Registry.get(PapConstants.REG_PAP_DAO_FACTORY, PolicyModelsProviderFactoryWrapper.class);
+ }
+
+ /**
+ * Processes a policy request.
+ *
+ * @param request PDP policy request
+ * @param processor function that processes the request
+ * @return a pair containing the status and the response
+ */
+ protected <T> Pair<Response.Status, R> process(T request, BiConsumer<SessionData, T> processor) {
+
+ synchronized (updateLock) {
+ // list of requests to be published to the PDPs
+ Collection<PdpUpdate> requests = Collections.emptyList();
+
+ try (PolicyModelsProvider dao = daoFactory.create()) {
+
+ SessionData data = new SessionData(dao);
+ processor.accept(data, request);
+
+ requests = data.getUpdates();
+
+ } catch (PfModelException e) {
+ logger.warn(DEPLOY_FAILED, e);
+ return Pair.of(Response.Status.INTERNAL_SERVER_ERROR, makeResponse(DB_ERROR_MSG));
+
+ } catch (PolicyPapRuntimeException e) {
+ logger.warn(DEPLOY_FAILED, e);
+ return Pair.of(Response.Status.INTERNAL_SERVER_ERROR, makeResponse(e.getMessage()));
+
+ } catch (RuntimeException e) {
+ logger.warn(DEPLOY_FAILED, e);
+ return Pair.of(Response.Status.INTERNAL_SERVER_ERROR, makeResponse("request failed"));
+ }
+
+
+ // publish the requests
+ for (PdpUpdate req : requests) {
+ requestMap.addRequest(req);
+ }
+ }
+
+ return Pair.of(Response.Status.OK, makeResponse(null));
+ }
+
+ /**
+ * Makes a response.
+ *
+ * @param errorMsg error message, or {@code null} if there was no error
+ * @return a new response
+ */
+ public abstract R makeResponse(String errorMsg);
+
+ /**
+ * Finds a Policy having the given name and version. If the specified version is
+ * {@code null}, then it finds the matching Policy with the latest version.
+ *
+ * @param data session data
+ * @param desiredPolicy the policy desired, with the "name" and optional
+ * "policyVersion" populated
+ * @return the matching Policy type
+ * @throws PfModelException if a DAO error occurred
+ * @throws PolicyPapRuntimeException if there is no matching policy type
+ */
+ private ToscaPolicy getPolicy(SessionData data, ToscaPolicyIdentifierOptVersion desiredPolicy)
+ throws PfModelException {
+
+ if (desiredPolicy.isNullVersion()) {
+ return data.getPolicyMaxVersion(desiredPolicy.getName());
+
+ } else {
+ return data.getPolicy(new ToscaPolicyIdentifier(desiredPolicy.getName(), desiredPolicy.getVersion()));
+ }
+ }
+
+ /**
+ * Process a single policy from the request.
+ *
+ * @param data session data
+ * @param desiredPolicy request policy
+ * @throws PolicyPapRuntimeException if an error occurs
+ * @throws PfModelException if a DAO error occurred
+ */
+ protected void processPolicy(SessionData data, ToscaPolicyIdentifierOptVersion desiredPolicy)
+ throws PfModelException {
+
+ ToscaPolicy policy = getPolicy(data, desiredPolicy);
+
+ Collection<PdpGroup> groups = getGroups(data, policy.getTypeIdentifier());
+ if (groups.isEmpty()) {
+ throw new PolicyPapRuntimeException("policy not supported by any PDP group: " + desiredPolicy.getName()
+ + " " + desiredPolicy.getVersion());
+ }
+
+ BiFunction<PdpGroup, PdpSubGroup, Boolean> updater = makeUpdater(policy);
+
+ for (PdpGroup group : groups) {
+ upgradeGroup(data, policy, group, updater);
+ }
+ }
+
+ /**
+ * Makes a function to update a subgroup. The function is expected to return
+ * {@code true} if the subgroup was updated, {@code false} if no update was
+ * necessary/appropriate.
+ *
+ * @param policy policy to be added to or removed from each subgroup
+ * @return a function to update a subgroup
+ */
+ protected abstract BiFunction<PdpGroup, PdpSubGroup, Boolean> makeUpdater(ToscaPolicy policy);
+
+ /**
+ * Finds the active PDP group(s) with the highest version that supports the given
+ * policy type.
+ *
+ * @param data session data
+ * @param policyType the policy type of interest
+ * @return the matching PDP group, or {@code null} if no active group supports the
+ * given PDP types
+ * @throws PfModelException if an error occurs
+ */
+ private Collection<PdpGroup> getGroups(SessionData data, ToscaPolicyTypeIdentifier policyType)
+ throws PfModelException {
+ // build a map containing the group with the highest version for each name
+ Map<String, GroupData> name2data = new HashMap<>();
+
+ for (PdpGroup group : data.getActivePdpGroupsByPolicyType(policyType)) {
+ Version vers = Version.makeVersion("PdpGroup", group.getName(), group.getVersion());
+ if (vers == null) {
+ continue;
+ }
+
+ GroupData grpdata = name2data.get(group.getName());
+
+ if (grpdata == null) {
+ // not in the map yet
+ name2data.put(group.getName(), new GroupData(group, vers));
+
+ } else if (vers.compareTo(grpdata.version) >= 0) {
+ // higher version
+ grpdata.replace(group, vers);
+ }
+ }
+
+ return name2data.values().stream().map(grpdata -> grpdata.group).collect(Collectors.toList());
+ }
+
+ /**
+ * Updates a group, assigning a new version number, if it actually changes.
+ *
+ * @param data session data
+ * @param policy policy to be added to or removed from the group
+ * @param oldGroup the original group, to be updated
+ * @param updater function to update a group
+ * @throws PfModelException if a DAO error occurred
+ */
+ private void upgradeGroup(SessionData data, ToscaPolicy policy, PdpGroup oldGroup,
+ BiFunction<PdpGroup, PdpSubGroup, Boolean> updater) throws PfModelException {
+
+ PdpGroup newGroup = new PdpGroup(oldGroup);
+ boolean updated = false;
+
+ for (PdpSubGroup subgroup : newGroup.getPdpSubgroups()) {
+
+ if (!updater.apply(newGroup, subgroup)) {
+ continue;
+ }
+
+ updated = true;
+
+ /*
+ * generate an UPDATE for each PDP instance. Since the group is active, we
+ * assume that the PDP is, too, thus no need for a STATE-CHANGE.
+ */
+ for (Pdp pdpInstance : subgroup.getPdpInstances()) {
+ data.addUpdate(makeUpdate(data, newGroup, subgroup, pdpInstance));
+ }
+ }
+
+
+ if (!updated) {
+ return;
+ }
+
+
+ // something changed
+
+ if (data.isNewlyCreated(newGroup.getName())) {
+ /*
+ * It's already in the list of new groups - update the policies, but not the
+ * version.
+ */
+ data.updatePdpGroup(newGroup);
+
+ } else {
+ // haven't seen this group before - update the version
+ upgradeGroupVersion(data, oldGroup, newGroup);
+ }
+ }
+
+ /**
+ * Makes an UPDATE message for a particular PDP.
+ *
+ * @param data session data
+ * @param group group to which the PDP should belong
+ * @param subgroup subgroup to which the PDP should belong
+ * @param pdpInstance identifies the PDP of interest
+ * @return a new UPDATE message
+ */
+ private PdpUpdate makeUpdate(SessionData data, PdpGroup group, PdpSubGroup subgroup, Pdp pdpInstance) {
+
+ PdpUpdate update = new PdpUpdate();
+
+ update.setName(pdpInstance.getInstanceId());
+ update.setDescription(group.getDescription());
+ update.setPdpGroup(group.getName());
+ update.setPdpSubgroup(subgroup.getPdpType());
+ update.setPolicies(subgroup.getPolicies().stream().map(data::getPolicy).collect(Collectors.toList()));
+
+ return update;
+ }
+
+ /**
+ * Upgrades a group's version. Updates the version in the new group, persists the new
+ * group, and deactivates the old group.
+ *
+ * @param data session data
+ * @param newGroup the new version of the group
+ * @param oldGroup the original group, to be updated
+ * @throws PfModelException if a DAO error occurred
+ */
+ private void upgradeGroupVersion(SessionData data, PdpGroup newGroup, PdpGroup oldGroup) throws PfModelException {
+
+ // change versions
+ newGroup.setVersion(makeNewVersion(data, oldGroup).toString());
+
+ // create it before we update the old group
+ newGroup = data.createPdpGroup(newGroup);
+
+ // deactivate the old group
+ oldGroup.setPdpGroupState(PdpState.PASSIVE);
+ oldGroup = data.updatePdpGroup(oldGroup);
+ }
+
+ /**
+ * Makes a new version for the PDP group.
+ *
+ * @param data session data
+ * @param group current group
+ * @return a new version
+ * @throws PfModelException if a DAO error occurred
+ */
+ private Version makeNewVersion(SessionData data, PdpGroup group) throws PfModelException {
+ PdpGroup group2 = data.getPdpGroupMaxVersion(group.getName());
+ Version vers = Version.makeVersion("PdpGroup", group2.getName(), group2.getVersion());
+ return vers.newVersion();
+ }
+
+ /**
+ * Data associated with a group. Used to find the group with the maximum version.
+ */
+ private static class GroupData {
+ private PdpGroup group;
+ private Version version;
+
+ public GroupData(PdpGroup group, Version version) {
+ this.group = group;
+ this.version = version;
+ }
+
+ public void replace(PdpGroup group, Version version) {
+ this.group = group;
+ this.version = version;
+ }
+ }
+}
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java
new file mode 100644
index 00000000..01dc8f47
--- /dev/null
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java
@@ -0,0 +1,214 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
+
+/**
+ * Data used during a single REST call when updating PDP policies.
+ */
+public class SessionData {
+ private final PolicyModelsProvider dao;
+
+ /**
+ * The names of newly created groups are added to this set to prevent the version
+ * number from being updated in case the group is re-used during the same REST call.
+ */
+ private final Set<String> newGroups;
+
+ /**
+ * Maps a PDP name to its most recently generated update request.
+ */
+ private final Map<String, PdpUpdate> updates;
+
+ /**
+ * Maps a policy's identifier to the policy.
+ */
+ private final Map<ToscaPolicyIdentifier, ToscaPolicy> policyMap;
+
+
+ /**
+ * Constructs the object.
+ *
+ * @param dao DAO provider
+ */
+ public SessionData(PolicyModelsProvider dao) {
+ this.dao = dao;
+ this.newGroups = new HashSet<>();
+ this.updates = new HashMap<>();
+ this.policyMap = new HashMap<>();
+ }
+
+ /**
+ * Gets the policy, referenced by an identifier. Loads it from the cache, if possible.
+ * Otherwise, gets it from the DB.
+ *
+ * @param ident policy identifier
+ * @return the specified policy
+ * @throws PolicyPapRuntimeException if an error occurs
+ */
+ public ToscaPolicy getPolicy(ToscaPolicyIdentifier ident) {
+
+ return policyMap.computeIfAbsent(ident, key -> {
+
+ try {
+ List<ToscaPolicy> lst = dao.getPolicyList(ident.getName(), ident.getVersion());
+
+ if (lst.isEmpty()) {
+ throw new PolicyPapRuntimeException(
+ "cannot find policy: " + ident.getName() + " " + ident.getVersion());
+ }
+
+ if (lst.size() > 1) {
+ throw new PolicyPapRuntimeException(
+ "too many policies match: " + ident.getName() + " " + ident.getVersion());
+ }
+
+ return lst.get(0);
+
+ } catch (PfModelException e) {
+ throw new PolicyPapRuntimeException("cannot get policy: " + ident.getName() + " " + ident.getVersion(),
+ e);
+ }
+ });
+ }
+
+ /**
+ * Adds an update to the set of updates, replacing any previous entry for the given
+ * PDP.
+ *
+ * @param update the update to be added
+ */
+ public void addUpdate(PdpUpdate update) {
+ updates.put(update.getName(), update);
+ }
+
+ /**
+ * Gets the accumulated UPDATE requests.
+ *
+ * @return the UPDATE requests
+ */
+ public Collection<PdpUpdate> getUpdates() {
+ return updates.values();
+ }
+
+ /**
+ * Determines if a group has been newly created as part of this REST call.
+ *
+ * @param group name to the group of interest
+ * @return {@code true} if the group has been newly created, {@code false} otherwise
+ */
+ public boolean isNewlyCreated(String group) {
+ return newGroups.contains(group);
+ }
+
+ /**
+ * Gets the policy having the given name and the maximum version.
+ *
+ * @param name name of the desired policy
+ * @return the desired policy, or {@code null} if there is no policy with given name
+ * @throws PfModelException if an error occurs
+ */
+ public ToscaPolicy getPolicyMaxVersion(String name) throws PfModelException {
+ ToscaPolicyFilter filter = ToscaPolicyFilter.builder().name(name).build();
+ // TODO setLatest, setActive?
+
+ List<ToscaPolicy> policies = dao.getFilteredPolicyList(filter);
+ if (policies.isEmpty()) {
+ throw new PolicyPapRuntimeException("cannot find policy: " + name);
+ }
+
+ return policies.get(0);
+ }
+
+ /**
+ * Gets the group having the given name and the maximum version.
+ *
+ * @param name name of the desired group
+ * @return the desired group, or {@code null} if there is no group with given name
+ * @throws PfModelException if an error occurs
+ */
+ public PdpGroup getPdpGroupMaxVersion(String name) throws PfModelException {
+ PdpGroupFilter filter = PdpGroupFilter.builder().name(name).build();
+ // TODO setLatest
+
+ List<PdpGroup> groups = dao.getFilteredPdpGroups(filter);
+ if (groups.isEmpty()) {
+ throw new PolicyPapRuntimeException("cannot find group: " + name);
+ }
+
+ return groups.get(0);
+ }
+
+ /**
+ * Gets the active groups supporting the given policy.
+ *
+ * @param type desired policy type
+ * @return the active groups supporting the given policy
+ * @throws PfModelException if an error occurs
+ */
+ public List<PdpGroup> getActivePdpGroupsByPolicyType(ToscaPolicyTypeIdentifier type) throws PfModelException {
+
+ PdpGroupFilter filter = PdpGroupFilter.builder().policyType(type).build();
+ // TODO setActive, setHasPdps
+
+ return dao.getFilteredPdpGroups(filter);
+ }
+
+ /**
+ * Creates a PDP group.
+ *
+ * @param pdpGroup the group to be created
+ * @return the created group
+ * @throws PfModelException if an error occurs
+ */
+ public PdpGroup createPdpGroup(PdpGroup pdpGroup) throws PfModelException {
+ newGroups.add(pdpGroup.getName());
+ return dao.createPdpGroups(Collections.singletonList(pdpGroup)).get(0);
+ }
+
+ /**
+ * Updates a PDP group.
+ *
+ * @param pdpGroup the group to be updated
+ * @return the updated group
+ * @throws PfModelException if an error occurs
+ */
+ public PdpGroup updatePdpGroup(PdpGroup pdpGroup) throws PfModelException {
+ return dao.updatePdpGroups(Collections.singletonList(pdpGroup)).get(0);
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java
index 8f064035..c36a7d4b 100644
--- a/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java
+++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java
@@ -42,6 +42,7 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -56,7 +57,6 @@ import org.onap.policy.models.pdp.concepts.PdpStatus;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.pdp.enums.PdpState;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
import org.onap.policy.pap.main.PapConstants;
import org.onap.policy.pap.main.comm.PdpModifyRequestMap.ModifyReqData;
import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams;
@@ -133,7 +133,8 @@ public class PdpModifyRequestMapTest {
response.setState(PdpState.SAFE);
response.setPdpGroup(update.getPdpGroup());
response.setPdpSubgroup(update.getPdpSubgroup());
- response.setPolicies(convertToscaPolicyToToscaPolicyIndentifier());
+ response.setPolicies(update.getPolicies().stream().map(ToscaPolicy::getIdentifier)
+ .collect(Collectors.toList()));
map = new PdpModifyRequestMap(makeParameters()) {
@@ -327,10 +328,13 @@ public class PdpModifyRequestMapTest {
public void testModifyReqDataIsActive() {
map.addRequest(update);
+ ModifyReqData reqdata = getReqData(PDP1);
+ assertNotNull(reqdata);
+
+ // this should remove it from the map
invokeProcessResponse();
- // name should have been removed
- assertNull(getReqData(PDP1));
+ assertFalse(reqdata.isActive());
}
@Test
@@ -584,18 +588,4 @@ public class PdpModifyRequestMapTest {
return cng;
}
-
- /**
- * Converts a ToscaPolicy list to ToscaPolicyIdentifier list.
- *
- * @return the ToscaPolicyIdentifier list
- */
- private List<ToscaPolicyIdentifier> convertToscaPolicyToToscaPolicyIndentifier() {
- final List<ToscaPolicy> toscaPolicies = update.getPolicies();
- final List<ToscaPolicyIdentifier> toscaPolicyIdentifiers = new ArrayList<>();
- for (final ToscaPolicy toscaPolicy : toscaPolicies) {
- toscaPolicyIdentifiers.add(new ToscaPolicyIdentifier(toscaPolicy.getName(), toscaPolicy.getVersion()));
- }
- return toscaPolicyIdentifiers;
- }
}
diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateDataTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateDataTest.java
index 352b92df..bac85ed0 100644
--- a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateDataTest.java
+++ b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateDataTest.java
@@ -72,7 +72,7 @@ public class UpdateDataTest {
response.setName(MY_NAME);
response.setPdpGroup(update.getPdpGroup());
response.setPdpSubgroup(update.getPdpSubgroup());
- response.setPolicies(convertToscaPolicyToToscaPolicyIndentifier(update.getPolicies()));
+ response.setPolicies(policyToIdent(update.getPolicies()));
data = new MyData(update);
}
@@ -114,24 +114,26 @@ public class UpdateDataTest {
}
@Test
- public void testUpdateDataCheckResponse_MismatchedPoliciesLength() {
- response.setPolicies(convertToscaPolicyToToscaPolicyIndentifier(Arrays.asList(update.getPolicies().get(0))));
-
- assertEquals("policies do not match", data.checkResponse(response));
- }
-
- @Test
public void testUpdateDataCheckResponse_MismatchedPolicies() {
- ArrayList<ToscaPolicyIdentifier> policies =
- new ArrayList<>(convertToscaPolicyToToscaPolicyIndentifier(update.getPolicies()));
- policies.set(0, new ToscaPolicyIdentifier(DIFFERENT, "10.0.0"));
+ ArrayList<ToscaPolicy> policies = new ArrayList<>(update.getPolicies());
+ policies.set(0, makePolicy(DIFFERENT, "10.0.0"));
- response.setPolicies(policies);
+ response.setPolicies(policyToIdent(policies));
assertEquals("policies do not match", data.checkResponse(response));
}
/**
+ * Converts a list of policies to their corresponding identifiers.
+ *
+ * @param policies policies to be converted
+ * @return a list of policy identifiers
+ */
+ private List<ToscaPolicyIdentifier> policyToIdent(List<ToscaPolicy> policies) {
+ return policies.stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList());
+ }
+
+ /**
* Makes an update message.
*
* @return a new update message
@@ -184,15 +186,4 @@ public class UpdateDataTest {
// do nothing
}
}
-
- /**
- * Converts a ToscaPolicy list to ToscaPolicyIdentifier list.
- *
- * @param toscaPolicies the list of ToscaPolicy
- * @return the ToscaPolicyIdentifier list
- */
- private List<ToscaPolicyIdentifier> convertToscaPolicyToToscaPolicyIndentifier(List<ToscaPolicy> toscaPolicies) {
- return toscaPolicies.stream().map(policy -> new ToscaPolicyIdentifier(policy.getName(), policy.getVersion()))
- .collect(Collectors.toList());
- }
}
diff --git a/main/src/test/java/org/onap/policy/pap/main/internal/TestModels.java b/main/src/test/java/org/onap/policy/pap/main/internal/TestModels.java
deleted file mode 100644
index 7cdd06ee..00000000
--- a/main/src/test/java/org/onap/policy/pap/main/internal/TestModels.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
- * Modifications Copyright (C) 2019 AT&T Intellectual Property.
- * ================================================================================
- * 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.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.pap.main.internal;
-
-import com.openpojo.reflection.filters.FilterPackageInfo;
-import com.openpojo.validation.Validator;
-import com.openpojo.validation.ValidatorBuilder;
-import com.openpojo.validation.test.impl.GetterTester;
-import com.openpojo.validation.test.impl.SetterTester;
-
-import org.junit.Test;
-import org.onap.policy.common.utils.validation.ToStringTester;
-
-/**
- * Class to perform unit testing of models.
- *
- * @author Ram Krishna Verma (ram.krishna.verma@est.tech)
- */
-public class TestModels {
-
- @Test
- public void testPapModels() {
- final Validator validator = ValidatorBuilder.create().with(new ToStringTester()).with(new SetterTester())
- .with(new GetterTester()).build();
- validator.validate(TestModels.class.getPackage().getName(), new FilterPackageInfo());
- }
-}
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java
new file mode 100644
index 00000000..3a3673d5
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java
@@ -0,0 +1,225 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.pap.main.PapConstants;
+import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper;
+import org.onap.policy.pap.main.comm.PdpModifyRequestMap;
+
+/**
+ * Super class for TestPdpGroupDeployProviderXxx classes.
+ */
+public class ProviderSuper {
+ private static final Coder coder = new StandardCoder();
+
+ @Mock
+ protected PolicyModelsProvider dao;
+
+ /**
+ * Used to capture input to dao.createPdpGroups().
+ */
+ @Captor
+ private ArgumentCaptor<List<PdpGroup>> createCaptor;
+
+
+ /**
+ * Used to capture input to dao.updatePdpGroups().
+ */
+ @Captor
+ private ArgumentCaptor<List<PdpGroup>> updateCaptor;
+
+ protected Object lockit;
+ protected PdpModifyRequestMap reqmap;
+ protected PolicyModelsProviderFactoryWrapper daofact;
+ protected ToscaPolicy policy1;
+
+
+ /**
+ * Configures DAO, captors, and various mocks.
+ */
+ @Before
+ public void setUp() throws Exception {
+
+ Registry.newRegistry();
+
+ MockitoAnnotations.initMocks(this);
+
+ reqmap = mock(PdpModifyRequestMap.class);
+
+ lockit = new Object();
+ daofact = mock(PolicyModelsProviderFactoryWrapper.class);
+ policy1 = loadFile("policy.json", ToscaPolicy.class);
+
+ when(daofact.create()).thenReturn(dao);
+
+ List<PdpGroup> groups = loadGroups("groups.json");
+
+ when(dao.getFilteredPdpGroups(any())).thenReturn(groups);
+
+ when(dao.createPdpGroups(any())).thenAnswer(answer -> answer.getArgumentAt(0, List.class));
+ when(dao.updatePdpGroups(any())).thenAnswer(answer -> answer.getArgumentAt(0, List.class));
+
+ Registry.register(PapConstants.REG_PDP_MODIFY_LOCK, lockit);
+ Registry.register(PapConstants.REG_PDP_MODIFY_MAP, reqmap);
+ Registry.register(PapConstants.REG_PAP_DAO_FACTORY, daofact);
+ }
+
+ protected void assertGroup(List<PdpGroup> groups, String name, String version) {
+ PdpGroup group = groups.remove(0);
+
+ assertEquals(name, group.getName());
+ assertEquals(version, group.getVersion());
+ }
+
+ protected void assertUpdateIgnorePolicy(List<PdpUpdate> updates, String groupName, String pdpType, String pdpName) {
+
+ PdpUpdate update = updates.remove(0);
+
+ assertEquals(groupName, update.getPdpGroup());
+ assertEquals(pdpType, update.getPdpSubgroup());
+ assertEquals(pdpName, update.getName());
+ }
+
+ /**
+ * Gets the input to the method.
+ *
+ * @param count the number of times the method is expected to have been called.
+ * @return the input that was passed to the dao.createPdpGroups() method
+ * @throws Exception if an error occurred
+ */
+ protected List<List<PdpGroup>> getGroupCreates(int count) throws Exception {
+ verify(dao, times(count)).createPdpGroups(createCaptor.capture());
+
+ return copyLists(createCaptor.getAllValues());
+ }
+
+ /**
+ * Gets the input to the method.
+ *
+ * @param count the number of times the method is expected to have been called
+ * @return the input that was passed to the dao.updatePdpGroups() method
+ * @throws Exception if an error occurred
+ */
+ protected List<List<PdpGroup>> getGroupUpdates(int count) throws Exception {
+ verify(dao, times(count)).updatePdpGroups(updateCaptor.capture());
+
+ return copyLists(updateCaptor.getAllValues());
+ }
+
+ /**
+ * Gets the updates that were added to the request map.
+ *
+ * @param count the number of times the method is expected to have been called
+ * @return the updates that were added to the request map
+ */
+ protected List<PdpUpdate> getUpdateRequests(int count) {
+ ArgumentCaptor<PdpUpdate> captor = ArgumentCaptor.forClass(PdpUpdate.class);
+
+ verify(reqmap, times(count)).addRequest(captor.capture());
+
+ return new ArrayList<>(captor.getAllValues());
+ }
+
+ /**
+ * Makes a partly deep copy of the list.
+ *
+ * @param source source list to copy
+ * @return a copy of the source list
+ */
+ private List<List<PdpGroup>> copyLists(List<List<PdpGroup>> source) {
+ List<List<PdpGroup>> target = new ArrayList<>(source.size());
+
+ for (List<PdpGroup> lst : source) {
+ target.add(new ArrayList<>(lst));
+ }
+
+ return target;
+ }
+
+ /**
+ * Loads a list of groups.
+ *
+ * @param fileName name of the file from which to load
+ * @return a list of groups
+ */
+ protected List<PdpGroup> loadGroups(String fileName) {
+ return loadFile(fileName, org.onap.policy.models.pdp.concepts.PdpGroups.class).getGroups();
+ }
+
+ /**
+ * Loads a list of policies.
+ *
+ * @param fileName name of the file from which to load
+ * @return a list of policies
+ */
+ protected List<ToscaPolicy> loadPolicies(String fileName) {
+ return loadFile(fileName, PolicyList.class).policies;
+ }
+
+ /**
+ * Loads an object from a JSON file.
+ *
+ * @param fileName name of the file from which to load
+ * @param clazz the class of the object to be loaded
+ * @return the object that was loaded from the file
+ */
+ protected <T> T loadFile(String fileName, Class<T> clazz) {
+ File propFile = new File(ResourceUtils.getFilePath4Resource("simpleDeploy/" + fileName));
+ try {
+ return coder.decode(propFile, clazz);
+
+ } catch (CoderException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Wraps a list of policies. The decoder doesn't work with generic lists, so we wrap
+ * the list and decode it into the wrapper before extracting the list contents.
+ */
+ private static class PolicyList {
+ private List<ToscaPolicy> policies;
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/TestPdpGroupDeployControllerV1.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployControllerV1.java
index 09e91a99..73a4f0e5 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/TestPdpGroupDeployControllerV1.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployControllerV1.java
@@ -1,4 +1,4 @@
-/*-
+/*
* ============LICENSE_START=======================================================
* Copyright (C) 2019 Nordix Foundation.
* Modifications Copyright (C) 2019 AT&T Intellectual Property.
@@ -19,10 +19,10 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.policy.pap.main.rest;
+package org.onap.policy.pap.main.rest.depundep;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
import java.util.Arrays;
import javax.ws.rs.client.Entity;
@@ -35,6 +35,7 @@ import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse;
import org.onap.policy.models.pdp.concepts.PdpGroup;
import org.onap.policy.models.pdp.concepts.PdpSubGroup;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion;
+import org.onap.policy.pap.main.rest.CommonPapRestServer;
public class TestPdpGroupDeployControllerV1 extends CommonPapRestServer {
@@ -49,18 +50,18 @@ public class TestPdpGroupDeployControllerV1 extends CommonPapRestServer {
@Test
public void testDeployGroup() throws Exception {
- final Entity<PdpGroup> entgrp = makePdpGroupEntity();
+ Entity<PdpGroup> entgrp = makePdpGroupEntity();
- final Invocation.Builder invocationBuilder = sendRequest(DEPLOY_GROUP_ENDPOINT);
+ Invocation.Builder invocationBuilder = sendRequest(DEPLOY_GROUP_ENDPOINT);
Response rawresp = invocationBuilder.post(entgrp);
PdpGroupDeployResponse resp = rawresp.readEntity(PdpGroupDeployResponse.class);
- assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
- assertNull(resp.getErrorDetails());
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
+ assertNotNull(resp.getErrorDetails());
rawresp = invocationBuilder.post(entgrp);
resp = rawresp.readEntity(PdpGroupDeployResponse.class);
- assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
- assertNull(resp.getErrorDetails());
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
+ assertNotNull(resp.getErrorDetails());
// verify it fails when no authorization info is included
checkUnauthRequest(DEPLOY_GROUP_ENDPOINT, req -> req.post(entgrp));
@@ -68,28 +69,28 @@ public class TestPdpGroupDeployControllerV1 extends CommonPapRestServer {
@Test
public void testDeployPolicies() throws Exception {
- final Entity<PdpDeployPolicies> entgrp = makePdpPoliciesEntity();
+ Entity<PdpDeployPolicies> entgrp = makePdpPoliciesEntity();
- final Invocation.Builder invocationBuilder = sendRequest(DEPLOY_POLICIES_ENDPOINT);
+ Invocation.Builder invocationBuilder = sendRequest(DEPLOY_POLICIES_ENDPOINT);
Response rawresp = invocationBuilder.post(entgrp);
PdpGroupDeployResponse resp = rawresp.readEntity(PdpGroupDeployResponse.class);
- assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
- assertNull(resp.getErrorDetails());
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
+ assertNotNull(resp.getErrorDetails());
rawresp = invocationBuilder.post(entgrp);
resp = rawresp.readEntity(PdpGroupDeployResponse.class);
- assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
- assertNull(resp.getErrorDetails());
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
+ assertNotNull(resp.getErrorDetails());
// verify it fails when no authorization info is included
checkUnauthRequest(DEPLOY_POLICIES_ENDPOINT, req -> req.post(entgrp));
}
private Entity<PdpGroup> makePdpGroupEntity() {
- final PdpSubGroup subgrp = new PdpSubGroup();
+ PdpSubGroup subgrp = new PdpSubGroup();
subgrp.setPdpType("drools");
- final PdpGroup group = new PdpGroup();
+ PdpGroup group = new PdpGroup();
group.setName("drools-group");
group.setDescription("my description");
group.setVersion("my-version");
@@ -99,14 +100,10 @@ public class TestPdpGroupDeployControllerV1 extends CommonPapRestServer {
}
private Entity<PdpDeployPolicies> makePdpPoliciesEntity() {
- final ToscaPolicyIdentifierOptVersion pol1 = new ToscaPolicyIdentifierOptVersion();
- pol1.setName("policy-a");
- pol1.setVersion("1");
+ ToscaPolicyIdentifierOptVersion pol1 = new ToscaPolicyIdentifierOptVersion("policy-a", "1");
+ ToscaPolicyIdentifierOptVersion pol2 = new ToscaPolicyIdentifierOptVersion("policy-b", null);
- final ToscaPolicyIdentifierOptVersion pol2 = new ToscaPolicyIdentifierOptVersion();
- pol2.setName("policy-b");
-
- final PdpDeployPolicies policies = new PdpDeployPolicies();
+ PdpDeployPolicies policies = new PdpDeployPolicies();
policies.setPolicies(Arrays.asList(pol1, pol2));
return Entity.entity(policies, MediaType.APPLICATION_JSON);
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
new file mode 100644
index 00000000..d3ffda84
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
@@ -0,0 +1,214 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.onap.policy.pap.main.rest.depundep.ProviderBase.DB_ERROR_MSG;
+
+import java.util.List;
+import javax.ws.rs.core.Response.Status;
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
+import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.pap.main.rest.depundep.PdpGroupDeployProvider;
+
+public class TestPdpGroupDeployProvider extends ProviderSuper {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final Object REQUEST_FAILED_MSG = "request failed";
+
+ private static final String POLICY1_NAME = "policyA";
+ private static final String POLICY1_VERSION = "1.2.3";
+ private static final String GROUP1_NAME = "groupA";
+ private static final String GROUP1_VERSION = "200.2.3";
+ private static final String GROUP1_NEW_VERSION = "201.0.0";
+ private static final String PDP1_TYPE = "pdpTypeA";
+ private static final String PDP2_TYPE = "pdpTypeB";
+ private static final String PDP4_TYPE = "pdpTypeD";
+ private static final String PDP2 = "pdpB";
+ private static final String PDP4 = "pdpD";
+
+ private PdpGroupDeployProvider prov;
+
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ Registry.newRegistry();
+ }
+
+ /**
+ * Configures mocks and objects.
+ *
+ * @throws Exception if an error occurs
+ */
+ @Before
+ public void setUp() throws Exception {
+
+ super.setUp();
+
+ when(dao.getPolicyList(POLICY1_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("daoPolicyList.json"));
+
+ prov = new PdpGroupDeployProvider();
+ }
+
+ @Test
+ public void testDeployGroup() {
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployGroup(new PdpGroups());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals("not implemented yet", pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testDeployPolicies() {
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadEmptyRequest());
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testDeploySimplePolicies() throws Exception {
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testDeploySimplePolicies_DaoEx() throws Exception {
+ when(dao.getFilteredPdpGroups(any())).thenThrow(new PfModelException(Status.BAD_REQUEST, EXPECTED_EXCEPTION));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals(DB_ERROR_MSG, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testDeploySimplePolicies_RuntimeEx() throws Exception {
+ when(dao.getPolicyList(any(), any())).thenThrow(new RuntimeException(EXPECTED_EXCEPTION));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals(REQUEST_FAILED_MSG, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testDeploySimplePolicies_NoGroups() throws Exception {
+ when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("emptyGroups.json"));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals("policy not supported by any PDP group: policyA 1.2.3", pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testMakeUpdater() throws Exception {
+ /*
+ * Each subgroup has a different PDP type and name.
+ *
+ * Type is not supported by the first subgroup.
+ *
+ * Second subgroup matches.
+ *
+ * Third subgroup already contains the policy.
+ *
+ * Last subgroup matches.
+ */
+
+ when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroupDao.json"));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ assertGroup(getGroupUpdates(1).get(0), GROUP1_NAME, GROUP1_VERSION);
+ assertGroup(getGroupCreates(1).get(0), GROUP1_NAME, GROUP1_NEW_VERSION);
+
+ List<PdpUpdate> requests = getUpdateRequests(2);
+ assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2);
+ assertUpdate(requests, GROUP1_NAME, PDP4_TYPE, PDP4);
+ }
+
+ @Test
+ public void testMakeUpdater_NoPdps() throws Exception {
+
+ // subgroup has no PDPs
+ when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroup_NoPdpsDao.json"));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.deployPolicies(loadRequest());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals("group " + GROUP1_NAME + " subgroup " + PDP1_TYPE + " has no active PDPs",
+ pair.getRight().getErrorDetails());
+
+ verify(dao, never()).createPdpGroups(any());
+ verify(dao, never()).updatePdpGroups(any());
+ verify(reqmap, never()).addRequest(any(PdpUpdate.class));
+ }
+
+
+ protected void assertUpdate(List<PdpUpdate> updates, String groupName, String pdpType, String pdpName) {
+
+ PdpUpdate update = updates.remove(0);
+
+ assertEquals(groupName, update.getPdpGroup());
+ assertEquals(pdpType, update.getPdpSubgroup());
+ assertEquals(pdpName, update.getName());
+ assertTrue(update.getPolicies().contains(policy1));
+ }
+
+ /**
+ * Loads a standard request.
+ *
+ * @return a standard request
+ */
+ protected PdpDeployPolicies loadRequest() {
+ return loadRequest("request.json");
+ }
+
+ /**
+ * Loads a request from a JSON file.
+ *
+ * @param fileName name of the file from which to load
+ * @return the request that was loaded
+ */
+ protected PdpDeployPolicies loadRequest(String fileName) {
+ return loadFile(fileName, PdpDeployPolicies.class);
+ }
+
+ /**
+ * Loads an empty request.
+ *
+ * @return an empty request
+ */
+ protected PdpDeployPolicies loadEmptyRequest() {
+ return loadRequest("emptyRequest.json");
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java
new file mode 100644
index 00000000..f64f77da
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java
@@ -0,0 +1,421 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.onap.policy.pap.main.rest.depundep.ProviderBase.DB_ERROR_MSG;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.function.BiFunction;
+import javax.ws.rs.core.Response.Status;
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
+import org.onap.policy.models.pap.concepts.SimpleResponse;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
+import org.powermock.reflect.Whitebox;
+
+public class TestProviderBase extends ProviderSuper {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final Object REQUEST_FAILED_MSG = "request failed";
+
+ private static final String POLICY1_NAME = "policyA";
+ private static final String POLICY1_VERSION = "1.2.3";
+ private static final String GROUP1_NAME = "groupA";
+ private static final String GROUP1_VERSION = "200.2.3";
+ private static final String GROUP1_NEW_VERSION = "201.0.0";
+ private static final String GROUP2_NAME = "groupB";
+ private static final String PDP1_TYPE = "pdpTypeA";
+ private static final String PDP2_TYPE = "pdpTypeB";
+ private static final String PDP3_TYPE = "pdpTypeC";
+ private static final String PDP4_TYPE = "pdpTypeD";
+ private static final String PDP1 = "pdpA";
+ private static final String PDP2 = "pdpB";
+ private static final String PDP3 = "pdpC";
+ private static final String PDP4 = "pdpD";
+
+ private MyProvider prov;
+
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ Registry.newRegistry();
+ }
+
+ /**
+ * Configures mocks and objects.
+ *
+ * @throws Exception if an error occurs
+ */
+ @Before
+ public void setUp() throws Exception {
+
+ super.setUp();
+
+ when(dao.getPolicyList(POLICY1_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("daoPolicyList.json"));
+
+ prov = new MyProvider();
+ }
+
+ @Test
+ public void testProviderBase() {
+ assertSame(lockit, Whitebox.getInternalState(prov, "updateLock"));
+ assertSame(reqmap, Whitebox.getInternalState(prov, "requestMap"));
+ assertSame(daofact, Whitebox.getInternalState(prov, "daoFactory"));
+ }
+
+ @Test
+ public void testProcess() throws Exception {
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ assertGroup(getGroupUpdates(1).get(0), GROUP1_NAME, GROUP1_VERSION);
+ assertGroup(getGroupCreates(1).get(0), GROUP1_NAME, GROUP1_NEW_VERSION);
+
+ assertUpdate(getUpdateRequests(1), GROUP1_NAME, PDP1_TYPE, PDP1);
+ }
+
+ @Test
+ public void testProcess_CreateEx() throws Exception {
+ when(daofact.create()).thenThrow(new PfModelException(Status.BAD_REQUEST, EXPECTED_EXCEPTION));
+
+ Pair<Status, MyResponse> pair = prov.process(loadEmptyRequest(), this::handle);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals(DB_ERROR_MSG, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testProcess_PapEx() throws Exception {
+ when(daofact.create()).thenThrow(new PolicyPapRuntimeException(EXPECTED_EXCEPTION));
+
+ Pair<Status, MyResponse> pair = prov.process(loadEmptyRequest(), this::handle);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals(EXPECTED_EXCEPTION, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testProcess_RuntimeEx() throws Exception {
+ when(daofact.create()).thenThrow(new RuntimeException(EXPECTED_EXCEPTION));
+
+ Pair<Status, MyResponse> pair = prov.process(loadEmptyRequest(), this::handle);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals(REQUEST_FAILED_MSG, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testProcessPolicy_NoGroups() throws Exception {
+ when(dao.getFilteredPdpGroups(any())).thenReturn(Collections.emptyList());
+
+ SessionData session = new SessionData(dao);
+ ToscaPolicyIdentifierOptVersion ident = new ToscaPolicyIdentifierOptVersion(POLICY1_NAME, POLICY1_VERSION);
+ assertThatThrownBy(() -> prov.processPolicy(session, ident)).isInstanceOf(PolicyPapRuntimeException.class)
+ .hasMessage("policy not supported by any PDP group: policyA 1.2.3");
+
+ }
+
+ @Test
+ public void testGetPolicy() throws Exception {
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ verify(dao).getPolicyList(any(), any());
+ verify(dao, never()).getFilteredPolicyList(any());
+ }
+
+ @Test
+ public void testGetPolicy_NullVersion() throws Exception {
+ // only allow this query once
+ when(dao.getPolicyList(POLICY1_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("daoPolicyList.json"))
+ .thenThrow(new RuntimeException(EXPECTED_EXCEPTION));
+
+ when(dao.getFilteredPolicyList(any())).thenReturn(loadPolicies("daoPolicyList.json"));
+
+ Pair<Status, MyResponse> pair = prov.process(loadRequest("getPolicyReqNullVersion.json"), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ verify(dao).getFilteredPolicyList(any());
+ verify(dao, never()).getPolicies(any(), any());
+ }
+
+ @Test
+ public void testGetPolicy_NotFound() throws Exception {
+ when(dao.getPolicyList(any(), any())).thenReturn(Collections.emptyList());
+
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertEquals("cannot find policy: " + POLICY1_NAME + " " + POLICY1_VERSION, pair.getRight().getErrorDetails());
+ }
+
+ @Test
+ public void testGetGroup() throws Exception {
+ when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("getGroupDao.json"))
+ .thenReturn(loadGroups("groups.json"));
+
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ assertGroup(getGroupUpdates(1).get(0), GROUP1_NAME, GROUP1_VERSION);
+ assertGroup(getGroupCreates(1).get(0), GROUP1_NAME, GROUP1_NEW_VERSION);
+ }
+
+ @Test
+ public void testUpgradeGroup() throws Exception {
+ /*
+ * Each subgroup has a different PDP type and name.
+ *
+ * Type is not supported by the first subgroup.
+ *
+ * Second subgroup matches.
+ *
+ * Third subgroup already contains the policy.
+ *
+ * Last subgroup matches.
+ */
+
+ when(dao.getFilteredPdpGroups(any())).thenReturn(loadGroups("upgradeGroupDao.json"));
+
+ prov.clear();
+ prov.add(false, true, false, true);
+
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ assertGroup(getGroupUpdates(1).get(0), GROUP1_NAME, GROUP1_VERSION);
+ assertGroup(getGroupCreates(1).get(0), GROUP1_NAME, GROUP1_NEW_VERSION);
+
+ List<PdpUpdate> requests = getUpdateRequests(2);
+ assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2);
+ assertUpdate(requests, GROUP1_NAME, PDP4_TYPE, PDP4);
+ }
+
+ @Test
+ public void testUpgradeGroup_Multiple() throws Exception {
+ /*
+ * Policy data in the DB: policy1=type1, policy2=type2, policy3=type3,
+ * policy4=type1
+ *
+ * Group data in the DB: group1=(type1=pdp1, type3=pdp3) group2=(type2=pdp2)
+ *
+ * Request specifies: policy1, policy2, policy3, policy4
+ *
+ * Should create new versions of group1 and group2.
+ *
+ * Should update old versions of group1 and group2. Should also update new version
+ * of group1 twice.
+ *
+ * Should generate updates to pdp1, pdp2, and pdp3.
+ */
+
+ when(dao.getPolicyList(POLICY1_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("daoPolicyList.json"));
+ when(dao.getPolicyList("policyB", POLICY1_VERSION)).thenReturn(loadPolicies("upgradeGroupPolicy2.json"));
+ when(dao.getPolicyList("policyC", POLICY1_VERSION)).thenReturn(loadPolicies("upgradeGroupPolicy3.json"));
+ when(dao.getPolicyList("policyD", POLICY1_VERSION)).thenReturn(loadPolicies("upgradeGroupPolicy4.json"));
+
+ List<PdpGroup> groups1 = loadGroups("upgradeGroupGroup1.json");
+ List<PdpGroup> groups2 = loadGroups("upgradeGroupGroup2.json");
+
+ /*
+ * these are in pairs of (get-group, get-max-group) matching each policy in the
+ * request
+ */
+ // @formatter:off
+ when(dao.getFilteredPdpGroups(any()))
+ .thenReturn(groups1).thenReturn(groups1)
+ .thenReturn(groups2).thenReturn(groups2)
+ .thenReturn(groups1).thenReturn(groups1)
+ .thenReturn(groups1).thenReturn(groups1);
+ // @formatter:on
+
+ // multiple policies in the request
+ PdpDeployPolicies request = loadFile("updateGroupReqMultiple.json", PdpDeployPolicies.class);
+
+ Pair<Status, MyResponse> pair = prov.process(request, (data, deploy) -> {
+ for (ToscaPolicyIdentifierOptVersion policy : deploy.getPolicies()) {
+ handle(data, policy);
+ }
+ });
+
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ List<List<PdpGroup>> creates = getGroupCreates(2);
+ assertGroup(creates.get(0), GROUP1_NAME, GROUP1_NEW_VERSION);
+ assertGroup(creates.get(1), GROUP2_NAME, "301.0.0");
+
+ List<List<PdpGroup>> updates = getGroupUpdates(4);
+ assertGroup(updates.get(0), GROUP1_NAME, GROUP1_VERSION);
+ assertGroup(updates.get(1), GROUP2_NAME, "300.2.3");
+ assertGroup(updates.get(2), GROUP1_NAME, GROUP1_NEW_VERSION);
+ assertGroup(updates.get(3), GROUP1_NAME, GROUP1_NEW_VERSION);
+
+ List<PdpUpdate> requests = getUpdateRequests(3);
+ assertUpdateIgnorePolicy(requests, GROUP1_NAME, PDP1_TYPE, PDP1);
+ assertUpdateIgnorePolicy(requests, GROUP2_NAME, PDP2_TYPE, PDP2);
+ assertUpdateIgnorePolicy(requests, GROUP1_NAME, PDP3_TYPE, PDP3);
+ }
+
+ @Test
+ public void testUpgradeGroup_NothingUpdated() throws Exception {
+ prov.clear();
+ prov.add(false);
+
+ Pair<Status, MyResponse> pair = prov.process(loadRequest(), this::handle);
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ verify(dao, never()).createPdpGroups(any());
+ verify(dao, never()).updatePdpGroups(any());
+ verify(reqmap, never()).addRequest(any(PdpUpdate.class));
+ }
+
+
+ protected void assertUpdate(List<PdpUpdate> updates, String groupName, String pdpType, String pdpName) {
+
+ PdpUpdate update = updates.remove(0);
+
+ assertEquals(groupName, update.getPdpGroup());
+ assertEquals(pdpType, update.getPdpSubgroup());
+ assertEquals(pdpName, update.getName());
+ assertTrue(update.getPolicies().contains(policy1));
+ }
+
+ /**
+ * Loads a standard request.
+ *
+ * @return a standard request
+ */
+ protected ToscaPolicyIdentifierOptVersion loadRequest() {
+ return loadRequest("requestBase.json");
+ }
+
+ /**
+ * Loads a request from a JSON file.
+ *
+ * @param fileName name of the file from which to load
+ * @return the request that was loaded
+ */
+ protected ToscaPolicyIdentifierOptVersion loadRequest(String fileName) {
+ return loadFile(fileName, ToscaPolicyIdentifierOptVersion.class);
+ }
+
+ /**
+ * Loads an empty request.
+ *
+ * @return an empty request
+ */
+ protected ToscaPolicyIdentifierOptVersion loadEmptyRequest() {
+ return loadRequest("emptyRequestBase.json");
+ }
+
+ /**
+ * Handles a request by invoking the provider's processPolicy method.
+ *
+ * @param data session data
+ * @param request request to be handled
+ */
+ private void handle(SessionData data, ToscaPolicyIdentifierOptVersion request) {
+ try {
+ prov.processPolicy(data, request);
+
+ } catch (PfModelException e) {
+ throw new PolicyPapRuntimeException(e);
+ }
+ }
+
+
+ private static class MyProvider extends ProviderBase<MyResponse> {
+ /**
+ * Used to determine whether or not to make an update when
+ * {@link #makeUpdater(ToscaPolicy)} is called. The updater function removes an
+ * item from this queue each time it is invoked.
+ */
+ private final Queue<Boolean> shouldUpdate = new LinkedList<>();
+
+ /**
+ * Constructs the object and queues up several successful updates.
+ */
+ public MyProvider() {
+ for (int x = 0; x < 10; ++x) {
+ shouldUpdate.add(true);
+ }
+ }
+
+ public void clear() {
+ shouldUpdate.clear();
+ }
+
+ public void add(Boolean... update) {
+ shouldUpdate.addAll(Arrays.asList(update));
+ }
+
+ @Override
+ public MyResponse makeResponse(String errorMsg) {
+ return new MyResponse(errorMsg);
+ }
+
+ @Override
+ protected BiFunction<PdpGroup, PdpSubGroup, Boolean> makeUpdater(ToscaPolicy policy) {
+ return (group, subgroup) -> {
+ if (shouldUpdate.remove()) {
+ // queue indicated that the update should succeed
+ subgroup.getPolicies().add(policy.getIdentifier());
+ return true;
+
+ } else {
+ // queue indicated that no update should be made this time
+ return false;
+ }
+ };
+ }
+ }
+
+ private static class MyResponse extends SimpleResponse {
+ public MyResponse(String errorMsg) {
+ setErrorDetails(errorMsg);
+ }
+ }
+}
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java
new file mode 100644
index 00000000..6be5c8ac
--- /dev/null
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java
@@ -0,0 +1,258 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP PAP
+ * ================================================================================
+ * 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.pap.main.rest.depundep;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import javax.ws.rs.core.Response.Status;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
+
+public class TestSessionData extends ProviderSuper {
+ private static final String GROUP_VERSION_PREFIX = "9.8.";
+ private static final String GROUP_NAME = "group";
+ private static final String GROUP_VERSION = GROUP_VERSION_PREFIX + "7";
+ private static final String GROUP_NAME2 = "group2";
+ private static final String GROUP_VERSION2 = GROUP_VERSION_PREFIX + "6";
+ private static final String PDP1 = "pdp_1";
+ private static final String PDP2 = "pdp_2";
+ private static final String PDP3 = "pdp_3";
+ private static final String POLICY_VERSION_PREFIX = "1.2.";
+ private static final String POLICY_NAME = "myPolicy";
+ private static final String POLICY_VERSION = POLICY_VERSION_PREFIX + "3";
+ private static final String POLICY_VERSION2 = POLICY_VERSION_PREFIX + "4";
+
+ private SessionData session;
+ private ToscaPolicyIdentifier ident;
+
+ /**
+ * Initializes mocks and a session.
+ *
+ * @throws Exception if an error occurs
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ ident = new ToscaPolicyIdentifier(POLICY_NAME, POLICY_VERSION);
+
+ session = new SessionData(dao);
+ }
+
+ @Test
+ public void testGetPolicy() throws Exception {
+ ToscaPolicy policy1 = makePolicy(POLICY_NAME, POLICY_VERSION);
+ when(dao.getPolicyList(POLICY_NAME, POLICY_VERSION)).thenReturn(Arrays.asList(policy1));
+
+ ToscaPolicy policy2 = makePolicy(POLICY_NAME, POLICY_VERSION2);
+ when(dao.getPolicyList(POLICY_NAME, POLICY_VERSION2)).thenReturn(Arrays.asList(policy2));
+
+ ToscaPolicyIdentifier ident2 = new ToscaPolicyIdentifier(POLICY_NAME, POLICY_VERSION2);
+
+ assertSame(policy1, session.getPolicy(ident));
+ assertSame(policy2, session.getPolicy(ident2));
+
+ // repeat
+ assertSame(policy1, session.getPolicy(ident));
+ assertSame(policy2, session.getPolicy(ident2));
+
+ assertSame(policy1, session.getPolicy(ident));
+ assertSame(policy2, session.getPolicy(ident2));
+
+ // should have only invoked this once for each policy
+ verify(dao, times(2)).getPolicyList(any(), any());
+ }
+
+ @Test
+ public void testGetPolicy_NotFound() throws Exception {
+ when(dao.getPolicyList(any(), any())).thenReturn(Collections.emptyList());
+
+ assertThatThrownBy(() -> session.getPolicy(ident)).hasMessage("cannot find policy: myPolicy 1.2.3");
+ }
+
+ @Test
+ public void testGetPolicy_TooMany() throws Exception {
+ ToscaPolicy policy = new ToscaPolicy();
+ when(dao.getPolicyList(any(), any())).thenReturn(Arrays.asList(policy, policy));
+
+ assertThatThrownBy(() -> session.getPolicy(ident)).hasMessage("too many policies match: myPolicy 1.2.3");
+ }
+
+ @Test
+ public void testGetPolicy_DaoEx() throws Exception {
+ PfModelException ex = new PfModelException(Status.INTERNAL_SERVER_ERROR, "expected exception");
+ when(dao.getPolicyList(any(), any())).thenThrow(ex);
+
+ assertThatThrownBy(() -> session.getPolicy(ident)).hasMessage("cannot get policy: myPolicy 1.2.3").hasCause(ex);
+ }
+
+ @Test
+ public void testAddUpdate() {
+ // several different updates, but one duplicate
+ PdpUpdate update1 = makeUpdate(PDP1);
+ session.addUpdate(update1);
+
+ PdpUpdate update2 = makeUpdate(PDP2);
+ session.addUpdate(update2);
+
+ PdpUpdate update3 = makeUpdate(PDP3);
+ session.addUpdate(update3);
+
+ List<PdpUpdate> lst = sort(session.getUpdates(), this::compare);
+ assertEquals(Arrays.asList(update1, update2, update3).toString(), lst.toString());
+
+ // overwrite one
+ update2 = makeUpdate(PDP2);
+ session.addUpdate(update2);
+
+ lst = sort(session.getUpdates(), this::compare);
+ assertEquals(Arrays.asList(update1, update2, update3).toString(), lst.toString());
+ }
+
+ private ToscaPolicy makePolicy(String name, String version) {
+ ToscaPolicy policy = new ToscaPolicy();
+
+ policy.setName(name);
+ policy.setVersion(version);
+
+ return policy;
+ }
+
+ @Test
+ public void testGetPolicyMaxVersion() throws Exception {
+ ToscaPolicy policy1 = makePolicy(POLICY_NAME, POLICY_VERSION);
+
+ when(dao.getFilteredPolicyList(any())).thenReturn(Arrays.asList(policy1));
+
+ assertSame(policy1, session.getPolicyMaxVersion(POLICY_NAME));
+
+ // no matching policies - should throw an exception
+ when(dao.getFilteredPolicyList(any())).thenReturn(Collections.emptyList());
+ assertThatThrownBy(() -> session.getPolicyMaxVersion(POLICY_NAME)).hasMessage("cannot find policy: myPolicy");
+ }
+
+ @Test
+ public void testIsNewlyCreated_testCreatePdpGroup() throws Exception {
+ assertFalse(session.isNewlyCreated(GROUP_NAME));
+
+ PdpGroup group1 = makeGroup(GROUP_NAME, GROUP_VERSION);
+ when(dao.createPdpGroups(any())).thenReturn(Arrays.asList(group1));
+
+ session.createPdpGroup(group1);
+
+ assertTrue(session.isNewlyCreated(GROUP_NAME));
+ assertFalse(session.isNewlyCreated(GROUP_NAME2));
+
+ PdpGroup group2 = makeGroup(GROUP_NAME2, GROUP_VERSION2);
+ when(dao.createPdpGroups(any())).thenReturn(Arrays.asList(group2));
+ session.createPdpGroup(group2);
+
+ List<List<PdpGroup>> creates = getGroupCreates(2);
+ assertEquals(group1, creates.get(0).get(0));
+ assertEquals(group2, creates.get(1).get(0));
+
+ assertTrue(session.isNewlyCreated(GROUP_NAME));
+ assertTrue(session.isNewlyCreated(GROUP_NAME2));
+ }
+
+ private PdpGroup makeGroup(String name, String version) {
+ PdpGroup group = new PdpGroup();
+
+ group.setName(name);
+ group.setVersion(version);
+
+ return group;
+ }
+
+ @Test
+ public void testGetPdpGroupMaxVersion() throws Exception {
+ PdpGroup group = makeGroup(GROUP_NAME, GROUP_VERSION);
+ when(dao.getFilteredPdpGroups(any())).thenReturn(Arrays.asList(group));
+
+ assertEquals(group, session.getPdpGroupMaxVersion(GROUP_NAME));
+
+ // try empty list
+ when(dao.getFilteredPdpGroups(any())).thenReturn(Collections.emptyList());
+ assertThatThrownBy(() -> session.getPdpGroupMaxVersion(GROUP_NAME))
+ .isInstanceOf(PolicyPapRuntimeException.class).hasMessage("cannot find group: group");
+ }
+
+ @Test
+ public void testGetActivePdpGroupsByPolicyType() throws Exception {
+ List<PdpGroup> groups =
+ Arrays.asList(makeGroup(GROUP_NAME, GROUP_VERSION), makeGroup(GROUP_NAME2, GROUP_VERSION2));
+ when(dao.getFilteredPdpGroups(any())).thenReturn(groups);
+
+ assertEquals(groups, session
+ .getActivePdpGroupsByPolicyType(new ToscaPolicyTypeIdentifier(POLICY_NAME, POLICY_VERSION)));
+ }
+
+ @Test
+ public void testUpdatePdpGroup() throws Exception {
+ PdpGroup group = makeGroup(GROUP_NAME, GROUP_VERSION);
+ when(dao.updatePdpGroups(any())).thenReturn(Arrays.asList(group));
+
+ session.updatePdpGroup(group);
+
+ List<PdpGroup> updates = getGroupUpdates(1).get(0);
+ assertEquals(group, updates.get(0));
+ }
+
+ private PdpUpdate makeUpdate(String pdpName) {
+ PdpUpdate update = new PdpUpdate();
+
+ update.setName(pdpName);
+
+ return update;
+ }
+
+ private <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
+ List<T> lst = new ArrayList<>(collection);
+ Collections.sort(lst, comparator);
+
+ return lst;
+ }
+
+ private int compare(PdpUpdate left, PdpUpdate right) {
+ return left.getName().compareTo(right.getName());
+ }
+}
diff --git a/main/src/test/resources/simpleDeploy/daoPolicyList.json b/main/src/test/resources/simpleDeploy/daoPolicyList.json
new file mode 100644
index 00000000..93ee9146
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/daoPolicyList.json
@@ -0,0 +1,10 @@
+{
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3",
+ "type": "typeA",
+ "typeVersion": "100.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/emptyGroups.json b/main/src/test/resources/simpleDeploy/emptyGroups.json
new file mode 100644
index 00000000..44e05c87
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/emptyGroups.json
@@ -0,0 +1,3 @@
+{
+ "groups": []
+}
diff --git a/main/src/test/resources/simpleDeploy/emptyRequest.json b/main/src/test/resources/simpleDeploy/emptyRequest.json
new file mode 100644
index 00000000..4c458a32
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/emptyRequest.json
@@ -0,0 +1,3 @@
+{
+ "policies": []
+}
diff --git a/main/src/test/resources/simpleDeploy/emptyRequestBase.json b/main/src/test/resources/simpleDeploy/emptyRequestBase.json
new file mode 100644
index 00000000..2c63c085
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/emptyRequestBase.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/main/src/test/resources/simpleDeploy/getGroupDao.json b/main/src/test/resources/simpleDeploy/getGroupDao.json
new file mode 100644
index 00000000..2e74d1bf
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/getGroupDao.json
@@ -0,0 +1,84 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "0.0.0",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "groupA",
+ "version": "0.0.1",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "groupA",
+ "version": "non-numeric-version",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/getPolicyReqNullVersion.json b/main/src/test/resources/simpleDeploy/getPolicyReqNullVersion.json
new file mode 100644
index 00000000..bf2d132b
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/getPolicyReqNullVersion.json
@@ -0,0 +1,7 @@
+{
+ "policies": [
+ {
+ "name": "policyA"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/groups.json b/main/src/test/resources/simpleDeploy/groups.json
new file mode 100644
index 00000000..7fd7684b
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/groups.json
@@ -0,0 +1,25 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/policy.json b/main/src/test/resources/simpleDeploy/policy.json
new file mode 100644
index 00000000..7786aab7
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/policy.json
@@ -0,0 +1,6 @@
+{
+ "name": "policyA",
+ "version": "1.2.3",
+ "type": "typeA",
+ "typeVersion": "100.2.3"
+}
diff --git a/main/src/test/resources/simpleDeploy/request.json b/main/src/test/resources/simpleDeploy/request.json
new file mode 100644
index 00000000..060637cc
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/request.json
@@ -0,0 +1,8 @@
+{
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/requestBase.json b/main/src/test/resources/simpleDeploy/requestBase.json
new file mode 100644
index 00000000..67fcdcb6
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/requestBase.json
@@ -0,0 +1,4 @@
+{
+ "name": "policyA",
+ "version": "1.2.3"
+}
diff --git a/main/src/test/resources/simpleDeploy/updateGroupReqMultiple.json b/main/src/test/resources/simpleDeploy/updateGroupReqMultiple.json
new file mode 100644
index 00000000..3d4684cc
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/updateGroupReqMultiple.json
@@ -0,0 +1,20 @@
+{
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3"
+ },
+ {
+ "name": "policyB",
+ "version": "1.2.3"
+ },
+ {
+ "name": "policyC",
+ "version": "1.2.3"
+ },
+ {
+ "name": "policyD",
+ "version": "1.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupDao.json b/main/src/test/resources/simpleDeploy/upgradeGroupDao.json
new file mode 100644
index 00000000..278b69a6
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupDao.json
@@ -0,0 +1,72 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ],
+ "policies": []
+ },
+ {
+ "pdpType": "pdpTypeB",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpB"
+ }
+ ],
+ "policies": []
+ },
+ {
+ "pdpType": "pdpTypeC",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpC"
+ }
+ ],
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3",
+ "type": "typeA",
+ "typeVersion": "100.2.3"
+ }
+ ]
+ },
+ {
+ "pdpType": "pdpTypeD",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpD"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupGroup1.json b/main/src/test/resources/simpleDeploy/upgradeGroupGroup1.json
new file mode 100644
index 00000000..a63eadd9
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupGroup1.json
@@ -0,0 +1,40 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ],
+ "policies": []
+ },
+ {
+ "pdpType": "pdpTypeC",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeC",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpC"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupGroup2.json b/main/src/test/resources/simpleDeploy/upgradeGroupGroup2.json
new file mode 100644
index 00000000..d4946579
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupGroup2.json
@@ -0,0 +1,25 @@
+{
+ "groups": [
+ {
+ "name": "groupB",
+ "version": "300.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeB",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeB",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpB"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupPolicy2.json b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy2.json
new file mode 100644
index 00000000..3a13d0c3
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy2.json
@@ -0,0 +1,10 @@
+{
+ "policies": [
+ {
+ "name": "policyB",
+ "version": "1.2.3",
+ "type": "typeB",
+ "typeVersion": "100.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupPolicy3.json b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy3.json
new file mode 100644
index 00000000..bf5602ea
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy3.json
@@ -0,0 +1,10 @@
+{
+ "policies": [
+ {
+ "name": "policyC",
+ "version": "1.2.3",
+ "type": "typeC",
+ "typeVersion": "100.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroupPolicy4.json b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy4.json
new file mode 100644
index 00000000..3c0fb72f
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroupPolicy4.json
@@ -0,0 +1,10 @@
+{
+ "policies": [
+ {
+ "name": "policyD",
+ "version": "1.2.3",
+ "type": "typeA",
+ "typeVersion": "100.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroup_NoPdpsDao.json b/main/src/test/resources/simpleDeploy/upgradeGroup_NoPdpsDao.json
new file mode 100644
index 00000000..72563d47
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroup_NoPdpsDao.json
@@ -0,0 +1,21 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/upgradeGroup_NothingUpdatedDao.json b/main/src/test/resources/simpleDeploy/upgradeGroup_NothingUpdatedDao.json
new file mode 100644
index 00000000..60d6a68c
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/upgradeGroup_NothingUpdatedDao.json
@@ -0,0 +1,25 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeB",
+ "supportedPolicyTypes": [
+ {
+ "name": "typeX",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpB"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}