Changes for Checkstyle 8.32
[policy/xacml-pdp.git] / applications / common / src / test / java / org / onap / policy / pdp / xacml / application / common / matchable / MatchablePolicyTypeTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 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.pdp.xacml.application.common.matchable;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNotNull;
29
30 import com.att.research.xacml.api.Identifier;
31 import com.att.research.xacml.api.XACML3;
32 import com.att.research.xacml.std.IdentifierImpl;
33 import com.att.research.xacml.util.XACMLPolicyWriter;
34 import java.io.ByteArrayOutputStream;
35 import java.io.IOException;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOfType;
41 import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
42 import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
43 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
44 import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
47 import org.onap.policy.common.utils.coder.CoderException;
48 import org.onap.policy.common.utils.coder.StandardYamlCoder;
49 import org.onap.policy.common.utils.resources.ResourceUtils;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaEntrySchema;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
54 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
56 import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
57 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
58 import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 public class MatchablePolicyTypeTest implements MatchableCallback {
63     private static final Logger LOGGER = LoggerFactory.getLogger(MatchablePolicyTypeTest.class);
64     private static final StandardYamlCoder yamlCoder = new StandardYamlCoder();
65     private static final String TEST_POLICYTYPE_FILE = "src/test/resources/matchable/onap.policies.Test-1.0.0.yaml";
66     private static final String TEST_POLICY_FILE = "src/test/resources/matchable/test.policies.input.tosca.yaml";
67     private static final String TEST_POLICYTYPE = "onap.policies.base.middle.Test";
68     private static ToscaServiceTemplate testTemplate;
69     private static ToscaPolicy testPolicy;
70
71     /**
72      * Loads our resources.
73      *
74      * @throws CoderException object
75      */
76     @BeforeClass
77     public static void setupLoadPolicy() throws CoderException {
78         //
79         // Load our test policy type
80         //
81         String policyType = ResourceUtils.getResourceAsString(TEST_POLICYTYPE_FILE);
82         //
83         // Serialize it into a class
84         //
85         ToscaServiceTemplate serviceTemplate = yamlCoder.decode(policyType, ToscaServiceTemplate.class);
86         //
87         // Make sure all the fields are setup properly
88         //
89         JpaToscaServiceTemplate jtst = new JpaToscaServiceTemplate();
90         jtst.fromAuthorative(serviceTemplate);
91         testTemplate = jtst.toAuthorative();
92         //
93         // Make sure the Policy Types are there
94         //
95         assertEquals(3, testTemplate.getPolicyTypes().size());
96         assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.Base"));
97         assertNotNull(testTemplate.getPolicyTypes().get("onap.policies.base.Middle"));
98         assertNotNull(testTemplate.getPolicyTypes().get(TEST_POLICYTYPE));
99         //
100         // Load our test policy
101         //
102         String policy = ResourceUtils.getResourceAsString(TEST_POLICY_FILE);
103         //
104         // Serialize it into a class
105         //
106         serviceTemplate = yamlCoder.decode(policy, ToscaServiceTemplate.class);
107         //
108         // Make sure all the fields are setup properly
109         //
110         jtst = new JpaToscaServiceTemplate();
111         jtst.fromAuthorative(serviceTemplate);
112         ToscaServiceTemplate policyTemplate = jtst.toAuthorative();
113         assertEquals(1, policyTemplate.getToscaTopologyTemplate().getPolicies().size());
114         testPolicy = policyTemplate.getToscaTopologyTemplate().getPolicies().get(0).get("Test.policy");
115         assertNotNull(testPolicy);
116     }
117
118     @Test
119     public void testAllCodeCoverage() {
120         assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
121             new MatchablePolicyType(null, null));
122
123         assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
124             new MatchablePropertyTypeMap(null));
125         assertThatExceptionOfType(NullPointerException.class).isThrownBy(() ->
126             MatchablePolicyType.isMatchable(null));
127         assertThat(MatchablePolicyType.isMatchable(new ToscaProperty())).isFalse();
128         //
129         // Unlikely these would be called - just get code coverage on them
130         //
131         ToscaEntrySchema schema = new ToscaEntrySchema();
132         schema.setType("integer");
133         assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
134         schema.setType("float");
135         assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
136         schema.setType("boolean");
137         assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
138         schema.setType("timestamp");
139         assertThat(MatchablePolicyType.handlePrimitive("foo", schema)).isNotNull();
140         schema.setType("footype");
141         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
142             MatchablePolicyType.handlePrimitive("foo", schema)
143         );
144         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
145             MatchablePolicyType.handlePrimitive("foo", schema)
146         );
147         ToscaProperty toscaProperty = new ToscaProperty();
148         Map<String, String> metadata = new HashMap<>();
149         metadata.put("matchable", "true");
150         toscaProperty.setMetadata(metadata);
151         toscaProperty.setType("garbage");
152         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
153             MatchablePolicyType.handlePrimitive("foo", toscaProperty)
154         );
155         Map<String, MatchableProperty> matchables = null;
156         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
157             MatchablePolicyType.handleList("foo", toscaProperty, matchables, this)
158         );
159         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
160             MatchablePolicyType.handleMap("foo", toscaProperty, matchables, this)
161         );
162     }
163
164     @Test
165     public void testPrimitiveValidation() throws Exception {
166         ToscaProperty property = new ToscaProperty();
167         MatchablePropertyTypeBoolean booleanValue = new MatchablePropertyTypeBoolean(property);
168         assertThat(booleanValue.validate(Boolean.TRUE)).isEqualTo(Boolean.TRUE);
169         assertThat(booleanValue.validate("no")).isEqualTo(Boolean.FALSE);
170         assertThat(booleanValue.validate("foo")).isEqualTo(Boolean.FALSE);
171
172         MatchablePropertyTypeInteger integerValue = new MatchablePropertyTypeInteger(property);
173         assertThat(integerValue.validate("5")).isEqualTo(5);
174         assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> integerValue.validate("foo"));
175
176         MatchablePropertyTypeFloat floatValue = new MatchablePropertyTypeFloat(property);
177         assertThat(floatValue.validate("5")).isEqualTo(5);
178         assertThat(floatValue.validate(Float.MIN_NORMAL)).isEqualTo(Float.MIN_NORMAL);
179         assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() -> floatValue.validate("foo"));
180
181         MatchablePropertyTypeTimestamp timestampValue = new MatchablePropertyTypeTimestamp(property);
182         assertThat(timestampValue.validate("2018-10-11T22:12:44").getHour()).isEqualTo(22);
183         assertThatExceptionOfType(ToscaPolicyConversionException.class).isThrownBy(() ->
184             timestampValue.validate("foo"));
185
186         ToscaEntrySchema schema = new ToscaEntrySchema();
187         schema.setType("string");
188         property.setEntrySchema(schema);
189         MatchablePropertyTypeMap mapValue = new MatchablePropertyTypeMap(property);
190         assertThat(mapValue.validate(new String("foo"))).hasSize(0);
191
192         MatchablePropertyTypeList listValue = new MatchablePropertyTypeList(property);
193         assertThat(listValue.validate(new String("foo"))).hasSize(0);
194     }
195
196     @Test
197     public void testMatchables() throws ToscaPolicyConversionException {
198         //
199         // Step 1: Create matchables from the PolicyType
200         //
201         MatchablePolicyType matchablePolicyType = new MatchablePolicyType(testTemplate.getPolicyTypes()
202                 .get(TEST_POLICYTYPE), this);
203         assertThat(matchablePolicyType).isNotNull();
204         assertThat(matchablePolicyType.getPolicyId()).isNotNull();
205         assertThat(matchablePolicyType.getPolicyId().getName()).isEqualTo(TEST_POLICYTYPE);
206         //
207         // Dump them out to see what we have
208         //
209         matchablePolicyType.getMatchables().forEach((matchable, property) -> {
210             LOGGER.info("matchable: {}: {}", matchable, property);
211         });
212         //
213         // Sanity check - these are the total possible match types available
214         //
215         assertThat(matchablePolicyType.getMatchables()).hasSize(19);
216         //
217         // Step 2) Go through example policy and generate data for our Target
218         //
219         final TargetType target = new TargetType();
220         target.getAnyOf().add(new AnyOfType());
221         generateTargetType(target, matchablePolicyType, testPolicy.getProperties());
222         //
223         // Stuff results in a simple Policy
224         //
225         final PolicyType policy = new PolicyType();
226         policy.setTarget(target);
227         policy.setPolicyId("foo");
228         policy.setVersion("1");
229         policy.setRuleCombiningAlgId(XACML3.DENY_UNLESS_PERMIT);
230         //
231         // Dump it out so we can see what was created
232         //
233         try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
234             XACMLPolicyWriter.writePolicyFile(os, policy);
235             LOGGER.info("{}", os);
236         } catch (IOException e) {
237             LOGGER.error("Failed to create byte array stream", e);
238         }
239         //
240         // Sanity check - the example policy should have each possible match type plus
241         // an extra one for the list and an extra one for the map.
242         //
243         assertThat(policy.getTarget().getAnyOf()).hasSize(20);
244     }
245
246     @Override
247     public ToscaPolicyType retrievePolicyType(String derivedFrom) {
248         for (Entry<String, ToscaPolicyType> entrySet : testTemplate.getPolicyTypes().entrySet()) {
249             if (entrySet.getValue().getName().equals(derivedFrom)) {
250                 return entrySet.getValue();
251             }
252         }
253         return null;
254     }
255
256     @Override
257     public ToscaDataType retrieveDataType(String datatype) {
258         return testTemplate.getDataTypes().get(datatype);
259     }
260
261     @SuppressWarnings("unchecked")
262     private void generateTargetType(TargetType target, MatchablePolicyType matchablePolicyType,
263             Map<String, Object> properties) throws ToscaPolicyConversionException {
264         for (Entry<String, Object> entrySet : properties.entrySet()) {
265             String propertyName = entrySet.getKey();
266             Object propertyValue = entrySet.getValue();
267             MatchableProperty matchable = matchablePolicyType.get(propertyName);
268             if (matchable != null) {
269                 Identifier id = new IdentifierImpl(ToscaDictionary.ID_RESOURCE_MATCHABLE + propertyName);
270                 Object object = matchable.getType().generate(propertyValue, id);
271                 //
272                 // Depending on what type it is, add it into the target
273                 //
274                 if (object instanceof AnyOfType) {
275                     target.getAnyOf().add((AnyOfType) object);
276                 } else if (object instanceof MatchType) {
277                     AllOfType allOf = new AllOfType();
278                     allOf.getMatch().add((MatchType) object);
279                     AnyOfType anyOf = new AnyOfType();
280                     anyOf.getAllOf().add(allOf);
281                     target.getAnyOf().add(anyOf);
282                 }
283             } else {
284                 //
285                 // Here is the special case where we look for a Collection of values that may
286                 // contain potential matchables
287                 //
288                 if (propertyValue instanceof List) {
289                     for (Object listValue : ((List<?>) propertyValue)) {
290                         if (listValue instanceof Map) {
291                             generateTargetType(target, matchablePolicyType, (Map<String, Object>) listValue);
292                         }
293                     }
294                 } else if (propertyValue instanceof Map) {
295                     generateTargetType(target, matchablePolicyType, (Map<String, Object>) propertyValue);
296                 }
297             }
298         }
299     }
300 }