2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019-2021 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * SPDX-License-Identifier: Apache-2.0
21 * ============LICENSE_END=========================================================
24 package org.onap.policy.xacml.pdp.application.optimization;
26 import static org.assertj.core.api.Assertions.assertThat;
27 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
29 import com.att.research.xacml.api.Response;
30 import com.google.common.collect.Lists;
32 import java.nio.file.Files;
33 import java.nio.file.Paths;
34 import java.util.Collection;
35 import java.util.Iterator;
36 import java.util.List;
38 import java.util.Map.Entry;
39 import java.util.Properties;
40 import java.util.ServiceLoader;
41 import org.apache.commons.lang3.tuple.Pair;
42 import org.assertj.core.api.Condition;
43 import org.junit.BeforeClass;
44 import org.junit.ClassRule;
45 import org.junit.FixMethodOrder;
46 import org.junit.Test;
47 import org.junit.rules.TemporaryFolder;
48 import org.junit.runners.MethodSorters;
49 import org.onap.policy.common.utils.coder.CoderException;
50 import org.onap.policy.common.utils.coder.StandardCoder;
51 import org.onap.policy.common.utils.coder.StandardYamlCoder;
52 import org.onap.policy.common.utils.resources.ResourceUtils;
53 import org.onap.policy.common.utils.resources.TextFileUtils;
54 import org.onap.policy.models.decisions.concepts.DecisionRequest;
55 import org.onap.policy.models.decisions.concepts.DecisionResponse;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
59 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
60 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
61 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
62 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
63 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
68 public class OptimizationPdpApplicationTest {
70 private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
71 private static Properties properties = new Properties();
72 private static File propertiesFile;
73 private static XacmlApplicationServiceProvider service;
74 private static StandardCoder gson = new StandardCoder();
75 private static DecisionRequest baseRequest;
76 private static String[] listPolicyTypeFiles = {
77 "onap.policies.Optimization",
78 "onap.policies.optimization.Resource",
79 "onap.policies.optimization.Service",
80 "onap.policies.optimization.resource.AffinityPolicy",
81 "onap.policies.optimization.resource.DistancePolicy",
82 "onap.policies.optimization.resource.HpaPolicy",
83 "onap.policies.optimization.resource.OptimizationPolicy",
84 "onap.policies.optimization.resource.PciPolicy",
85 "onap.policies.optimization.service.QueryPolicy",
86 "onap.policies.optimization.service.SubscriberPolicy",
87 "onap.policies.optimization.resource.Vim_fit",
88 "onap.policies.optimization.resource.VnfPolicy"};
91 public static final TemporaryFolder policyFolder = new TemporaryFolder();
94 * Copies the xacml.properties and policies files into
95 * temporary folder and loads the service provider saving
96 * instance of provider off for other tests to use.
99 public static void setUp() throws Exception {
101 // Load Single Decision Request
103 baseRequest = gson.decode(
105 .getTextFileAsString(
106 "src/test/resources/decision.optimization.input.json"),
107 DecisionRequest.class);
109 // Setup our temporary folder
111 XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
112 propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
113 properties, myCreator);
115 // Copy the test policy types into data area
117 for (String policy : listPolicyTypeFiles) {
118 String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
119 LOGGER.info("Copying {}", policyType);
120 Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
121 policyType.getBytes());
126 ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
127 ServiceLoader.load(XacmlApplicationServiceProvider.class);
129 // Iterate through Xacml application services and find
130 // the optimization service. Save it for use throughout
131 // all the Junit tests.
133 StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
134 Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
135 while (iterator.hasNext()) {
136 XacmlApplicationServiceProvider application = iterator.next();
138 // Is it our service?
140 if (application instanceof OptimizationPdpApplication) {
142 // Should be the first and only one
144 assertThat(service).isNull();
145 service = application;
147 strDump.append(application.applicationName());
148 strDump.append(" supports ");
149 strDump.append(application.supportedPolicyTypes());
150 strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
152 LOGGER.debug("{}", strDump);
153 assertThat(service).isNotNull();
155 // Tell it to initialize based on the properties file
156 // we just built for it.
158 service.initialize(propertiesFile.toPath().getParent(), null);
162 * Simply test some of the simple methods for the application.
165 public void test01Basics() {
167 // Make sure there's an application name
169 assertThat(service.applicationName()).isNotEmpty();
171 // Does it return the correct decisions
173 assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
174 assertThat(service.actionDecisionsSupported()).contains("optimize");
176 // Ensure it has the supported policy types and
177 // can support the correct policy types.
179 assertThat(service.canSupportPolicyType(new ToscaConceptIdentifier(
180 "onap.policies.optimization.resource.AffinityPolicy", "1.0.0"))).isTrue();
181 assertThat(service.canSupportPolicyType(new ToscaConceptIdentifier(
182 "onap.policies.optimization.service.SubscriberPolicy", "1.0.0"))).isTrue();
183 assertThat(service.canSupportPolicyType(new ToscaConceptIdentifier(
184 "onap.policies.optimization.service.CustomUseCase", "1.0.0"))).isTrue();
185 assertThat(service.canSupportPolicyType(new ToscaConceptIdentifier(
186 "onap.foobar", "1.0.0"))).isFalse();
190 * With no policies loaded, there should be 0 policies returned.
192 * @throws CoderException CoderException
195 public void test02NoPolicies() throws CoderException {
197 // Ask for a decision when there are no policies loaded
199 LOGGER.info("Request {}", gson.encode(baseRequest));
200 Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
201 LOGGER.info("Decision {}", decision.getKey());
203 assertThat(decision.getKey()).isNotNull();
204 assertThat(decision.getKey().getPolicies()).isEmpty();
206 // Optimization applications should not have this information returned. Except advice
207 // for subscriber details, which does get checked in the tests following.
209 assertThat(decision.getKey().getAdvice()).isNull();
210 assertThat(decision.getKey().getObligations()).isNull();
211 assertThat(decision.getKey().getAttributes()).isNull();
215 * Should return ONLY default policies.
217 * @throws XacmlApplicationException could not load policies
220 public void test03OptimizationDefault() throws XacmlApplicationException {
222 // Now load all the optimization policies
224 List<ToscaPolicy> loadedPolicies = TestUtils.loadPolicies("src/test/resources/test-optimization-policies.yaml",
226 assertThat(loadedPolicies).isNotNull().hasSize(14);
228 validateDecisionCount(2);
232 * Should only return default HPA policy type.
234 @SuppressWarnings("unchecked")
236 public void test04OptimizationDefaultHpa() {
238 // Add in policy type
240 List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.HpaPolicy");
241 baseRequest.getResource().put("policy-type", policyTypes);
243 // Ask for a decision for default HPA policy
245 DecisionResponse response = makeDecision();
247 assertThat(response).isNotNull();
248 assertThat(response.getPolicies()).hasSize(1);
249 response.getPolicies().forEach((key, value) -> {
250 assertThat(((Map<String, Object>) value)).containsEntry("type",
251 "onap.policies.optimization.resource.HpaPolicy");
256 validateDecision(response, baseRequest);
260 * Refine for US only policies.
262 @SuppressWarnings("unchecked")
264 public void test05OptimizationDefaultGeography() throws CoderException {
266 // Remove all the policy-type resources from the request
270 // Add US to the geography list
272 ((List<String>) baseRequest.getResource().get("geography")).add("US");
274 validateDecisionCount(2);
278 * Add more refinement for service.
280 @SuppressWarnings("unchecked")
282 public void test06OptimizationDefaultGeographyAndService() {
284 // Add vCPE to the service list
286 ((List<String>) baseRequest.getResource().get("services")).add("vCPE");
288 validateDecisionCount(3);
292 * Add more refinement for specific resource.
294 @SuppressWarnings("unchecked")
296 public void test07OptimizationDefaultGeographyAndServiceAndResource() {
298 // Add vG to the resource list
300 ((List<String>) baseRequest.getResource().get("resources")).add("vG");
302 validateDecisionCount(6);
306 * Now we need to add in subscriberName in order to get scope for gold.
308 @SuppressWarnings("unchecked")
310 public void test08OptimizationGeographyAndServiceAndResourceAndScopeIsGoldSubscriber() {
312 // Add gold as a scope
314 ((List<String>) baseRequest.getContext().get("subscriberName")).add("subscriber_a");
316 validateDecisionCount(6, 2);
320 * Add a subscriber that should be platinum.
322 @SuppressWarnings("unchecked")
324 public void test09OptimizationGeographyAndServiceAndResourceAndScopeGoldOrPlatinumSubscriber() {
326 // Add platinum to the scope list: this is now gold OR platinum
328 ((List<String>) baseRequest.getResource().get("scope")).remove("gold");
329 ((List<String>) baseRequest.getContext().get("subscriberName")).add("subscriber_x");
331 validateDecisionCount(8, 2);
335 * Remove gold subscriber, keep the platinum one.
337 @SuppressWarnings("unchecked")
339 public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGoldStillPlatinum() {
341 // Add gold as a scope
343 ((List<String>) baseRequest.getResource().get("scope")).remove("gold");
344 ((List<String>) baseRequest.getResource().get("scope")).remove("platinum");
345 ((List<String>) baseRequest.getContext().get("subscriberName")).remove("subscriber_a");
347 validateDecisionCount(7);
351 * Filter by Affinity policy.
354 public void test11OptimizationPolicyTypeDefault() {
356 // Add in policy type
358 List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.AffinityPolicy");
359 baseRequest.getResource().put("policy-type", policyTypes);
361 validateDecisionCount(1);
365 * Now filter by HPA policy type.
367 @SuppressWarnings("unchecked")
369 public void test12OptimizationPolicyTypeDefault() {
371 // Add in another policy type
373 ((List<String>) baseRequest.getResource().get("policy-type"))
374 .add("onap.policies.optimization.resource.HpaPolicy");
376 validateDecisionCount(2);
380 public void test999BadSubscriberPolicies() throws Exception {
381 final StandardYamlCoder yamlCoder = new StandardYamlCoder();
385 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/bad-subscriber-policies.yaml");
387 // Serialize it into a class
389 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
390 ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
391 jtst.fromAuthorative(serviceTemplate);
393 // Make sure all the fields are setup properly
395 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
399 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
400 for (ToscaPolicy policy : policies.values()) {
401 if ("missing-subscriberProperties".equals(policy.getName())) {
402 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
403 service.loadPolicy(policy));
404 } else if ("missing-subscriberName".equals(policy.getName())) {
405 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
406 service.loadPolicy(policy));
407 } else if ("missing-subscriberRole".equals(policy.getName())) {
408 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
409 service.loadPolicy(policy));
415 private DecisionResponse makeDecision() {
416 Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
417 LOGGER.info("Request Resources {}", baseRequest.getResource());
418 LOGGER.info("Decision {}", decision.getKey());
419 for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
420 LOGGER.info("Policy {}", entrySet.getKey());
422 return decision.getKey();
425 private DecisionResponse validateDecisionCount(int expectedPolicyCount) {
427 // Ask for a decision for default
429 DecisionResponse response = makeDecision();
431 assertThat(response).isNotNull();
432 assertThat(response.getPolicies()).hasSize(expectedPolicyCount);
434 // Optimization applications should not have this information returned
436 assertThat(response.getObligations()).isNull();
437 assertThat(response.getAttributes()).isNull();
441 validateDecision(response, baseRequest);
446 private void validateDecisionCount(int expectedPolicyCount, int expectedAdviceCount) {
447 DecisionResponse response = validateDecisionCount(expectedPolicyCount);
449 assertThat(response.getAdvice()).hasSize(expectedAdviceCount);
452 @SuppressWarnings("unchecked")
453 private void validateDecision(DecisionResponse decision, DecisionRequest request) {
454 for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
455 LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
456 assertThat(entrySet.getValue()).isInstanceOf(Map.class);
457 Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
458 assertThat(policyContents).containsKey("properties");
459 assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
460 Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
462 validateMatchable((Collection<String>) request.getResource().get("scope"),
463 (Collection<String>) policyProperties.get("scope"));
465 validateMatchable((Collection<String>) request.getResource().get("services"),
466 (Collection<String>) policyProperties.get("services"));
468 validateMatchable((Collection<String>) request.getResource().get("resources"),
469 (Collection<String>) policyProperties.get("resources"));
471 validateMatchable((Collection<String>) request.getResource().get("geography"),
472 (Collection<String>) policyProperties.get("geography"));
476 private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
477 LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
479 // Null or empty implies '*' - that is any value is acceptable
482 if (policyProperties == null || policyProperties.isEmpty()) {
485 Condition<String> condition = new Condition<>(
486 requestList::contains,
487 "Request list is contained");
488 assertThat(policyProperties).haveAtLeast(1, condition);
492 @SuppressWarnings("unchecked")
493 private void cleanOutResources() {
494 ((List<String>) baseRequest.getResource().get("scope")).clear();
495 ((List<String>) baseRequest.getResource().get("services")).clear();
496 ((List<String>) baseRequest.getResource().get("resources")).clear();
497 ((List<String>) baseRequest.getResource().get("geography")).clear();
498 if (((List<String>) baseRequest.getResource().get("policy-type")) != null) {
499 baseRequest.getResource().remove("policy-type");