Optimization improvements and test cases
[policy/xacml-pdp.git] / applications / optimization / src / test / java / org / onap / policy / xacml / pdp / application / optimization / OptimizationPdpApplicationTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.xacml.pdp.application.optimization;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.when;
28
29 import com.att.research.xacml.api.Response;
30 import java.io.File;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.Collection;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.Properties;
41 import java.util.ServiceLoader;
42 import jersey.repackaged.com.google.common.collect.Lists;
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.resources.ResourceUtils;
55 import org.onap.policy.common.utils.resources.TextFileUtils;
56 import org.onap.policy.models.decisions.concepts.DecisionRequest;
57 import org.onap.policy.models.decisions.concepts.DecisionResponse;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
59 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
60 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
61 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
62 import org.onap.policy.pdp.xacml.xacmltest.TestUtils;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
67 public class OptimizationPdpApplicationTest {
68
69     private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTest.class);
70     private static Properties properties = new Properties();
71     private static File propertiesFile;
72     private static XacmlApplicationServiceProvider service;
73     private static StandardCoder gson = new StandardCoder();
74     private static DecisionRequest baseRequest;
75     private static RestServerParameters clientParams;
76     private static String[] listPolicyTypeFiles = {
77         "onap.policies.Optimization",
78         "onap.policies.optimization.AffinityPolicy",
79         "onap.policies.optimization.DistancePolicy",
80         "onap.policies.optimization.HpaPolicy",
81         "onap.policies.optimization.OptimizationPolicy",
82         "onap.policies.optimization.PciPolicy",
83         "onap.policies.optimization.QueryPolicy",
84         "onap.policies.optimization.SubscriberPolicy",
85         "onap.policies.optimization.Vim_fit",
86         "onap.policies.optimization.VnfPolicy"};
87
88     @ClassRule
89     public static final TemporaryFolder policyFolder = new TemporaryFolder();
90
91     /**
92      * Copies the xacml.properties and policies files into
93      * temporary folder and loads the service provider saving
94      * instance of provider off for other tests to use.
95      */
96     @BeforeClass
97     public static void setUp() throws Exception {
98         clientParams = mock(RestServerParameters.class);
99         when(clientParams.getHost()).thenReturn("localhost");
100         when(clientParams.getPort()).thenReturn(6969);
101         //
102         // Load Single Decision Request
103         //
104         baseRequest = gson.decode(
105                 TextFileUtils
106                     .getTextFileAsString(
107                             "src/test/resources/decision.optimization.input.json"),
108                     DecisionRequest.class);
109         //
110         // Setup our temporary folder
111         //
112         XacmlPolicyUtils.FileCreator myCreator = (String filename) -> policyFolder.newFile(filename);
113         propertiesFile = XacmlPolicyUtils.copyXacmlPropertiesContents("src/test/resources/xacml.properties",
114                 properties, myCreator);
115         //
116         // Copy the test policy types into data area
117         //
118         for (String policy : listPolicyTypeFiles) {
119             String policyType = ResourceUtils.getResourceAsString("policytypes/" + policy + ".yaml");
120             LOGGER.info("Copying {}", policyType);
121             Files.write(Paths.get(policyFolder.getRoot().getAbsolutePath(), policy + "-1.0.0.yaml"),
122                     policyType.getBytes());
123         }
124         //
125         // Load service
126         //
127         ServiceLoader<XacmlApplicationServiceProvider> applicationLoader =
128                 ServiceLoader.load(XacmlApplicationServiceProvider.class);
129         //
130         // Iterate through Xacml application services and find
131         // the optimization service. Save it for use throughout
132         // all the Junit tests.
133         //
134         StringBuilder strDump = new StringBuilder("Loaded applications:" + XacmlPolicyUtils.LINE_SEPARATOR);
135         Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
136         while (iterator.hasNext()) {
137             XacmlApplicationServiceProvider application = iterator.next();
138             //
139             // Is it our service?
140             //
141             if (application instanceof OptimizationPdpApplication) {
142                 //
143                 // Should be the first and only one
144                 //
145                 assertThat(service).isNull();
146                 service = application;
147             }
148             strDump.append(application.applicationName());
149             strDump.append(" supports ");
150             strDump.append(application.supportedPolicyTypes());
151             strDump.append(XacmlPolicyUtils.LINE_SEPARATOR);
152         }
153         LOGGER.debug("{}", strDump);
154         assertThat(service).isNotNull();
155         //
156         // Tell it to initialize based on the properties file
157         // we just built for it.
158         //
159         service.initialize(propertiesFile.toPath().getParent(), clientParams);
160     }
161
162     @Test
163     public void test01Basics() {
164         //
165         // Make sure there's an application name
166         //
167         assertThat(service.applicationName()).isNotEmpty();
168         //
169         // Decisions
170         //
171         assertThat(service.actionDecisionsSupported().size()).isEqualTo(1);
172         assertThat(service.actionDecisionsSupported()).contains("optimize");
173         //
174         // Ensure it has the supported policy types and
175         // can support the correct policy types.
176         //
177         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
178                 "onap.policies.optimization.AffinityPolicy", "1.0.0"))).isTrue();
179         assertThat(service.canSupportPolicyType(new ToscaPolicyTypeIdentifier(
180                 "onap.foobar", "1.0.0"))).isFalse();
181     }
182
183     @Test
184     public void test02NoPolicies() {
185         //
186         // Ask for a decision when there are no policies loaded
187         //
188         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
189         LOGGER.info("Decision {}", decision.getKey());
190
191         assertThat(decision.getKey()).isNotNull();
192         assertThat(decision.getKey().getPolicies().size()).isEqualTo(0);
193     }
194
195     @Test
196     public void test03OptimizationDefault() throws CoderException, FileNotFoundException, IOException,
197         XacmlApplicationException {
198         //
199         // Now load all the optimization policies
200         //
201         TestUtils.loadPolicies("src/test/resources/vCPE.policies.optimization.input.tosca.yaml", service);
202         //
203         // Ask for a decision for default
204         //
205         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
206         LOGGER.info("Decision {}", decision.getKey());
207
208         assertThat(decision.getKey()).isNotNull();
209         assertThat(decision.getKey().getPolicies().size()).isEqualTo(1);
210         //
211         // Double check that the contents are what we expect
212         //
213         LOGGER.info(gson.encode(decision.getKey()));
214         //
215         // Validate it
216         //
217         validateDecision(decision.getKey(), baseRequest);
218     }
219
220     @SuppressWarnings("unchecked")
221     @Test
222     public void test04OptimizationDefaultGeography() throws CoderException {
223         //
224         // Add US to the geography list
225         //
226         ((List<String>)baseRequest.getResource().get("geography")).add("US");
227         //
228         // Ask for a decision for default US Policy
229         //
230         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
231         LOGGER.info("Decision {}", decision.getKey());
232
233         assertThat(decision.getKey()).isNotNull();
234         assertThat(decision.getKey().getPolicies().size()).isEqualTo(2);
235         //
236         // Double check that the contents are what we expect
237         //
238         LOGGER.info(gson.encode(decision.getKey()));
239         //
240         // Validate it
241         //
242         validateDecision(decision.getKey(), baseRequest);
243     }
244
245     @SuppressWarnings("unchecked")
246     @Test
247     public void test05OptimizationDefaultGeographyAndService() throws CoderException {
248         //
249         // Add vCPE to the service list
250         //
251         ((List<String>)baseRequest.getResource().get("services")).add("vCPE");
252         //
253         // Ask for a decision for default US policy for vCPE service
254         //
255         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
256         LOGGER.info("Decision {}", decision.getKey());
257
258         assertThat(decision.getKey()).isNotNull();
259         assertThat(decision.getKey().getPolicies().size()).isEqualTo(5);
260         //
261         // Double check that the contents are what we expect
262         //
263         LOGGER.info(gson.encode(decision.getKey()));
264         //
265         // Validate it
266         //
267         validateDecision(decision.getKey(), baseRequest);
268     }
269
270     @SuppressWarnings("unchecked")
271     @Test
272     public void test06OptimizationDefaultGeographyAndServiceAndResource() throws CoderException {
273         //
274         // Add vCPE to the service list
275         //
276         ((List<String>)baseRequest.getResource().get("resources")).add("vG");
277         //
278         // Ask for a decision for default US service vCPE resource vG policy
279         //
280         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
281         LOGGER.info("Decision {}", decision.getKey());
282
283         assertThat(decision.getKey()).isNotNull();
284         assertThat(decision.getKey().getPolicies().size()).isEqualTo(9);
285         //
286         // Double check that the contents are what we expect
287         //
288         LOGGER.info(gson.encode(decision.getKey()));
289         //
290         // Validate it
291         //
292         validateDecision(decision.getKey(), baseRequest);
293     }
294
295     @SuppressWarnings("unchecked")
296     @Test
297     public void test07OptimizationGeographyAndServiceAndResourceAndScope() throws CoderException {
298         //
299         // Add gold as a scope
300         //
301         ((List<String>)baseRequest.getResource().get("scope")).add("gold");
302         //
303         // Ask for a decision for specific US vCPE vG gold
304         //
305         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
306         LOGGER.info("Decision {}", decision.getKey());
307
308         assertThat(decision.getKey()).isNotNull();
309         assertThat(decision.getKey().getPolicies().size()).isEqualTo(10);
310         //
311         // Double check that the contents are what we expect
312         //
313         LOGGER.info(gson.encode(decision.getKey()));
314         //
315         // Validate it
316         //
317         validateDecision(decision.getKey(), baseRequest);
318     }
319
320     @SuppressWarnings("unchecked")
321     @Test
322     public void test08OptimizationGeographyAndServiceAndResourceAndScopeIsGoldOrPlatinum() throws CoderException {
323         //
324         // Add platinum to the scope list: this is now gold OR platinum
325         //
326         ((List<String>)baseRequest.getResource().get("scope")).add("platinum");
327         //
328         // Ask for a decision for specific US vCPE vG (gold or platinum)
329         //
330         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
331         LOGGER.info("Decision {}", decision.getKey());
332
333         assertThat(decision.getKey()).isNotNull();
334         assertThat(decision.getKey().getPolicies().size()).isEqualTo(11);
335         //
336         // Double check that the contents are what we expect
337         //
338         LOGGER.info(gson.encode(decision.getKey()));
339         //
340         // Validate it
341         //
342         validateDecision(decision.getKey(), baseRequest);
343     }
344
345     @SuppressWarnings("unchecked")
346     @Test
347     public void test09OptimizationGeographyAndServiceAndResourceAndScopeNotGold() throws CoderException {
348         //
349         // Add gold as a scope
350         //
351         ((List<String>)baseRequest.getResource().get("scope")).remove("gold");
352         //
353         // Ask for a decision for specific US vCPE vG gold
354         //
355         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
356         LOGGER.info("Decision {}", decision.getKey());
357
358         assertThat(decision.getKey()).isNotNull();
359         assertThat(decision.getKey().getPolicies().size()).isEqualTo(11);
360         //
361         // Double check that the contents are what we expect
362         //
363         LOGGER.info(gson.encode(decision.getKey()));
364         //
365         // Validate it
366         //
367         validateDecision(decision.getKey(), baseRequest);
368     }
369
370     @Test
371     public void test10OptimizationPolicyTypeDefault() throws CoderException {
372         //
373         // Remove all the other resources from the request
374         //
375         cleanOutResources();
376         //
377         // Add in policy type
378         //
379         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.AffinityPolicy");
380         baseRequest.getResource().put("policy-type", policyTypes);
381         //
382         // Ask for a decision for default
383         //
384         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
385         LOGGER.info("Decision {}", decision.getKey());
386
387         assertThat(decision.getKey()).isNotNull();
388         assertThat(decision.getKey().getPolicies().size()).isEqualTo(4);
389         //
390         // Double check that the contents are what we expect
391         //
392         LOGGER.info(gson.encode(decision.getKey()));
393     }
394
395     @Test
396     public void test20OptimizationPolicyTypeDefault() throws CoderException {
397         //
398         // Remove all the other resources from the request
399         //
400         cleanOutResources();
401         //
402         // Add in policy type
403         //
404         List<String> policyTypes = Lists.newArrayList("onap.policies.optimization.HpaPolicy");
405         baseRequest.getResource().put("policy-type", policyTypes);
406         //
407         // Ask for a decision for default
408         //
409         Pair<DecisionResponse, Response> decision = service.makeDecision(baseRequest, null);
410         LOGGER.info("Decision {}", decision.getKey());
411
412         assertThat(decision.getKey()).isNotNull();
413         assertThat(decision.getKey().getPolicies().size()).isEqualTo(1);
414         //
415         // Double check that the contents are what we expect
416         //
417         LOGGER.info(gson.encode(decision.getKey()));
418     }
419
420     @SuppressWarnings("unchecked")
421     private void validateDecision(DecisionResponse decision, DecisionRequest request) {
422         for (Entry<String, Object> entrySet : decision.getPolicies().entrySet()) {
423             LOGGER.info("Decision Returned Policy {}", entrySet.getKey());
424             assertThat(entrySet.getValue()).isInstanceOf(Map.class);
425             Map<String, Object> policyContents = (Map<String, Object>) entrySet.getValue();
426             assertThat(policyContents.containsKey("properties")).isTrue();
427             assertThat(policyContents.get("properties")).isInstanceOf(Map.class);
428             Map<String, Object> policyProperties = (Map<String, Object>) policyContents.get("properties");
429
430             validateMatchable((Collection<String>) request.getResource().get("scope"),
431                     (Collection<String>) policyProperties.get("scope"));
432
433             validateMatchable((Collection<String>) request.getResource().get("services"),
434                     (Collection<String>) policyProperties.get("services"));
435
436             validateMatchable((Collection<String>) request.getResource().get("resources"),
437                     (Collection<String>) policyProperties.get("resources"));
438
439             validateMatchable((Collection<String>) request.getResource().get("geography"),
440                     (Collection<String>) policyProperties.get("geography"));
441         }
442     }
443
444     private void validateMatchable(Collection<String> requestList, Collection<String> policyProperties) {
445         LOGGER.info("Validating matchable: {} with {}", policyProperties, requestList);
446         //
447         // Null or empty implies '*' - that is any value is acceptable
448         // for this policy.
449         //
450         if (policyProperties == null || policyProperties.isEmpty()) {
451             return;
452         }
453         Condition<String> condition = new Condition<>(
454                 requestList::contains,
455                 "Request list is contained");
456         assertThat(policyProperties).haveAtLeast(1, condition);
457
458     }
459
460     @SuppressWarnings("unchecked")
461     private void cleanOutResources() {
462         ((List<String>)baseRequest.getResource().get("scope")).clear();
463         ((List<String>)baseRequest.getResource().get("services")).clear();
464         ((List<String>)baseRequest.getResource().get("resources")).clear();
465         ((List<String>)baseRequest.getResource().get("geography")).clear();
466     }
467 }