2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
6 Modifications Copyright (C) 2019 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;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.when;
31 import com.att.research.xacml.api.Response;
32 import com.google.common.collect.Lists;
34 import java.nio.file.Files;
35 import java.nio.file.Paths;
36 import java.util.Collection;
37 import java.util.Iterator;
38 import java.util.List;
40 import java.util.Map.Entry;
41 import java.util.Properties;
42 import java.util.ServiceLoader;
43 import org.apache.commons.lang3.tuple.Pair;
44 import org.assertj.core.api.Condition;
45 import org.junit.BeforeClass;
46 import org.junit.ClassRule;
47 import org.junit.FixMethodOrder;
48 import org.junit.Test;
49 import org.junit.rules.TemporaryFolder;
50 import org.junit.runners.MethodSorters;
51 import org.onap.policy.common.endpoints.parameters.RestServerParameters;
52 import org.onap.policy.common.utils.coder.CoderException;
53 import org.onap.policy.common.utils.coder.StandardCoder;
54 import org.onap.policy.common.utils.coder.StandardYamlCoder;
55 import org.onap.policy.common.utils.resources.ResourceUtils;
56 import org.onap.policy.common.utils.resources.TextFileUtils;
57 import org.onap.policy.models.decisions.concepts.DecisionRequest;
58 import org.onap.policy.models.decisions.concepts.DecisionResponse;
59 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
60 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
61 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
62 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
63 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
64 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
65 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
66 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
71 public class OptimizationPdpApplicationTest {
73 private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
74 private static Properties properties = new Properties();
75 private static File propertiesFile;
76 private static XacmlApplicationServiceProvider service;
77 private static StandardCoder gson = new StandardCoder();
78 private static DecisionRequest baseRequest;
79 private static RestServerParameters clientParams;
80 private static String[] listPolicyTypeFiles = {
81 "onap.policies.Optimization",
82 "onap.policies.optimization.Resource",
83 "onap.policies.optimization.Service",
84 "onap.policies.optimization.resource.AffinityPolicy",
85 "onap.policies.optimization.resource.DistancePolicy",
86 "onap.policies.optimization.resource.HpaPolicy",
87 "onap.policies.optimization.resource.OptimizationPolicy",
88 "onap.policies.optimization.resource.PciPolicy",
89 "onap.policies.optimization.service.QueryPolicy",
90 "onap.policies.optimization.service.SubscriberPolicy",
91 "onap.policies.optimization.resource.Vim_fit",
92 "onap.policies.optimization.resource.VnfPolicy"};
95 public static final TemporaryFolder policyFolder = new TemporaryFolder();
98 * Copies the xacml.properties and policies files into
99 * temporary folder and loads the service provider saving
100 * instance of provider off for other tests to use.
103 public static void setUp() throws Exception {
104 clientParams = mock(RestServerParameters.class);
105 when(clientParams.getHost()).thenReturn("localhost");
106 when(clientParams.getPort()).thenReturn(6969);
108 // Load Single Decision Request
110 baseRequest = gson.decode(
112 .getTextFileAsString(
113 "src/test/resources/decision.optimization.input.json"),
114 DecisionRequest.class);
116 // Setup our temporary folder
118 XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
119 propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
120 properties, myCreator);
122 // Copy the test policy types into data area
124 for (String policy : listPolicyTypeFiles) {
125 String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
126 LOGGER.info("Copying {}", policyType);
127 Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
128 policyType.getBytes());
133 ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
134 ServiceLoader.load(XacmlApplicationServiceProvider.class);
136 // Iterate through Xacml application services and find
137 // the optimization service. Save it for use throughout
138 // all the Junit tests.
140 StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
141 Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
142 while (iterator.hasNext()) {
143 XacmlApplicationServiceProvider application = iterator.next();
145 // Is it our service?
147 if (application instanceof OptimizationPdpApplication) {
149 // Should be the first and only one
151 assertThat(service).isNull();
152 service = application;
154 strDump.append(application.applicationName());
155 strDump.append(" supports ");
156 strDump.append(application.supportedPolicyTypes());
157 strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
159 LOGGER.debug("{}", strDump);
160 assertThat(service).isNotNull();
162 // Tell it to initialize based on the properties file
163 // we just built for it.
165 service.initialize(propertiesFile.toPath().getParent(), clientParams);
169 * Simply test some of the simple methods for the application.
172 public void test01Basics() {
174 // Make sure there's an application name
176 assertThat(service.applicationName()).isNotEmpty();
178 // Does it return the correct decisions
180 assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
181 assertThat(service.actionDecisionsSupported()).contains("optimize");
183 // Ensure it has the supported policy types and
184 // can support the correct policy types.
186 assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
187 "onap.policies.optimization.resource.AffinityPolicy", "1.0.0"))).isTrue();
188 assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
189 "onap.policies.optimization.service.SubscriberPolicy", "1.0.0"))).isTrue();
190 assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
191 "onap.policies.optimization.service.CustomUseCase", "1.0.0"))).isTrue();
192 assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
193 "onap.foobar", "1.0.0"))).isFalse();
197 * With no policies loaded, there should be 0 policies returned.
199 * @throws CoderException CoderException
202 public void test02NoPolicies() throws CoderException {
204 // Ask for a decision when there are no policies loaded
206 LOGGER.info("Request {}", gson.encode(baseRequest));
207 Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
208 LOGGER.info("Decision {}", decision.getKey());
210 assertThat(decision.getKey()).isNotNull();
211 assertThat(decision.getKey().getPolicies().size()).isEqualTo(0);
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();
227 assertThat(loadedPolicies).hasSize(14);
229 // Ask for a decision for available default policies
231 DecisionResponse response = makeDecision();
233 assertThat(response).isNotNull();
234 assertThat(response.getPolicies().size()).isEqualTo(2);
238 validateDecision(response, baseRequest);
242 * Should only return default HPA policy type.
244 @SuppressWarnings("unchecked")
246 public void test04OptimizationDefaultHpa() {
248 // Add in policy type
250 List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.HpaPolicy");
251 baseRequest.getResource().put("policy-type", policyTypes);
253 // Ask for a decision for default HPA policy
255 DecisionResponse response = makeDecision();
257 assertThat(response).isNotNull();
258 assertThat(response.getPolicies().size()).isEqualTo(1);
259 response.getPolicies().forEach((key, value) -> {
260 assertThat(((Map<String, Object>) value).get("type"))
261 .isEqualTo(("onap.policies.optimization.resource.HpaPolicy"));
266 validateDecision(response, baseRequest);
270 * Refine for US only policies.
272 @SuppressWarnings("unchecked")
274 public void test05OptimizationDefaultGeography() throws CoderException {
276 // Remove all the policy-type resources from the request
280 // Add US to the geography list
282 ((List<String>)baseRequest.getResource().get("geography")).add("US");
284 // Ask for a decision for default US Policy
286 DecisionResponse response = makeDecision();
287 assertThat(response).isNotNull();
288 assertThat(response.getPolicies().size()).isEqualTo(2);
292 validateDecision(response, baseRequest);
296 * Add more refinement for service.
298 @SuppressWarnings("unchecked")
300 public void test06OptimizationDefaultGeographyAndService() {
302 // Add vCPE to the service list
304 ((List<String>)baseRequest.getResource().get("services")).add("vCPE");
306 // Ask for a decision for default US policy for vCPE service
308 DecisionResponse response = makeDecision();
310 assertThat(response).isNotNull();
311 assertThat(response.getPolicies().size()).isEqualTo(3);
315 validateDecision(response, baseRequest);
319 * Add more refinement for specific resource.
321 @SuppressWarnings("unchecked")
323 public void test07OptimizationDefaultGeographyAndServiceAndResource() {
325 // Add vG to the resource list
327 ((List<String>)baseRequest.getResource().get("resources")).add("vG");
329 // Ask for a decision for default US service vCPE resource vG policy
331 DecisionResponse response = makeDecision();
333 assertThat(response).isNotNull();
334 assertThat(response.getPolicies().size()).isEqualTo(6);
338 validateDecision(response, baseRequest);
342 * Now we need to add in subscriberName in order to get scope for gold.
344 @SuppressWarnings("unchecked")
346 public void test08OptimizationGeographyAndServiceAndResourceAndScopeIsGoldSubscriber() {
348 // Add gold as a scope
350 ((List<String>)baseRequest.getContext().get("subscriberName")).add("subscriber_a");
352 // Ask for a decision for specific US vCPE vG gold
354 DecisionResponse response = makeDecision();
356 assertThat(response).isNotNull();
357 assertThat(response.getPolicies()).hasSize(6);
358 assertThat(response.getAdvice()).hasSize(2);
362 validateDecision(response, baseRequest);
366 * Add a subscriber that should be platinum.
368 @SuppressWarnings("unchecked")
370 public void test09OptimizationGeographyAndServiceAndResourceAndScopeGoldOrPlatinumSubscriber() {
372 // Add platinum to the scope list: this is now gold OR platinum
374 ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
375 ((List<String>)baseRequest.getContext().get("subscriberName")).add("subscriber_x");
377 // Ask for a decision for specific US vCPE vG (gold or platinum)
379 DecisionResponse response = makeDecision();
381 assertThat(response).isNotNull();
382 assertThat(response.getPolicies()).hasSize(8);
383 assertThat(response.getAdvice()).hasSize(2);
387 validateDecision(response, baseRequest);
391 * Remove gold subscriber, keep the platinum one.
393 @SuppressWarnings("unchecked")
395 public void test10OptimizationGeographyAndServiceAndResourceAndScopeNotGoldStillPlatinum() {
397 // Add gold as a scope
399 ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
400 ((List<String>)baseRequest.getResource().get("scope")).remove("platinum");
401 ((List<String>)baseRequest.getContext().get("subscriberName")).remove("subscriber_a");
403 // Ask for a decision for specific US vCPE vG gold
405 DecisionResponse response = makeDecision();
407 assertThat(response).isNotNull();
408 assertThat(response.getPolicies().size()).isEqualTo(7);
412 validateDecision(response, baseRequest);
416 * Filter by Affinity policy.
419 public void test11OptimizationPolicyTypeDefault() {
421 // Add in policy type
423 List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.resource.AffinityPolicy");
424 baseRequest.getResource().put("policy-type", policyTypes);
426 // Ask for a decision for default
428 DecisionResponse response = makeDecision();
430 assertThat(response).isNotNull();
431 assertThat(response.getPolicies().size()).isEqualTo(1);
435 validateDecision(response, baseRequest);
439 * Now filter by HPA policy type.
441 @SuppressWarnings("unchecked")
443 public void test12OptimizationPolicyTypeDefault() {
445 // Add in another policy type
447 ((List<String>) baseRequest.getResource().get("policy-type"))
448 .add("onap.policies.optimization.resource.HpaPolicy");
450 // Ask for a decision for default
452 DecisionResponse response = makeDecision();
454 assertThat(response).isNotNull();
455 assertThat(response.getPolicies().size()).isEqualTo(2);
459 validateDecision(response, baseRequest);
463 public void test999BadSubscriberPolicies() throws Exception {
464 final StandardYamlCoder yamlCoder = new StandardYamlCoder();
468 String policyYaml = ResourceUtils.getResourceAsString("src/test/resources/bad-subscriber-policies.yaml");
470 // Serialize it into a class
472 ToscaServiceTemplate serviceTemplate;
474 serviceTemplate = yamlCoder.decode(policyYaml, ToscaServiceTemplate.class);
475 } catch (CoderException e) {
476 throw new XacmlApplicationException("Failed to decode policy from resource file", e);
479 // Make sure all the fields are setup properly
481 JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
482 jtst.fromAuthorative(serviceTemplate);
483 ToscaServiceTemplate completedJtst = jtst.toAuthorative();
487 for (Map<String, ToscaPolicy> policies : completedJtst.getToscaTopologyTemplate().getPolicies()) {
488 for (ToscaPolicy policy : policies.values()) {
489 if ("missing-subscriberProperties".equals(policy.getName())) {
490 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
491 service.loadPolicy(policy));
492 } else if ("missing-subscriberName".equals(policy.getName())) {
493 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
494 service.loadPolicy(policy));
495 } else if ("missing-subscriberRole".equals(policy.getName())) {
496 assertThatExceptionOfType(XacmlApplicationException.class).isThrownBy(() ->
497 service.loadPolicy(policy));
503 private DecisionResponse makeDecision() {
504 Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
505 LOGGER.info("Request Resources {}", baseRequest.getResource());
506 LOGGER.info("Decision {}", decision.getKey());
507 for (Entry<String, Object> entrySet : decision.getKey().getPolicies().entrySet()) {
508 LOGGER.info("Policy {}", entrySet.getKey());
510 return decision.getKey();
513 @SuppressWarnings("unchecked")
514 private void validateDecision(DecisionResponse decision, DecisionRequest request) {
515 for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
516 LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
517 assertThat(entrySet.getValue()).isInstanceOf(Map.class);
518 Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
519 assertThat(policyContents.containsKey("properties")).isTrue();
520 assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
521 Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
523 validateMatchable((Collection<String>) request.getResource().get("scope"),
524 (Collection<String>) policyProperties.get("scope"));
526 validateMatchable((Collection<String>) request.getResource().get("services"),
527 (Collection<String>) policyProperties.get("services"));
529 validateMatchable((Collection<String>) request.getResource().get("resources"),
530 (Collection<String>) policyProperties.get("resources"));
532 validateMatchable((Collection<String>) request.getResource().get("geography"),
533 (Collection<String>) policyProperties.get("geography"));
537 private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
538 LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
540 // Null or empty implies '*' - that is any value is acceptable
543 if (policyProperties == null || policyProperties.isEmpty()) {
546 Condition<String> condition = new Condition<>(
547 requestList::contains,
548 "Request list is contained");
549 assertThat(policyProperties).haveAtLeast(1, condition);
553 @SuppressWarnings("unchecked")
554 private void cleanOutResources() {
555 ((List<String>)baseRequest.getResource().get("scope")).clear();
556 ((List<String>)baseRequest.getResource().get("services")).clear();
557 ((List<String>)baseRequest.getResource().get("resources")).clear();
558 ((List<String>)baseRequest.getResource().get("geography")).clear();
559 if (((List<String>)baseRequest.getResource().get("policy-type")) != null) {
560 baseRequest.getResource().remove("policy-type");