diff options
author | Guo Ruijing <ruijing.guo@intel.com> | 2017-07-31 08:47:35 +0000 |
---|---|---|
committer | Pamela Dragosh <pdragosh@research.att.com> | 2017-07-31 15:51:10 -0400 |
commit | 073cc188efe9abb4c010cf674e34e2cf46ef1c52 (patch) | |
tree | 155c23fbdf3a838ecb5f4183fc3bb6b09aac41eb /ONAP-PDP/src | |
parent | 4ca818fdfb9b807562166800a086b413593d6894 (diff) |
[POLICY-73] replace openecomp for policy-engine
Change-Id: I54072f6bcd388c0e05562614ee89b4ae7ad67004
Signed-off-by: Guo Ruijing <ruijing.guo@intel.com>
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'ONAP-PDP/src')
55 files changed, 23398 insertions, 0 deletions
diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/FindAction.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/FindAction.java new file mode 100644 index 000000000..c6a889821 --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/FindAction.java @@ -0,0 +1,356 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.action; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.json.Json; +import javax.json.JsonReader; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.rest.XACMLRestProperties; + +import com.att.research.xacml.api.Advice; +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.RequestAttributes; +import com.att.research.xacml.api.Result; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdAdvice; +import com.att.research.xacml.std.StdAttributeAssignment; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdMutableResponse; +import com.att.research.xacml.std.StdMutableResult; +import com.att.research.xacml.std.StdObligation; +import com.att.research.xacml.util.XACMLProperties; + +@SuppressWarnings("deprecation") +public class FindAction { + private Logger LOGGER = FlexLogger.getLogger(this.getClass()); + private Boolean changeIt = false; + private String configURL = null; + private StdMutableResponse newResponse = new StdMutableResponse(); + private StdMutableResult addResult = new StdMutableResult(); + + public StdMutableResponse run(StdMutableResponse stdResponse, Request pepRequest) { + int count = 0; + boolean config = false; + boolean decide = false; + Collection<RequestAttributes> requestAttributes = pepRequest.getRequestAttributes(); + for(RequestAttributes requestAttribute : requestAttributes){ + Collection<Attribute> attributes = requestAttribute.getAttributes(); + for(Attribute attribute : attributes){ + if(attribute.getAttributeId().stringValue().equals("urn:oasis:names:tc:xacml:1.0:action:action-id")){ + for(AttributeValue<?> attributeValue : attribute.getValues()){ + if(attributeValue.getValue().toString().equalsIgnoreCase("ACCESS")){ + count++; + } + if(attributeValue.getValue().toString().equalsIgnoreCase("DECIDE")){ + decide = true; + } + } + } + if(attribute.getAttributeId().stringValue().equals("urn:oasis:names:tc:xacml:1.0:resource:resource-id")){ + for(AttributeValue<?> attributeValue : attribute.getValues()){ + if(attributeValue.getValue().toString().equalsIgnoreCase("Config")){ + count++; + } + } + } + } + } + if(count==2){ + config = true; + } + if(!config){ + search(stdResponse); + } + addResults(stdResponse, config , decide); + LOGGER.info("Original Result is " + stdResponse.toString()); + LOGGER.info("Generated Result is " + addResult.toString()); + return newResponse; + } + + private Collection<Obligation> obligations = new ArrayList<>(); + private Map<String, String> matchValues = new HashMap<>(); + private Map<String, String> headers = new HashMap<>(); + private boolean header = false; + + private void search(StdMutableResponse stdResponse) { + for (Result result : stdResponse.getResults()) { + if (!result.getObligations().isEmpty()) { + System.out.println("Obligation Received"); + // Is there any action that PDP needs to take + for (Obligation obligation : result.getObligations()) { + int count = 0, uri = 0, PEP = 0; + header = false; + changeIt = false; + Collection<AttributeAssignment> afterRemoveAssignments = new ArrayList<>(); + Identifier oblId = new IdentifierImpl(obligation.getId().stringValue()); + StdAttributeAssignment attributeURI = null; + for (AttributeAssignment attribute : obligation.getAttributeAssignments()) { + matchValues.put(attribute.getAttributeId().stringValue(), attribute.getAttributeValue().getValue().toString()); + if (attribute.getAttributeId().stringValue().equalsIgnoreCase("performer")) { + if (attribute.getAttributeValue().getValue().toString().equalsIgnoreCase("PEPACTION")) { + PEP++; + } else if (attribute.getAttributeValue().getValue().toString().equalsIgnoreCase("PDPACTION")) { + count++; + } + } else if (attribute.getAttributeId().stringValue().equalsIgnoreCase("URL")) { + uri++; + if (uri == 1) { + configURL = attribute.getAttributeValue().getValue().toString(); + attributeURI = new StdAttributeAssignment(attribute); + } + } else if (attribute.getAttributeId().stringValue().startsWith("headers")) { + LOGGER.info("Headers are : "+ attribute.getAttributeValue().getValue().toString()); + header = true; + headers.put(attribute.getAttributeId().stringValue().replaceFirst("(headers).", ""), + attribute.getAttributeValue().getValue().toString()); + afterRemoveAssignments.add(attribute); + } else if (attribute.getAttributeId().stringValue().equalsIgnoreCase("body")) { + String papPath = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL); + papPath= papPath.replace("/pap", ""); + matchValues.put("body",attribute.getAttributeValue().getValue().toString().replace("$URL", papPath)); + }else { + StdAttributeAssignment attributeObligation = new StdAttributeAssignment(attribute); + afterRemoveAssignments.add(attributeObligation); + } + } + if (count == 1 && uri == 1 && PEP == 0) { + // Remove Obligation and add Advice + changeIt = true; + takeAction(stdResponse, oblId, afterRemoveAssignments); + } else if (PEP == 1 && count == 0) { + // Strip the PEPACTION if available + if (uri == 1) { + afterRemoveAssignments.add(attributeURI); + } + Obligation afterRemoveObligation = new StdObligation( + oblId, afterRemoveAssignments); + obligations.add(afterRemoveObligation); + } else { + obligations.add(obligation); + } + } + } + } + } + + private void takeAction(StdMutableResponse stdResponse, Identifier advId, + Collection<AttributeAssignment> afterRemoveAssignments) { + if (changeIt) { + LOGGER.info("the URL is :" + configURL); + // Calling Rest URL.. + callRest(); + // Including the Results in an Advice + Identifier id = new IdentifierImpl( + "org.onap.policy:pdp:reply"); + Identifier statId = new IdentifierImpl( + "org:onap:onap:policy:pdp:reply:status"); + Identifier statCategory = new IdentifierImpl( + "urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject"); + Identifier strId = new IdentifierImpl( + "http://www.w3.org/2001/XMLSchema#string"); + Identifier resId = new IdentifierImpl( + "org:onap:onap:policy:pdp:reply:resource"); + Identifier resCategory = new IdentifierImpl( + "urn:oasis:names:tc:xacml:3.0:attribute-category:resource"); + Identifier urlId = new IdentifierImpl( + "http://www.w3.org/2001/XMLSchema#anyURI"); + AttributeValue<String> attributeStatusValue = new StdAttributeValue<>( + strId, status + response); + AttributeValue<String> attributeResourceValue = new StdAttributeValue<>( + urlId, configURL); + StdAttributeAssignment attributeStatus = new StdAttributeAssignment( + statCategory, statId, "PDP", attributeStatusValue); + StdAttributeAssignment attributeResouce = new StdAttributeAssignment( + resCategory, resId, "PDP", attributeResourceValue); + afterRemoveAssignments.add(attributeStatus); + afterRemoveAssignments.add(attributeResouce); + Advice advice = new StdAdvice(id, afterRemoveAssignments); + addResult.addAdvice(advice); + } + } + + private void addResults(StdMutableResponse stdResponse, boolean config, boolean decide) { + if(decide){ + newResponse = stdResponse; + return; + } + for (Result result : stdResponse.getResults()) { + if(config){ + addResult.addAdvice(result.getAssociatedAdvice()); + } + addResult.addAttributeCategories(result.getAttributes()); + addResult.addPolicyIdentifiers(result.getPolicyIdentifiers()); + addResult.addPolicySetIdentifiers(result.getPolicySetIdentifiers()); + addResult.setStatus(result.getStatus()); + addResult.setDecision(result.getDecision()); + if(!config){ + addResult.addObligations(obligations); + } + } + newResponse.add(addResult); + } + + private int status; + private String response; + private DefaultHttpClient httpClient; + + private void callRest() { + // Finding the Macros in the URL.. + Pattern pattern = Pattern.compile("\\$([a-zA-Z0-9.:]*)"); + Matcher match = pattern.matcher(configURL); + StringBuffer sb = new StringBuffer(); + while (match.find()) { + LOGGER.info("Found Macro : " + match.group(1)); + String replaceValue = matchValues.get(match.group(1)); + LOGGER.info("Replacing with :" + replaceValue); + match.appendReplacement(sb, replaceValue); + } + match.appendTail(sb); + LOGGER.info("URL is : " + sb.toString()); + configURL = sb.toString(); + // Calling the Requested service. + if (matchValues.get("method").equalsIgnoreCase("GET")) { + httpClient = new DefaultHttpClient(); + try { + HttpGet getRequest = new HttpGet(configURL); + // Adding Headers here + if (header) { + for (String key : headers.keySet()) { + getRequest.addHeader(key, headers.get(key)); + } + } + HttpResponse result = httpClient.execute(getRequest); + status = result.getStatusLine().getStatusCode(); + BufferedReader br = new BufferedReader(new InputStreamReader( + (result.getEntity().getContent()))); + String output = " "; + String out; + while ((out = br.readLine()) != null) { + output = output + out; + } + response = output; + } catch (Exception e) { + LOGGER.error(e.getMessage()+e); + response = e.getMessage(); + } finally { + httpClient.getConnectionManager().shutdown(); + } + } else if(matchValues.get("method").equalsIgnoreCase("POST")) { + httpClient = new DefaultHttpClient(); + try { + HttpPost postRequest = new HttpPost(configURL); + // Adding Headers here + if (header) { + for (String key : headers.keySet()) { + postRequest.addHeader(key, headers.get(key)); + } + } + // Adding the Body. + URL configURL = new URL(matchValues.get("body")); + URLConnection connection = null; + connection = configURL.openConnection(); + // InputStream in = connection.getInputStrem(); + // LOGGER.info("The Body Content is : " + IOUtils.toString(in)); + JsonReader jsonReader = Json.createReader(connection.getInputStream()); + StringEntity input = new StringEntity(jsonReader.readObject().toString()); + input.setContentType("application/json"); + postRequest.setEntity(input); + // Executing the Request. + HttpResponse result = httpClient.execute(postRequest); + LOGGER.info("Result Headers are : " + result.getAllHeaders()); + status = result.getStatusLine().getStatusCode(); + BufferedReader br = new BufferedReader(new InputStreamReader( + (result.getEntity().getContent()))); + String output = " "; + String out; + while ((out = br.readLine()) != null) { + output = output + out; + } + response = output; + }catch (Exception e) { + LOGGER.error(e.getMessage() +e); + response = e.getMessage(); + } finally { + httpClient.getConnectionManager().shutdown(); + } + } else if(matchValues.get("method").equalsIgnoreCase("PUT")) { + httpClient = new DefaultHttpClient(); + try { + HttpPut putRequest = new HttpPut(configURL); + // Adding Headers here + if (header) { + for (String key : headers.keySet()) { + putRequest.addHeader(key, headers.get(key)); + } + } + // Adding the Body. + URL configURL = new URL(matchValues.get("body")); + URLConnection connection = null; + connection = configURL.openConnection(); + //InputStream in = connection.getInputStream(); + //LOGGER.info("The Body Content is : " + IOUtils.toString(in)); + JsonReader jsonReader = Json.createReader(connection.getInputStream()); + StringEntity input = new StringEntity(jsonReader.readObject().toString()); + input.setContentType("application/json"); + putRequest.setEntity(input); + // Executing the Request. + HttpResponse result = httpClient.execute(putRequest); + status = result.getStatusLine().getStatusCode(); + BufferedReader br = new BufferedReader(new InputStreamReader( + (result.getEntity().getContent()))); + String output = " "; + String out; + while ((out = br.readLine()) != null) { + output = output + out; + } + response = output; + } catch (Exception e) { + LOGGER.error(e.getMessage() +e); + response = e.getMessage(); + }finally { + httpClient.getConnectionManager().shutdown(); + } + } + } +}
\ No newline at end of file diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/package-info.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/package-info.java new file mode 100644 index 000000000..82c6182b9 --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/action/package-info.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.action; + +/** + * org.onap.policy.xacml.action contains the implementation of the PDP Actions. + * Changes: + * Now PDP supports actions based on PUT, GET, POST methods + * + * @version 0.2 + * + */ diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/custom/OnapFunctionDefinitionFactory.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/custom/OnapFunctionDefinitionFactory.java new file mode 100644 index 000000000..87075f9bb --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/custom/OnapFunctionDefinitionFactory.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.custom; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import org.onap.policy.xacml.pdp.std.functions.FunctionDefinitionCustomRegexpMatch; + +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinitionFactory; +import com.att.research.xacmlatt.pdp.std.StdFunctions; + +public class OnapFunctionDefinitionFactory extends FunctionDefinitionFactory { + private static Logger logger = FlexLogger.getLogger(OnapFunctionDefinitionFactory.class); + private static Map<Identifier,FunctionDefinition> mapFunctionDefinitions = new HashMap<>(); + private static boolean needMapInit = true; + + public static final Identifier ID_FUNCTION_CUSTOM_REGEXP_MATCH = new IdentifierImpl("org.onap.function.regex-match"); + + private static final FunctionDefinition FD_CUSTOM_REGEXP_MATCH = new FunctionDefinitionCustomRegexpMatch<>(ID_FUNCTION_CUSTOM_REGEXP_MATCH, DataTypes.DT_STRING); + + private static void register(FunctionDefinition functionDefinition) { + mapFunctionDefinitions.put(functionDefinition.getId(), functionDefinition); + } + + private static void initMap() { + if (needMapInit) { + synchronized(mapFunctionDefinitions) { + if (needMapInit) { + needMapInit = false; + Field[] declaredFields = StdFunctions.class.getDeclaredFields(); + for (Field field : declaredFields) { + if (Modifier.isStatic(field.getModifiers()) && + field.getName().startsWith(StdFunctions.FD_PREFIX) && + FunctionDefinition.class.isAssignableFrom(field.getType()) && + Modifier.isPublic(field.getModifiers()) + ) { + try { + register((FunctionDefinition)(field.get(null))); + } catch (IllegalAccessException ex) { + logger.error(ex.getMessage() +ex); + } + } + } + // + // Our custom function + // + //register(FunctionDefinitionCustomRegexpMatch); + register(FD_CUSTOM_REGEXP_MATCH); + } + } + } + } + + public OnapFunctionDefinitionFactory() { + initMap(); + } + + @Override + public FunctionDefinition getFunctionDefinition(Identifier functionId) { + return mapFunctionDefinitions.get(functionId); + } +} diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngine.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngine.java new file mode 100644 index 000000000..fb90d0a2e --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngine.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.pdp; + +import java.util.Properties; + +import org.onap.policy.xacml.action.FindAction; + +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.pdp.PDPException; +import com.att.research.xacml.api.pdp.ScopeResolver; +import com.att.research.xacml.std.StdMutableResponse; +import com.att.research.xacmlatt.pdp.ATTPDPEngine; +import com.att.research.xacmlatt.pdp.eval.EvaluationContextFactory; + +public class ONAPPDPEngine extends ATTPDPEngine { + + public ONAPPDPEngine(EvaluationContextFactory evaluationContextFactoryIn, Decision defaultDecisionIn, + ScopeResolver scopeResolverIn, Properties properties) { + super(evaluationContextFactoryIn, defaultDecisionIn, scopeResolverIn, properties); + } + + public ONAPPDPEngine(EvaluationContextFactory evaluationContextFactoryIn, Decision defaultDecisionIn, + ScopeResolver scopeResolverIn) { + super(evaluationContextFactoryIn, defaultDecisionIn, scopeResolverIn); + } + + public ONAPPDPEngine(EvaluationContextFactory evaluationContextFactoryIn, ScopeResolver scopeResolverIn) { + super(evaluationContextFactoryIn, scopeResolverIn); + } + + @Override + public Response decide(Request pepRequest) throws PDPException { + Response response = super.decide(pepRequest); + + FindAction findAction = new FindAction(); + return findAction.run((StdMutableResponse) response, pepRequest); + } + + +} diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngineFactory.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngineFactory.java new file mode 100644 index 000000000..2e796bf68 --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/ONAPPDPEngineFactory.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.pdp; + +import java.util.Properties; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPEngineFactory; +import com.att.research.xacml.util.FactoryException; +import com.att.research.xacmlatt.pdp.eval.EvaluationContextFactory; + +public class ONAPPDPEngineFactory extends PDPEngineFactory { + private Logger logger = FlexLogger.getLogger(this.getClass()); + + @Override + public PDPEngine newEngine() throws FactoryException { + EvaluationContextFactory evaluationContextFactory = EvaluationContextFactory.newInstance(); + if (evaluationContextFactory == null) { + this.logger.error("Null EvaluationContextFactory"); + throw new FactoryException("Null EvaluationContextFactory"); + } + return new ONAPPDPEngine(evaluationContextFactory, this.getDefaultBehavior(), this.getScopeResolver()); + } + + @Override + public PDPEngine newEngine(Properties properties) throws FactoryException { + EvaluationContextFactory evaluationContextFactory = EvaluationContextFactory.newInstance(properties); + if (evaluationContextFactory == null) { + this.logger.error("Null EvaluationContextFactory"); + throw new FactoryException("Null EvaluationContextFactory"); + } + return new ONAPPDPEngine(evaluationContextFactory, this.getDefaultBehavior(), this.getScopeResolver(), properties); + } + +} diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/FunctionDefinitionCustomRegexpMatch.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/FunctionDefinitionCustomRegexpMatch.java new file mode 100644 index 000000000..590d519cc --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/FunctionDefinitionCustomRegexpMatch.java @@ -0,0 +1,130 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.pdp.std.functions; + + +import java.util.List; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.std.functions.ConvertedArgument; +import com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionBase; + +/** + * FunctionDefinitionCustomRegexMatch implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the custom 'type'-regex-match predicates as functions taking two arguments, the first of <code>String</code>, + * and the second of the type for that specific predicate as a regular expression, + * and returning a <code>Boolean</code> for whether the regular expression matches the string representation of the first argument. + * + * + * @version $Revision: 0.2 $ + * + * @param <I> the java class for the data type of the function Input arguments + */ +public class FunctionDefinitionCustomRegexpMatch<I> extends FunctionDefinitionBase<Boolean, I> { + private static Logger logger = FlexLogger.getLogger(FunctionDefinitionCustomRegexpMatch.class); + + /** + * Constructor - need dataTypeArgs input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionCustomRegexpMatch(Identifier idIn, DataType<I> dataTypeArgsIn) { + super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, false); + } + + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + if (arguments == null || arguments.size() != 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected 2 arguments, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + // get the regular expression + FunctionArgument regexpArgument = arguments.get(0); + + ConvertedArgument<String> convertedArgument = new ConvertedArgument<>(regexpArgument, DataTypes.DT_STRING, false); + if ( ! convertedArgument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedArgument.getStatus())); + } + + // String regexpValue = (String)regexpArgument.getValue().getValue(); + String regexpValue = convertedArgument.getValue(); + + + // now get the element to match + FunctionArgument elementArgument = arguments.get(1); + + ConvertedArgument<I> convertedElement = new ConvertedArgument<>(elementArgument, this.getDataTypeArgs(), false); + if ( ! convertedElement.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedElement.getStatus())); + } + + I elementValueObject = convertedElement.getValue(); + + String elementValueString; + try { + elementValueString = this.getDataTypeArgs().toStringValue(elementValueObject); + } catch (DataTypeException e) { + logger.error(e.getMessage() +e); + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + + // ConvertedArgument checks for null value, so do not need to do again here + + // Adding this code will Change the Functionality which allows to retrieve Multiple-policy using single request. + elementValueString = elementValueString + regexpValue ; + regexpValue = elementValueString.substring(0,(elementValueString.length()- regexpValue.length())); + elementValueString = elementValueString.substring(regexpValue.length(),(elementValueString.length())); + // + // Supporting multiple values in the element and be able to query them. + if(elementValueString.contains(",")){ + String[] elements = elementValueString.split(","); + for(int i=0; i<elements.length; i++){ + if(elements[i].trim().matches(regexpValue)) { + return ER_TRUE; + } + } + } + if (elementValueString.matches(regexpValue)) { + return ER_TRUE; + } else { + return ER_FALSE; + } + + } +} diff --git a/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/PolicyList.java b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/PolicyList.java new file mode 100644 index 000000000..794276f6a --- /dev/null +++ b/ONAP-PDP/src/main/java/org/onap/policy/xacml/pdp/std/functions/PolicyList.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.xacml.pdp.std.functions; + +import java.util.ArrayList; +import java.util.List; +/** + * Creates a list of policy ids. + * + * @version $Revision: 1.3 $ + */ +public class PolicyList { + + private static List<String> policyList = new ArrayList<>(); + + + public static List<String> getpolicyList(){ + return policyList; + } + + public static void addPolicyID(String policyID){ + if (!policyList.contains(policyID)){ + policyList.add(policyID); + } + } + + public static void clearPolicyList(){ + if (!policyList.isEmpty()){ + policyList.clear(); + } + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionAccessPermittedTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionAccessPermittedTest.java new file mode 100644 index 000000000..4abfd99dc --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionAccessPermittedTest.java @@ -0,0 +1,521 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; + +import org.junit.Ignore; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdMutableRequest; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdEvaluationContext; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionAccessPermitted; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * NOT IMPLEMENTED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * This function is not yet implemented so these tests intentionally fail. + * + * + */ +public class FunctionDefinitionAccessPermittedTest { + + // + // Strings for the Request contents + // + + String reqStrMainStart = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<Request xsi:schemaLocation=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" + + " http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd\"" + + " ReturnPolicyIdList=\"false\"" + + " CombinedDecision=\"false\"" + + " xmlns=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\"" + + " xmlns:md=\"http://www.medico.com/schemas/record\"" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + + " <Attributes Category=\"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject\">" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:subject:subject-id\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">Julius Hibbert</AttributeValue>" + + " </Attribute>" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\"> This is IT! </AttributeValue>" + + " </Attribute>" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\"> This is IT! </AttributeValue>" + + " </Attribute>" + + "</Attributes>"; + + String reqStrResourceStart = "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:resource\">"; + + String reqStrMdRecordSimpson = + "<md:record>" + + "<md:hospital_info>" + + "<md:name>ABC Hospital</md:name>" + + "<md:department>Surgery</md:department>" + + "</md:hospital_info>" + + "<md:patient_info>" + + "<md:name>Bart Simpson</md:name>" + + "<md:age>60</md:age>" + + "<md:sex>male</md:sex>" + + "<md:health_insurance>123456</md:health_insurance>" + + "</md:patient_info>" + + "<md:diagnosis_info>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">Gastric Cancer</md:item>" + + "<md:item type=\"secondary\">Hyper tension</md:item>" + + "</md:diagnosis>" + + "<md:pathological_diagnosis>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">Well differentiated adeno carcinoma</md:item>" + + "</md:diagnosis>" + + "<md:date>2000-10-05</md:date>" + + "<md:malignancy type=\"yes\"/>" + + "</md:pathological_diagnosis>" + + "</md:diagnosis_info>" + + " </md:record>"; + String reqStrContentMdRecordSimpson = "<Content>" + reqStrMdRecordSimpson + "</Content>"; + String reqStrMalformedContent = + " <Content>" + + "<md:record>" + + "<md:hospital_info>" + + "<md:name>ABC Hospital</md:name>" + + "<md:malignancy type=\"yes\"/>" + + "</Content>"; + String reqStrMdRecordSpringer = + "<md:record>" + + "<md:hospital_info>" + + "<md:name>XYZ Hospital</md:name>" + + "<md:department>Surgery</md:department>" + + "</md:hospital_info>" + + "<md:patient_info>" + + "<md:name>Jerry Springer</md:name>" + + "<md:age>65</md:age>" + + "<md:sex>male</md:sex>" + + "<md:health_insurance>765432</md:health_insurance>" + + "</md:patient_info>" + + "<md:diagnosis_info>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">Hyatal Hernia</md:item>" + + "<md:item type=\"secondary\">Diabetes</md:item>" + + "<md:item type=\"tertiary\">Neuronal Collapse</md:item>" + + "</md:diagnosis>" + + "<md:pathological_diagnosis>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">We have no idea</md:item>" + + "</md:diagnosis>" + + "<md:date>2012-07-22</md:date>" + + "<md:malignancy type=\"no\"/>" + + "</md:pathological_diagnosis>" + + "</md:diagnosis_info>" + + " </md:record>"; + String reqStrContentMdRecordSpringer = + "<Content>" + reqStrMdRecordSpringer + "</Content>"; + + String reqStrResourceEnd = " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:resource:resource-id\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#anyURI\">http://medico.com/record/patient/BartSimpson</AttributeValue>" + + " </Attribute>" + + "</Attributes> "; + String reqStrActionStart = "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:action\">"; + + String reqStrActionEnd = "<Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\">" + + "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">read</AttributeValue>" + + "</Attribute>" + + "</Attributes> "; + String reqStrEnvironmentStartEnd = " <Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:environment\" />"; + String reqStrMainEnd = " </Request>"; + + + // combined strings for convenience + String reqStrMainResourceStart = reqStrMainStart + reqStrResourceStart; + String reqStrResourceAllEnd = reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrEnvironmentStartEnd + reqStrMainEnd; + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + + // Name Spaces used in the XML as part of these examples - needed for compiling XPaths + NamespaceContext nameSpaceContext = new NamespaceContext() { + @Override + public Iterator<?> getPrefixes(String arg0) { return null;} + + @Override + public String getPrefix(String arg0) {return null;} + + @Override + public String getNamespaceURI(String arg0) { + if("md".equals(arg0)) { + return "http://www.medico.com/schemas/record"; + } else if ("xacml-context".equals(arg0)) { + return "urn:oasis:names:tc:xacml:3.0:context:schema:os"; + } else if ("xsi".equals(arg0)) { + return "http://www.w3.org/2001/XMLSchema-instance"; + } + return null; + } + }; + + + + // + // URIs for attribute categroies + // + + FunctionArgumentAttributeValue attrUriNull = null; + FunctionArgumentAttributeValue attrUriEmpty = null; + FunctionArgumentAttributeValue attrUriResources = null; + FunctionArgumentAttributeValue attrUriAction = null; + FunctionArgumentAttributeValue attrUriNotInRequest = null; + FunctionArgumentAttributeValue attrUriNotCategory = null; + + + + // + // XML Contents + // + + FunctionArgumentAttributeValue attrXnull = null; + FunctionArgumentAttributeValue attrXEmpty = null; + FunctionArgumentAttributeValue attrXSimpson = null; + FunctionArgumentAttributeValue attrXSpringer = null; + FunctionArgumentAttributeValue attrXContentSimpson = null; + FunctionArgumentAttributeValue attrXContentSpringer = null; + FunctionArgumentAttributeValue attrXBadXML = null; + + + + + + + // + // REQUEST objects available for use in tests + // + Request requestEmpty = new StdMutableRequest(); + Request requestMdRecord = null; + Request requestDoubleResources = null; + Request requestDoubleContent = null; + Request requestResourceActionContent = null; + Request requestContentInAction = null; + + + + + /** + * Set up all variables in one place because it is complicated (lots of steps needed for each attribute) + */ + public FunctionDefinitionAccessPermittedTest() { + try { + + + // create Function Attributes for URIs + attrUriNull = null; + attrUriEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("")); + attrUriResources = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("urn:oasis:names:tc:xacml:3.0:attribute-category:resource")); + attrUriAction = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("urn:oasis:names:tc:xacml:3.0:attribute-category:action")); + attrUriNotInRequest = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("NoSuchURI")); + attrUriNotCategory = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("urn:oasis:names:tc:xacml:1.0:resource:resource-id")); + + // create Function Attributes for XML Strings + attrXnull = new FunctionArgumentAttributeValue(null); + attrXEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrXSimpson = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(reqStrMdRecordSimpson)); + attrXSpringer = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(reqStrMdRecordSpringer)); + attrXContentSimpson = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(reqStrContentMdRecordSimpson)); + attrXContentSpringer = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(reqStrContentMdRecordSpringer)); + attrXBadXML = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(reqStrMalformedContent)); + + + + // Request objects + // to create a Request object the easiest way is to put the xml into a file and use the DOMRequest to load it. + + // single Content in the Resources section (normal valid request) + String reqString = reqStrMainResourceStart + reqStrContentMdRecordSimpson + reqStrResourceAllEnd; + File tFile = File.createTempFile("functionJunit", "request"); + BufferedWriter bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestMdRecord = DOMRequest.load(tFile); + tFile.delete(); + + // Resources included twice + reqString = reqStrMainResourceStart + reqStrContentMdRecordSimpson + reqStrResourceEnd + reqStrResourceStart + reqStrContentMdRecordSimpson +reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestDoubleResources = DOMRequest.load(tFile); + tFile.delete(); + + // Content included twice - error + reqString = reqStrMainResourceStart + reqStrContentMdRecordSimpson + reqStrContentMdRecordSimpson +reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestDoubleContent = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + // content included in both Resource and Action - ok + reqString = reqStrMainResourceStart + reqStrContentMdRecordSimpson + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecordSimpson + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestResourceActionContent = DOMRequest.load(tFile); + tFile.delete(); + + // Content included only in Action - missing content produces non-error result according to spec + reqString = reqStrMainResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecordSimpson + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestContentInAction = DOMRequest.load(tFile); + tFile.delete(); + + + + // Test that Bad XML is caught + @SuppressWarnings("unused") + Request requestContentMisplaced = null; + @SuppressWarnings("unused") + Request requestMalformedContent = null; + + + // Bad XML - Content not under a Category + reqString = reqStrMainStart + reqStrContentMdRecordSimpson + reqStrResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestContentMisplaced = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + // Bad XML - Content is not valid XML + reqString = reqStrMainResourceStart + reqStrMalformedContent + reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestMalformedContent = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + } catch (Exception e) { + fail("Constructor initializing variables, e="+ e + " cause="+e.getCause()); + } + + } + + + + + + + + + @Ignore //@Test + public void testAccess_permitted() { + + ExpressionResult res = null; + Boolean resValue = null; + + FunctionDefinitionAccessPermitted fd = (FunctionDefinitionAccessPermitted) StdFunctions.FD_ACCESS_PERMITTED; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ACCESS_PERMITTED, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + + // successful invoke returns true + arguments.clear(); + arguments.add(attrUriResources); + arguments.add(attrXEmpty); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + + // successful invoke returns false + + + // URI not in Request (ok - evaluate anyway) + + // test for infinite loop + + // second arg ok both with and without <Content> tag + arguments.clear(); + arguments.add(attrUriResources); + arguments.add(attrXContentSpringer); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrUriResources); + arguments.add(attrXSpringer); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // second arg not valid XML + arguments.clear(); + arguments.add(attrUriResources); + arguments.add(attrXBadXML); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Parsing of XML string failed. Cause='The element type \"md:hospital_info\" must be terminated by the matching end-tag \"</md:hospital_info>\".'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null Evaluation Context + arguments.clear(); + arguments.add(attrUriNotCategory); + arguments.add(attrXContentSimpson); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted First argument must be a urn for an attribute-category, not 'urn:oasis:names:tc:xacml:1.0:resource:resource-id", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null Request + arguments.clear(); + arguments.add(attrUriAction); + arguments.add(attrXContentSimpson); + res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Got null Request in EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first arg not uri + arguments.clear(); + arguments.add(attrUriNotCategory); + arguments.add(attrXContentSimpson); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted First argument must be a urn for an attribute-category, not 'urn:oasis:names:tc:xacml:1.0:resource:resource-id", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first arg not attribute-category urn + arguments.clear(); + arguments.add(attrXContentSimpson); + arguments.add(attrXContentSimpson); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Expected data type 'anyURI' saw 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second arg not string + arguments.clear(); + arguments.add(attrUriAction); + arguments.add(attrUriAction); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Expected data type 'string' saw 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // too few args + arguments.clear(); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXContentSimpson); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // too many args + arguments.clear(); + arguments.add(attrUriEmpty); + arguments.add(attrXContentSimpson); + arguments.add(attrXContentSimpson); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:access-permitted Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionArithmeticTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionArithmeticTest.java new file mode 100644 index 000000000..56e79cf29 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionArithmeticTest.java @@ -0,0 +1,717 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionArithmeticTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + @Test + public void testInteger_add() { + + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + FunctionArgumentAttributeValue attrBadType = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_ADD; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_ADD, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("2"), resValue); + + arguments.clear(); + arguments.add(attr1); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-add Expected data type 'integer' saw 'double' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testDouble_add() { + + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.5)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_DOUBLE_ADD; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_ADD, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(4.0), resValue); + + } + + + @Test + public void testInteger_subtract() { + + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(6)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_SUBTRACT; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_SUBTRACT, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("5"), resValue); + + } + + + @Test + public void testDouble_subtract() { + + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(8.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.3)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_DOUBLE_SUBTRACT; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_SUBTRACT, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(6.2), resValue); + + } + + + @Test + public void testInteger_multiply() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(2)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_MULTIPLY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_MULTIPLY, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("10"), resValue); + + + // test 0 + arguments.clear(); + arguments.add(attr1); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("0"), resValue); + } + + + @Test + public void testDouble_multiply() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.5)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_DOUBLE_MULTIPLY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_MULTIPLY, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(3.75), resValue); + + // test multiply by 0 + arguments.clear(); + arguments.add(attr1); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(0), resValue); + } + + + @Test + public void testInteger_divide() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(2)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_DIVIDE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_DIVIDE, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("2"), resValue); + + + // test 0 + arguments.clear(); + arguments.add(attr1); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-divide Divide by 0 error: 5, 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testDouble_divide() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.5)); + + } catch (Exception e) { + fail("creating attributes e="+e); + } + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_DOUBLE_DIVIDE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_DIVIDE, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(0.6), resValue); + + // test multiply by 0 + arguments.clear(); + arguments.add(attr1); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:double-divide Divide by 0 error: 1.5, 0.0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + @Test + public void testInteger_mod() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(28)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_MOD; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_MOD, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + arguments.add(attr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("3"), resValue); + + + // test 0 + arguments.clear(); + arguments.add(attr1); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-mod Divide by 0 error: 28, 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testInteger_abs() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attrM1 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + attrM1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(-7)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_INTEGER_ABS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_ABS, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("5"), resValue); + + arguments.clear(); + arguments.add(attrM1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("7"), resValue); + + arguments.clear(); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("0"), resValue); + } + + + @Test + public void testDouble_abs() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.5)); + + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_DOUBLE_ABS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_ABS, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(1.5), resValue); + + arguments.clear(); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(2.5), resValue); + + arguments.clear(); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(0), resValue); + + } + + + @Test + public void testDouble_round() { + + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + FunctionArgumentAttributeValue attr3 = null; + FunctionArgumentAttributeValue attr4 = null; + FunctionArgumentAttributeValue attr5 = null; + FunctionArgumentAttributeValue attr6 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.49)); + attr3 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.51)); + attr4 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.5)); + attr5 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.49)); + attr6 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.51)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_ROUND; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ROUND, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal + arguments.add(attr0); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(0), resValue); + + arguments.clear(); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(2), resValue); + + arguments.clear(); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(1), resValue); + + arguments.clear(); + arguments.add(attr3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(2), resValue); + + arguments.clear(); + arguments.add(attr4); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-2), resValue); + + arguments.clear(); + arguments.add(attr5); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-2), resValue); + + arguments.clear(); + arguments.add(attr6); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-3), resValue); + } + + + @Test + public void testDouble_floor() { + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + FunctionArgumentAttributeValue attr3 = null; + FunctionArgumentAttributeValue attr4 = null; + FunctionArgumentAttributeValue attr5 = null; + FunctionArgumentAttributeValue attr6 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(0)); + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.5)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.49)); + attr3 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.51)); + attr4 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.5)); + attr5 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.49)); + attr6 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-2.51)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionArithmetic<?> fd = (FunctionDefinitionArithmetic<?>) StdFunctions.FD_FLOOR; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_FLOOR, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal + arguments.add(attr0); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(0), resValue); + + arguments.clear(); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(1), resValue); + + arguments.clear(); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(1), resValue); + + arguments.clear(); + arguments.add(attr3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(1), resValue); + + arguments.clear(); + arguments.add(attr4); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-3), resValue); + + arguments.clear(); + arguments.add(attr5); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-3), resValue); + + arguments.clear(); + arguments.add(attr6); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(-3), resValue); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagIsInTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagIsInTest.java new file mode 100644 index 000000000..09fd95f05 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagIsInTest.java @@ -0,0 +1,221 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionBagIsInTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + @Test + public void testString() { + String v1 = new String("abc"); + String v2 = new String("def"); + String notInBag = new String("lmnop"); + String sameValueV1 = new String("abc"); + Integer vOtherType = new Integer(11); + + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrV2 = null; + FunctionArgumentAttributeValue attrNotInBag = null; + FunctionArgumentAttributeValue attrSameValueV1 = null; + FunctionArgumentAttributeValue attrOtherType = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrV2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v2)); + attrNotInBag = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(notInBag)); + attrSameValueV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(sameValueV1)); + attrOtherType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(vOtherType)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + Bag bag0 = new Bag(); + Bag bag1 = new Bag(); + bag1.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + Bag bag2 = new Bag(); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v2));; + + + + FunctionArgumentBag attrBag0 = new FunctionArgumentBag(bag0); + FunctionArgumentBag attrBag1 = new FunctionArgumentBag(bag1); + FunctionArgumentBag attrBag2 = new FunctionArgumentBag(bag2); + + + + FunctionDefinitionBagIsIn<?> fd = (FunctionDefinitionBagIsIn<?>) StdFunctions.FD_STRING_IS_IN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_IS_IN, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // element is in bag + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBag2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // element not in bag + arguments.clear(); + arguments.add(attrNotInBag); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // different element with the same value is in bag + arguments.clear(); + arguments.add(attrSameValueV1); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty bag + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBag0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // missing arg + arguments.clear(); + arguments.add(attrSameValueV1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 1st arg is bag + arguments.clear(); + arguments.add(attrBag1); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Expected a simple value, saw a bag", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2nd arg not bag + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first arg null + arguments.clear(); + arguments.add(null); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2nd arg null + arguments.clear(); + arguments.add(attrV1); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first arg type does not match bag elements + arguments.clear(); + arguments.add(attrOtherType); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-is-in Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag has mixed element types +// behavior not specified for this case in spec. It ASSUMES that all elements in bag are same type. + + } + + + + + // + // + // REST OF DATA TYPES OMITTED + // because they "should" all work the same + // + // + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagOneAndOnlyTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagOneAndOnlyTest.java new file mode 100644 index 000000000..192747aec --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagOneAndOnlyTest.java @@ -0,0 +1,224 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.math.BigInteger; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionBagOneAndOnlyTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + @Test + public void testString() { + String v1 = new String("abc"); + String v2 = new String("def"); + BigInteger vOtherType = BigInteger.valueOf(11); + + Bag bag0 = new Bag(); + Bag bag1 = new Bag(); + bag1.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + Bag bag2 = new Bag(); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v2)); + Bag bagOtherType = new Bag(); + bagOtherType.add(new StdAttributeValue<BigInteger>(DataTypes.DT_INTEGER.getId(), vOtherType)); + + FunctionArgumentBag attrBag0 = new FunctionArgumentBag(bag0); + FunctionArgumentBag attrBag1 = new FunctionArgumentBag(bag1); + FunctionArgumentBag attrBag2 = new FunctionArgumentBag(bag2); + FunctionArgumentBag attrBagOtherType = new FunctionArgumentBag(bagOtherType); + + + FunctionDefinitionBagOneAndOnly<?> fd = (FunctionDefinitionBagOneAndOnly<?>) StdFunctions.FD_STRING_ONE_AND_ONLY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_ONE_AND_ONLY, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + + + // bag with only one + arguments.clear(); + arguments.add(attrBag1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + String resValue = (String)res.getValue().getValue(); + assertEquals(v1, resValue); + + // null bag + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-one-and-only Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with exactly one but of other type in it + arguments.clear(); + arguments.add(attrBagOtherType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-one-and-only Element in bag of wrong type. Expected string got integer", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with none + arguments.clear(); + arguments.add(attrBag0); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-one-and-only Expected 1 but Bag has 0 elements", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with multiple + arguments.clear(); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-one-and-only Expected 1 but Bag has 2 elements", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + @Test + public void testBoolean() { + Boolean v1 = new Boolean(true); + Boolean v2 = new Boolean(false); + BigInteger vOtherType = BigInteger.valueOf(11); + + Bag bag0 = new Bag(); + Bag bag1 = new Bag(); + bag1.add(new StdAttributeValue<Boolean>(DataTypes.DT_BOOLEAN.getId(), v1)); + Bag bag2 = new Bag(); + bag2.add(new StdAttributeValue<Boolean>(DataTypes.DT_BOOLEAN.getId(), v1)); + bag2.add(new StdAttributeValue<Boolean>(DataTypes.DT_BOOLEAN.getId(), v2)); + Bag bagOtherType = new Bag(); + bagOtherType.add(new StdAttributeValue<BigInteger>(DataTypes.DT_STRING.getId(), vOtherType)); + + + FunctionArgumentBag attrBag0 = new FunctionArgumentBag(bag0); + FunctionArgumentBag attrBag1 = new FunctionArgumentBag(bag1); + FunctionArgumentBag attrBag2 = new FunctionArgumentBag(bag2); + FunctionArgumentBag attrBagOtherType = new FunctionArgumentBag(bagOtherType); + + + FunctionDefinitionBagOneAndOnly<?> fd = (FunctionDefinitionBagOneAndOnly<?>) StdFunctions.FD_BOOLEAN_ONE_AND_ONLY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_BOOLEAN_ONE_AND_ONLY, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + + + // bag with only one + arguments.clear(); + arguments.add(attrBag1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // null bag + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-one-and-only Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with exactly one but of other type in it + arguments.clear(); + arguments.add(attrBagOtherType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-one-and-only Element in bag of wrong type. Expected boolean got string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with none + arguments.clear(); + arguments.add(attrBag0); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-one-and-only Expected 1 but Bag has 0 elements", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with multiple + arguments.clear(); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-one-and-only Expected 1 but Bag has 2 elements", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + // + // + // REST OF DATA TYPES OMITTED + // because they "should" all work the same + // + // + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagSizeTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagSizeTest.java new file mode 100644 index 000000000..f2bcbc5c2 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagSizeTest.java @@ -0,0 +1,158 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionBagSizeTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + @Test + public void testString() { + String v1 = new String("abc"); + String v2 = new String("def"); + Integer vOtherType = new Integer(11); + + + + Bag bag0 = new Bag(); + Bag bag1 = new Bag(); + bag1.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + Bag bag2 = new Bag(); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v1)); + bag2.add(new StdAttributeValue<String>(DataTypes.DT_STRING.getId(), v2)); + Bag bagOtherType = new Bag(); + bagOtherType.add(new StdAttributeValue<Integer>(DataTypes.DT_INTEGER.getId(), vOtherType)); + + + FunctionArgumentBag attrBag0 = new FunctionArgumentBag(bag0); + FunctionArgumentBag attrBag1 = new FunctionArgumentBag(bag1); + FunctionArgumentBag attrBag2 = new FunctionArgumentBag(bag2); + FunctionArgumentBag attrBagOtherType = new FunctionArgumentBag(bagOtherType); + + + FunctionDefinitionBagSize<?> fd = (FunctionDefinitionBagSize<?>) StdFunctions.FD_STRING_BAG_SIZE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_BAG_SIZE, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + + + // bag with only one + arguments.clear(); + arguments.add(attrBag1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.math.BigInteger.class, res.getValue().getValue().getClass()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(BigInteger.valueOf(1), resValue); + + // null bag + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-bag-size Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag with exactly one but of other type in it + arguments.clear(); + arguments.add(attrBagOtherType); + res = fd.evaluate(null, arguments); + // NOTE: Size does not care about content type! + assertTrue(res.isOk()); + assertEquals(java.math.BigInteger.class, res.getValue().getValue().getClass()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(BigInteger.valueOf(1), resValue); + + // bag with none + arguments.clear(); + arguments.add(attrBag0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.math.BigInteger.class, res.getValue().getValue().getClass()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(BigInteger.valueOf(0), resValue); + + // bag with multiple + arguments.clear(); + arguments.add(attrBag2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.math.BigInteger.class, res.getValue().getValue().getClass()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(BigInteger.valueOf(2), resValue); + } + + + + + + + + // + // + // REST OF DATA TYPES OMITTED + // because they "should" all work the same + // + // + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagTest.java new file mode 100644 index 000000000..d96bd273f --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBagTest.java @@ -0,0 +1,547 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionBagTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + FunctionArgumentAttributeValue attrInteger = null; + FunctionArgumentAttributeValue attrString = null; + + public FunctionDefinitionBagTest() { + try { + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1111111111)); + attrString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("a string value")); + } catch (Exception e) { + fail("creating attributes e="+e); + } + } + + @Test + public void testString() { + + String s1 = "abc"; + String s2 = "def"; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(s1)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(s2)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionBag<?> fd = (FunctionDefinitionBag<?>) StdFunctions.FD_STRING_BAG; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_BAG, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // bag with only one + arguments.clear(); + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // zero args => empty bag + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + assertEquals(0, bag.size()); + + + // null argument + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-bag Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // argument of other type + arguments.clear(); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-bag Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args (check response is correct) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(2, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + + // duplicate args (verify return) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // lots of args + arguments.clear(); + for (int i = 0; i < 1000; i++) { + arguments.add(attr1); + } + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1000, bag.size()); + + } + + + @Test + public void testBoolean() { + + Boolean s1 = true; + Boolean s2 = false; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(s1)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(s2)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionBag<?> fd = (FunctionDefinitionBag<?>) StdFunctions.FD_BOOLEAN_BAG; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_BOOLEAN_BAG, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // bag with only one + arguments.clear(); + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // zero args => empty bag + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + assertEquals(0, bag.size()); + + + // null argument + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-bag Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // argument of other type + arguments.clear(); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-bag Expected data type 'boolean' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args (check response is correct) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(2, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + + // duplicate args (verify return) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_BOOLEAN.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // lots of args + arguments.clear(); + for (int i = 0; i < 1000; i++) { + arguments.add(attr1); + } + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1000, bag.size()); + + } + + + + @Test + public void testInteger() { + + BigInteger s1 = new BigInteger("123"); + BigInteger s2 = new BigInteger("456"); + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(s1)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(s2)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionBag<?> fd = (FunctionDefinitionBag<?>) StdFunctions.FD_INTEGER_BAG; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_BAG, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // bag with only one + arguments.clear(); + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // zero args => empty bag + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + assertEquals(0, bag.size()); + + + // null argument + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-bag Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // argument of other type + arguments.clear(); + arguments.add(attrString); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-bag Expected data type 'integer' saw 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args (check response is correct) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(2, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + + // duplicate args (verify return) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // lots of args + arguments.clear(); + for (int i = 0; i < 1000; i++) { + arguments.add(attr1); + } + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1000, bag.size()); + + } + + + + + @Test + public void testDouble() { + + Double s1 = 123.45; + Double s2 = 678.901; + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(s1)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(s2)); + } catch (Exception e) { + fail("creating attributes e="+e); + } + + FunctionDefinitionBag<?> fd = (FunctionDefinitionBag<?>) StdFunctions.FD_DOUBLE_BAG; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_BAG, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // bag with only one + arguments.clear(); + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // zero args => empty bag + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + assertEquals(0, bag.size()); + + + // null argument + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:double-bag Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // argument of other type + arguments.clear(); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:double-bag Expected data type 'double' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args (check response is correct) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(2, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + + // duplicate args (verify return) + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + arguments.add(attr1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s2, attrValueObject.getValue()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_DOUBLE.getId(), attrValueObject.getDataTypeId()); + assertEquals(s1, attrValueObject.getValue()); + + // lots of args + arguments.clear(); + for (int i = 0; i < 1000; i++) { + arguments.add(attr1); + } + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1000, bag.size()); + + } + + + + + + // + // + // REST OF DATA TYPES OMITTED + // because they "should" all work the same + // + // + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBaseTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBaseTest.java new file mode 100644 index 000000000..334226c84 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionBaseTest.java @@ -0,0 +1,131 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test functions in the abstract FunctionDefinitionSimpleTest class. + * Functions are tested by creating instances of other classes that should have appropriate properties to verify all variations of the responses expected. + * + * Note: we do not test getDataTypeId() because all it does is get the String out of the Identity object and we assume that the Data Type Identity objects + * are tested enough in everything else that any errors in them will be found and fixed quickly. + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionBaseTest { + /** + * getId() is pretty trivial, so verifying one should be enough to check that the mechanism is working ok + */ + @Test + public void testGetId() { + FunctionDefinition fd = StdFunctions.FD_STRING_EQUAL; + Identifier id = fd.getId(); + assertTrue(XACML3.ID_FUNCTION_STRING_EQUAL.stringValue().equals(id.stringValue()) ); + } + + /** + * check an instance of every result type that we can deal with + */ + @Test + public void testGetDataType() { + +//?? Need functions that return each of these data types except for Boolean which is returned by any of the EQUAL functions + FunctionDefinition fdstring = StdFunctions.FD_STRING_NORMALIZE_SPACE; + assertEquals(XACML3.ID_DATATYPE_STRING, fdstring.getDataTypeId()); + + FunctionDefinition fdboolean = StdFunctions.FD_STRING_EQUAL; + assertEquals(XACML3.ID_DATATYPE_BOOLEAN, fdboolean.getDataTypeId()); + + FunctionDefinition fdinteger = StdFunctions.FD_INTEGER_ADD; + assertEquals(XACML3.ID_DATATYPE_INTEGER, fdinteger.getDataTypeId()); + + FunctionDefinition fddouble = StdFunctions.FD_DOUBLE_ADD; + assertEquals(XACML3.ID_DATATYPE_DOUBLE, fddouble.getDataTypeId()); + + FunctionDefinition fddate = StdFunctions.FD_DATE_BAG; + assertEquals(XACML3.ID_DATATYPE_DATE, fddate.getDataTypeId()); + + FunctionDefinition fdtime = StdFunctions.FD_TIME_BAG; + assertEquals(XACML3.ID_DATATYPE_TIME, fdtime.getDataTypeId()); + + FunctionDefinition fddateTime = StdFunctions.FD_DATETIME_BAG; + assertEquals(XACML3.ID_DATATYPE_DATETIME, fddateTime.getDataTypeId()); + + FunctionDefinition fddayTimeDuration = StdFunctions.FD_DAYTIMEDURATION_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_DAYTIMEDURATION, fddayTimeDuration.getDataTypeId()); + + FunctionDefinition fdyearMonthDuration = StdFunctions.FD_YEARMONTHDURATION_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_YEARMONTHDURATION, fdyearMonthDuration.getDataTypeId()); + + FunctionDefinition fdanyURI = StdFunctions.FD_ANYURI_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_ANYURI, fdanyURI.getDataTypeId()); + + FunctionDefinition fdhexBinary = StdFunctions.FD_HEXBINARY_UNION; + assertEquals(XACML3.ID_DATATYPE_HEXBINARY, fdhexBinary.getDataTypeId()); + + FunctionDefinition fdbase64Binary = StdFunctions.FD_BASE64BINARY_UNION; + assertEquals(XACML3.ID_DATATYPE_BASE64BINARY, fdbase64Binary.getDataTypeId()); + + FunctionDefinition fdrfc822Name = StdFunctions.FD_RFC822NAME_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_RFC822NAME, fdrfc822Name.getDataTypeId()); + + FunctionDefinition fdx500Name = StdFunctions.FD_X500NAME_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_X500NAME, fdx500Name.getDataTypeId()); + +//TODO - There are currently no functions that return XPathExpression objects +// FunctionDefinition fdxpathExpression = StdFunctions.FD_XPATHEXPRESSION_FROM_STRING; +// assertEquals(XACML3.ID_DATATYPE_XPATHEXPRESSION, fdxpathExpression.getDataTypeId()); + + FunctionDefinition fdipAddress = StdFunctions.FD_IPADDRESS_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_IPADDRESS, fdipAddress.getDataTypeId()); + + FunctionDefinition fddnsName = StdFunctions.FD_DNSNAME_FROM_STRING; + assertEquals(XACML3.ID_DATATYPE_DNSNAME, fddnsName.getDataTypeId()); + } + + /** + * check the type of return, single vs multiple values + */ + @Test + public void testReturnsBag() { + FunctionDefinition fdNotBag = StdFunctions.FD_BOOLEAN_EQUAL; + assertFalse(fdNotBag.returnsBag()); + + FunctionDefinitionBag<?> fdBag = (FunctionDefinitionBag<?>) StdFunctions.FD_STRING_BAG; + assertTrue(fdBag.returnsBag()); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionComparisonTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionComparisonTest.java new file mode 100644 index 000000000..4cd558536 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionComparisonTest.java @@ -0,0 +1,1366 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.ISO8601Date; +import com.att.research.xacml.std.datatypes.ISO8601DateTime; +import com.att.research.xacml.std.datatypes.ISO8601Time; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test FunctionDefinitionComparison + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionComparisonTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + FunctionArgumentAttributeValue stringAttr1 = null; + FunctionArgumentAttributeValue stringAttr1a = null; + FunctionArgumentAttributeValue stringAttr2 = null; + FunctionArgumentAttributeValue stringAttrNeg1 = null; + + + FunctionArgumentAttributeValue intAttr1 = null; + FunctionArgumentAttributeValue intAttr1a = null; + FunctionArgumentAttributeValue intAttr2 = null; + FunctionArgumentAttributeValue intAttr0 = null; + FunctionArgumentAttributeValue intAttrNeg1 = null; + + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr1a = null; + FunctionArgumentAttributeValue attr2 = null; + FunctionArgumentAttributeValue attrNeg1 = null; + + FunctionArgumentAttributeValue attrDateToday = null; + FunctionArgumentAttributeValue attrDateSameDay = null; + FunctionArgumentAttributeValue attrDateTommorrow = null; + FunctionArgumentAttributeValue attrDateYesterday = null; + FunctionArgumentAttributeValue attrDateWithTimeZone = null; + FunctionArgumentAttributeValue attrDateNoTimeZone = null; + + + FunctionArgumentAttributeValue attrTimeToday = null; + FunctionArgumentAttributeValue attrTimeSameDay = null; + FunctionArgumentAttributeValue attrTimeTommorrow = null; + FunctionArgumentAttributeValue attrTimeYesterday = null; + FunctionArgumentAttributeValue attrTimeWithTimeZone = null; + FunctionArgumentAttributeValue attrTimeNoTimeZone = null; + + FunctionArgumentAttributeValue attrDateTimeToday = null; + FunctionArgumentAttributeValue attrDateTimeSameDay = null; + FunctionArgumentAttributeValue attrDateTimeTommorrow = null; + FunctionArgumentAttributeValue attrDateTimeYesterday = null; + FunctionArgumentAttributeValue attrDateTimeWithTimeZone = null; + FunctionArgumentAttributeValue attrDateTimeNoTimeZone = null; + + /** + * Set up some common variables on startup + */ + public FunctionDefinitionComparisonTest() { + try { + stringAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr1a = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("def")); + stringAttrNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("AAA")); + + + intAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + intAttr1a = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + intAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(2)); + intAttr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + intAttrNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(-1)); + + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.0)); + attr1a = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.0)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.4)); + attrNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-1.0)); + + // create dates + Calendar calendar = Calendar.getInstance(); + Date today = calendar.getTime(); + Date longAgo = new Date(1234); + // create a date that is different than "today" but within the same day (i.e. has a different hour) + if (calendar.get(Calendar.HOUR_OF_DAY) > 3) { + calendar.set(Calendar.HOUR_OF_DAY, 3); + } else { + calendar.set(Calendar.HOUR_OF_DAY, 5); + } + Date todayPlus = calendar.getTime(); + calendar.add(Calendar.DATE, 1); + Date tommorrow = calendar.getTime(); + attrDateToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(today)); + attrDateSameDay = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(todayPlus)); + attrDateTommorrow = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(tommorrow)); + attrDateYesterday = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(longAgo)); + ISO8601Date isoDate = new ISO8601Date(1920, 5, 8); + attrDateNoTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(isoDate)); + isoDate = new ISO8601Date("GMT+00:02", 1920, 5, 8); + attrDateWithTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(isoDate)); + + // create Times + ISO8601Time isoTime = new ISO8601Time(14, 43, 12, 145); + attrTimeToday = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + attrTimeSameDay = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + isoTime = new ISO8601Time(18, 53, 34, 423); + attrTimeTommorrow = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + isoTime = new ISO8601Time(7, 34, 6,543); + attrTimeYesterday = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + isoTime = new ISO8601Time(12, 12, 12, 12); + attrTimeNoTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + isoTime = new ISO8601Time("GMT:+00:03", 12, 12, 12, 12); + attrTimeWithTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(isoTime)); + + // create DateTimes + isoDate = new ISO8601Date(1920, 5, 8); + isoTime = new ISO8601Time( 18, 53, 34, 423); + ISO8601DateTime isoDateTime = new ISO8601DateTime((String)null, 1920, 5, 8, 18, 53, 34, 423); + attrDateTimeToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + attrDateTimeSameDay = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + isoTime = new ISO8601Time(20, 53, 34, 423); + isoDateTime = new ISO8601DateTime((String)null, 1920, 5, 8, 20, 53, 34, 423); + attrDateTimeTommorrow = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + isoTime = new ISO8601Time(7, 34, 6,543); + isoDateTime = new ISO8601DateTime((String)null, 1920, 5, 8, 7, 34, 6, 543); + attrDateTimeYesterday = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + isoTime = new ISO8601Time(12, 12, 12, 12); + isoDateTime = new ISO8601DateTime((String)null, 1920, 5, 8, 12, 12, 12, 12); + attrDateTimeNoTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + isoTime = new ISO8601Time("GMT:+00:03", 12, 12, 12, 12); + isoDate = new ISO8601Date("GMT:+00:03", 1920, 5, 8); + isoDateTime = new ISO8601DateTime("GMT:+00:03", 1920, 5, 8, 12, 12, 12, 12); + attrDateTimeWithTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(isoDateTime)); + + + + + } catch (Exception e) { + fail("Error creating values e="+ e); + } + } + + /** + * String + */ + @Test + public void testString_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_STRING_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(stringAttr1); + arguments.add(stringAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // check first < second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(intAttr1); + arguments.add(stringAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + } + + @Test + public void testString_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_STRING_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(stringAttr1); + arguments.add(stringAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check first < second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testString_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_STRING_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(stringAttr1); + arguments.add(stringAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // check first < second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testString_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_STRING_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(stringAttr1); + arguments.add(stringAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check first < second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + + /** + * Integer + */ + @Test + public void testInteger_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_INTEGER_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(intAttr1); + arguments.add(intAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // check first < second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + } + + @Test + public void testInteger_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_INTEGER_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(intAttr1); + arguments.add(intAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check first < second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testInteger_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_INTEGER_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(intAttr1); + arguments.add(intAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // check first < second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testInteger_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_INTEGER_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(intAttr1); + arguments.add(intAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check first < second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + + + /** + * Double + */ + @Test + public void testDouble_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DOUBLE_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attr1); + arguments.add(attr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attr1); + arguments.add(attrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + @Test + public void testDouble_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DOUBLE_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attr1); + arguments.add(attr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attr1); + arguments.add(attrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testDouble_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DOUBLE_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attr1); + arguments.add(attr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attr1); + arguments.add(attrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testDouble_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DOUBLE_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attr1); + arguments.add(attr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attr1); + arguments.add(attrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + + /** + * Date + */ + + @Test + public void testDate_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATE_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateToday); + arguments.add(attrDateSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? One with TimeZone and one without + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // test with TimeZone vs without + arguments.clear(); + arguments.add(attrDateWithTimeZone); + arguments.add(attrDateNoTimeZone); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-greater-than Cannot compare this ISO8601DateTime with non-time-zoned ISO8601DateTime", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + } + + @Test + public void testDate_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATE_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateToday); + arguments.add(attrDateSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testDate_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATE_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateToday); + arguments.add(attrDateSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testDate_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATE_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateToday); + arguments.add(attrDateSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateToday); + arguments.add(attrDateYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + + + + + + /** + * Time + */ + + @Test + public void testTime_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_TIME_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrTimeToday); + arguments.add(attrTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? One with TimeZone and one without + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // test with TimeZone vs without + arguments.clear(); + arguments.add(attrTimeWithTimeZone); + arguments.add(attrTimeNoTimeZone); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-greater-than Cannot compare this ISO8601DateTime with non-time-zoned ISO8601DateTime", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + } + + @Test + public void testTime_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_TIME_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrTimeToday); + arguments.add(attrTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testTime_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_TIME_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrTimeToday); + arguments.add(attrTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testTime_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_TIME_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrTimeToday); + arguments.add(attrTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + + + + /** + * Time-in-range + */ + @Test + public void testTime_in_range() { + + FunctionDefinitionTimeInRange<?> fd = (FunctionDefinitionTimeInRange<?>) StdFunctions.FD_TIME_IN_RANGE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_IN_RANGE, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(3), fd.getNumArgs()); + + // arg 0 in range of others + arguments.add(attrTimeToday); + arguments.add(attrTimeYesterday); + arguments.add(attrTimeTommorrow); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // below range + arguments.clear(); + arguments.add(attrTimeYesterday); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // above range + arguments.clear(); + arguments.add(attrTimeTommorrow); + arguments.add(attrTimeYesterday); + arguments.add(attrTimeToday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // range bad + arguments.clear(); + arguments.add(attrTimeToday); + arguments.add(attrTimeTommorrow); + arguments.add(attrTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bad types + arguments.clear(); + arguments.add(attrDateTimeWithTimeZone); + arguments.add(attrDateTimeNoTimeZone); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-in-range Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrDateTimeWithTimeZone); + arguments.add(attrDateTimeNoTimeZone); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-in-range Expected data type 'time' saw 'dateTime' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + /** + * DateTime + */ + + @Test + public void testDateTime_GT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATETIME_GREATER_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_GREATER_THAN, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? One with TimeZone and one without + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // test with TimeZone vs without + arguments.clear(); + arguments.add(attrDateTimeWithTimeZone); + arguments.add(attrDateTimeNoTimeZone); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-greater-than Cannot compare this ISO8601DateTime with non-time-zoned ISO8601DateTime", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + } + + @Test + public void testDateTime_GTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATETIME_GREATER_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_GREATER_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + } + + @Test + public void testDateTime_LT() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATETIME_LESS_THAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_LESS_THAN, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + @Test + public void testDateTime_LTE() { + + FunctionDefinitionComparison<?> fd = (FunctionDefinitionComparison<?>) StdFunctions.FD_DATETIME_LESS_THAN_OR_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_LESS_THAN_OR_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // first == second + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeSameDay); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first < second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeTommorrow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first > second + arguments.clear(); + arguments.add(attrDateTimeToday); + arguments.add(attrDateTimeYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + } + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionDateTimeArithmeticTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionDateTimeArithmeticTest.java new file mode 100644 index 000000000..809733ea8 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionDateTimeArithmeticTest.java @@ -0,0 +1,1602 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.ISO8601Date; +import com.att.research.xacml.std.datatypes.ISO8601DateTime; +import com.att.research.xacml.std.datatypes.ISO8601Time; +import com.att.research.xacml.std.datatypes.ISO8601TimeZone; +import com.att.research.xacml.std.datatypes.XPathDayTimeDuration; +import com.att.research.xacml.std.datatypes.XPathYearMonthDuration; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionDateTimeArithmeticTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + ExpressionResult res; + + + @Test + public void testDateTime_add_dayTimeDuration() { + // Date objects to be adjusted + ISO8601DateTime dateTimeStdExample1 = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601DateTime dateTimeMsecs = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 777)); + ISO8601DateTime dateTimeCrossover = new ISO8601DateTime(null, + new ISO8601Date(2000, 12, 31), + new ISO8601Time(23, 59, 30, 1)); + ISO8601DateTime dateTimeBC = new ISO8601DateTime(null, + new ISO8601Date(-2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601DateTime dateTimeTimeZone0 = new ISO8601DateTime(timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0)); + ISO8601DateTime dateTimeTimeZone5 = new ISO8601DateTime(timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0)); + ISO8601DateTime dateTimeIIC102Result = null; + + // Durations + XPathDayTimeDuration duration0 = new XPathDayTimeDuration(1, 0, 0, 0, 0); + XPathDayTimeDuration durationStdExample1 = new XPathDayTimeDuration(1, 5, 7, 10, 3.3); + XPathDayTimeDuration durationNStdExample1 = new XPathDayTimeDuration(-1, 5, 7, 10, 3.3); + XPathDayTimeDuration durationMsecs = new XPathDayTimeDuration(1, 5, 7, 10, 3.223); + XPathDayTimeDuration durationCrossover = new XPathDayTimeDuration(1, 0, 0, 0, 29.999); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + FunctionArgumentAttributeValue attrDateTimeIIC102 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + FunctionArgumentAttributeValue attrDurationIIC102 = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone5)); + attrDateTimeIIC102 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(DataTypes.DT_DATETIME.convert("2002-03-22T08:23:47-05:00"))); + + dateTimeIIC102Result = DataTypes.DT_DATETIME.convert("2002-03-27T10:23:47-05:00"); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationCrossover)); + attrDurationIIC102 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue("P5DT2H0M0S")); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATETIME_ADD_DAYTIMEDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_ADD_DAYTIMEDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + ISO8601DateTime resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + ISO8601DateTime testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 17), + new ISO8601Time(19, 23, 17, 300) ); + assertEquals(testResponse, resValue); + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 7), + new ISO8601Time(5, 3, 10, 700) ); + assertEquals(testResponse, resValue); + + // millisecs work correctly + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 17), + new ISO8601Time(19, 23, 18, 0) ); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2001, 1, 1), + new ISO8601Time(0, 0, 0, 0) ); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(-2000, 1, 17), + new ISO8601Time(19, 23, 17, 300) ); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 17), + new ISO8601Time(timeZone0, 19, 23, 17, 300) ); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 17), + new ISO8601Time(timeZone5, 19, 23, 17, 300) ); + assertEquals(testResponse, resValue); + + // conformance test IIC102 + arguments.clear(); + arguments.add(attrDateTimeIIC102); + arguments.add(attrDurationIIC102); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(dateTimeIIC102Result, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Expected data type 'dateTime' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + @Test + public void testDateTime_subtract_dayTimeDuration() { + // Date objects to be adjusted + ISO8601DateTime dateTimeStdExample1 = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601DateTime dateTimeMsecs = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 777)); + ISO8601DateTime dateTimeCrossover = new ISO8601DateTime(null, + new ISO8601Date(2001, 1, 1), + new ISO8601Time(0, 0, 0, 0) ); + ISO8601DateTime dateTimeBC = new ISO8601DateTime(null, + new ISO8601Date(-2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601DateTime dateTimeTimeZone0 = new ISO8601DateTime(timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0)); + ISO8601DateTime dateTimeTimeZone5 = new ISO8601DateTime(timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0)); + + // Durations + XPathDayTimeDuration duration0 = new XPathDayTimeDuration(1, 0, 0, 0, 0); + XPathDayTimeDuration durationStdExample1 = new XPathDayTimeDuration(1, 5, 7, 10, 3.3); + XPathDayTimeDuration durationNStdExample1 = new XPathDayTimeDuration(-1, 5, 7, 10, 3.3); + XPathDayTimeDuration durationMsecs = new XPathDayTimeDuration(1, 5, 7, 10, 14.778); + XPathDayTimeDuration durationCrossover = new XPathDayTimeDuration(1, 0, 0, 0, 29.999); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone5)); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(durationCrossover)); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATETIME_SUBTRACT_DAYTIMEDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_SUBTRACT_DAYTIMEDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + ISO8601DateTime resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + ISO8601DateTime testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 7), + new ISO8601Time(5, 3, 10, 700) ); + assertEquals(testResponse, resValue); + + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 17), + new ISO8601Time(19, 23, 17, 300) ); + assertEquals(testResponse, resValue); + + // millisecs work correctly + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 1, 7), + new ISO8601Time(5, 2, 59, 999) ); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2000, 12, 31), + new ISO8601Time(23, 59, 30, 1)); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(-2000, 1, 7), + new ISO8601Time(5, 3, 10, 700) ); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 7), + new ISO8601Time(timeZone0, 5, 3, 10, 700) ); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 7), + new ISO8601Time(timeZone5, 5, 3, 10, 700) ); + assertEquals(testResponse, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Expected data type 'dateTime' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-dayTimeDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + + + + @Test + public void testDateTime_add_yearMonthDuration() { + // Date objects to be adjusted + ISO8601DateTime dateTimeStdExample1 = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601DateTime dateTimeMsecs = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 777)); + ISO8601DateTime dateTimeCrossover = new ISO8601DateTime(null, + new ISO8601Date(2000, 12, 31), + new ISO8601Time(23, 59, 30, 1)); + ISO8601DateTime dateTimeBC = new ISO8601DateTime(null, + new ISO8601Date(-2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601DateTime dateTimeTimeZone0 = new ISO8601DateTime(timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0)); + ISO8601DateTime dateTimeTimeZone5 = new ISO8601DateTime(timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0)); + + // Durations + XPathYearMonthDuration duration0 = new XPathYearMonthDuration(1, 0, 0); + XPathYearMonthDuration durationStdExample1 = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationNStdExample1 = new XPathYearMonthDuration(-1, 5, 7); + XPathYearMonthDuration durationMsecs = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationCrossover = new XPathYearMonthDuration(1, 0, 1); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone5)); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationCrossover)); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATETIME_ADD_YEARMONTHDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_ADD_YEARMONTHDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + ISO8601DateTime resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + ISO8601DateTime testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2005, 8, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(1994, 6, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // millisecs work correctly (not relevant to YearMonth, but should not break + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2005, 8, 12), + new ISO8601Time(12, 13, 14, 777) ); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2001, 1, 31), + new ISO8601Time(23, 59, 30, 1) ); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(-1995, 8, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone0, + new ISO8601Date(timeZone0, 2005, 8, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone5, + new ISO8601Date(timeZone5, 2005, 8, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Expected data type 'dateTime' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + @Test + public void testDateTime_subtract_yearMonthDuration() { + // Date objects to be adjusted + ISO8601DateTime dateTimeStdExample1 = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601DateTime dateTimeMsecs = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 12), + new ISO8601Time(12, 13, 14, 777)); + ISO8601DateTime dateTimeCrossover = new ISO8601DateTime(null, + new ISO8601Date(2000, 1, 1), + new ISO8601Time(23, 59, 30, 1)); + ISO8601DateTime dateTimeBC = new ISO8601DateTime(null, + new ISO8601Date(-2000, 1, 12), + new ISO8601Time(12, 13, 14, 0)); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601DateTime dateTimeTimeZone0 = new ISO8601DateTime(timeZone0, + new ISO8601Date(timeZone0, 2000, 1, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0)); + ISO8601DateTime dateTimeTimeZone5 = new ISO8601DateTime(timeZone5, + new ISO8601Date(timeZone5, 2000, 1, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0)); + + // Durations + XPathYearMonthDuration duration0 = new XPathYearMonthDuration(1, 0, 0); + XPathYearMonthDuration durationStdExample1 = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationNStdExample1 = new XPathYearMonthDuration(-1, 5, 7); + XPathYearMonthDuration durationMsecs = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationCrossover = new XPathYearMonthDuration(1, 0, 1); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(dateTimeTimeZone5)); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationCrossover)); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATETIME_SUBTRACT_YEARMONTHDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_SUBTRACT_YEARMONTHDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + ISO8601DateTime resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + ISO8601DateTime testResponse = new ISO8601DateTime( + null, + new ISO8601Date(1994, 6, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(2005, 8, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // millisecs work correctly (not relevant to YearMonth, but should not break + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(1994, 6, 12), + new ISO8601Time(12, 13, 14, 777) ); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(1999, 12, 1), + new ISO8601Time(23, 59, 30, 1) ); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + null, + new ISO8601Date(-2006, 6, 12), + new ISO8601Time(12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone0, + new ISO8601Date(timeZone0, 1994, 6, 12), + new ISO8601Time(timeZone0, 12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601DateTime.class, res.getValue().getValue().getClass()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + testResponse = new ISO8601DateTime( + timeZone5, + new ISO8601Date(timeZone5, 1994, 6, 12), + new ISO8601Time(timeZone5, 12, 13, 14, 0) ); + assertEquals(testResponse, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Expected data type 'dateTime' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + + + + + + @Test + public void testDate_add_yearMonthDuration() { + // Date objects to be adjusted + ISO8601Date dateTimeStdExample1 = new ISO8601Date(2000, 1, 12); + ISO8601Date dateTimeMsecs =new ISO8601Date(2000, 1, 12); + ISO8601Date dateTimeCrossover = new ISO8601Date(2000, 12, 31); + ISO8601Date dateTimeBC = new ISO8601Date(-2000, 1, 12); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601Date dateTimeTimeZone0 = new ISO8601Date(timeZone0, 2000, 1, 12); + ISO8601Date dateTimeTimeZone5 = new ISO8601Date(timeZone5, 2000, 1, 12); + + // Durations + XPathYearMonthDuration duration0 = new XPathYearMonthDuration(1, 0, 0); + XPathYearMonthDuration durationStdExample1 = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationNStdExample1 = new XPathYearMonthDuration(-1, 5, 7); + XPathYearMonthDuration durationMsecs = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationCrossover = new XPathYearMonthDuration(1, 0, 1); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeTimeZone5)); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationCrossover)); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATE_ADD_YEARMONTHDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_ADD_YEARMONTHDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + ISO8601Date resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + ISO8601Date testResponse = new ISO8601Date(2005, 8, 12); + assertEquals(testResponse, resValue); + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(1994, 6, 12); + assertEquals(testResponse, resValue); + + // millisecs work correctly (not relevant to YearMonth, but should not break + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(2005, 8, 12); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(2001, 1, 31); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(-1995, 8, 12); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(timeZone0, 2005, 8, 12); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(timeZone5, 2005, 8, 12); + assertEquals(testResponse, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Expected data type 'date' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-add-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + @Test + public void testDate_subtract_yearMonthDuration() { + // Date objects to be adjusted + ISO8601Date dateTimeStdExample1 =new ISO8601Date(2000, 1, 12); + ISO8601Date dateTimeMsecs = new ISO8601Date(2000, 1, 12); + ISO8601Date dateTimeCrossover = new ISO8601Date(2000, 1, 1); + ISO8601Date dateTimeBC = new ISO8601Date(-2000, 1, 12); + ISO8601TimeZone timeZone0 = new ISO8601TimeZone(0); + ISO8601TimeZone timeZone5 = new ISO8601TimeZone(5 * 60); + ISO8601Date dateTimeTimeZone0 = new ISO8601Date(timeZone0, 2000, 1, 12); + ISO8601Date dateTimeTimeZone5 = new ISO8601Date(timeZone5, 2000, 1, 12); + + // Durations + XPathYearMonthDuration duration0 = new XPathYearMonthDuration(1, 0, 0); + XPathYearMonthDuration durationStdExample1 = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationNStdExample1 = new XPathYearMonthDuration(-1, 5, 7); + XPathYearMonthDuration durationMsecs = new XPathYearMonthDuration(1, 5, 7); + XPathYearMonthDuration durationCrossover = new XPathYearMonthDuration(1, 0, 1); + + // ARGS declarations + // Dates + FunctionArgumentAttributeValue attrDateTimeStdExample1 = null; + FunctionArgumentAttributeValue attrDateTimeMsecs = null; + FunctionArgumentAttributeValue attrDateTimeCrossover = null; + FunctionArgumentAttributeValue attrDateTimeBC = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone0 = null; + FunctionArgumentAttributeValue attrDateTimeTimeZone5 = null; + + // Durations + FunctionArgumentAttributeValue attrDuration0 = null; + FunctionArgumentAttributeValue attrDurationStdExample1 = null; + FunctionArgumentAttributeValue attrDurationNStdExample1 = null; + FunctionArgumentAttributeValue attrDurationMsecs = null; + FunctionArgumentAttributeValue attrDurationCrossover = null; + + // misc bad + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + // set values + try { + // Date attrs + attrDateTimeStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeStdExample1)); + attrDateTimeMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeMsecs)); + attrDateTimeCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeCrossover)); + attrDateTimeBC = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeBC)); + attrDateTimeTimeZone0 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeTimeZone0)); + attrDateTimeTimeZone5 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(dateTimeTimeZone5)); + + // Duration attrs + attrDuration0 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(duration0)); + attrDurationStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationStdExample1)); + attrDurationNStdExample1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationNStdExample1)); + attrDurationMsecs = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationMsecs)); + attrDurationCrossover = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(durationCrossover)); + + // misc bad + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionDateTimeArithmetic<?,?> fd = (FunctionDefinitionDateTimeArithmetic<?,?>) StdFunctions.FD_DATE_SUBTRACT_YEARMONTHDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_SUBTRACT_YEARMONTHDURATION, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // Duration = 0 => same as original + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDuration0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + ISO8601Date resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(dateTimeStdExample1, resValue); + + + // simple positive operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + ISO8601Date testResponse = new ISO8601Date(1994, 6, 12); + assertEquals(testResponse, resValue); + + // negative operation + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrDurationNStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(2005, 8, 12); + assertEquals(testResponse, resValue); + + // millisecs work correctly (not relevant to YearMonth, but should not break + arguments.clear(); + arguments.add(attrDateTimeMsecs); + arguments.add(attrDurationMsecs); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(1994, 6, 12); + assertEquals(testResponse, resValue); + + // cross minute => cross day => cross month => cross year + arguments.clear(); + arguments.add(attrDateTimeCrossover); + arguments.add(attrDurationCrossover); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(1999, 12, 1); + assertEquals(testResponse, resValue); + + // negative (BC) original date add goes the right direction + arguments.clear(); + arguments.add(attrDateTimeBC); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(-2006, 6, 12); + assertEquals(testResponse, resValue); + + // non-null timezone not changed + // original has timezone offset = 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone0); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(timeZone0, 1994, 6, 12); + assertEquals(testResponse, resValue); + + // original has timezone offset not 0 + arguments.clear(); + arguments.add(attrDateTimeTimeZone5); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(com.att.research.xacml.std.datatypes.ISO8601Date.class, res.getValue().getValue().getClass()); + resValue = (ISO8601Date)res.getValue().getValue(); + testResponse = new ISO8601Date(timeZone5, 1994, 6, 12); + assertEquals(testResponse, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrDurationStdExample1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Expected data type 'date' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrDateTimeStdExample1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-subtract-yearMonthDuration Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionEqualityTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionEqualityTest.java new file mode 100644 index 000000000..9a94ef631 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionEqualityTest.java @@ -0,0 +1,1192 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML1; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.Base64Binary; +import com.att.research.xacml.std.datatypes.DataTypeRFC822Name; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.HexBinary; +import com.att.research.xacml.std.datatypes.RFC822Name; +import com.att.research.xacml.std.datatypes.XPathDayTimeDuration; +import com.att.research.xacml.std.datatypes.XPathYearMonthDuration; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test FunctionDefinitionEquality, all of its super-classes, and all XACML functions supported by that class. + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-equal + * boolean-equal + * integer-equal + * double-equal + * date-equal + * time-equal + * dateTime-equal + * dayTimeDuration-equal + * yearMonthDuration-equal + * + * Each of these is put into a separate test method just to keep things organized. + * + * + */ +public class FunctionDefinitionEqualityTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + FunctionArgumentAttributeValue stringAttr1 = null; + FunctionArgumentAttributeValue stringAttr2 = null; + FunctionArgumentAttributeValue stringAttr3 = null; + FunctionArgumentAttributeValue stringAttr4 = null; + + FunctionArgumentAttributeValue booleanAttrT1 = null; + FunctionArgumentAttributeValue booleanAttrT2 = null; + FunctionArgumentAttributeValue booleanAttrF1 = null; + FunctionArgumentAttributeValue booleanAttrF2 = null; + + FunctionArgumentAttributeValue intAttr1 = null; + FunctionArgumentAttributeValue intAttr1a = null; + FunctionArgumentAttributeValue intAttr2 = null; + FunctionArgumentAttributeValue intAttr0 = null; + FunctionArgumentAttributeValue intAttrNeg1 = null; + + public FunctionDefinitionEqualityTest() { + try { + stringAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("ABC")); + stringAttr4 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("def")); + + booleanAttrT1 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + booleanAttrT2 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + booleanAttrF1 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + booleanAttrF2 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + + intAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + intAttr1a = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + intAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(2)); + intAttr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + intAttrNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(-1)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + } + + + + + /** + * String (matching case) + */ + @Test + public void testString_Equal() { + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_STRING_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check "abc" with "abc" - separate string objects with same value + arguments.add(stringAttr1); + arguments.add(stringAttr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check "abc" with "ABC" (not same) + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + /** + * Boolean + */ + @Test + public void testBoolean_Equal() { + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_BOOLEAN_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_BOOLEAN_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with same value + arguments.add(booleanAttrT1); + arguments.add(booleanAttrT2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check different values + arguments.clear(); + arguments.add(booleanAttrT1); + arguments.add(booleanAttrF1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * Integer + */ + @Test + public void testInteger_Equal() { + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_INTEGER_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with same value + arguments.add(intAttr1); + arguments.add(intAttr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(intAttr1); + arguments.add(intAttrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + /** + * Double + */ + @Test + public void testDouble_Equal() { + FunctionArgumentAttributeValue attr1 = null; + FunctionArgumentAttributeValue attr1a = null; + FunctionArgumentAttributeValue attr2 = null; + FunctionArgumentAttributeValue attrNeg1 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.0)); + attr1a = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.0)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(2.4)); + attrNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(-1.0)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_DOUBLE_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attr1); + arguments.add(attr1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attr1); + arguments.add(attr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attr1); + arguments.add(attrNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + + + /** + * Date + */ + @Test + public void testDate_Equal() { + Calendar calendar = Calendar.getInstance(); + Date today = calendar.getTime(); + Date longAgo = new Date(1234); + // create a date that is different than "today" but within the same day (i.e. has a different hour) + if (calendar.get(Calendar.HOUR_OF_DAY) > 3) { + calendar.set(Calendar.HOUR_OF_DAY, 3); + } else { + calendar.set(Calendar.HOUR_OF_DAY, 5); + } + Date todayPlus = calendar.getTime(); + + + FunctionArgumentAttributeValue attrToday = null; + FunctionArgumentAttributeValue attrToday2 = null; + FunctionArgumentAttributeValue attrLaterToday = null; + FunctionArgumentAttributeValue attrYesterday = null; + try { + attrToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(today)); + attrToday2 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(today)); + attrLaterToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(todayPlus)); + attrYesterday = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue(longAgo)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_DATE_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrToday); + arguments.add(attrToday2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrToday); + arguments.add(attrYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // Date objects with different times but within the same day should match + arguments.clear(); + arguments.add(attrToday); + arguments.add(attrLaterToday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + + /** + * Time + */ + @Test + public void testTime_Equal() { + + Date now = new Date(); + Date now2 = new Date(now.getTime()); + Date notNow = new Date(now.getTime() - 100000); + + FunctionArgumentAttributeValue attrNow = null; + FunctionArgumentAttributeValue attrNow2 = null; + FunctionArgumentAttributeValue attrNotNow = null; + try { + attrNow = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(now)); + attrNow2 = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(now2)); + attrNotNow = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue(notNow)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_TIME_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrNow); + arguments.add(attrNow2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrNow); + arguments.add(attrNotNow); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + + /** + * DateTime + */ + @Test + public void testDateTime_Equal() { + Calendar calendar = Calendar.getInstance(); + Date today = calendar.getTime(); + Date longAgo = new Date(1234); + // create a dateTime that is different than "today" changing only the Timezone + if (calendar.get(Calendar.ZONE_OFFSET) > 3) { + calendar.set(Calendar.ZONE_OFFSET, 3); + } else { + calendar.set(Calendar.ZONE_OFFSET, 5); + } + Date todayPlus = calendar.getTime(); + + + FunctionArgumentAttributeValue attrToday = null; + FunctionArgumentAttributeValue attrToday2 = null; + FunctionArgumentAttributeValue attrLaterToday = null; + FunctionArgumentAttributeValue attrYesterday = null; + try { + attrToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(today)); + attrToday2 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(today)); + attrLaterToday = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(todayPlus)); + attrYesterday = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue(longAgo)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + // String exact match + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_DATETIME_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrToday); + arguments.add(attrToday2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrToday); + arguments.add(attrYesterday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // DateTime with different Zones should not match + arguments.clear(); + arguments.add(attrToday); + arguments.add(attrLaterToday); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * dayTimeDuration - Version1 + */ + @Test + public void testDayTimeDuration_Equal_V1() { + + XPathDayTimeDuration dur1 = new XPathDayTimeDuration(1, 3, 5, 12, 38); + XPathDayTimeDuration dur2 = new XPathDayTimeDuration(1, 3, 5, 12, 38); + XPathDayTimeDuration differentDur = new XPathDayTimeDuration(-1, 4, 7, 5, 33); + + FunctionArgumentAttributeValue attrDur1 = null; + FunctionArgumentAttributeValue attrDur2 = null; + FunctionArgumentAttributeValue attrDifferentDur = null; + try { + attrDur1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(dur1)); + attrDur2 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(dur2)); + attrDifferentDur = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(differentDur)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_DAYTIMEDURATION_EQUAL_VERSION1; + + // check identity and type of the thing created + assertEquals(XACML1.ID_FUNCTION_DAYTIMEDURATION_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DAYTIMEDURATION.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrDur1); + arguments.add(attrDur2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrDur1); + arguments.add(attrDifferentDur); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * dayTimeDuration - Current version + */ + @Test + public void testDayTimeDuration_Equal() { + + XPathDayTimeDuration dur1 = new XPathDayTimeDuration(1, 3, 5, 12, 38); + XPathDayTimeDuration dur2 = new XPathDayTimeDuration(1, 3, 5, 12, 38); + XPathDayTimeDuration differentDur = new XPathDayTimeDuration(-1, 4, 7, 5, 33); + + FunctionArgumentAttributeValue attrDur1 = null; + FunctionArgumentAttributeValue attrDur2 = null; + FunctionArgumentAttributeValue attrDifferentDur = null; + try { + attrDur1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(dur1)); + attrDur2 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(dur2)); + attrDifferentDur = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(differentDur)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_DAYTIMEDURATION_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DAYTIMEDURATION_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_DAYTIMEDURATION.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrDur1); + arguments.add(attrDur2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrDur1); + arguments.add(attrDifferentDur); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + /** + * dayTimeDuration - Version1 + */ + @Test + public void testYearMonthDuration_Equal_V1() { + + XPathYearMonthDuration dur1 = new XPathYearMonthDuration(1, 3, 5); + XPathYearMonthDuration dur2 = new XPathYearMonthDuration(1, 3, 5); + XPathYearMonthDuration differentDur = new XPathYearMonthDuration(-1, 4, 7); + + FunctionArgumentAttributeValue attrDur1 = null; + FunctionArgumentAttributeValue attrDur2 = null; + FunctionArgumentAttributeValue attrDifferentDur = null; + try { + attrDur1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(dur1)); + attrDur2 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(dur2)); + attrDifferentDur = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(differentDur)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_YEARMONTHDURATION_EQUAL_VERSION1; + + // check identity and type of the thing created + assertEquals(XACML1.ID_FUNCTION_YEARMONTHDURATION_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_YEARMONTHDURATION.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrDur1); + arguments.add(attrDur2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrDur1); + arguments.add(attrDifferentDur); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + + /** + * dayTimeDuration - Current version + */ + @Test + public void testYearMonthDuration_Equal() { + + XPathYearMonthDuration dur1 = new XPathYearMonthDuration(1, 3, 5); + XPathYearMonthDuration dur2 = new XPathYearMonthDuration(1, 3, 5); + XPathYearMonthDuration differentDur = new XPathYearMonthDuration(-1, 4, 7); + + FunctionArgumentAttributeValue attrDur1 = null; + FunctionArgumentAttributeValue attrDur2 = null; + FunctionArgumentAttributeValue attrDifferentDur = null; + try { + attrDur1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(dur1)); + attrDur2 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(dur2)); + attrDifferentDur = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(differentDur)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_YEARMONTHDURATION_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_YEARMONTHDURATION_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_YEARMONTHDURATION.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrDur1); + arguments.add(attrDur2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrDur1); + arguments.add(attrDifferentDur); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * URI + */ + @Test + public void testAnyURI_Equal() { + + URI uri1 = null; + URI uri2 = null; + URI uriNotThere = null; + try { + uri1 = new URI("http://someplace.com/gothere"); + uri2 = new URI("http://someplace.com/gothere"); + uriNotThere = new URI("http://someplace.com/notGoingThere"); + } catch (Exception e) { + fail(e.toString()); + } + + FunctionArgumentAttributeValue attrUri1 = null; + FunctionArgumentAttributeValue attrUri2 = null; + FunctionArgumentAttributeValue attrUriNotThere = null; + try { + attrUri1 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(uri1)); + attrUri2 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(uri2)); + attrUriNotThere = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(uriNotThere)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_ANYURI_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_ANYURI.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrUri1); + arguments.add(attrUri2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrUri1); + arguments.add(attrUriNotThere); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * X500Name + */ + @Test + public void testX500Name_Equal() { + + X500Principal name1 = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US"); + X500Principal name2 = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US"); + X500Principal name3 = new X500Principal("CN=NotDuke, OU=NotThere, O=Oracle, C=US"); + + + FunctionArgumentAttributeValue attrName1 = null; + FunctionArgumentAttributeValue attrName1a = null; + FunctionArgumentAttributeValue attrNotSameName = null; + try { + attrName1 = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(name1)); + attrName1a = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(name2)); + attrNotSameName = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(name3)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_X500NAME_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_X500NAME_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_X500NAME.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrName1); + arguments.add(attrName1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrName1); + arguments.add(attrNotSameName); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + + /** + * RFC822Name + */ + @Test + public void testRfc822Name_Equal() { + + RFC822Name name1 = null; + RFC822Name name1a = null; + RFC822Name differentLocalName = null; + RFC822Name differentDomainName = null; + RFC822Name localCaseName = null; + RFC822Name domainCaseName = null; + @SuppressWarnings("unused") + RFC822Name noAtName = null; + + try { + name1 = RFC822Name.newInstance("localPart@DomainPart"); + name1a = RFC822Name.newInstance("localPart@DomainPart"); + differentLocalName = RFC822Name.newInstance("differentlocalPart@DomainPart"); + differentDomainName = RFC822Name.newInstance("localPart@differentDomainPart"); + localCaseName = RFC822Name.newInstance("LOCALPart@DomainPart"); + domainCaseName = RFC822Name.newInstance("localPart@DOMAINPart"); + + + } catch (Exception e) { + fail(e.toString()); + } + + // should not be able to create a name without an @. If you try, newInstance returns null + Exception exSeen = null; + try { + noAtName = RFC822Name.newInstance("nameWithoutAnAtSign"); + } catch (Exception e) { + exSeen = e; + } + assertNotNull(exSeen); + + + FunctionArgumentAttributeValue attrName1 = null; + FunctionArgumentAttributeValue attrName1a = null; + FunctionArgumentAttributeValue attrDifferentLocalName = null; + FunctionArgumentAttributeValue attrDifferentDomainName = null; + FunctionArgumentAttributeValue attrLocalCaseName = null; + FunctionArgumentAttributeValue attrDomainCaseName = null; + try { + attrName1 = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(name1)); + attrName1a = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(name1a)); + attrDifferentLocalName = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(differentLocalName)); + attrDifferentDomainName = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(differentDomainName)); + attrLocalCaseName = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(localCaseName)); + attrDomainCaseName = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(domainCaseName)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_RFC822NAME_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_RFC822NAME_EQUAL, fd.getId()); + assertEquals(DataTypeRFC822Name.newInstance().getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrName1); + arguments.add(attrName1a); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same Local + arguments.clear(); + arguments.add(attrName1); + arguments.add(attrDifferentLocalName); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // check not same Domain + arguments.clear(); + arguments.add(attrName1); + arguments.add(attrDifferentDomainName); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test case-sensitivity in local part + arguments.clear(); + arguments.add(attrName1); + arguments.add(attrLocalCaseName); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test non-case-sensitivity in Domain part + arguments.clear(); + arguments.add(attrName1); + arguments.add(attrDomainCaseName); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * Hex Binary + */ + @Test + public void testHexBinary_Equal() { + HexBinary binary = null; + HexBinary sameBinary = null; + HexBinary differentBinary = null; + try { + binary = HexBinary.newInstance("e04fd020ea3a6910a2d808002b30309d"); + sameBinary = HexBinary.newInstance("e04fd020ea3a6910a2d808002b30309d"); + differentBinary = HexBinary.newInstance("f123a890ee3d"); + } catch (Exception e) { + fail(e.toString()); + } + + FunctionArgumentAttributeValue attrBinary = null; + FunctionArgumentAttributeValue attrSameBinary = null; + FunctionArgumentAttributeValue attrDifferentBinary = null;; + try { + attrBinary = new FunctionArgumentAttributeValue(DataTypes.DT_HEXBINARY.createAttributeValue(binary)); + attrSameBinary = new FunctionArgumentAttributeValue(DataTypes.DT_HEXBINARY.createAttributeValue(sameBinary)); + attrDifferentBinary = new FunctionArgumentAttributeValue(DataTypes.DT_HEXBINARY.createAttributeValue(differentBinary)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_HEXBINARY_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_HEXBINARY_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_HEXBINARY.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrBinary); + arguments.add(attrSameBinary); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrBinary); + arguments.add(attrDifferentBinary); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } + + + /** + * Base64 Binary + */ + @Test + public void testBase64Binary_Equal() { + Base64Binary binary = null; + Base64Binary sameBinary = null; + Base64Binary differentBinary = null; + try { + binary = Base64Binary.newInstance("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"); + sameBinary = Base64Binary.newInstance("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"); + differentBinary = Base64Binary.newInstance("f123a890ee3d"); + } catch (Exception e) { + fail(e.toString()); + } + + FunctionArgumentAttributeValue attrBinary = null; + FunctionArgumentAttributeValue attrSameBinary = null; + FunctionArgumentAttributeValue attrDifferentBinary = null; + try { + attrBinary = new FunctionArgumentAttributeValue(DataTypes.DT_BASE64BINARY.createAttributeValue(binary)); + attrSameBinary = new FunctionArgumentAttributeValue(DataTypes.DT_BASE64BINARY.createAttributeValue(sameBinary)); + attrDifferentBinary = new FunctionArgumentAttributeValue(DataTypes.DT_BASE64BINARY.createAttributeValue(differentBinary)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_BASE64BINARY_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_BASE64BINARY_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_BASE64BINARY.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + // test normal equals and non-equals + // check separate objects with the same value + arguments.add(attrBinary); + arguments.add(attrSameBinary); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check not same + arguments.clear(); + arguments.add(attrBinary); + arguments.add(attrDifferentBinary); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHigherOrderBagTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHigherOrderBagTest.java new file mode 100644 index 000000000..95a83d76e --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHigherOrderBagTest.java @@ -0,0 +1,2193 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionHigherOrderBagTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + + // + // ANY-OF tests + // + + + @Test + public void testAny_of() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansTrue = null; + Bag bagStringBooleansFalse = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrb = null; + FunctionArgumentAttributeValue attrh = null; + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrb = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(b)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + FunctionArgumentBag attrBagStringBooleansFalse = new FunctionArgumentBag(bagStringBooleansFalse); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ANY_OF; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANY_OF, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attra); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag in first position - match + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagabcdefg); + arguments.add(attra); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attra); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // multiple primitives + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + arguments.add(attrb); + arguments.add(attrBagace); + arguments.add(attra); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Predicate error: function:string-equal Expected 2 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // no primitives - predicate function expects 2 + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Predicate error: function:string-equal Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansFalse); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Did not get any Bag argument; must have at least 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // extra bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of must have only 1 bag; found one at index 2 and another at 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Predicate error: function:string-equal Expected data type 'string' saw 'anyURI' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Predicate Function (first argument) was null", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of Got null argument at index 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + @Test + public void testAll_of() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + String w = "w"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrh = null; + FunctionArgumentAttributeValue attrw = null; + + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThan = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + attrw = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(w)); + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateStringGreaterThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + FunctionArgumentBag attrBagStringBooleansFalse = new FunctionArgumentBag(bagStringBooleansFalse); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ALL_OF; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ALL_OF, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrw); + arguments.add(attrBagace); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attra); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // no primitives - predicate function expects 2 + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Predicate error: function:string-equal Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansFalse); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Did not get any Bag argument; must have at least 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // extra bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of must have only 1 bag; found one at index 2 and another at 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Predicate error: function:string-greater-than Expected data type 'string' saw 'anyURI' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Predicate Function (first argument) was null", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of Got null argument at index 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + + @Test + public void testAny_of_any() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + String w = "w"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + Bag bagBooleansFalse = null; + Bag bagBooleansTrue = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrh = null; + FunctionArgumentAttributeValue attrw = null; + + + FunctionArgumentAttributeValue attrInt4 = null; + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThan = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + FunctionArgumentAttributeValue attrPredicateNof = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagBooleansTrue = new Bag(); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + bagBooleansFalse = new Bag(); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + attrw = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(w)); + + attrInt4 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(4)); + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateStringGreaterThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + attrPredicateNof = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_N_OF)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + FunctionArgumentBag attrBagStringBooleansFalse = new FunctionArgumentBag(bagStringBooleansFalse); + FunctionArgumentBag attrBagBooleansTrue = new FunctionArgumentBag(bagBooleansTrue); + FunctionArgumentBag attrBagBooleansFalse = new FunctionArgumentBag(bagBooleansFalse); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ANY_OF_ANY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANY_OF_ANY, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrw); + arguments.add(attrBagace); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attra); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // no primitives - predicate function expects 2 + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Predicate error: function:string-equal Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansFalse); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // n-of with lots of bags - success + arguments.clear(); + arguments.add(attrPredicateNof); + arguments.add(attrInt4); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // n-of with lots of bags - fail + arguments.clear(); + arguments.add(attrPredicateNof); + arguments.add(attrInt4); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansTrue); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + arguments.add(attrBagBooleansFalse); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Bag is empty at index 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Predicate error: function:string-greater-than Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Predicate error: function:string-greater-than Expected data type 'string' saw 'anyURI' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Predicate Function (first argument) was null", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-any Got null argument at index 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + + + + @Test + public void testAll_of_any() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + String w = "w"; + String x = "x"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagawx = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + Bag bagBooleansFalse = null; + Bag bagBooleansTrue = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrh = null; + + + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateStringLessThan = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThan = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagawx = new Bag(); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(w)); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(x)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagBooleansTrue = new Bag(); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + bagBooleansFalse = new Bag(); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateStringLessThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_LESS_THAN)); + attrPredicateStringGreaterThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagawx = new FunctionArgumentBag(bagawx); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ALL_OF_ANY; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ALL_OF_ANY, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringLessThan); + arguments.add(attrBagabcdefg); + arguments.add(attrBagawx); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagawx); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // primitive instead of bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attra); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any 2nd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + arguments.add(attra); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any 3rd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Predicate error: function:boolean-from-string Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagEmpty); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any 2nd argument must be bag, got 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Predicate error: function:string-greater-than Expected data type 'string' saw 'integer' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Expected at least 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Expected at least 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Expected 3 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-any 3rd argument must be bag, got 'null'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + @Test + public void testAny_of_all() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + String w = "w"; + String x = "x"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagewx = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + Bag bagBooleansFalse = null; + Bag bagBooleansTrue = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrh = null; + + + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThanOrEqual = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThan = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagewx = new Bag(); + bagewx.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagewx.add(DataTypes.DT_STRING.createAttributeValue(w)); + bagewx.add(DataTypes.DT_STRING.createAttributeValue(x)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagBooleansTrue = new Bag(); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + bagBooleansFalse = new Bag(); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateStringGreaterThanOrEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN_OR_EQUAL)); + attrPredicateStringGreaterThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagewx = new FunctionArgumentBag(bagewx); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ANY_OF_ALL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANY_OF_ALL, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThanOrEqual); + arguments.add(attrBagewx); + arguments.add(attrBagace); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagewx); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // primitive instead of bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attra); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all 2nd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + arguments.add(attra); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all 3rd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Predicate error: function:boolean-from-string Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagEmpty); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all 2nd argument must be bag, got 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Predicate error: function:string-greater-than Expected data type 'string' saw 'integer' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Expected at least 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Expected at least 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Expected 3 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:any-of-all 3rd argument must be bag, got 'null'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + @Test + public void testAll_of_all() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + String w = "w"; + String x = "x"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagawx = null; + Bag bagwx = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + Bag bagBooleansFalse = null; + Bag bagBooleansTrue = null; + + + // primitive attrs + FunctionArgumentAttributeValue attra = null; + FunctionArgumentAttributeValue attrh = null; + + + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringEqual = null; + FunctionArgumentAttributeValue attrPredicateStringIntersection = null; + FunctionArgumentAttributeValue attrPredicateStringGreaterThan = null; + FunctionArgumentAttributeValue attrPredicateBooleanFromString = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagawx = new Bag(); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(w)); + bagawx.add(DataTypes.DT_STRING.createAttributeValue(x)); + bagwx = new Bag(); + bagwx.add(DataTypes.DT_STRING.createAttributeValue(w)); + bagwx.add(DataTypes.DT_STRING.createAttributeValue(x)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagBooleansTrue = new Bag(); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansTrue.add(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + bagBooleansFalse = new Bag(); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + bagBooleansFalse.add(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + + + // create primitive attrs + attra = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(a)); + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + + + + // predicates passed as function arguments + attrPredicateStringEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_EQUAL)); + attrPredicateStringIntersection = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_INTERSECTION)); + attrPredicateStringGreaterThan = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_GREATER_THAN)); + attrPredicateBooleanFromString = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagawx = new FunctionArgumentBag(bagawx); + FunctionArgumentBag attrBagwx = new FunctionArgumentBag(bagwx); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_ALL_OF_ALL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ALL_OF_ALL, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagwx); + arguments.add(attrBagace); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // normal no-match + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagawx); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagwx); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // primitive instead of bag + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attra); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all 2nd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrPredicateStringEqual); + arguments.add(attrBagace); + arguments.add(attra); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all 3rd argument must be bag, got 'string'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no primitives - predicate expects only 1 arg + arguments.clear(); + arguments.add(attrPredicateBooleanFromString); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Predicate error: function:boolean-from-string Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagace); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagEmpty); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-boolean predicate + arguments.clear(); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Predicate Function must return boolean, but 'urn:oasis:names:tc:xacml:1.0:function:string-intersection' returns 'string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate after first arg + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrPredicateStringIntersection); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all 2nd argument must be bag, got 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagwx); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Predicate error: function:string-greater-than Expected data type 'string' saw 'integer' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Expected at least 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Expected at least 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Expected 3 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringGreaterThan); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:all-of-all 3rd argument must be bag, got 'null'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + @Test + public void testMap() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + Bag bagStringBooleansFalse = null; + Bag bagStringBooleansTrue = null; + Bag bagInt123 = null; + Bag bagInt789 = null; + + + // primitive attrs + FunctionArgumentAttributeValue attrh = null; + FunctionArgumentAttributeValue attrInt7 = null; + + + + // predicates passed as arguments + FunctionArgumentAttributeValue attrPredicateStringNormalizeToLowerCase = null; + FunctionArgumentAttributeValue attrPredicateIntegerEqual = null; + FunctionArgumentAttributeValue attrPredicateIntegerAdd = null; + + try { + + // Create Bag contents + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue("A")); + bagace.add(DataTypes.DT_STRING.createAttributeValue("C")); + bagace.add(DataTypes.DT_STRING.createAttributeValue("E")); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + bagStringBooleansTrue = new Bag(); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansTrue.add(DataTypes.DT_STRING.createAttributeValue("true")); + bagStringBooleansFalse = new Bag(); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagStringBooleansFalse.add(DataTypes.DT_STRING.createAttributeValue("false")); + bagInt123 = new Bag(); + bagInt123.add(DataTypes.DT_INTEGER.createAttributeValue(1)); + bagInt123.add(DataTypes.DT_INTEGER.createAttributeValue(2)); + bagInt123.add(DataTypes.DT_INTEGER.createAttributeValue(3)); + bagInt789 = new Bag(); + bagInt789.add(DataTypes.DT_INTEGER.createAttributeValue(7)); + bagInt789.add(DataTypes.DT_INTEGER.createAttributeValue(8)); + bagInt789.add(DataTypes.DT_INTEGER.createAttributeValue(9)); + + + + // create primitive attrs + attrh = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(h)); + attrInt7 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(7)); + + + // predicates passed as function arguments + attrPredicateStringNormalizeToLowerCase = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_STRING_NORMALIZE_TO_LOWER_CASE)); + attrPredicateIntegerEqual = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_INTEGER_EQUAL)); + attrPredicateIntegerAdd = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(XACML3.ID_FUNCTION_INTEGER_ADD)); + + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + FunctionArgumentBag attrBagStringBooleansTrue = new FunctionArgumentBag(bagStringBooleansTrue); + FunctionArgumentBag attrBagInt789 = new FunctionArgumentBag(bagInt789); + + FunctionDefinitionHigherOrderBag<?,?> fd = (FunctionDefinitionHigherOrderBag<?,?>) StdFunctions.FD_MAP; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_MAP, fd.getId()); + assertNull( fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // normal match + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrBagace); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertTrue(res.isBag()); + Bag bag = res.getBag(); + assertEquals(3, bag.size()); + List<AttributeValue<?>> bagAttributes = bag.getAttributeValueList(); + try { + assertTrue(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("a"))); + assertFalse(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("A"))); + assertTrue(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("c"))); + assertFalse(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("C"))); + assertTrue(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("e"))); + assertFalse(bagAttributes.contains(DataTypes.DT_STRING.createAttributeValue("E"))); + } catch (Exception ex) { + fail("checking result e="+ex); + } + + // 2-input predicate + arguments.clear(); + arguments.add(attrPredicateIntegerAdd); + arguments.add(attrInt7); + arguments.add(attrBagInt789); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertTrue(res.isBag()); + bag = res.getBag(); + assertEquals(3, bag.size()); + bagAttributes = bag.getAttributeValueList(); + try { + assertTrue(bagAttributes.contains(DataTypes.DT_INTEGER.createAttributeValue("14"))); + assertTrue(bagAttributes.contains(DataTypes.DT_INTEGER.createAttributeValue("15"))); + assertTrue(bagAttributes.contains(DataTypes.DT_INTEGER.createAttributeValue("16"))); + } catch (Exception ex) { + fail("checking result e="+ex); + } + + + // predicate returns booleans + arguments.clear(); + arguments.add(attrPredicateIntegerEqual); + arguments.add(attrInt7); + arguments.add(attrBagInt789); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertTrue(res.isBag()); + bag = res.getBag(); + assertEquals(3, bag.size()); + bagAttributes = bag.getAttributeValueList(); + try { + assertEquals(bagAttributes.get(0), (DataTypes.DT_BOOLEAN.createAttributeValue(true))); + assertEquals(bagAttributes.get(1), (DataTypes.DT_BOOLEAN.createAttributeValue(false))); + assertEquals(bagAttributes.get(2), (DataTypes.DT_BOOLEAN.createAttributeValue(false))); + } catch (Exception ex) { + fail("checking result e="+ex); + } + + // predicate returns bag + + + + // no primitives - predicate function expects 2 + arguments.clear(); + arguments.add(attrPredicateIntegerAdd); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Predicate error: function:integer-add Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bag is empty + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrh); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertTrue(res.isBag()); + bag = res.getBag(); + assertEquals(0, bag.size());; + + // no bag + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrh); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Did not get any Bag argument; must have at least 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // extra bag + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + arguments.add(attrh); + arguments.add(attrBagStringBooleansTrue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map must have only 1 bag; found one at index 2 and another at 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad predicate + arguments.clear(); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map First argument expected URI, got http://www.w3.org/2001/XMLSchema#string", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate gets unexpected number of args + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Predicate error: function:string-normalize-to-lower-case Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // predicate gets bad primitive type + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Predicate error: function:string-normalize-to-lower-case Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bags of different types + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrh); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Predicate Function (first argument) was null", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrPredicateStringNormalizeToLowerCase); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:map Got null argument at index 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHomogeneousSimpleTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHomogeneousSimpleTest.java new file mode 100644 index 000000000..c72bfaba1 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionHomogeneousSimpleTest.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.Status; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * FunctionDefinitionHomogeneousSimple is an abstract class, so we have to test it by creating a sub-class. + * The constructor is tested by default when an instance of the sub-class is created for other tests. + * + * Each of these functions needs to be tested for each type of function to be sure the values are correct, + * so this is just a simple test to see that the mechanism works. + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionHomogeneousSimpleTest { + + + + @Test + public void testGetDataTypeArgs() { + + // test a simple instance using the Equality class + FunctionDefinitionEquality<String> fd = new FunctionDefinitionEquality<String>(XACML3.ID_FUNCTION_STRING_EQUAL, DataTypes.DT_STRING); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + } + + @Test + public void testGetNumArgs() { + // test a simple instance using the Equality class + FunctionDefinitionEquality<String> fd = new FunctionDefinitionEquality<String>(XACML3.ID_FUNCTION_STRING_EQUAL, DataTypes.DT_STRING); + assertEquals(new Integer(2), fd.getNumArgs()); + } + + @Test + public void testValidateArguments() { + // create some arguments to use later + FunctionArgumentAttributeValue stringAttr1 = null; + FunctionArgumentAttributeValue stringAttr2 = null; + FunctionArgumentAttributeValue stringAttr3 = null; + FunctionArgumentAttributeValue intAttr = null; + try { + stringAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("def")); + stringAttr3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("ghi")); + intAttr = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionEquality<String> fd = new FunctionDefinitionEquality<String>(XACML3.ID_FUNCTION_STRING_EQUAL, DataTypes.DT_STRING); + List<String> convertedValues = new ArrayList<>(); + List<FunctionArgument> listFunctionArguments = new ArrayList<>(); + + // test correct # of args, both of them strings + listFunctionArguments.add(stringAttr1); + listFunctionArguments.add(stringAttr2); + Status status = fd.validateArguments(listFunctionArguments, convertedValues); + assertTrue(status.isOk()); + assertEquals(convertedValues.size(),2); + + // test too few args + listFunctionArguments.remove(1); + status = fd.validateArguments(listFunctionArguments, convertedValues); + assertFalse(status.isOk()); + assertEquals("Expected 2 arguments, got 1", status.getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", status.getStatusCode().getStatusCodeValue().stringValue()); + + // test too many args + listFunctionArguments.add(stringAttr2); + listFunctionArguments.add(stringAttr3); + status = fd.validateArguments(listFunctionArguments, convertedValues); + assertFalse(status.isOk()); + assertEquals("Expected 2 arguments, got 3", status.getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", status.getStatusCode().getStatusCodeValue().stringValue()); + + // test with null arg + listFunctionArguments.clear(); + listFunctionArguments.add(null); + listFunctionArguments.add(stringAttr1); + status = fd.validateArguments(listFunctionArguments, convertedValues); + assertFalse(status.isOk()); + assertEquals("Got null argument at arg index 0", status.getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", status.getStatusCode().getStatusCodeValue().stringValue()); + + // test function that takes 0 args +//TODO test with func that specifies 0 args? ASSUME for now that there are no such functions since a function needs to operate on something +// fail("need to test function with 0 args and various inputs - see validateArguments code"); + + + // test with one is a bag + listFunctionArguments.clear(); + listFunctionArguments.add(stringAttr1); + Bag bag = new Bag(); + FunctionArgument bagArg = new FunctionArgumentBag(bag); + listFunctionArguments.add(bagArg); + status = fd.validateArguments(listFunctionArguments, convertedValues); + assertFalse(status.isOk()); + assertEquals("Expected a simple value, saw a bag at arg index 1", status.getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", status.getStatusCode().getStatusCodeValue().stringValue()); + + // test with string and int + listFunctionArguments.clear(); + listFunctionArguments.add(stringAttr1); + listFunctionArguments.add(intAttr); + status = fd.validateArguments(listFunctionArguments, convertedValues); + assertFalse(status.isOk()); + assertEquals("Expected data type 'string' saw 'integer' at arg index 1", status.getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", status.getStatusCode().getStatusCodeValue().stringValue()); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionLogicalTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionLogicalTest.java new file mode 100644 index 000000000..1778dd112 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionLogicalTest.java @@ -0,0 +1,422 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionLogicalTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + // use the same args for each test + FunctionArgumentAttributeValue attrT = null; + FunctionArgumentAttributeValue attrF = null; + public FunctionDefinitionLogicalTest () { + try { + attrT = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(true)); + attrF = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(false)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + } + + + @Test + public void testOR() { + FunctionArgumentAttributeValue attr5 = null; + try { + attr5 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionLogical fd = (FunctionDefinitionLogical) StdFunctions.FD_OR; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_OR, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // test normal + arguments.add(attrT); + arguments.add(attrF); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + arguments.clear(); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + // test no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + // first true, second error + arguments.clear(); + arguments.add(attrT); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // first false, second error + arguments.clear(); + arguments.add(attrF); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:or Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // multiple false + arguments.clear(); + arguments.add(attrF); + arguments.add(attrF); + arguments.add(attrF); + arguments.add(attrF); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + // non-boolean + arguments.clear(); + arguments.add(attrF); + arguments.add(attr5); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:or Expected data type 'boolean' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first arg error + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:or Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testAND() { + FunctionArgumentAttributeValue attr5 = null; + try { + attr5 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + + FunctionDefinitionLogical fd = (FunctionDefinitionLogical) StdFunctions.FD_AND; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_AND, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // test normal + arguments.add(attrT); + arguments.add(attrF); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + arguments.clear(); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + // test no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // first true, second error + arguments.clear(); + arguments.add(attrT); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:and Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first false, second error + arguments.clear(); + arguments.add(attrF); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + // multiple true + arguments.clear(); + arguments.add(attrT); + arguments.add(attrT); + arguments.add(attrT); + arguments.add(attrT); + arguments.add(attrT); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // non-boolean + arguments.clear(); + arguments.add(attrT); + arguments.add(attr5); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals("function:and Expected data type 'boolean' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // first arg error + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals("function:and Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + @Test + public void testN_of() { + FunctionArgumentAttributeValue attr0 = null; + FunctionArgumentAttributeValue attr2 = null; + try { + attr0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attr2 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(2)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + + FunctionDefinitionLogical fd = (FunctionDefinitionLogical) StdFunctions.FD_N_OF; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_N_OF, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // test normal + arguments.add(attr2); + arguments.add(attrT); + arguments.add(attrF); + arguments.add(attrT); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // normal fail + arguments.clear(); + arguments.add(attr2); + arguments.add(attrT); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + + // null count + arguments.clear(); + arguments.add(null); + arguments.add(attrT); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // 0 count + arguments.clear(); + arguments.add(attr0); + arguments.add(attrT); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // bad object type for count + arguments.clear(); + arguments.add(attrT); + arguments.add(attrT); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:n-of For input string: \"true\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // count larger than list + arguments.clear(); + arguments.add(attr2); + arguments.add(attrT); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:n-of Expected 2 arguments but only 1 arguments in list after the count", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // aborts after find ok + arguments.clear(); + arguments.add(attr2); + arguments.add(attrT); + arguments.add(attrT); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // error before find ok + arguments.clear(); + arguments.add(attr2); + arguments.add(null); + arguments.add(attrT); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:n-of Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // non-boolean in list + arguments.clear(); + arguments.add(attr2); + arguments.add(attrT); + arguments.add(attr0); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:n-of Expected data type 'boolean' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testNot() { + + FunctionDefinitionLogical fd = (FunctionDefinitionLogical) StdFunctions.FD_NOT; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_NOT, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // test normal + arguments.clear(); + arguments.add(attrT); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(false), resValue); + + arguments.clear(); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + + // test null/0 args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:not Expected 1 argument, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // test 2 args + arguments.clear(); + arguments.add(attrT); + arguments.add(attrF); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:not Expected 1 argument, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionNumberTypeConversionTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionNumberTypeConversionTest.java new file mode 100644 index 000000000..471025e12 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionNumberTypeConversionTest.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Tests for various classes containing only one function. + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionNumberTypeConversionTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + @Test + public void testDouble_to_integer() { + FunctionArgumentAttributeValue attr1 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(5.432)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionNumberTypeConversion<?, ?> fd = (FunctionDefinitionNumberTypeConversion<?, ?>) StdFunctions.FD_DOUBLE_TO_INTEGER; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_TO_INTEGER, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(BigInteger.valueOf(5), resValue); + } + + + @Test + public void testInteger_to_double() { + FunctionArgumentAttributeValue attr1 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(5)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionNumberTypeConversion<?, ?> fd = (FunctionDefinitionNumberTypeConversion<?, ?>) StdFunctions.FD_INTEGER_TO_DOUBLE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_TO_DOUBLE, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(5.0), resValue); + } + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionRegexpMatchTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionRegexpMatchTest.java new file mode 100644 index 000000000..c631e1e2d --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionRegexpMatchTest.java @@ -0,0 +1,511 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.IPAddress; +import com.att.research.xacml.std.datatypes.RFC2396DomainName; +import com.att.research.xacml.std.datatypes.RFC822Name; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionRegexpMatchTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + @Test + public void testString() { + String v1 = new String("abc"); + String v2 = new String("def"); + + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrV2 = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrV2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v2)); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_STRING_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrV1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // null regex + arguments.clear(); + arguments.add(null); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null object to match + arguments.clear(); + arguments.add(attrV1); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // regex not string + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // object to match not correct type + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-regexp-match Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + @Test + public void testAnyURI() { + String regexp = new String("abc"); + URI uri1 = null; + URI uri2 = null; + try { + uri1 = new URI("abc"); + uri2 = new URI("def"); + } catch (Exception e) { + fail("Unable to create URIs, e="+e); + } + + + FunctionArgumentAttributeValue attrRegexp = null; + FunctionArgumentAttributeValue attrUri1 = null; + FunctionArgumentAttributeValue attrUri2 = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrRegexp = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(regexp)); + attrUri1 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(uri1)); + attrUri2 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(uri2)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_ANYURI_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrUri1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrUri2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // object to match not correct type + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-regexp-match Expected data type 'anyURI' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testIpAddress() { + String regexp = new String(".*123.*"); + IPAddress addr1 = null; + IPAddress addr2 = null; + try { + addr1 = IPAddress.newInstance("10.123.13.14"); + addr2 = IPAddress.newInstance("10.12.13.14"); + } catch (Exception e) { + fail("Unable to create IPAddresses, e="+e); + } + + + FunctionArgumentAttributeValue attrRegexp = null; + FunctionArgumentAttributeValue attrAddr1 = null; + FunctionArgumentAttributeValue attrAddr2 = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrRegexp = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(regexp)); + attrAddr1 = new FunctionArgumentAttributeValue(DataTypes.DT_IPADDRESS.createAttributeValue(addr1)); + attrAddr2 = new FunctionArgumentAttributeValue(DataTypes.DT_IPADDRESS.createAttributeValue(addr2)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_IPADDRESS_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_IPADDRESS_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // object to match not correct type + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-regexp-match Expected data type 'ipAddress' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testDnsName() { + String regexp = new String("abc"); + RFC2396DomainName addr1 = null; + RFC2396DomainName addr2 = null; + try { + addr1 = RFC2396DomainName.newInstance("abc"); + addr2 = RFC2396DomainName.newInstance("def"); + } catch (Exception e) { + fail("Unable to create DNSNames, e="+e); + } + + + FunctionArgumentAttributeValue attrRegexp = null; + FunctionArgumentAttributeValue attrAddr1 = null; + FunctionArgumentAttributeValue attrAddr2 = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrRegexp = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(regexp)); + attrAddr1 = new FunctionArgumentAttributeValue(DataTypes.DT_DNSNAME.createAttributeValue(addr1)); + attrAddr2 = new FunctionArgumentAttributeValue(DataTypes.DT_DNSNAME.createAttributeValue(addr2)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_DNSNAME_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DNSNAME_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // object to match not correct type + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-regexp-match Expected data type 'dnsName' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testRfc822Name() { + String regexp = new String(".*abc.*"); + RFC822Name addr1 = null; + RFC822Name addr2 = null; + try { + addr1 = RFC822Name.newInstance("abc@somewhere"); + addr2 = RFC822Name.newInstance("def@somewhere"); + } catch (Exception e) { + fail("Unable to create RFC822Names, e="+e); + } + + + FunctionArgumentAttributeValue attrRegexp = null; + FunctionArgumentAttributeValue attrAddr1 = null; + FunctionArgumentAttributeValue attrAddr2 = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrRegexp = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(regexp)); + attrAddr1 = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(addr1)); + attrAddr2 = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(addr2)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_RFC822NAME_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_RFC822NAME_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // object to match not correct type + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-regexp-match Expected data type 'rfc822Name' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testX500Name() { + String regexp = new String(".*Duke.*"); + X500Principal addr1 = null; + X500Principal addr2 = null; + try { + addr1 = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US"); + addr2 = new X500Principal("CN=Policy Engine, OU=Research, O=ATT, C=US"); + } catch (Exception e) { + fail("Unable to create X500Name, e="+e); + } + + + FunctionArgumentAttributeValue attrRegexp = null; + FunctionArgumentAttributeValue attrAddr1 = null; + FunctionArgumentAttributeValue attrAddr2 = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrRegexp = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(regexp)); + attrAddr1 = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(addr1)); + attrAddr2 = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(addr2)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionRegexpMatch<?> fd = (FunctionDefinitionRegexpMatch<?>) StdFunctions.FD_X500NAME_REGEXP_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_X500NAME_REGEXP_MATCH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrAddr2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // object to match not correct type + arguments.clear(); + arguments.add(attrRegexp); + arguments.add(attrInteger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:x500Name-regexp-match Expected data type 'x500Name' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSetTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSetTest.java new file mode 100644 index 000000000..8f22c8227 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSetTest.java @@ -0,0 +1,1903 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionSetTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + + // + // INTERSECTION tests + // + + + @Test + public void testString_intersection() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagb = new FunctionArgumentBag(bagb); + FunctionArgumentBag attrBagaaacccef = new FunctionArgumentBag(bagaaacccef); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_STRING_INTERSECTION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_INTERSECTION, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(7, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // several but not all intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(b, attrValueObject.getValue() ); + + // no intersection + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // one intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagb); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(b, attrValueObject.getValue() ); + + // bag one has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(f, attrValueObject.getValue() ); + + // bag one has duplicates that do intersect + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // bag 2 has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(f, attrValueObject.getValue() ); + + // bag 2 has duplicates that intersect + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // first bag is empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // second bag is empty + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-intersection Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + @Test + public void testInteger_intersection() { + BigInteger a = new BigInteger("1"); + BigInteger b = new BigInteger("2"); + BigInteger c = new BigInteger("3"); + BigInteger d = new BigInteger("4"); + BigInteger e = new BigInteger("5"); + BigInteger f = new BigInteger("6"); + BigInteger g = new BigInteger("7"); + BigInteger h = new BigInteger("8"); + BigInteger j = new BigInteger("9"); + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_INTEGER.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_INTEGER.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_INTEGER.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_INTEGER.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_INTEGER.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_INTEGER.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_INTEGER.createAttributeValue(a)); + bagace.add(DataTypes.DT_INTEGER.createAttributeValue(c)); + bagace.add(DataTypes.DT_INTEGER.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_INTEGER.createAttributeValue(b)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_INTEGER.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue("abc")); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(1)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagb = new FunctionArgumentBag(bagb); + FunctionArgumentBag attrBagaaacccef = new FunctionArgumentBag(bagaaacccef); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_INTEGER_INTERSECTION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_INTERSECTION, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(7, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // several but not all intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(b, attrValueObject.getValue() ); + + // no intersection + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // one intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagb); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(b, attrValueObject.getValue() ); + + // bag one has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(f, attrValueObject.getValue() ); + + // bag one has duplicates that do intersect + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // bag 2 has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(f, attrValueObject.getValue() ); + + // bag 2 has duplicates that intersect + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(3, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // first bag is empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // second bag is empty + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(1, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_INTEGER.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-intersection Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + + // + // AT_LEAST_ONE_MEMBER_OF tests + // + + @Test + public void testString_at_least_one_member_of() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaaccce = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaaccce = new Bag(); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagb = new FunctionArgumentBag(bagb); + FunctionArgumentBag attrBagaaaccce = new FunctionArgumentBag(bagaaaccce); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_STRING_AT_LEAST_ONE_MEMBER_OF; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_AT_LEAST_ONE_MEMBER_OF, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + // several but not all intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no intersection + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // one intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagb); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag one has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag one has duplicates that do intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag 2 has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag 2 has duplicates that intersect + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // 2 empty bags + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first non-empty, 2nd empty + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first empty, 2nd not empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-at-least-one-member-of Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + + // + // UNION tests + // + + + + + + @Test + public void testString_union() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagaaacccef = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef = new Bag(); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagaaacccef.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagaaacccef = new FunctionArgumentBag(bagaaacccef); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_STRING_UNION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_UNION, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertTrue(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Bag bag = res.getBag(); + assertNotNull(bag); + Iterator<AttributeValue<?>> it = bag.getAttributeValues(); + assertEquals(7, bag.size()); + AttributeValue<?> attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // several but not all union + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(8, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // bag one has duplicates that do not match first bag + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(8, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // bag one has duplicates that do match first bag + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // bag 2 has duplicates that do not match first bag + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(8, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(b, attrValueObject.getValue() ); + + // bag 2 has duplicates that do match first bag + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(c, attrValueObject.getValue() ); + attrValueObject = it.next(); + assertEquals(e, attrValueObject.getValue() ); + + // two empty bags + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(0, bag.size()); + + // first bag empty, 2nd not empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaacccef); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + + // first bag not empty, 2nd empty + arguments.clear(); + arguments.add(attrBagaaacccef); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + bag = res.getBag(); + assertNotNull(bag); + it = bag.getAttributeValues(); + assertEquals(4, bag.size()); + attrValueObject = it.next(); + assertEquals(DataTypes.DT_STRING.getId(), attrValueObject.getDataTypeId()); + assertEquals(a, attrValueObject.getValue() ); + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-union Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + // + // SUBSET tests + // + + @Test + public void testString_subset() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaaccce = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaaccce = new Bag(); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagb = new FunctionArgumentBag(bagb); + FunctionArgumentBag attrBagaaaccce = new FunctionArgumentBag(bagaaaccce); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_STRING_SUBSET; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_SUBSET, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + // not subset + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // subset + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + // no intersection + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // Not + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagb); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // Subset + arguments.clear(); + arguments.add(attrBagb); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag one has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag one has duplicates that do intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag 2 has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag 2 has duplicates that intersect + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // 2 empty bags + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first non-empty, 2nd empty + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first empty, 2nd not empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrBagb); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-subset Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + // + // SET_EQUALS tests + // + + @Test + public void testString_set_equals() { + String a = "a"; + String b = "b"; + String c = "c"; + String d = "d"; + String e = "e"; + String f = "f"; + String g = "g"; + String h = "h"; + String j = "j"; + + + Bag bagabcdefg = null; + Bag bagbdfhj = null; + Bag bagace = null; + Bag bagb = null; + Bag bagaaaccce = null; + Bag bagInt = null; + Bag bagStringInt = null; + Bag bagEmpty = null; + + FunctionArgumentAttributeValue attrBadType = null; + + try { + bagabcdefg = new Bag(); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagabcdefg.add(DataTypes.DT_STRING.createAttributeValue(g)); + bagbdfhj = new Bag(); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(d)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(f)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(h)); + bagbdfhj.add(DataTypes.DT_STRING.createAttributeValue(j)); + bagace = new Bag(); + bagace.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagace.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagb = new Bag(); + bagb.add(DataTypes.DT_STRING.createAttributeValue(b)); + bagaaaccce = new Bag(); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(c)); + bagaaaccce.add(DataTypes.DT_STRING.createAttributeValue(e)); + bagInt = new Bag(); + bagInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagStringInt = new Bag(); + bagStringInt.add(DataTypes.DT_STRING.createAttributeValue(a)); + bagStringInt.add(DataTypes.DT_INTEGER.createAttributeValue(123)); + bagEmpty = new Bag(); + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(1.1)); + } catch (Exception ex) { + fail("creating attribute e="+ ex); + } + + // make into attributes + FunctionArgumentBag attrBagabcdefg = new FunctionArgumentBag(bagabcdefg); + FunctionArgumentBag attrBagbdfhj = new FunctionArgumentBag(bagbdfhj); + FunctionArgumentBag attrBagace = new FunctionArgumentBag(bagace); + FunctionArgumentBag attrBagb = new FunctionArgumentBag(bagb); + FunctionArgumentBag attrBagaaaccce = new FunctionArgumentBag(bagaaaccce); + FunctionArgumentBag attrBagInt = new FunctionArgumentBag(bagInt); + FunctionArgumentBag attrBagStringInt = new FunctionArgumentBag(bagStringInt); + FunctionArgumentBag attrBagEmpty = new FunctionArgumentBag(bagEmpty); + + FunctionDefinitionSet<?,?> fd = (FunctionDefinitionSet<?,?>) StdFunctions.FD_STRING_SET_EQUALS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_SET_EQUALS, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + // normal intersection (everything in both bags, no duplicates) + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + // several but not all intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // no intersection + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // one intersection + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagb); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag one has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagbdfhj); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag one has duplicates that do intersect + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagace); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // bag 2 has duplicates that do not intersect + arguments.clear(); + arguments.add(attrBagbdfhj); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bag 2 has duplicates that intersect + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // 2 empty bags + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first non-empty, 2nd empty + arguments.clear(); + arguments.add(attrBagaaaccce); + arguments.add(attrBagEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first empty, 2nd not empty + arguments.clear(); + arguments.add(attrBagEmpty); + arguments.add(attrBagaaaccce); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bags of different types + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagStringInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrBagace); + arguments.add(attrBagInt); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first not a bag + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second not a bag + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Expected a bag, saw a simple value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first null + arguments.clear(); + arguments.add(null); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // second null + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Got null argument", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + arguments.add(attrBagabcdefg); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-set-equals Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + // + // + // REST OF DATA TYPES OMITTED + // because they "should" all work the same + // + // + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSpecialMatchTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSpecialMatchTest.java new file mode 100644 index 000000000..e4c68514d --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionSpecialMatchTest.java @@ -0,0 +1,487 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentBag; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionSpecialMatchTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + @Test + public void testX500NameMatch() { + // assume that the contents of the name components are not significant and we can treat them as simple blocks of "<name>=<value>" + String A = "cn=Some person"; + String B = "O=Medico Corp"; + String C = "C=US"; + String D = "DNQUALIFIER=d string"; + String E = "SURNAME=some name"; + String F = "INITIALS=inits"; + + + X500Principal abc = new X500Principal(A + "," + B + "," + C); + X500Principal dabc = new X500Principal(D + "," + A + "," + B + "," + C); + X500Principal abcd = new X500Principal(A + "," + B + "," + C + "," + D); + X500Principal adbc = new X500Principal(A + "," + D + "," + B + "," + C); + X500Principal dcab = new X500Principal(D + "," + C + "," + A + "," + B) ; + X500Principal def = new X500Principal(D + "," + E + "," + F) ; + + + FunctionArgumentAttributeValue attrABC = null; + FunctionArgumentAttributeValue attrDABC = null; + FunctionArgumentAttributeValue attrABCD = null; + FunctionArgumentAttributeValue attrADBC = null; + FunctionArgumentAttributeValue attrDCAB = null; + FunctionArgumentAttributeValue attrDEF = null; + + FunctionArgumentAttributeValue attrBad = null; + FunctionArgumentBag attrBag = new FunctionArgumentBag(new Bag()); + + + try { + attrABC = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(abc)); + attrDABC = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(dabc)); + attrABCD = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(abcd)); + attrADBC = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(adbc)); + attrDCAB = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(dcab)); + attrDEF = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(def)); + + attrBad = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionX500NameMatch fd = (FunctionDefinitionX500NameMatch) StdFunctions.FD_X500NAME_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_X500NAME_MATCH, fd.getId()); + assertEquals(DataTypes.DT_X500NAME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal, first exact match for second + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrABC); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test first is end of second + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrDABC); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // first exact match for sub-section but not end of second + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrABCD); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // components of first match components in second but not contiguous + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrADBC); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // components of first match components in second but not in order + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrDCAB); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first does not match second at all + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrDEF); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first arg larger than 2nd arg + arguments.clear(); + arguments.add(attrABCD); + arguments.add(attrABC); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // bad arg types + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrBad); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Expected data type 'x500Name' saw 'integer' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrABC); + arguments.add(attrABC); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrABC); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg is bag + arguments.clear(); + arguments.add(attrABC); + arguments.add(attrBag); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Expected a simple value, saw a bag at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null arg + arguments.clear(); + arguments.add(null); + arguments.add(attrBag); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:x500Name-match Got null argument at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testRfc822NameMatch() { + + + + + FunctionArgumentAttributeValue attrStringabcxyz = null; + FunctionArgumentAttributeValue attrStringABCxyz = null; + FunctionArgumentAttributeValue attrStringabcXYZ = null; + FunctionArgumentAttributeValue attrStringcx = null; + FunctionArgumentAttributeValue attrStringwholedomainpart = null; + FunctionArgumentAttributeValue attrStringWholeDomainPart = null; + FunctionArgumentAttributeValue attrStringWholeDomain = null; + FunctionArgumentAttributeValue attrStringdomainpart = null; + FunctionArgumentAttributeValue attrStringDomainPart = null; + FunctionArgumentAttributeValue attrStringdotWholeDomain = null; + FunctionArgumentAttributeValue attrStringdomain = null; + + FunctionArgumentAttributeValue attrStringNoMatch = null; + FunctionArgumentAttributeValue attrStringMultipleAt = null; + FunctionArgumentAttributeValue attrStringMissingLocal = null; + FunctionArgumentAttributeValue attrStringMissingDomain = null; + + + FunctionArgumentAttributeValue attrRfcabcxyz = null; + FunctionArgumentAttributeValue attrRfcwholedomainpart = null; + FunctionArgumentAttributeValue attrRfcWholeDomainPart = null; + + FunctionArgumentBag attrBag = new FunctionArgumentBag(new Bag()); + + try { + attrStringabcxyz = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc@xyz")); + attrStringABCxyz = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("ABC@xyz")); + attrStringabcXYZ = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc@XYZ")); + attrStringcx = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("c@x")); + attrStringwholedomainpart = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("whole.domain.part")); + attrStringWholeDomainPart = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("Whole.Domain.Part")); + attrStringWholeDomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("Whole.Domain")); + attrStringdomainpart = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(".domain.part")); + attrStringDomainPart = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(".Domain.Part")); + attrStringdotWholeDomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(".Whole.Domain")); + attrStringdomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(".domain.")); + + attrStringNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("no match to any legal name")); + attrStringMultipleAt = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("name@with@multipleAts")); + attrStringMissingLocal = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("@multipleAts")); + attrStringMissingDomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("localpart@")); + + attrRfcabcxyz = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue("abc@xyz")); + attrRfcwholedomainpart = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue("abc@whole.domain.part")); + attrRfcWholeDomainPart = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue("abc@Whole.Domain.Part")); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionRFC822NameMatch fd = (FunctionDefinitionRFC822NameMatch) StdFunctions.FD_RFC822NAME_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_RFC822NAME_MATCH, fd.getId()); + assertEquals(DataTypes.DT_RFC822NAME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // string identical to name - exact match on whole search term + arguments.clear(); + arguments.add(attrStringabcxyz); + arguments.add(attrRfcabcxyz); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // no match local case different + arguments.clear(); + arguments.add(attrStringABCxyz); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // match domain case different + arguments.clear(); + arguments.add(attrStringabcXYZ); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + + // partial local + partial domain + arguments.clear(); + arguments.add(attrStringcx); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // whole domain + arguments.clear(); + arguments.add(attrStringwholedomainpart); + arguments.add(attrRfcwholedomainpart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // whole domain different case + arguments.clear(); + arguments.add(attrStringWholeDomainPart); + arguments.add(attrRfcwholedomainpart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + arguments.clear(); + arguments.add(attrStringwholedomainpart); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // whole domain fail + arguments.clear(); + arguments.add(attrStringWholeDomain); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // partial domain match + arguments.clear(); + arguments.add(attrStringDomainPart); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // partial domain different case + arguments.clear(); + arguments.add(attrStringdomainpart); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // partial domain fail + arguments.clear(); + arguments.add(attrStringdotWholeDomain); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + arguments.clear(); + arguments.add(attrStringdomain); + arguments.add(attrRfcWholeDomainPart); + res = fd.evaluate(null, arguments); + assertTrue(res.getStatus().isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // search term contains more than 1 @ + arguments.clear(); + arguments.add(attrStringMultipleAt); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match String contained more than 1 '@' in 'name@with@multipleAts'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // search term missing local part + arguments.clear(); + arguments.add(attrStringMissingLocal); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match String missing local part in '@multipleAts'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // search term missing domain part + arguments.clear(); + arguments.add(attrStringMissingDomain); + arguments.add(attrRfcabcxyz); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match String missing domain part in 'localpart@'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg types + arguments.clear(); + arguments.add(attrRfcabcxyz); + arguments.add(attrStringNoMatch); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Expected data type 'string' saw 'rfc822Name' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrStringNoMatch); + arguments.add(attrStringNoMatch); + arguments.add(attrStringNoMatch); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + arguments.add(attrStringNoMatch); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg is bag + arguments.clear(); + arguments.add(attrStringNoMatch); + arguments.add(attrBag); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Expected a simple value, saw a bag at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null arg + arguments.clear(); + arguments.add(null); + arguments.add(attrStringNoMatch); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:rfc822Name-match Got null argument at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringConversionTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringConversionTest.java new file mode 100644 index 000000000..3268266f4 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringConversionTest.java @@ -0,0 +1,2504 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.math.BigInteger; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.IPAddress; +import com.att.research.xacml.std.datatypes.IPv4Address; +import com.att.research.xacml.std.datatypes.IPv6Address; +import com.att.research.xacml.std.datatypes.ISO8601Date; +import com.att.research.xacml.std.datatypes.ISO8601DateTime; +import com.att.research.xacml.std.datatypes.ISO8601Time; +import com.att.research.xacml.std.datatypes.ISO8601TimeZone; +import com.att.research.xacml.std.datatypes.PortRange; +import com.att.research.xacml.std.datatypes.RFC2396DomainName; +import com.att.research.xacml.std.datatypes.RFC822Name; +import com.att.research.xacml.std.datatypes.XPathDayTimeDuration; +import com.att.research.xacml.std.datatypes.XPathYearMonthDuration; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Tests for converting objects to/from Strings. + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionStringConversionTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + /** + * Boolean + */ + @Test + public void testBoolean_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("true")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_BOOLEAN_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_BOOLEAN_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(new Boolean(true), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-from-string Cannot convert from \"java.lang.String\" with value \"not valid obj value\" to boolean", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:boolean-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_boolean() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "false"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_BOOLEAN.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_BOOLEAN; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_BOOLEAN, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-boolean Expected data type 'boolean' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + /** + * Integer + */ + @Test + public void testInteger_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123456")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_INTEGER_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_INTEGER_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("123456"), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-from-string For input string: \"n\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:integer-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_integer() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "1234"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_INTEGER; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_INTEGER, fd.getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-integer Expected data type 'integer' saw 'double' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + /** + * Double + */ + @Test + public void testDouble_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("5.432")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_DOUBLE_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DOUBLE_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Double resValue = (Double)res.getValue().getValue(); + assertEquals(new Double(5.432), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:double-from-string For input string: \"not valid obj value\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:double-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_double() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrObjBig = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "5.432"; + String objValueStringBig = "55555555555555555555.123455"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(objValueString)); + attrObjBig = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(objValueStringBig)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_DOUBLE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_DOUBLE, fd.getId()); + assertEquals(DataTypes.DT_DOUBLE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + arguments.clear(); + arguments.add(attrObjBig); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("5.555555555555556E19", res.getValue().getValue()); + + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-double Expected data type 'double' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + /** + * Time + */ + @Test + public void testTime_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrString2 = null; + FunctionArgumentAttributeValue attrString3 = null; + FunctionArgumentAttributeValue attrString4 = null; + FunctionArgumentAttributeValue attrStringTimeZone = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("05:12:34.323")); + attrString2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("5:12:34.323")); + attrString3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("05:12")); + attrString4 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("05:12:34")); + attrStringTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("05:12:34.323+03:00")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_TIME_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_TIME_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + ISO8601Time resValue = (ISO8601Time)res.getValue().getValue(); + assertEquals(new ISO8601Time(5, 12, 34, 323), resValue); + + // check missing 0 in front + arguments.clear(); + arguments.add(attrString2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-from-string Invalid hour of day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // check missing seconds/msecs + arguments.clear(); + arguments.add(attrString3); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-from-string Time string too short", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // check missing just msecs + arguments.clear(); + arguments.add(attrString4); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Time)res.getValue().getValue(); + assertEquals(new ISO8601Time(5, 12, 34, 0), resValue); + + // check TimeZone + arguments.clear(); + arguments.add(attrStringTimeZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Time)res.getValue().getValue(); + assertEquals(new ISO8601Time(new ISO8601TimeZone(180), 5, 12, 34, 323), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-from-string Invalid hour of day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:time-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_time() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrObj2 = null; + FunctionArgumentAttributeValue attrObjTimeZone = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue("05:12:34.323")); + attrObj2 = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue("05:01:02.323")); + attrObjTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_TIME.createAttributeValue("05:12:34.323+03:00")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_TIME; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_TIME, fd.getId()); + assertEquals(DataTypes.DT_TIME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("05:12:34.323", res.getValue().getValue()); + + // missing digits in string value? + arguments.clear(); + arguments.add(attrObj2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("05:01:02.323", res.getValue().getValue()); + + // include TimeZone + arguments.clear(); + arguments.add(attrObjTimeZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("05:12:34.323+03:00", res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-time Expected data type 'time' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + /** + * Date + */ + @Test + public void testDate_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrString2 = null; + FunctionArgumentAttributeValue attrString3 = null; + FunctionArgumentAttributeValue attrString4 = null; + FunctionArgumentAttributeValue attrString5 = null; + FunctionArgumentAttributeValue attrString6 = null; + FunctionArgumentAttributeValue attrString7 = null; + FunctionArgumentAttributeValue attrString8 = null; + FunctionArgumentAttributeValue attrString9 = null; + FunctionArgumentAttributeValue attrStringDateZone = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-12")); + attrString2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-2013-05-12")); + attrString3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("1232013-05-12")); + attrString4 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-1232013-05-12")); + attrString5 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("213-05-12")); + attrString6 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-5-12")); + attrString7 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-2")); + attrString8 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-32-12")); + attrString9 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-45")); + attrStringDateZone = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-12+03:00")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_DATE_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATE_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + ISO8601Date resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(new ISO8601Date(2013, 5, 12), resValue); + + // check negative + arguments.clear(); + arguments.add(attrString2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(new ISO8601Date(-2013, 5, 12), resValue); + + // check big + arguments.clear(); + arguments.add(attrString3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(new ISO8601Date(1232013, 5, 12), resValue); + + // check big negative + arguments.clear(); + arguments.add(attrString4); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(new ISO8601Date(-1232013, 5, 12), resValue); + + // bad year + arguments.clear(); + arguments.add(attrString5); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid year (must be at least 4 digits)", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad month + arguments.clear(); + arguments.add(attrString6); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid month", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad day format + arguments.clear(); + arguments.add(attrString7); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // month out of range + arguments.clear(); + arguments.add(attrString8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid month", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // day out of range + arguments.clear(); + arguments.add(attrString9); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // check TimeZone + arguments.clear(); + arguments.add(attrStringDateZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601Date)res.getValue().getValue(); + assertEquals(new ISO8601Date(new ISO8601TimeZone(180), 2013, 5, 12), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Invalid year", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:date-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_date() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrObj2 = null; + FunctionArgumentAttributeValue attrObjDateZone = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue("2013-05-12")); + attrObj2 = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue("0001-01-01")); + attrObjDateZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATE.createAttributeValue("2013-05-12+03:00")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_DATE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_DATE, fd.getId()); + assertEquals(DataTypes.DT_DATE.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("2013-05-12", res.getValue().getValue()); + + // missing digits in string value? + arguments.clear(); + arguments.add(attrObj2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("1-01-01", res.getValue().getValue()); + + // include DateZone + arguments.clear(); + arguments.add(attrObjDateZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("2013-05-12+03:00", res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-date Expected data type 'date' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + /** + * DateTime + */ + @Test + public void testDateTime_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrString2 = null; + FunctionArgumentAttributeValue attrString3 = null; + FunctionArgumentAttributeValue attrString4 = null; + FunctionArgumentAttributeValue attrString5 = null; + FunctionArgumentAttributeValue attrString6 = null; + FunctionArgumentAttributeValue attrString7 = null; + FunctionArgumentAttributeValue attrString8 = null; + FunctionArgumentAttributeValue attrString9 = null; + FunctionArgumentAttributeValue attrStringDateTimeZone = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-12T12:14:15.323")); + attrString2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-2013-05-12T12:14:15.323")); + attrString3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("1232013-05-12T12:14:15.323")); + attrString4 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-1232013-05-12T12:14:15.323")); + attrString5 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("213-05-12T12:14:15.323")); + attrString6 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-5-12T12:14:15.323")); + attrString7 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-2T12:14:15.323")); + attrString8 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-32-12T12:14:15.323")); + attrString9 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-45T12:14:15.323")); + attrStringDateTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2013-05-12T12:14:15.323+03:00")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_DATETIME_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DATETIME_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + ISO8601DateTime resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(new ISO8601DateTime(null, new ISO8601Date(2013, 5, 12), new ISO8601Time(12, 14, 15, 323)), resValue); + + // check negative + arguments.clear(); + arguments.add(attrString2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(new ISO8601DateTime(null, new ISO8601Date(-2013, 5, 12), new ISO8601Time(12, 14, 15, 323)), resValue); + + + // check big + arguments.clear(); + arguments.add(attrString3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(new ISO8601DateTime(null, new ISO8601Date(1232013, 5, 12), new ISO8601Time(12, 14, 15, 323)), resValue); + + // check big negative + arguments.clear(); + arguments.add(attrString4); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(new ISO8601DateTime(null, new ISO8601Date(-1232013, 5, 12), new ISO8601Time(12, 14, 15, 323)), resValue); + + // bad year + arguments.clear(); + arguments.add(attrString5); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid year (must be at least 4 digits)", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad month + arguments.clear(); + arguments.add(attrString6); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid month", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad day format + arguments.clear(); + arguments.add(attrString7); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // month out of range + arguments.clear(); + arguments.add(attrString8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid month", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // day out of range + arguments.clear(); + arguments.add(attrString9); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid day", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // check TimeZone + arguments.clear(); + arguments.add(attrStringDateTimeZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (ISO8601DateTime)res.getValue().getValue(); + assertEquals(new ISO8601DateTime(new ISO8601TimeZone(180), new ISO8601Date(new ISO8601TimeZone(180), 2013, 5, 12), new ISO8601Time(new ISO8601TimeZone(180),12, 14, 15, 323)), resValue); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Invalid year", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dateTime-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_dateTime() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrObj2 = null; + FunctionArgumentAttributeValue attrObjDateTimeZone = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue("2013-05-12T12:14:15.323")); + attrObj2 = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue("0001-01-01T12:14:15.323")); + attrObjDateTimeZone = new FunctionArgumentAttributeValue(DataTypes.DT_DATETIME.createAttributeValue("2013-05-12T12:14:15.323+03:00")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_DATETIME; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_DATETIME, fd.getId()); + assertEquals(DataTypes.DT_DATETIME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("2013-05-12T12:14:15.323", res.getValue().getValue()); + + // missing digits in string value? + arguments.clear(); + arguments.add(attrObj2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("1-01-01T12:14:15.323", res.getValue().getValue()); + + // include DateTimeZone + arguments.clear(); + arguments.add(attrObjDateTimeZone); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("2013-05-12T12:14:15.323+03:00", res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-dateTime Expected data type 'dateTime' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + /** + * URI + */ + @Test + public void testURI_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("http://someMachine.com/subdir")); + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_ANYURI_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_ANYURI.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + URI resValue = (URI)res.getValue().getValue(); + try { + assertEquals(new URI("http://someMachine.com/subdir"), resValue); + } catch (URISyntaxException e) { + fail("uri generation e="+e); + } + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-from-string Illegal character in path at index 3: not valid obj value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_anyURI() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "http://aMachine.com:8080/aRef"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_ANYURI; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_ANYURI, fd.getId()); + assertEquals(DataTypes.DT_ANYURI.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-anyURI Expected data type 'anyURI' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + /** + * XPathDayTimeDuration + */ + @Test + public void testXPathDayTimeDuration_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringNeg1 = null; + FunctionArgumentAttributeValue attrStringNeg2 = null; + FunctionArgumentAttributeValue attrStringNoDay = null; + FunctionArgumentAttributeValue attrStringNoHour = null; + FunctionArgumentAttributeValue attrStringNoMin = null; + FunctionArgumentAttributeValue attrStringNoSec = null; + FunctionArgumentAttributeValue attrStringNoP = null; + FunctionArgumentAttributeValue attrStringSecondsDot = null; + FunctionArgumentAttributeValue attrStringMissingTOk = null; + FunctionArgumentAttributeValue attrStringMissingTBad = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3DT10H30M23S")); + attrStringNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-P3DT10H30M23S")); + attrStringNeg2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P-3DT10H30M23S")); + attrStringNoDay = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("PT10H30M23S")); + attrStringNoHour = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3DT30M23S")); + attrStringNoMin = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3DT10H23S")); + attrStringNoSec = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3DT10H30M")); + attrStringNoP = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("3DT10H30M")); + attrStringSecondsDot = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3DT10H30M23.456S")); + attrStringMissingTOk = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3D")); + attrStringMissingTBad = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3D10H30M23S")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_DAYTIMEDURATION_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DAYTIMEDURATION_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DAYTIMEDURATION.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + XPathDayTimeDuration resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 10, 30, 23), resValue); + + + // negative values in front is allowed + arguments.clear(); + arguments.add(attrStringNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(-1, 3, 10, 30, 23), resValue); + + // negative in middle of string not ok + arguments.clear(); + arguments.add(attrStringNeg2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dayTimeDuration-from-string Invalid chunk \"P-3DT10H30M23S\" at position 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // omit parts that are 0 + arguments.clear(); + arguments.add(attrStringNoDay); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 0, 10, 30, 23), resValue); + + arguments.clear(); + arguments.add(attrStringNoHour); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 0, 30, 23), resValue); + + arguments.clear(); + arguments.add(attrStringNoMin); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 10, 0, 23), resValue); + + arguments.clear(); + arguments.add(attrStringNoSec); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 10, 30, 0), resValue); + + // P must always be present + arguments.clear(); + arguments.add(attrStringNoP); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dayTimeDuration-from-string Invalid ISO8601 duration string \"3DT10H30M\" at position 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // seconds may contain decimal + arguments.clear(); + arguments.add(attrStringSecondsDot); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 10, 30, 23.456), resValue); + + // T must be absent iff all time items are absent + arguments.clear(); + arguments.add(attrStringMissingTOk); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathDayTimeDuration)res.getValue().getValue(); + assertEquals(new XPathDayTimeDuration(1, 3, 0, 0, 0), resValue); + + // negative in middle of string not ok + arguments.clear(); + arguments.add(attrStringMissingTBad); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dayTimeDuration-from-string Invalid ISO8601 duration string \"P3D10H30M23S\" at position 6: out of order component", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dayTimeDuration-from-string Invalid ISO8601 duration string \"not valid obj value\" at position 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dayTimeDuration-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_dayTimeDuration() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "P3DT10H30M23S"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_DAYTIMEDURATION.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_DAYTIMEDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_DAYTIMEDURATION, fd.getId()); + assertEquals(DataTypes.DT_DAYTIMEDURATION.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-dayTimeDuration Expected data type 'dayTimeDuration' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + + + + /** + * XPathYearMonthDuration + */ + @Test + public void testXPathYearMonthDuration_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringNeg1 = null; + FunctionArgumentAttributeValue attrStringNeg2 = null; + FunctionArgumentAttributeValue attrStringNoYear1 = null; + FunctionArgumentAttributeValue attrStringNoYear2 = null; + FunctionArgumentAttributeValue attrStringNoMonth1 = null; + FunctionArgumentAttributeValue attrStringNoMonth2 = null; + FunctionArgumentAttributeValue attrStringNoValue = null; + FunctionArgumentAttributeValue attrStringNoP = null; + FunctionArgumentAttributeValue attrStringBigMonths = null; + FunctionArgumentAttributeValue attrStringMissingTOk = null; + FunctionArgumentAttributeValue attrStringMissingTBad = null; + FunctionArgumentAttributeValue attrStringZeroMonths = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P1Y2M")); + attrStringNeg1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("-P1Y2M")); + attrStringNeg2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P-1Y2M")); + attrStringNoYear1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P2M")); + attrStringNoYear2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("PY2M")); + attrStringNoMonth1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P1Y")); + attrStringNoMonth2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P1YM")); + attrStringNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P")); + attrStringNoP = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("1Y2M")); + attrStringBigMonths = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P1Y12M")); + attrStringMissingTOk = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3D")); + attrStringMissingTBad = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P3D10H30M23S")); + attrStringZeroMonths = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("P0M")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_YEARMONTHDURATION_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_YEARMONTHDURATION_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_YEARMONTHDURATION.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + XPathYearMonthDuration resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(1,1, 2), resValue); + + + // negative values in front is allowed + arguments.clear(); + arguments.add(attrStringNeg1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(-1, 1, 2), resValue); + + // negative in middle of string not ok + arguments.clear(); + arguments.add(attrStringNeg2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid chunk \"P-1Y2M\" at position 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // omit parts that are 0 + arguments.clear(); + arguments.add(attrStringNoYear1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(1, 0, 2), resValue); + + arguments.clear(); + arguments.add(attrStringNoYear2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid chunk \"PY2M\" at position 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + arguments.clear(); + arguments.add(attrStringNoMonth1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(1, 1, 0), resValue); + + arguments.clear(); + arguments.add(attrStringNoMonth2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid chunk \"P1YM\" at position 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // No field with a value + arguments.clear(); + arguments.add(attrStringNoValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid ISO8601 duration string \"P\": No duration components following P", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // P must always be present + arguments.clear(); + arguments.add(attrStringNoP); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid ISO8601 duration string \"1Y2M\" at position 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // Canonical Form of output may not have more than 12 months, but input as string is ok? + arguments.clear(); + arguments.add(attrStringBigMonths); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(1, 1, 12), resValue); + + // Canonical representation of 0 Months + arguments.clear(); + arguments.add(attrStringZeroMonths); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (XPathYearMonthDuration)res.getValue().getValue(); + assertEquals(new XPathYearMonthDuration(1, 0, 0), resValue); + + // T must be absent iff all time items are absent + arguments.clear(); + arguments.add(attrStringMissingTOk); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid XPath yearMonthDuraiton \"{durationSign=1years=0months=0days=3hours=0minutes=0seconds=0millis=0}\": includes days, hours, minutes, or seconds", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // negative in middle of string not ok + arguments.clear(); + arguments.add(attrStringMissingTBad); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid ISO8601 duration string \"P3D10H30M23S\" at position 6: out of order component", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Invalid ISO8601 duration string \"not valid obj value\" at position 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:yearMonthDuration-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_yearMonthDuration() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "P1Y2M"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_YEARMONTHDURATION.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_YEARMONTHDURATION; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_YEARMONTHDURATION, fd.getId()); + assertEquals(DataTypes.DT_YEARMONTHDURATION.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-yearMonthDuration Expected data type 'yearMonthDuration' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + /** + * X500Principal + * + * See http://www.ietf.org/rfc/rfc2253.txt and http://www.ietf.org/rfc/rfc2251.txt + */ + @Test + public void testX500Principal_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringNoComma = null; + FunctionArgumentAttributeValue attrStringEmpty = null; + FunctionArgumentAttributeValue attrStringNoValue = null; + FunctionArgumentAttributeValue attrStringOrder = null; + FunctionArgumentAttributeValue attrStringDottedDecimalOID = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("CN=Name, L=local, ST=NJ, O=ATT, C=USA")); + attrStringNoComma = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("CN=Name, L=local ST=NJ, O=ATT, C=USA")); + attrStringEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrStringNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("CN=Name, L=, ST=NJ, O=ATT, C=USA")); + attrStringOrder = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("L=local, ST=NJ, O=ATT, CN=Name, C=USA")); + attrStringDottedDecimalOID = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2.5.4.3=A. N. Other")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_X500NAME_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_X500NAME_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_X500NAME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + X500Principal resValue = (X500Principal)res.getValue().getValue(); + assertEquals(new X500Principal("CN=Name, L=local, ST=NJ, O=ATT, C=USA"), resValue); + + // no comma between components => next attribute/value is included as part of first value + arguments.clear(); + arguments.add(attrStringNoComma); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (X500Principal)res.getValue().getValue(); + assertEquals(new X500Principal("CN=Name, L=local ST=NJ, O=ATT, C=USA"), resValue); + + // nothing in name (fail) + arguments.clear(); + arguments.add(attrStringEmpty); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (X500Principal)res.getValue().getValue(); + assertEquals(new X500Principal(""), resValue); + + // type value with no = + arguments.clear(); + arguments.add(attrStringNoValue); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (X500Principal)res.getValue().getValue(); + assertEquals(new X500Principal("CN=Name, L=, ST=NJ, O=ATT, C=USA"), resValue); + + // different order + arguments.clear(); + arguments.add(attrStringOrder); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (X500Principal)res.getValue().getValue(); + assertNotEquals(new X500Principal("CN=Name, L=local, ST=NJ, O=ATT, C=USA"), resValue); + + // dotted-decimal name with numbers + arguments.clear(); + arguments.add(attrStringDottedDecimalOID); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (X500Principal)res.getValue().getValue(); + assertEquals(new X500Principal("2.5.4.3=A. N. Other"), resValue); + + + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:x500Name-from-string improperly specified input name: not valid obj value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:x500Name-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_x500Name() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "CN=Name, L=local, ST=NJ, O=ATT, C=USA"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_X500NAME.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_X500NAME; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_X500NAME, fd.getId()); + assertEquals(DataTypes.DT_X500NAME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-x500Name Expected data type 'x500Name' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + /** + * RFC822Name + */ + @Test + public void testRFC822Name_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringCapsDomain = null; + FunctionArgumentAttributeValue attrStringCapsLocal = null; + FunctionArgumentAttributeValue attrStringMissingAt = null; + FunctionArgumentAttributeValue attrStringMissingLocal = null; + FunctionArgumentAttributeValue attrStringMissingDomain = null; + FunctionArgumentAttributeValue attrStringEmpty = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("local@Domain")); + attrStringCapsDomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("local@DOMAIN")); + attrStringCapsLocal = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("LOCAL@Domain")); + attrStringMissingAt = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("localDomain")); + attrStringMissingLocal = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("@Domain")); + attrStringMissingDomain = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("local@")); + attrStringEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_RFC822NAME_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_RFC822NAME_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_RFC822NAME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + RFC822Name resValue = (RFC822Name)res.getValue().getValue(); + assertEquals(new RFC822Name("local", "domain"), resValue); + + // caps domain + arguments.clear(); + arguments.add(attrStringCapsDomain); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC822Name)res.getValue().getValue(); + assertEquals(new RFC822Name("local", "domain"), resValue); + + // caps local + arguments.clear(); + arguments.add(attrStringCapsLocal); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC822Name)res.getValue().getValue(); + assertNotEquals(new RFC822Name("local", "domain"), resValue); + + // missing at + arguments.clear(); + arguments.add(attrStringMissingAt); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Invalid RFC822Name \"localDomain\": missing local part", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // missing local + arguments.clear(); + arguments.add(attrStringMissingLocal); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Invalid RFC822Name \"@Domain\": empty parts", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // missing domain + arguments.clear(); + arguments.add(attrStringMissingDomain); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Invalid RFC822Name \"local@\": empty parts", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // empty + arguments.clear(); + arguments.add(attrStringEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Invalid RFC822Name \"\": missing local part", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Invalid RFC822Name \"not valid obj value\": missing local part", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:rfc822Name-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_rfc822Name() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "local@DOMAIN"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_RFC822NAME.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_RFC822NAME; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_RFC822NAME, fd.getId()); + assertEquals(DataTypes.DT_RFC822NAME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals("local@domain", res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-rfc822Name Expected data type 'rfc822Name' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + /** + * IPAddress + */ + @Test + public void testIPAddress_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrStringFull = null; + FunctionArgumentAttributeValue attrStringMissingElement = null; + FunctionArgumentAttributeValue attrStringTooManyElement = null; + FunctionArgumentAttributeValue attrStringIllegalElement = null; + FunctionArgumentAttributeValue attrStringOutOfOrder = null; + + FunctionArgumentAttributeValue attrStringMask = null; + FunctionArgumentAttributeValue attrStringMissingMaskElement = null; + FunctionArgumentAttributeValue attrStringTooManyMaskElement = null; + FunctionArgumentAttributeValue attrStringIllegalMaskElement = null; + FunctionArgumentAttributeValue attrStringMaskNoValue = null; + + FunctionArgumentAttributeValue attrStringMinusPort = null; + FunctionArgumentAttributeValue attrStringPortMinus = null; + FunctionArgumentAttributeValue attrStringPortPort = null; + FunctionArgumentAttributeValue attrStringNoPort = null; + FunctionArgumentAttributeValue attrStringBadPort = null; + FunctionArgumentAttributeValue attrStringTooManyPorts = null; + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + + // set up for v4 address tests - this setup and the tests are repeated for V6 + short[] addrShorts= {123, 134, 156, 255 }; + short[] addrMaskShorts= {255, 255, 255, 255 }; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255")); + attrStringFull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/255.255.255.255:123-456")); + attrStringMissingElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.255")); + attrStringTooManyElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.255.111.222")); + attrStringIllegalElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.256.255")); + attrStringOutOfOrder = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.256.255:123-456/255.255.255.255")); + + attrStringMask = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/255.255.255.255")); + attrStringMissingMaskElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/123.134.255")); + attrStringTooManyMaskElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/122.134.155.111.222")); + attrStringIllegalMaskElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/123.134.256.255")); + attrStringMaskNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255/")); + // optional mask + // "/" with no mask (fail) + + attrStringMinusPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:-123")); + attrStringPortMinus = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:123-")); + attrStringPortPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:1234567-432")); + attrStringNoPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:")); + attrStringBadPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:12.34")); + attrStringTooManyPorts = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("123.134.156.255:-123-456")); + + + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_IPADDRESS_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_IPADDRESS_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_IPADDRESS.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + IPAddress resValue = (IPAddress)res.getValue().getValue(); + assertEquals(new IPv4Address(addrShorts, null, null), resValue); + + // fully-loaded address + arguments.clear(); + arguments.add(attrStringFull); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv4Address(addrShorts, addrMaskShorts, PortRange.newInstance("123-456")), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + // missing element + arguments.clear(); + arguments.add(attrStringMissingElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.255\": invalid address", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many elements + arguments.clear(); + arguments.add(attrStringTooManyElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.255.111.222\": invalid address", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal element + arguments.clear(); + arguments.add(attrStringIllegalElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.256.255\": invalid octet: \"256", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // Out of order + arguments.clear(); + arguments.add(attrStringOutOfOrder); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.256.255:123-456/255.255.255.255\": out of order components", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // simple mask + arguments.clear(); + arguments.add(attrStringMask); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv4Address(addrShorts, addrMaskShorts, null), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + // missing mask element + arguments.clear(); + arguments.add(attrStringMissingMaskElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.255\": invalid address", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many mask elements + arguments.clear(); + arguments.add(attrStringTooManyMaskElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"122.134.155.111.222\": invalid address", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal Mask element + arguments.clear(); + arguments.add(attrStringIllegalMaskElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.256.255\": invalid octet: \"256", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + //mask indicator without value + arguments.clear(); + arguments.add(attrStringMaskNoValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"\": invalid address", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // portrange (-port, port-, port-port) + arguments.clear(); + arguments.add(attrStringMinusPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv4Address(addrShorts, null, PortRange.newInstance("-123")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortMinus); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv4Address(addrShorts, null, PortRange.newInstance("123-")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv4Address(addrShorts, null, PortRange.newInstance("1234567-432")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + // ":" without port + arguments.clear(); + arguments.add(attrStringNoPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv4 address string \"123.134.156.255:\": no portrange given after ':'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad port number + arguments.clear(); + arguments.add(attrStringBadPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid PortRange \"12.34\": invalid port number", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad port range + arguments.clear(); + arguments.add(attrStringTooManyPorts); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid PortRange \"-123-456\": too many ranges", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Unknown IPAddress type for \"not valid obj value\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // + // V6 IP Addresses + // + + // reset the variable for IPv6 tests + FunctionArgumentAttributeValue attrStringAlternateFull = null; + FunctionArgumentAttributeValue attrStringEmptyElement = null; + FunctionArgumentAttributeValue attrString2xEmptyElement = null; + FunctionArgumentAttributeValue attrStringNoStartBracket = null; + FunctionArgumentAttributeValue attrStringNoEndBracket = null; + short[] addrv6Shorts = {(short)0x2001, (short)0xdb8, (short)0x85a3, (short)0x0, (short)0x0, (short)0x8a2e, (short)0x370, (short)0x1}; + Short prefix = new Short((short) 121); + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]")); + attrStringFull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1/121]:123-456")); + attrStringAlternateFull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]/121:123-456")); + attrStringEmptyElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3::8a2e:370:1]")); + attrString2xEmptyElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3::8a2e::1]")); + attrStringNoStartBracket = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("2002:db8:85a3::8a2e::1]")); + attrStringNoEndBracket = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3::8a2e::1")); + + attrStringMissingElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:1]")); + attrStringTooManyElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1:123]")); + attrStringIllegalElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:mnop:85a3:0:0:8a2e:370:1]")); + attrStringOutOfOrder = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:mnop:85a3:0:0:8a2e:370:1:123-456/121]")); + + attrStringMask = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1/21]")); + attrStringIllegalMaskElement = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1/130]")); + attrStringMaskNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1/]")); + + attrStringMinusPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:-123")); + attrStringPortMinus = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:123-")); + attrStringPortPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:1234567-432")); + attrStringNoPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:")); + attrStringBadPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:12.34")); + attrStringTooManyPorts = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("[2001:db8:85a3:0:0:8a2e:370:1]:-123-456")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + + // test normal + arguments.clear(); + arguments.add(attrString1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + assertEquals(new IPv6Address(addrv6Shorts, null, null), resValue); + + // fully-loaded address - "prefix" is inside the brackets (not clear if this is correct) + arguments.clear(); + arguments.add(attrStringFull); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, new Short(prefix), PortRange.newInstance("123-456")), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + // Alternate way of identifying "prefix" - outside the brackets + arguments.clear(); + arguments.add(attrStringAlternateFull); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, prefix, PortRange.newInstance("123-456")), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + + // consecutive zero elements removed + arguments.clear(); + arguments.add(attrStringEmptyElement); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, prefix, null), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + // consecutive zero elements removed in two locations (no-no) + arguments.clear(); + arguments.add(attrString2xEmptyElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"2001:db8:85a3::8a2e::1\": multiple zero runs", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // address must have [] on it + arguments.clear(); + arguments.add(attrStringNoStartBracket); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"2002:db8:85a3::8a2e::1]\": missing opening bracket", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrStringNoEndBracket); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"[2001:db8:85a3::8a2e::1\": missing closing bracket", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // missing element + arguments.clear(); + arguments.add(attrStringMissingElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"2001:db8:85a3:0:0:8a2e:1\": not enough address fields", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many elements + arguments.clear(); + arguments.add(attrStringTooManyElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"2001:db8:85a3:0:0:8a2e:370:1:123\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal element + arguments.clear(); + arguments.add(attrStringIllegalElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address component \"mnop\": invalid hex", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // Out of order + arguments.clear(); + arguments.add(attrStringOutOfOrder); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6Address string \"2001:mnop:85a3:0:0:8a2e:370:1:123-456\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // simple mask + arguments.clear(); + arguments.add(attrStringMask); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, prefix, null), resValue); + } catch (Exception e) { + fail("port error e="+e); + } + + // illegal Mask element + arguments.clear(); + arguments.add(attrStringIllegalMaskElement); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid Ipv6Address string \"[2001:db8:85a3:0:0:8a2e:370:1/130]\": prefix is larger than 128", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + //mask indicator without value + arguments.clear(); + arguments.add(attrStringMaskNoValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid Ipv6Address string \"[2001:db8:85a3:0:0:8a2e:370:1/]\": prefix designation without value", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // portrange (-port, port-, port-port) + arguments.clear(); + arguments.add(attrStringMinusPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, null, PortRange.newInstance("-123")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortMinus); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, null, PortRange.newInstance("123-")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (IPAddress)res.getValue().getValue(); + try { + assertEquals(new IPv6Address(addrv6Shorts, null, PortRange.newInstance("1234567-432")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + // ":" without port + arguments.clear(); + arguments.add(attrStringNoPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid IPv6 address string \"[2001:db8:85a3:0:0:8a2e:370:1]:\": no portrange given after ':'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // bad port number + arguments.clear(); + arguments.add(attrStringBadPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid PortRange \"12.34\": invalid port number", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad port range + arguments.clear(); + arguments.add(attrStringTooManyPorts); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:ipAddress-from-string Invalid PortRange \"-123-456\": too many ranges", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + + + + } + + @Test + public void testString_from_ipAddress() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrObjV6 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "123.145.255.255"; + String objValueStringV6 = "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_IPADDRESS.createAttributeValue(objValueString)); + attrObjV6 = new FunctionArgumentAttributeValue(DataTypes.DT_IPADDRESS.createAttributeValue(objValueStringV6)); + + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_IPADDRESS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_IPADDRESS, fd.getId()); + assertEquals(DataTypes.DT_IPADDRESS.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal V4 + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // test normal V6 + arguments.clear(); + arguments.add(attrObjV6); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueStringV6.toLowerCase(), res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-ipAddress Expected data type 'ipAddress' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + + + + + /** + * RFC2396DomainName + */ + @Test + public void testRFC2396DomainName_from_string() { + FunctionArgumentAttributeValue attrString1 = null; + FunctionArgumentAttributeValue attrString2 = null; + FunctionArgumentAttributeValue attrStringMinusPort = null; + FunctionArgumentAttributeValue attrStringPortMinus = null; + FunctionArgumentAttributeValue attrStringPortPort = null; + FunctionArgumentAttributeValue attrStringNoPort = null; + FunctionArgumentAttributeValue attrStringBadPort = null; + FunctionArgumentAttributeValue attrStringTooManyPorts = null; + + FunctionArgumentAttributeValue attrStringBadValue = null; + FunctionArgumentAttributeValue attrStringBadType = null; + try { + attrString1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host")); + attrString2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host")); + + attrStringMinusPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:-123")); + attrStringPortMinus = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:123-")); + attrStringPortPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:1234567-432")); + attrStringNoPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:")); + attrStringBadPort = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:12.34")); + attrStringTooManyPorts = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("host.host:-123-456")); + + attrStringBadValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("not valid obj value")); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_DNSNAME_FROM_STRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_DNSNAME_FROM_STRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_DNSNAME.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrString1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + RFC2396DomainName resValue = (RFC2396DomainName)res.getValue().getValue(); + assertEquals(new RFC2396DomainName("host", null), resValue); + + arguments.clear(); + arguments.add(attrString2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC2396DomainName)res.getValue().getValue(); + assertEquals(new RFC2396DomainName("host.host", null), resValue); + + + // portrange (-port, port-, port-port) + arguments.clear(); + arguments.add(attrStringMinusPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC2396DomainName)res.getValue().getValue(); + try { + assertEquals(new RFC2396DomainName("host.host", PortRange.newInstance("-123")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortMinus); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC2396DomainName)res.getValue().getValue(); + try { + assertEquals(new RFC2396DomainName("host.host", PortRange.newInstance("123-")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + arguments.clear(); + arguments.add(attrStringPortPort); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (RFC2396DomainName)res.getValue().getValue(); + try { + assertEquals(new RFC2396DomainName("host.host", PortRange.newInstance("1234567-432")), resValue); + } catch (ParseException e) { + fail("port error e="+e); + } + + // ":" without port + arguments.clear(); + arguments.add(attrStringNoPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-from-string Invalid RFC 2396 port range \"host.host:\": no port numbers", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad port number + arguments.clear(); + arguments.add(attrStringBadPort); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-from-string Invalid RFC 2396 port range \"12.34\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad port range + arguments.clear(); + arguments.add(attrStringTooManyPorts); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-from-string Invalid RFC 2396 port range \"-123-456\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad value + arguments.clear(); + arguments.add(attrStringBadValue); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-from-string Invalid RFC 2396 host name \"not valid obj value\"", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:dnsName-from-string Expected data type 'string' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + @Test + public void testString_from_dnsName() { + FunctionArgumentAttributeValue attrObj1 = null; + FunctionArgumentAttributeValue attrStringBadType = null; + String objValueString = "someName.com"; + try { + attrObj1 = new FunctionArgumentAttributeValue(DataTypes.DT_DNSNAME.createAttributeValue(objValueString)); + attrStringBadType = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(123)); + + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringConversion<?, ?> fd = (FunctionDefinitionStringConversion<?, ?>) StdFunctions.FD_STRING_FROM_DNSNAME; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_FROM_DNSNAME, fd.getId()); + assertEquals(DataTypes.DT_DNSNAME.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + // test normal + arguments.clear(); + arguments.add(attrObj1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(objValueString, res.getValue().getValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrStringBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-from-dnsName Expected data type 'dnsName' saw 'integer' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + } + + + + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringEqualIgnoreCaseTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringEqualIgnoreCaseTest.java new file mode 100644 index 000000000..9c5c8a1e7 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringEqualIgnoreCaseTest.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Only one function to test here. Code copy/pasted from FunctionDefinitionEqualityTest + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-equal-ignore-case + * + * + */ +public class FunctionDefinitionStringEqualIgnoreCaseTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + FunctionArgumentAttributeValue stringAttr1 = null; + FunctionArgumentAttributeValue stringAttr2 = null; + FunctionArgumentAttributeValue stringAttr3 = null; + FunctionArgumentAttributeValue stringAttr4 = null; + + FunctionArgumentAttributeValue intAttr1 = null; + + public FunctionDefinitionStringEqualIgnoreCaseTest() { + try { + stringAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("abc")); + stringAttr3 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("ABC")); + stringAttr4 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("def")); + intAttr1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + } + + + /** + * String match even when Case is different + */ + @Test + public void testFunctionDefinitionStringEqualIgnoreCase() { + + FunctionDefinitionEquality<?> fd = (FunctionDefinitionEquality<?>) StdFunctions.FD_STRING_EQUAL_IGNORE_CASE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_EQUAL_IGNORE_CASE, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + + // test normal equals and non-equals + // check "abc" with "abc" + arguments.add(stringAttr1); + arguments.add(stringAttr2); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // check "abc" with "ABC" (should be same) + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(stringAttr3); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // test bad args data types? Not needed? + arguments.clear(); + arguments.add(stringAttr1); + arguments.add(intAttr1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + + +//TODO - null in either first or 2nd arg => NullPointerException + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringFunctionsTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringFunctionsTest.java new file mode 100644 index 000000000..c6cba9f67 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringFunctionsTest.java @@ -0,0 +1,1497 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionStringFunctionsTest { + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + ExpressionResult res; + + + @Test + public void testConcatenate() { + String v1 = new String("abc"); + String v2 = new String("def"); + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrV2 = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrV2 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v2)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_STRING_CONCATENATE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_CONCATENATE, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + String resValue = (String)res.getValue().getValue(); + assertEquals(v1 + v2, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals(v2, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals(v1, resValue); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("", resValue); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-concatenate Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-concatenate Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrV2); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-concatenate Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-concatenate Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + @Test + public void testStringStartsWith() { + String v1 = new String("abc"); + String bigger = new String("abc some string"); + String biggerNoMatch = new String(" abc some string"); + String caps = new String("AbC"); + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_STRING_STARTS_WITH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_STARTS_WITH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBiggerNoMatch); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-starts-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-starts-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-starts-with Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testAnyuriStartsWith() { + + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrBigString = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlankString = null; + FunctionArgumentAttributeValue attrBlankURI = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + String v1 = new String("abc"); + URI bigger = new URI("abc.some.string"); + URI biggerNoMatch = new URI("Zabc.some.string"); + String caps = new String("AbC"); + String bigString = "thisIsSomeReallyBigStringToMatch"; + + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBigString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigString)); + attrBlankString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrBlankURI = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_ANYURI_STARTS_WITH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_STARTS_WITH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBiggerNoMatch); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + + // two blanks + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // arguments reversed + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-starts-with Expected data type 'string' saw 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-starts-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-starts-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-starts-with Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + @Test + public void testStringEndsWith() { + String v1 = new String("abc"); + String bigger = new String("abc some string abc"); + String biggerNoMatch = new String(" abc some string abc "); + String caps = new String("AbC"); + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_STRING_ENDS_WITH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_ENDS_WITH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBiggerNoMatch); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-ends-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-ends-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-ends-with Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testAnyuriEndsWith() { + + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrBigString = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlankString = null; + FunctionArgumentAttributeValue attrBlankURI = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + String v1 = new String("abc"); + URI bigger = new URI("abc.some.stringabc"); + URI biggerNoMatch = new URI("Zabc.some.stringabcZ"); + String caps = new String("AbC"); + String bigString = "thisIsSomeReallyBigStringToMatch"; + + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBigString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigString)); + attrBlankString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrBlankURI = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_ANYURI_ENDS_WITH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_ENDS_WITH, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBiggerNoMatch); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + + // two blanks + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // arguments reversed + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-ends-with Expected data type 'string' saw 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-ends-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-ends-with Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-ends-with Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + @Test + public void testStringSubstring() { + String bigString = new String("abc some string abc"); + + FunctionArgumentAttributeValue attrBigString = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrDouble = null; + + FunctionArgumentAttributeValue attrInteger0 = null; + FunctionArgumentAttributeValue attrInteger1 = null; + FunctionArgumentAttributeValue attrIntegerM1 = null; + FunctionArgumentAttributeValue attrInteger8 = null; + FunctionArgumentAttributeValue attrInteger19 = null; + FunctionArgumentAttributeValue attrInteger20 = null; + + + + try { + attrBigString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigString)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attrInteger1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + attrIntegerM1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(-1)); + attrInteger8 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(8)); + attrInteger19 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(19)); + attrInteger20 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(20)); + attrDouble = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(123.4)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_STRING_SUBSTRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_SUBSTRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger1); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + String resValue = (String)res.getValue().getValue(); + assertEquals("bc some", resValue); + + // edge: start + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger0); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("abc some", resValue); + + // edge: end + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrInteger19); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals(" string abc", resValue); + + // from index to end of string + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrIntegerM1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals(" string abc", resValue); + + // first index too low + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrIntegerM1); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Start point '-1' out of range 0-19 for string='abc some string abc'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // second index too big + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrInteger20); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring End point '20' out of range 0-19 for string='abc some string abc'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // indexes reversed + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring End point '1' less than start point 'null' for string='abc some string abc'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // indexes the same + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("", resValue); + + // blank string with indexes both 0 + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrInteger0); + arguments.add(attrInteger0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("", resValue); + + // non-string first attribute + arguments.clear(); + arguments.add(attrDouble); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Expected data type 'string' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-integer 2nd attr + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrDouble); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Expected data type 'integer' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-integer 3rd attr + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrDouble); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Expected data type 'integer' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 4 args + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Expected 3 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null 1st arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null 2nd arg + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrNull); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-substring Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + } + + + + + @Test + public void testAnyURISubstring() { + String bigString = new String("http://company.com:8080/this/is/some/long/uri"); + + FunctionArgumentAttributeValue attrURI = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrDouble = null; + + FunctionArgumentAttributeValue attrInteger0 = null; + FunctionArgumentAttributeValue attrInteger1 = null; + FunctionArgumentAttributeValue attrIntegerM1 = null; + FunctionArgumentAttributeValue attrInteger8 = null; + FunctionArgumentAttributeValue attrInteger45 = null; + FunctionArgumentAttributeValue attrInteger46 = null; + + + + try { + attrURI = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(bigString)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(null)); + attrInteger0 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(0)); + attrInteger1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1)); + attrIntegerM1 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(-1)); + attrInteger8 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(8)); + attrInteger45 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(45)); + attrInteger46 = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(46)); + attrDouble = new FunctionArgumentAttributeValue(DataTypes.DT_DOUBLE.createAttributeValue(123.4)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_ANYURI_SUBSTRING; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_SUBSTRING, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger1); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + String resValue = (String)res.getValue().getValue(); + assertEquals("ttp://c", resValue); + + // edge: start + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger0); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("http://c", resValue); + + // edge: end + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrInteger45); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("ompany.com:8080/this/is/some/long/uri", resValue); + + // from index to end of string + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrIntegerM1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("ompany.com:8080/this/is/some/long/uri", resValue); + + // first index too low + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrIntegerM1); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Start point '-1' out of range 0-45 for string='http://company.com:8080/this/is/some/long/uri'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // second index too big + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrInteger46); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring End point '46' out of range 0-45 for string='http://company.com:8080/this/is/some/long/uri'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // indexes reversed + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring End point '1' less than start point 'null' for string='http://company.com:8080/this/is/some/long/uri'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // indexes the same + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("", resValue); + + // blank string with indexes both 0 + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrInteger0); + arguments.add(attrInteger0); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.String.class, res.getValue().getValue().getClass()); + resValue = (String)res.getValue().getValue(); + assertEquals("", resValue); + + // non-string first attribute + arguments.clear(); + arguments.add(attrDouble); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Expected data type 'anyURI' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-integer 2nd attr + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrDouble); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Expected data type 'integer' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // non-integer 3rd attr + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrDouble); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Expected data type 'integer' saw 'double'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 4 args + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Expected 3 arguments, got 4", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // 2 args + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrInteger8); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Expected 3 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null 1st arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrInteger8); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null 2nd arg + arguments.clear(); + arguments.add(attrURI); + arguments.add(attrNull); + arguments.add(attrInteger1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-substring Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + + + + + + + + + + + + + + + + + + @Test + public void testStringContains() { + String v1 = new String("abc"); + String bigger = new String("abc some string abc"); + String biggerNoMatch = new String(" abc some string abc "); + String caps = new String("AbC"); + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlank = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBlank = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_STRING_CONTAINS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_CONTAINS, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrBiggerNoMatch); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // two blanks + arguments.clear(); + arguments.add(attrBlank); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlank); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-contains Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-contains Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:string-contains Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testAnyuriContains() { + + + FunctionArgumentAttributeValue attrV1 = null; + FunctionArgumentAttributeValue attrBigger = null; + FunctionArgumentAttributeValue attrBiggerNoMatch = null; + FunctionArgumentAttributeValue attrCaps = null; + FunctionArgumentAttributeValue attrBigString = null; + FunctionArgumentAttributeValue attrNull = null; + FunctionArgumentAttributeValue attrBlankString = null; + FunctionArgumentAttributeValue attrBlankURI = null; + FunctionArgumentAttributeValue attrInteger = null; + try { + String v1 = new String("abc"); + URI bigger = new URI("abc.some.stringabc"); + URI biggerNoMatch = new URI("Zabc.some.stringabcZ"); + String caps = new String("AbC"); + String bigString = "thisIsSomeReallyBigStringToMatch"; + + attrV1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(v1)); + attrBigger = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(bigger)); + attrBiggerNoMatch = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue(biggerNoMatch)); + attrCaps = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(caps)); + attrBigString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(bigString)); + attrBlankString = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrBlankURI = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("")); + attrNull = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(null)); + attrInteger = new FunctionArgumentAttributeValue(DataTypes.DT_INTEGER.createAttributeValue(1234)); + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + FunctionDefinitionStringFunctions<?,?> fd = (FunctionDefinitionStringFunctions<?,?>) StdFunctions.FD_ANYURI_CONTAINS; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_ANYURI_CONTAINS, fd.getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // match + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // no match + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrBiggerNoMatch); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // caps no match + arguments.clear(); + arguments.add(attrCaps); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // bigger on the inside + arguments.clear(); + arguments.add(attrBigString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + // empty non-null first arg + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // empty non-null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(false, resValue); + + + // two blanks + arguments.clear(); + arguments.add(attrBlankString); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.lang.Boolean.class, res.getValue().getValue().getClass()); + resValue = (Boolean)res.getValue().getValue(); + assertEquals(true, resValue); + + // arguments reversed + arguments.clear(); + arguments.add(attrBigger); + arguments.add(attrV1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-contains Expected data type 'string' saw 'anyURI'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // null firat arg + arguments.clear(); + arguments.add(attrNull); + arguments.add(attrBlankURI); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-contains Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null second arg + arguments.clear(); + arguments.add(attrV1); + arguments.add(attrNull); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-contains Got null attribute", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // illegal arg type + arguments.clear(); + arguments.add(attrInteger); + arguments.add(attrBigger); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:anyURI-contains Expected data type 'string' saw 'integer'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringNormalizeTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringNormalizeTest.java new file mode 100644 index 000000000..2631be06b --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionStringNormalizeTest.java @@ -0,0 +1,118 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionStringNormalizeTest { + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + @Test + public void testString_normalize_space() { + String initialString = " First and last are whitespace "; + FunctionArgumentAttributeValue attr1 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(initialString)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringNormalize fd = (FunctionDefinitionStringNormalize) StdFunctions.FD_STRING_NORMALIZE_SPACE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_NORMALIZE_SPACE, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + String resValue = (String)res.getValue().getValue(); + assertEquals(initialString.length() - 4, resValue.length()); + assertTrue(initialString.trim().equals(resValue)); + } + + + @Test + public void testString_normalize_to_lower_case() { + String initialString = " First and last are whitespace "; + FunctionArgumentAttributeValue attr1 = null; + try { + attr1 = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(initialString)); + } catch (Exception e) { + fail("creating attribute e="+ e); + } + + FunctionDefinitionStringNormalize fd = (FunctionDefinitionStringNormalize) StdFunctions.FD_STRING_NORMALIZE_TO_LOWER_CASE; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_STRING_NORMALIZE_TO_LOWER_CASE, fd.getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_STRING.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // test normal add + arguments.add(attr1); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + String resValue = (String)res.getValue().getValue(); + assertTrue(initialString.toLowerCase().equals(resValue)); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionURIStringConcatenateTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionURIStringConcatenateTest.java new file mode 100644 index 000000000..63ae2072b --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionURIStringConcatenateTest.java @@ -0,0 +1,185 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.att.research.xacml.api.XACML2; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionURIStringConcatenateTest { + + /* + * THE FUNCTION BEING TESTED BY THIS CLASS IS DEPRECATED + * uri-string-concatenate has been deprecated in XACML 3.0 + */ + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<>(); + + + @SuppressWarnings("deprecation") + @Test + public void testURI_string_concatenate() { + + // URI args + FunctionArgumentAttributeValue attrURI1 = null; + + + FunctionArgumentAttributeValue attrStrAbc = null; + FunctionArgumentAttributeValue attrStrSlashMno = null; + FunctionArgumentAttributeValue attrStrSlashInMiddle = null; + FunctionArgumentAttributeValue attrStrWithSpace = null; + + + try { + attrURI1 = new FunctionArgumentAttributeValue(DataTypes.DT_ANYURI.createAttributeValue("http://someplace")); + + + attrStrAbc = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("Abc")); + attrStrSlashMno = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("/Mno")); + attrStrSlashInMiddle = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("hij/pqr")); + attrStrWithSpace = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("x y z")); + + + } catch (Exception e) { + fail("creating attributes e="+ e); + } + + // deprecation marking in the following line is correct - this function IS deprecated but still valid for XACML 3.0 + FunctionDefinitionURIStringConcatenate fd = (FunctionDefinitionURIStringConcatenate) StdFunctions.FD_URI_STRING_CONCATENATE; + + // check identity and type of the thing created + assertEquals(XACML2.ID_FUNCTION_URI_STRING_CONCATENATE, fd.getId()); + assertEquals(DataTypes.DT_ANYURI.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + + + // add one string to uri + arguments.clear(); + arguments.add(attrURI1); + arguments.add(attrStrAbc); + ExpressionResult res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.net.URI.class, res.getValue().getValue().getClass()); + URI resValue = (URI)res.getValue().getValue(); + assertEquals("http://someplaceAbc", resValue.toString()); + + + // add 2 strings to uri + arguments.clear(); + arguments.add(attrURI1); + arguments.add(attrStrAbc); + arguments.add(attrStrSlashMno); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.net.URI.class, res.getValue().getValue().getClass()); + resValue = (URI)res.getValue().getValue(); + assertEquals("http://someplaceAbc/Mno", resValue.toString()); + + // slash in middle of string + arguments.clear(); + arguments.add(attrURI1); + arguments.add(attrStrSlashInMiddle); + arguments.add(attrStrSlashMno); + res = fd.evaluate(null, arguments); + assertTrue(res.isOk()); + assertEquals(java.net.URI.class, res.getValue().getValue().getClass()); + resValue = (URI)res.getValue().getValue(); + assertEquals("http://someplacehij/pqr/Mno", resValue.toString()); + + // create bad uri + arguments.clear(); + arguments.add(attrURI1); + arguments.add(attrStrWithSpace); + arguments.add(attrStrSlashMno); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:uri-string-concatenate Final string 'http://someplacex y z/Mno' not URI, Illegal character in authority at index 7: http://someplacex y z/Mno", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:uri-string-concatenate Expected 2 or more arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // one arg + arguments.clear(); + arguments.add(attrURI1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:uri-string-concatenate Expected 2 or more arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // first arg not uri + arguments.clear(); + arguments.add(attrStrAbc); + arguments.add(attrURI1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:uri-string-concatenate Expected data type 'anyURI' saw 'string' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // 2nd arg not string + arguments.clear(); + arguments.add(attrURI1); + arguments.add(attrURI1); + res = fd.evaluate(null, arguments); + assertFalse(res.isOk()); + assertEquals("function:uri-string-concatenate Expected data type 'string' saw 'anyURI' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionXPathTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionXPathTest.java new file mode 100644 index 000000000..b174c4205 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/FunctionDefinitionXPathTest.java @@ -0,0 +1,1127 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; + +import org.junit.Test; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdRequest; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.XPathExpressionWrapper; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.std.StdEvaluationContext; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.*; + +/** + * Test of PDP Functions (See XACML core spec section A.3) + * + * TO RUN - use jUnit + * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test + * + * + */ +public class FunctionDefinitionXPathTest { + + // + // Strings for the Request contents + // + + String reqStrMainStart = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<Request xsi:schemaLocation=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" + + " http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd\"" + + " ReturnPolicyIdList=\"false\"" + + " CombinedDecision=\"false\"" + + " xmlns=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\"" + + " xmlns:md=\"http://www.medico.com/schemas/record\"" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + + " <Attributes Category=\"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject\">" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:subject:subject-id\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">Julius Hibbert</AttributeValue>" + + " </Attribute>" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\"> This is IT! </AttributeValue>" + + " </Attribute>" + + " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\"> This is IT! </AttributeValue>" + + " </Attribute>" + + "</Attributes>"; + + String reqStrResourceStart = "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:resource\">"; + + String reqStrContentMdRecord = + " <Content>" + + "<md:record>" + + "<md:hospital_info>" + + "<md:name>ABC Hospital</md:name>" + + "<md:department>Surgery</md:department>" + + "</md:hospital_info>" + + "<md:patient_info>" + + "<md:name>Bart Simpson</md:name>" + + "<md:age>60</md:age>" + + "<md:sex>male</md:sex>" + + "<md:health_insurance>123456</md:health_insurance>" + + "</md:patient_info>" + + "<md:diagnosis_info>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">Gastric Cancer</md:item>" + + "<md:item type=\"secondary\">Hyper tension</md:item>" + + "</md:diagnosis>" + + "<md:pathological_diagnosis>" + + "<md:diagnosis>" + + "<md:item type=\"primary\">Well differentiated adeno carcinoma</md:item>" + + "</md:diagnosis>" + + "<md:date>2000-10-05</md:date>" + + "<md:malignancy type=\"yes\"/>" + + "</md:pathological_diagnosis>" + + "</md:diagnosis_info> " + + " </md:record>" + + "</Content>"; + String reqStrMalformedContent = + " <Content>" + + "<md:record>" + + "<md:hospital_info>" + + "<md:name>ABC Hospital</md:name>" + + "<md:malignancy type=\"yes\"/>" + + "</Content>"; + String reqStrResourceEnd = " <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:resource:resource-id\">" + + " <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#anyURI\">http://medico.com/record/patient/BartSimpson</AttributeValue>" + + " </Attribute>" + + "</Attributes> "; + String reqStrActionStart = "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:action\">"; + + String reqStrActionEnd = "<Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\">" + + "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">read</AttributeValue>" + + "</Attribute>" + + "</Attributes> "; + String reqStrEnvironmentStartEnd = " <Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:environment\" />"; + String reqStrMainEnd = " </Request>"; + + + // combined strings for convenience + String reqStrMainResourceStart = reqStrMainStart + reqStrResourceStart; + String reqStrResourceAllEnd = reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrEnvironmentStartEnd + reqStrMainEnd; + + + /* + * variables useful in the following tests + */ + List<FunctionArgument> arguments = new ArrayList<FunctionArgument>(); + + + + // Name Spaces used in the XML as part of these examples (copied from the Conformance tests) - needed for compiling XPaths + NamespaceContext nameSpaceContext = new NamespaceContext() { + @Override + public Iterator<?> getPrefixes(String arg0) { return null;} + + @Override + public String getPrefix(String arg0) {return null;} + + @Override + public String getNamespaceURI(String arg0) { + if("md".equals(arg0)) { + return "http://www.medico.com/schemas/record"; + } else if ("xacml-context".equals(arg0)) { + return "urn:oasis:names:tc:xacml:3.0:context:schema:os"; + } else if ("xsi".equals(arg0)) { + return "http://www.w3.org/2001/XMLSchema-instance"; + } + return null; + } + }; + + + + // + // XPath Function Attributes available for use in tests (representing appropriate fragment of Policy) + // + + FunctionArgumentAttributeValue attrXnull = null; + FunctionArgumentAttributeValue attrXEmpty = null; + FunctionArgumentAttributeValue attrXNoCategory = null; + FunctionArgumentAttributeValue attrXNoValue = null; + FunctionArgumentAttributeValue attrXSlashSlashMdRecord = null; + FunctionArgumentAttributeValue attrXSlashSlashStar = null; + FunctionArgumentAttributeValue attrXSlashSlashMdName = null; + FunctionArgumentAttributeValue attrXSlashSlashMdMalignancy = null; + FunctionArgumentAttributeValue attrXNotInRequest = null; + FunctionArgumentAttributeValue attrXSlashSlashMdRecordSlashStar = null; + FunctionArgumentAttributeValue attrXMdPatientInfo = null; + + FunctionArgumentAttributeValue attrBadType = null; + + // String version of attrs for use in Deprecated functions + FunctionArgumentAttributeValue attrStrnull = null; + FunctionArgumentAttributeValue attrStrEmpty = null; + FunctionArgumentAttributeValue attrStrNoCategory = null; + FunctionArgumentAttributeValue attrStrNoValue = null; + FunctionArgumentAttributeValue attrStrSlashSlashMdRecord = null; + FunctionArgumentAttributeValue attrStrSlashSlashStar = null; + FunctionArgumentAttributeValue attrStrSlashSlashMdName = null; + FunctionArgumentAttributeValue attrStrSlashSlashMdMalignancy = null; + FunctionArgumentAttributeValue attrStrNotInRequest = null; + FunctionArgumentAttributeValue attrStrSlashSlashMdRecordSlashStar = null; + FunctionArgumentAttributeValue attrStrMdPatientInfo = null; + + + // + // REQUEST objects available for use in tests + // + Request requestEmpty = new StdRequest(StdStatus.STATUS_OK); + Request requestMdRecord = null; + Request requestDoubleResources = null; + Request requestResourceActionContent = null; + Request requestContentInAction = null; + + + + + /** + * Set up all variables in one place because it is complicated (lots of steps needed for each attribute) + */ + public FunctionDefinitionXPathTest() { + try { + XPathFactory xPathFactory = XPathFactory.newInstance(); + XPath xpath = xPathFactory.newXPath(); + xpath.setNamespaceContext(nameSpaceContext); + + // Create XPaths to use in expressions + XPathExpressionWrapper xEmpty = new XPathExpressionWrapper(""); + XPathExpressionWrapper xSlashSlashMdRecord = new XPathExpressionWrapper(xpath.compile("//md:record")); + XPathExpressionWrapper xSlashSlashStar = new XPathExpressionWrapper(xpath.compile("//*")); + XPathExpressionWrapper xSlashSlashMdName = new XPathExpressionWrapper(xpath.compile("//md:name")); + XPathExpressionWrapper xSlashSlashMdMalignancy = new XPathExpressionWrapper(xpath.compile("//md:malignancy")); + XPathExpressionWrapper xNotInRequest = new XPathExpressionWrapper(xpath.compile("value_Not_in_request")); + XPathExpressionWrapper xSlashSlashMdRecordSlashStar = new XPathExpressionWrapper(xpath.compile("//md:record/*")); + XPathExpressionWrapper xMdPatientInfo = new XPathExpressionWrapper(xpath.compile("md:patient_info")); + + + + // create Function Attributes out of the XPathExpressions + attrXnull = new FunctionArgumentAttributeValue(null); + attrXEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xEmpty)); + attrXNoCategory = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecord)); + attrXNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xEmpty, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXSlashSlashMdRecord = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecord, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXSlashSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashStar, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXSlashSlashMdName = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdName, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXSlashSlashMdMalignancy = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdMalignancy, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXNotInRequest = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xNotInRequest, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + + attrXSlashSlashMdRecordSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecordSlashStar, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrXMdPatientInfo = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xMdPatientInfo, + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + + + // Deprecated versions of args + attrStrnull = new FunctionArgumentAttributeValue(null); + attrStrEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("")); + attrStrNoCategory = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record")); + attrStrNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrSlashSlashMdRecord = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrSlashSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//*", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrSlashSlashMdName = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:name", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrSlashSlashMdMalignancy = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:malignancy", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrNotInRequest = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("value_Not_in_request", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + + attrStrSlashSlashMdRecordSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record/*", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + attrStrMdPatientInfo = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("md:patient_info", + new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" ))); + + + + + attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("some string")); + + + + // Request objects + // to create a Request object the easiest way is to put the xml into a file and use the DOMRequest to load it. + + // single Content in the Resources section (normal valid request) + String reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceAllEnd; + File tFile = File.createTempFile("functionJunit", "request"); + BufferedWriter bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestMdRecord = DOMRequest.load(tFile); + tFile.delete(); + + // Resources included twice + reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceEnd + reqStrResourceStart + reqStrContentMdRecord +reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestDoubleResources = DOMRequest.load(tFile); + tFile.delete(); + + + // content included in both Resource and Action - ok + reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecord + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestResourceActionContent = DOMRequest.load(tFile); + tFile.delete(); + + // Content included only in Action - missing content produces non-error result according to spec + reqString = reqStrMainResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecord + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + requestContentInAction = DOMRequest.load(tFile); + tFile.delete(); + + + + // Test that Bad XML is caught + @SuppressWarnings("unused") + Request requestContentMisplaced = null; + @SuppressWarnings("unused") + Request requestMalformedContent = null; + @SuppressWarnings("unused") + Request requestDoubleContent = null; + + + // Content included twice - error + reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrContentMdRecord +reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestDoubleContent = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + // Bad XML - Content not under a Category + reqString = reqStrMainStart + reqStrContentMdRecord + reqStrResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrMainEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestContentMisplaced = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + // Bad XML - Content is not valid XML + reqString = reqStrMainResourceStart + reqStrMalformedContent + reqStrResourceAllEnd; + tFile = File.createTempFile("functionJunit", "request"); + bw = new BufferedWriter(new FileWriter(tFile)); + bw.append(reqString); + bw.flush(); + bw.close(); + try { + requestMalformedContent = DOMRequest.load(tFile); + tFile.delete(); + } catch (com.att.research.xacml.std.dom.DOMStructureException e) { + // this is what it should do, so just continue + } catch (Exception e) { + fail("Unexpected exception for bad XML, e="+e); + } + + } catch (Exception e) { + fail("Constructor initializing variables, e="+ e + " cause="+e.getCause()); + } + + } + + + + + + + + + @Test + public void testXpath_node_count() { + + + + FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_COUNT; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_COUNT, fd.getId()); + assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(1), fd.getNumArgs()); + + + // match all elements within context + arguments.clear(); + arguments.add(attrXSlashSlashStar); + ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + BigInteger resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("18"), resValue); + + // match exactly 1 element + arguments.clear(); + arguments.add(attrXSlashSlashMdMalignancy); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("1"), resValue); + + // match a few but not all + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("2"), resValue); + + + // verify variables using in other tests: count nodes immediately under md:record + arguments.clear(); + arguments.add(attrXSlashSlashMdRecordSlashStar); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("3"), resValue); + + // verify variables using in other tests: count number of records containing patient_info + arguments.clear(); + arguments.add(attrXMdPatientInfo); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("1"), resValue); + + // verify variables using in other tests: count number of records containing md:name + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("2"), resValue); + + // verify variables using in other tests: count number of records containing md:malignancy + arguments.clear(); + arguments.add(attrXSlashSlashMdMalignancy); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("1"), resValue); + + + + + // match no element + arguments.clear(); + arguments.add(attrXNotInRequest); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("0"), resValue); + + // Resources included twice + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // Content in both Resource and Action categories (ok) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("2"), resValue); + + // Content only in Action category (missing in Resources -> 0 according to spec) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments); + assertTrue(res.isOk()); + resValue = (BigInteger)res.getValue().getValue(); + assertEquals(new BigInteger("0"), resValue); + + + + +//TODO - any other tests???? + + // null Evaluation Context + arguments.clear(); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Got null EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null Request + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Got null Request in EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null attribute + arguments.clear(); + arguments.add(attrXnull); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Got null attribute at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no value + arguments.clear(); + arguments.add(attrXNoValue); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no category + arguments.clear(); + arguments.add(attrXNoCategory); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Got null Category at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // too many args + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Expected 1 arguments, got 2", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Expected 1 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null args + arguments.clear(); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-count Got null argument at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + @Test + public void testXpath_node_equal() { + + + FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_EQUAL; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_EQUAL, fd.getId()); + assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal success - exactly the same set + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - second list is subset of first list + arguments.clear(); + arguments.add(attrXSlashSlashMdRecordSlashStar); + arguments.add(attrXMdPatientInfo); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - first list is subset of second list + arguments.clear(); + arguments.add(attrXMdPatientInfo); + arguments.add(attrXSlashSlashMdRecordSlashStar); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - second list contains children of first list + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // success - first list contains children of second list + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + + // two non-overlapping sets + arguments.clear(); + arguments.add(attrXSlashSlashMdMalignancy); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first list contains nothing + arguments.clear(); + arguments.add(attrXNotInRequest); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // second list contains nothing + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXNotInRequest); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + +//TODO + //????? + ///??????? add real tests + ////// + + + // Resources included twice + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + + // Content in both Resource and Action categories (ok) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // Content only in Action category (missing in Resources -> 0 according to spec) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + // null Evaluation Context + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null Request + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null Request in EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null attribute + arguments.clear(); + arguments.add(attrXnull); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null attribute at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXnull); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null attribute at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no value + arguments.clear(); + arguments.add(attrXNoValue); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXNoValue); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no category + arguments.clear(); + arguments.add(attrXNoCategory); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null Category at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXNoCategory); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(attrXEmpty); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Expected data type 'xpathExpression' saw 'string' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null args + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null argument at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(null); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-equal Got null argument at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + } + + + + + @Test + public void testXpath_node_match() { + + + FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_MATCH; + + // check identity and type of the thing created + assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_MATCH, fd.getId()); + assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId()); + assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId()); + + // just to be safe... If tests take too long these can probably be eliminated + assertFalse(fd.returnsBag()); + assertEquals(new Integer(2), fd.getNumArgs()); + + + // test normal success - exactly the same set + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + Boolean resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - second list is subset of first list + arguments.clear(); + arguments.add(attrXSlashSlashMdRecordSlashStar); + arguments.add(attrXMdPatientInfo); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - first list is subset of second list + arguments.clear(); + arguments.add(attrXMdPatientInfo); + arguments.add(attrXSlashSlashMdRecordSlashStar); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - second list contains children of first list + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // success - first list contains children of second list + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + + // two non-overlapping sets + arguments.clear(); + arguments.add(attrXSlashSlashMdMalignancy); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // first list contains nothing + arguments.clear(); + arguments.add(attrXNotInRequest); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + // second list contains nothing + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXNotInRequest); + res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + +//TODO + //????? + ///??????? add real tests + ////// + + + // Resources included twice + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + // Content in both Resource and Action categories (ok) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertTrue(resValue); + + // Content only in Action category (missing in Resources -> 0 according to spec) + arguments.clear(); + arguments.add(attrXSlashSlashMdName); + arguments.add(attrXSlashSlashMdName); + res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments); + assertTrue(res.isOk()); + resValue = (Boolean)res.getValue().getValue(); + assertFalse(resValue); + + + // null Evaluation Context + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null Request + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null Request in EvaluationContext", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null attribute + arguments.clear(); + arguments.add(attrXnull); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null attribute at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXnull); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null attribute at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no value + arguments.clear(); + arguments.add(attrXNoValue); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXNoValue); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // no category + arguments.clear(); + arguments.add(attrXNoCategory); + arguments.add(attrXSlashSlashMdRecord); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null Category at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXSlashSlashMdRecord); + arguments.add(attrXNoCategory); + res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too many args + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(attrXEmpty); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Expected 2 arguments, got 3", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // too few args + arguments.clear(); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Expected 2 arguments, got 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Expected 2 arguments, got 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // bad arg type + arguments.clear(); + arguments.add(attrBadType); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(attrBadType); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Expected data type 'xpathExpression' saw 'string' at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + // null args + arguments.clear(); + arguments.add(attrXEmpty); + arguments.add(null); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null argument at arg index 1", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + arguments.clear(); + arguments.add(null); + arguments.add(attrXEmpty); + res = fd.evaluate(null, arguments); + assertFalse(res.getStatus().isOk()); + assertEquals( "function:xpath-node-match Got null argument at arg index 0", res.getStatus().getStatusMessage()); + assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue()); + + + + } + + + + // + // DEPRECATED versions that use String arguments rather than XPATHEXPRESSIONs + // are NOT supported due to ambiguity in the semantics between 2.0 (<Request> is root and has only one <Content> in resources) + // and 3.0 (<Content> is root and there are multiple <Content> sections in any category) + // + + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/PDPTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/PDPTest.java new file mode 100644 index 000000000..6442d7a12 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/PDPTest.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + + +import static org.junit.Assert.assertNull; +//import static org.junit.Assert.fail; + +import org.junit.Test; + +public class PDPTest { + + @Test + public void testDummy() { + assertNull(null); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/TestRunner.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/TestRunner.java new file mode 100644 index 000000000..b131964d4 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/TestRunner.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test; + +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +public class TestRunner { + private static Result results; + + public static void main(String[] args) { + Result result = JUnitCore.runClasses(PDPTest.class); + for(Failure failure: result.getFailures()) { + System.out.println("Failed Test: " + failure.toString()); + } + results = null; + if(result.wasSuccessful()) { + System.out.println("Test Results... "); + System.out.println("Stats: \nRun Time: " + (results.getRunTime()+result.getRunTime()) + "\nTotal Tests:" + results.getRunCount()+ result.getRunCount() + + "\nFailures: " + results.getFailureCount()+ result.getFailureCount()); + System.exit(1); + } + System.out.println("Tests Failed..."); + System.out.println("Stats: \nRun Time: " + result.getRunTime() + "\nTests:" + result.getRunCount() + + "\nFailures: " + result.getFailureCount()); + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/Conformance.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/Conformance.java new file mode 100644 index 000000000..d7af8b008 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/Conformance.java @@ -0,0 +1,634 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import com.att.research.xacml.api.Advice; +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.AttributeCategory; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.IdReference; +import com.att.research.xacml.api.Obligation; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; + +/** + * Conformance is an application that runs a <code>ConformanceTestSet</code> and dumps results comparing the actual and + * expected results. + * + * TO RUN in Eclipse: + * This is run as a Java Application. + * You must first create a Run/Debug Configuration: + * Under the Argument tab, in Program Arguments you must set the -i or --input command line argument. + * You should also direct the output to a file using -o or --output. (default is Console) + * See the init() method in this file for other useful arguments. + * Example for a Windows machine: + * -i testsets/conformance/xacml3.0-ct-v.0.4 + * -o \Users\yourLogin\Downloads\conformance.txt + * You must also set the VM arguments: + * -Dxacml.properties=testsets/conformance/xacml.properties . + * -Dlog4j.configuration=.\logging.properties + * + * @version $Revision: 1.2 $ + */ +public class Conformance { + private ConformanceScopeResolver scopeResolver; + private ConformanceTestEngine testEngine; + private ConformanceTestSet testSet = new ConformanceTestSet(); + private File outputFile; + private PrintWriter outputFileWriter; + + private List<String> testNamesToRun = new ArrayList<String>(); + + private boolean verbose; + private boolean failuresOnly; + private boolean strict; + private boolean stopOnFirstError; + + private int testsRun; + private int decisionsMatch; + private int statusCodesMatch; + private int attributesMatch; + private int policyIdsMatch; + private int policySetIdsMatch; + private int associatedAdviceMatch; + private int obligationsMatch; + private int unknownFunctions; + + + + + protected synchronized ConformanceScopeResolver getScopeResolver() { + if (this.scopeResolver == null) { + this.scopeResolver = new ConformanceScopeResolver(); + + /* + * TODO: + * Add the known scopes for the 2.0 conformance test. This could be made more general by allowing loading + * from a properties file eventually. + */ + try { + URI ID_SCOPE_ROOT = new URI("urn:root"); + URI ID_SCOPE_CHILD1 = new URI("urn:root:child1"); + URI ID_SCOPE_CHILD2 = new URI("urn:root:child2"); + URI ID_SCOPE_C1D1 = new URI("urn:root:child1:descendant1"); + URI ID_SCOPE_C1D2 = new URI("urn:root:child1:descendant2"); + URI ID_SCOPE_C2D1 = new URI("urn:root:child2:descendant1"); + URI ID_SCOPE_C2D2 = new URI("urn:root:child2:descendant2"); + + this.scopeResolver.add(ID_SCOPE_ROOT, ID_SCOPE_CHILD1); + this.scopeResolver.add(ID_SCOPE_CHILD1, ID_SCOPE_C1D1); + this.scopeResolver.add(ID_SCOPE_CHILD1, ID_SCOPE_C1D2); + this.scopeResolver.add(ID_SCOPE_ROOT, ID_SCOPE_CHILD2); + this.scopeResolver.add(ID_SCOPE_CHILD2, ID_SCOPE_C2D1); + this.scopeResolver.add(ID_SCOPE_CHILD2, ID_SCOPE_C2D2); + } catch (Exception ex) { + ex.printStackTrace(System.err); + } + + } + return this.scopeResolver; + } + + private void close() throws IOException { + if (this.outputFileWriter != null) { + this.outputFileWriter.close(); + } + } + + private boolean init(String[] args) { + boolean lenientRequests = true; + boolean lenientPolicies = false; + // default is to not run any non-first-time iterations + int iterations = -1; + String testSetDirectoryNames = ""; + for (int i = 0 ; i < args.length ; ) { + + if (args[i].equals("-h") || args[i].equals("--help") || args[i].equals("-help")) { + printHelp(); + return false; + } + + + // where the XML Request/Response files are located + if (args[i].equals("-i") || args[i].equals("--input")) { + i++; + while (i < args.length && !args[i].startsWith("-")) { + testSetDirectoryNames += " " + args[i]; + try { + testSet.addConformanceTestSet(ConformanceTestSet.loadDirectory(new File(args[i]))); + } catch (Exception ex) { + ex.printStackTrace(System.err); + return false; + } + i++; + } + + // File path name where output will be put - default is stdout == Console + } else if (args[i].equals("-o") || args[i].equals("--output")) { + if (i+1 < args.length) { + this.outputFile = new File(args[i+1]); + i += 2; + } else { + System.err.println("Missing argument to " + args[i] + " command line option"); + return false; + } + // A list of specific test names (e.g.: -t IIA001 IIA007 IIIE301) - default is to run all tests + } else if (args[i].equals("-t") || args[i].equals("--tests")) { + i++; + while (i < args.length && !args[i].startsWith("-")) { + testNamesToRun.add(args[i]); + i++; + } + if (testNamesToRun.size() == 0) { + System.err.println("Missing test names after -t or --tests argument"); + return false; + } + // Include full details in the response, both the expected reqsponse (from file) and the actual response + } else if (args[i].equals("-v") || args[i].equals("--verbose")) { + this.verbose = true; + i++; + // Report only failures (success is silent) + } else if (args[i].equals("-f") || args[i].equals("--failures")) { + this.failuresOnly = true; + i++; + // When set, the XML must not contain extra attibutes/elements. Default is "lenient" where unexpected entries are ignored + } else if (args[i].equals("-s") || args[i].equals("--strict")) { + this.strict = true; + i++; + // (self explanatory) + } else if (args[i].equals("--stop-on-error")) { + this.stopOnFirstError = true; + i++; + } else if (args[i].equals("--lenient")) { + lenientPolicies = true; + lenientRequests = true; + i++; + } else if (args[i].equals("--lenient-policies")) { + lenientPolicies = true; + i++; + } else if (args[i].equals("--lenient-requests")) { + lenientRequests = true; + i++; + } else if (args[i].equals("--strict-policies")) { + lenientPolicies = false; + i++; + } else if (args[i].equals("--strict-requests")) { + lenientRequests = false; + i++; + } else if (args[i].equals("--iterations")) { + // this is a count of how many ADDITIONAL times the decide() should be called. + // The first time decide() is called it takes a long time to set up, + // so to get an accurate number for how fast a single Request is handled we need to ignore the time for the first run + // and timings for 1 or more non-first-time calls to decide(). + if (i+1 < args.length) { + try { + iterations = Integer.parseInt(args[i+1]); + i += 2; + } catch (NumberFormatException ex) { + System.err.println("Invalid iteration count '" + args[i+1] + "'"); + return false; + } + } else { + System.err.println("Missing argument to " + args[i] + " command line option"); + return false; + } + if (iterations < 1) { + System.err.println("Cannot use --iterations " + iterations + ". Must use an integer greater than 0"); + return false; + } + } else { + System.err.println("Unknown command line option " + args[i]); + return false; + } + } + + this.testEngine = new ConformanceTestEngine(this.getScopeResolver(), lenientRequests, lenientPolicies, iterations); + + if (testSetDirectoryNames.length() == 0) { + System.err.println("No test set directory given (need -i or --iniput command line option)"); + return false; + } + if (testSet.getListConformanceTests().size() == 0) { + System.err.println("No tests in given directories: " + testSetDirectoryNames); + } + + if (testNamesToRun.size() > 0) { + String s = ""; + for (String name : testNamesToRun) { + s += ", " + name; + } + System.out.println("Tests limited to: " + s.substring(1)); + } + + if (this.outputFile == null) { + this.outputFileWriter = new PrintWriter(System.out); + } else { + try { + this.outputFileWriter = new PrintWriter(new FileOutputStream(this.outputFile)); + } catch (IOException ex) { + System.err.println("Cannot open " + this.outputFile.getAbsolutePath() + " for writing."); + return false; + } + } + + return true; + } + + private void printHelp() { + System.out.println("usage: Conformance --input <tests_directory> OPTIONS"); + System.out.println(""); + System.out.println(" -f, --failures Only include failed tests in the output. \n"+ + " Default is to include all test's results in the output file."); + System.out.println(""); + System.out.println(" -h, --help Prints help."); + + System.out.println(""); + System.out.println(" -i, --input <dir> Directory containing the XML Request/Response files. \n"+ + " This may be multiple space-separated directory paths. REQUIRED"); + + System.out.println(""); + System.out.println(" --iterations The number of times to run through the set of tests in the input directory."); + + System.out.println(""); + System.out.println(" --lenient Allow both Requests and Policies to have unexpected elements, no data in <Content>, etc. \n"+ + " Default is to not allow anything that is not explicitly listed in the XACML spec."); + + System.out.println(""); + System.out.println(" --lenient-policies Allow Policies to have unexpected elements, no data in <Content>, etc. \n" + + " Default is to not allow anything that is not explicitly listed in the XACML spec."); + + System.out.println(""); + System.out.println(" --lenient-requests Allow Requests to have unexpected elements, no data in <Content>, etc. \n" + + " Default is to not allow anything that is not explicitly listed in the XACML spec."); + + System.out.println(""); + System.out.println(" -o, --output <dir> Directory where the output results file will be put."); + + System.out.println(""); + System.out.println(" -s, --strict Check both the Decision and all other parts of the Response (Attributes, Obligations and Advice). \n "+ + " Default is to check just the Decision."); + + System.out.println(""); + System.out.println(" --stop-on-error Stop running conformance tests the first time one fails. Default is to continue through all tests."); + + System.out.println(""); + System.out.println(" --strict-policies Require Policies to have no unexpected elements, data in <Content>, etc. \n" + + " This is the default, but can be used to override Policies when option --lenient is used."); + + System.out.println(""); + System.out.println(" --strict-requests Require Requests to have no unexpected elements, data in <Content>, etc. \n" + + " This is the default, but can be used to override Requests when option --lenient is used."); + + System.out.println(""); + System.out.println(" -t, --tests <list of test names> A space-separated list of specific tests to be run. \n" + + " These are just the names of the tests as in 'IIA001 IIC178'. \n" + + " Default is to run all tests in the input directory."); + + System.out.println(""); + System.out.println(" -v, --verbose The entire expected and actual Response objects in the output. \n"+ + " Default is just a summary line."); + + } + + private boolean failed(ConformanceTestResult conformanceTestResult) { + ResponseMatchResult responseMatchResult = conformanceTestResult.getResponseMatchResult(); + if (responseMatchResult == null) { + return true; + } + if (!responseMatchResult.decisionsMatch() || !responseMatchResult.statusCodesMatch()) { + return true; + } else if (this.strict) { + if (!responseMatchResult.associatedAdviceMatches() || + !responseMatchResult.attributesMatch() || + !responseMatchResult.obligationsMatch() || + !responseMatchResult.policyIdentifiersMatch() || + !responseMatchResult.policySetIdentifiersMatch() + ) { + return true; + } + } + return false; + } + + private void dump(AttributeAssignment attributeAssignment) { + this.outputFileWriter.println("\t\t\t\tAttributeAssignment:"); + if (attributeAssignment.getCategory() != null) { + this.outputFileWriter.println("\t\t\t\t\tCategory: " + attributeAssignment.getCategory().stringValue()); + } + if (attributeAssignment.getAttributeId() != null) { + this.outputFileWriter.println("\t\t\t\t\tAttributeId: " + attributeAssignment.getAttributeId().stringValue()); + } + if (attributeAssignment.getDataTypeId() != null) { + this.outputFileWriter.println("\t\t\t\t\tDataType: " + attributeAssignment.getDataTypeId().stringValue()); + } + if (attributeAssignment.getIssuer() != null) { + this.outputFileWriter.println("\t\t\t\t\tIssuer: " + attributeAssignment.getIssuer()); + } + if (attributeAssignment.getAttributeValue() != null && attributeAssignment.getAttributeValue().getValue() != null) { + this.outputFileWriter.println("\t\t\t\t\tValue: " + attributeAssignment.getAttributeValue().getValue().toString()); + } + } + + private void dump(Attribute attribute) { + this.outputFileWriter.println("\t\t\t\t\tAttribute: " + (attribute.getAttributeId() == null ? "" : attribute.getAttributeId().stringValue())); + if (attribute.getIssuer() != null) { + this.outputFileWriter.println("\t\t\t\t\t\tIssuer: " + attribute.getIssuer()); + } + Iterator<AttributeValue<?>> iterAttributeValues = attribute.getValues().iterator(); + if (iterAttributeValues.hasNext()) { + this.outputFileWriter.println("\t\t\t\t\t\tValues: "); + while (iterAttributeValues.hasNext()) { + this.outputFileWriter.print("\t\t\t\t\t\t\t"); + AttributeValue<?> attributeValue = iterAttributeValues.next(); + if (attributeValue.getDataTypeId() != null) { + this.outputFileWriter.print("DataType: " + attributeValue.getDataTypeId().stringValue() + " "); + } + if (attributeValue.getValue() != null) { + this.outputFileWriter.print("Value: " + attributeValue.getValue().toString()); + } + this.outputFileWriter.println(); + } + } + } + + private void dump(AttributeCategory attributeCategory) { + this.outputFileWriter.println("\t\t\tAttributeCategory: " + (attributeCategory.getCategory() == null ? "" : attributeCategory.getCategory().stringValue())); + Collection<Attribute> listAttributes = attributeCategory.getAttributes(); + if (listAttributes.size() > 0) { + this.outputFileWriter.println("\t\t\t\tAttributes:"); + for (Attribute attribute: listAttributes) { + this.dump(attribute); + } + } + } + + private void dump(Result result) { + this.outputFileWriter.println("\t\t======== Result =========="); + this.outputFileWriter.println("\t\tDecision: " + (result.getDecision() == null ? "null" : result.getDecision().name())); + if (result.getStatus() == null) { + this.outputFileWriter.println("\t\tStatus: null"); + } else { + this.outputFileWriter.println("\t\tStatus:"); + if (result.getStatus().getStatusCode() != null) { + this.outputFileWriter.println("\t\t\tStatusCode: " + result.getStatus().getStatusCode().toString()); + } + if (result.getStatus().getStatusMessage() != null) { + this.outputFileWriter.println("\t\t\tStatusMessage: " + result.getStatus().getStatusMessage()); + } + if (result.getStatus().getStatusDetail() != null) { + this.outputFileWriter.println("\t\t\tStatusDetail: " + result.getStatus().getStatusDetail().toString()); + } + } + Collection<Advice> listAdvice = result.getAssociatedAdvice(); + if (listAdvice.size() > 0) { + this.outputFileWriter.println("\t\tAdvice:"); + for (Advice advice : listAdvice) { + if (advice.getId() != null) { + this.outputFileWriter.println("\t\t\tId: " + advice.getId().stringValue()); + } + Collection<AttributeAssignment> attributeAssignments = advice.getAttributeAssignments(); + if (attributeAssignments.size() > 0) { + this.outputFileWriter.println("\t\t\tAttributeAssignments:"); + for (AttributeAssignment attributeAssignment: attributeAssignments) { + this.dump(attributeAssignment); + } + } + } + } + Collection<Obligation> listObligations = result.getObligations(); + if (listObligations.size() > 0) { + for (Obligation obligation: listObligations) { + if (obligation.getId() != null) { + this.outputFileWriter.println("\t\t\tId: " + obligation.getId().stringValue()); + } + Collection<AttributeAssignment> attributeAssignments = obligation.getAttributeAssignments(); + if (attributeAssignments.size() > 0) { + this.outputFileWriter.println("\t\t\tAttributeAssignments:"); + for (AttributeAssignment attributeAssignment : attributeAssignments) { + this.dump(attributeAssignment); + } + } + } + } + Collection<AttributeCategory> listAttributeCategories = result.getAttributes(); + if (listAttributeCategories.size() > 0) { + this.outputFileWriter.println("\t\tAttributes:"); + for (AttributeCategory attributeCategory : listAttributeCategories) { + this.dump(attributeCategory); + } + } + Collection<IdReference> listIdReferences; + if ((listIdReferences = result.getPolicyIdentifiers()).size() > 0) { + this.outputFileWriter.println("\t\tPolicyIds:"); + for (IdReference idReference : listIdReferences) { + this.outputFileWriter.println("\t\t\t" + idReference.toString()); + } + } + if ((listIdReferences = result.getPolicySetIdentifiers()).size() > 0) { + this.outputFileWriter.println("\t\tPolicySetIds:"); + for (IdReference idReference : listIdReferences) { + this.outputFileWriter.println("\t\t\t" + idReference.toString()); + } + } + } + + private void dump(String label, Response response) { + this.outputFileWriter.println("\t========== " + label + "=========="); + if (response == null) { + this.outputFileWriter.println("null"); + return; + } + + for (Result result : response.getResults()) { + this.dump(result); + } + } + + private void dump(ConformanceTestResult conformanceTestResult) { + + ResponseMatchResult responseMatchResult = conformanceTestResult.getResponseMatchResult(); + if (this.verbose) { + this.outputFileWriter.println("========== Test " + conformanceTestResult.getConformanceTest().getTestName() + " =========="); + this.dump("Expected Response", conformanceTestResult.getExpectedResponse()); + this.dump("Actual Response", conformanceTestResult.getActualResponse()); + if (responseMatchResult != null) { + this.outputFileWriter.println("\t========== Matching =========="); + this.outputFileWriter.println("\tDecisions Match? " + responseMatchResult.decisionsMatch()); + this.outputFileWriter.println("\tStatus Codes Match? " + responseMatchResult.statusCodesMatch()); + this.outputFileWriter.println("\tAttributes Match? " + responseMatchResult.attributesMatch()); + this.outputFileWriter.println("\tPolicyIds Match? " + responseMatchResult.policyIdentifiersMatch()); + this.outputFileWriter.println("\tPolicySetIds Match? " + responseMatchResult.policySetIdentifiersMatch()); + this.outputFileWriter.println("\tAssociated Advice Match? " + responseMatchResult.associatedAdviceMatches()); + this.outputFileWriter.println("\tObligations Match? " + responseMatchResult.obligationsMatch()); + this.outputFileWriter.println("========== End =========="); + } + } else { + String testName = conformanceTestResult.getConformanceTest().getTestName(); + if (responseMatchResult != null) { + Iterator<ResultMatchResult> iterResultMatches = responseMatchResult.getResultMatchResults(); + if (iterResultMatches == null || !iterResultMatches.hasNext()) { + this.outputFileWriter.println(testName); + } else { + while (iterResultMatches.hasNext()) { + ResultMatchResult resultMatchResult = iterResultMatches.next(); + this.outputFileWriter.printf("%s,%s,%s,%s,%s,%s,%s,%s,%d,%d\n", + testName, + resultMatchResult.decisionsMatch(), + resultMatchResult.statusCodesMatch(), + resultMatchResult.attributesMatch(), + resultMatchResult.policyIdentifiersMatch(), + resultMatchResult.policySetIdentifiersMatch(), + resultMatchResult.associatedAdviceMatches(), + resultMatchResult.obligationsMatch(), + conformanceTestResult.getFirstCallTime(), + conformanceTestResult.getAverageTotalLoopTime() + ); + } + } + } + } + this.outputFileWriter.flush(); + } + + private boolean run(ConformanceTest conformanceTest) throws Exception { + this.testsRun++; + ConformanceTestResult conformanceTestResult = this.testEngine.run(conformanceTest); + boolean bFailed = true; + if (conformanceTestResult != null) { + ResponseMatchResult responseMatchResult = conformanceTestResult.getResponseMatchResult(); + if (responseMatchResult != null) { + if (responseMatchResult.decisionsMatch()) { + this.decisionsMatch++; + this.statusCodesMatch += (responseMatchResult.statusCodesMatch() ? 1 : 0); + this.attributesMatch += (responseMatchResult.attributesMatch() ? 1 : 0); + this.policyIdsMatch += (responseMatchResult.policyIdentifiersMatch() ? 1 : 0); + this.policySetIdsMatch += (responseMatchResult.policySetIdentifiersMatch() ? 1 : 0); + this.associatedAdviceMatch += (responseMatchResult.associatedAdviceMatches() ? 1 : 0); + this.obligationsMatch += (responseMatchResult.obligationsMatch() ? 1 : 0); + } + this.unknownFunctions += (responseMatchResult.unknownFunction() ? 1 : 0); + bFailed = this.failed(conformanceTestResult); + if (bFailed || !this.failuresOnly) { + this.dump(conformanceTestResult); + } + } else if (conformanceTestResult.getError() != null) { + this.outputFileWriter.println(conformanceTestResult.getError()); + } + } + return (!bFailed || !this.stopOnFirstError); + } + + private void run() throws Exception { + long tStart = System.currentTimeMillis(); + + if (!this.verbose) { + this.outputFileWriter.println("Test,Decision,Status,Attributes,PolicyIds,PolicySetIds,Advice,Obligations"); + } + Iterator<ConformanceTest> iterConformanceTests = this.testSet.getConformanceTests(); + boolean bContinue = true; + while (bContinue && iterConformanceTests.hasNext()) { +// bContinue = this.run(iterConformanceTests.next()); + ConformanceTest test = iterConformanceTests.next(); + if (testNamesToRun.size() > 0) { + if ( ! testNamesToRun.contains(test.getTestName())) { + continue; + } + } + bContinue = this.run(test); + } + + long tElapsed = System.currentTimeMillis() - tStart; + + if (this.verbose) { + this.outputFileWriter.println("Tests run = " + this.testsRun); + this.outputFileWriter.println("Decisions match = " + this.decisionsMatch); + this.outputFileWriter.println("Status Codes match = " + this.statusCodesMatch); + this.outputFileWriter.println("Attributes match = " + this.attributesMatch); + this.outputFileWriter.println("PolicyIds match = " + this.policyIdsMatch); + this.outputFileWriter.println("PolicySetIds match = " + this.policySetIdsMatch); + this.outputFileWriter.println("Associated Advice match = " + this.associatedAdviceMatch); + this.outputFileWriter.println("Obligations match = " + this.obligationsMatch); + this.outputFileWriter.println("Unknown functions = " + this.unknownFunctions); + } else { + this.outputFileWriter.printf("Total (%d),%d,%d,%d,%d,%d,%d,%d,%d\n", + this.testsRun, + this.decisionsMatch, + this.statusCodesMatch, + this.attributesMatch, + this.policyIdsMatch, + this.policySetIdsMatch, + this.associatedAdviceMatch, + this.obligationsMatch, + this.unknownFunctions); + } + + if (tElapsed > 0) { + long tHours = tElapsed / (60*60*1000); + tElapsed = tElapsed - tHours * 60 * 60 *1000; + long tMinutes = tElapsed / (60*1000); + tElapsed = tElapsed - tMinutes * 60 * 1000; + long tSeconds = tElapsed / 1000; + tElapsed = tElapsed - tSeconds * 1000; + + this.outputFileWriter.printf("Elapsed time = %02d:%02d:%02d.%03d\n", tHours, tMinutes, tSeconds, tElapsed); + this.outputFileWriter.printf("First decide time in nano-seconds %d\n", this.testEngine.getFirstDecideTime()); + this.outputFileWriter.printf("Total Multiple decide time in nano-seconds %d\n", this.testEngine.getDecideTimeMultiple()); + + this.outputFileWriter.printf("\nAverage First decide time in nano-seconds %d\n", this.testEngine.getAvgFirstDecideTime()); + this.outputFileWriter.printf("Average decide time after first call in nano-seconds %d\n", this.testEngine.getAvgDecideTimeMultiple()); + } + } + + public Conformance() { + } + + public static void main(String[] args) { + Conformance conformance = new Conformance(); + try { + if (conformance.init(args)) { + conformance.run(); + } + + } catch (Exception ex) { + ex.printStackTrace(System.err); + System.exit(1); + } finally { + try { + conformance.close(); + } catch (IOException ex) { + ex.printStackTrace(System.err); + } + } + System.exit(0); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformancePIPEngine.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformancePIPEngine.java new file mode 100644 index 000000000..e81024159 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformancePIPEngine.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.DataTypeFactory; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.pip.StdPIPResponse; +import com.att.research.xacml.std.pip.engines.ConfigurableEngine; +import com.att.research.xacml.util.FactoryException; + +/** + * ConformancePIPEngine implements the {@link com.att.research.xacml.api.pip.PIPFinder} interface to find attributes + * loaded from a text file containing the following fields: + * category-id,attribute-id,datatype-id,issuer,value + * + * @version $Revision: 1.1 $ + */ +public class ConformancePIPEngine implements ConfigurableEngine { + public static final String PROP_DESCRIPTION = ".description"; + public static final String PROP_FILE = ".file"; + + private static final Logger logger = FlexLogger.getLogger(ConformancePIPEngine.class); + + private String name; + private String description; + private Map<String,PIPResponse> cache = new HashMap<>(); + private List<Attribute> listAttributes = new ArrayList<>(); + private DataTypeFactory dataTypeFactory; + + public ConformancePIPEngine() { + + } + + protected DataTypeFactory getDataTypeFactory() throws FactoryException { + if (this.dataTypeFactory == null) { + this.dataTypeFactory = DataTypeFactory.newInstance(); + } + return this.dataTypeFactory; + } + + protected static String generateKey(PIPRequest pipRequest) { + StringBuilder stringBuilder = new StringBuilder(pipRequest.getCategory().toString()); + stringBuilder.append('+'); + stringBuilder.append(pipRequest.getAttributeId().toString()); + stringBuilder.append('+'); + stringBuilder.append(pipRequest.getDataTypeId().toString()); + String issuer = pipRequest.getIssuer(); + if (issuer != null) { + stringBuilder.append('+'); + stringBuilder.append(issuer); + } + return stringBuilder.toString(); + } + + protected void store(String[] fields) throws FactoryException { + DataTypeFactory thisDataTypeFactory = this.getDataTypeFactory(); + Identifier identifierCategory = new IdentifierImpl(fields[0]); + Identifier identifierAttribute = new IdentifierImpl(fields[1]); + Identifier identifierDataType = new IdentifierImpl(fields[2]); + String issuer = (fields.length == 5 ? fields[3] : null); + String value = fields[fields.length - 1]; + + DataType<?> dataType = thisDataTypeFactory.getDataType(identifierDataType); + if (dataType == null) { + logger.error("Unknown data type " + identifierDataType.stringValue()); + return; + } + + AttributeValue<?> attributeValue = null; + try { + attributeValue = dataType.createAttributeValue(value); + } catch (DataTypeException ex) { + throw new FactoryException("DataTypeException creating AttributeValue", ex); + } + Attribute attribute = new StdMutableAttribute(identifierCategory, identifierAttribute, attributeValue, issuer, false); + this.listAttributes.add(attribute); + } + + public void loadAttributes(File fileAttributes) throws IOException, ParseException, FactoryException { + if (fileAttributes != null) { + if (!fileAttributes.exists()) { + throw new FileNotFoundException("Attributes file " + fileAttributes.getAbsolutePath() + " not found."); + } else if (!fileAttributes.canRead()) { + throw new IOException("Attributes file " + fileAttributes.getAbsolutePath() + " is not readable."); + } + + BufferedReader bufferedReader = null; + try { + bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileAttributes))); + String line; + while ((line = bufferedReader.readLine()) != null) { + if (line.length() > 0) { + String[] fields = line.split("[|]",-1); + if (fields.length < 4) { + logger.warn("Not enough fields in record \"" + line + "\""); + continue; + } + this.store(fields); + + } + } + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + } + } + + protected Attribute findAttribute(PIPRequest pipRequest) { + Attribute attributeResult = null; + Iterator<Attribute> iterAttributes = this.listAttributes.iterator(); + while ((attributeResult == null) && iterAttributes.hasNext()) { + Attribute attributeTest = iterAttributes.next(); + if (pipRequest.getCategory().equals(attributeTest.getCategory()) && + pipRequest.getAttributeId().equals(attributeTest.getAttributeId()) && + (pipRequest.getIssuer() == null || pipRequest.getIssuer().equals(attributeTest.getIssuer()))) { + attributeResult = attributeTest; + } + } + return attributeResult; + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { + String pipRequestKey = generateKey(pipRequest); + PIPResponse pipResponse = this.cache.get(pipRequestKey); + if (pipResponse != null) { + return pipResponse; + } + Attribute attributeMatch = this.findAttribute(pipRequest); + if (attributeMatch == null) { + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + /* + * Iterate through the values and only return the ones that match the requested data type + */ + List<AttributeValue<?>> matchingValues = new ArrayList<>(); + Iterator<AttributeValue<?>> iterAttributeValues = attributeMatch.getValues().iterator(); + while (iterAttributeValues.hasNext()) { + AttributeValue<?> attributeValue = iterAttributeValues.next(); + if (pipRequest.getDataTypeId().equals(attributeValue.getDataTypeId())) { + matchingValues.add(attributeValue); + } + } + if (matchingValues.size() > 0) { + Attribute attributeResponse = new StdMutableAttribute(attributeMatch.getCategory(), attributeMatch.getAttributeId(), matchingValues, attributeMatch.getIssuer(), false); + pipResponse = new StdPIPResponse(attributeResponse); + this.cache.put(pipRequestKey, pipResponse); + } + return pipResponse; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getDescription() { + return this.description; + } + + @Override + public void configure(String id, Properties properties) throws PIPException { + this.name = id; + this.description = properties.getProperty(id + PROP_DESCRIPTION); + if (this.description == null) { + this.description = "PIPEngine for the Conformance tests that loads attributes from a CSV file"; + } + String pipFile = properties.getProperty(id + PROP_FILE); + if (pipFile != null) { + try { + this.loadAttributes(new File(pipFile)); + } catch (Exception ex) { + logger.error("Exception loading PIP file " + pipFile, ex); + throw new PIPException("Exception loading PIP file " + pipFile, ex); + } + } + } + + @Override + public Collection<PIPRequest> attributesRequired() { + return Collections.emptyList(); + } + + @Override + public Collection<PIPRequest> attributesProvided() { + // + // We could return everything in our list + // + return Collections.emptyList(); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceRepository.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceRepository.java new file mode 100644 index 000000000..995537ecd --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceRepository.java @@ -0,0 +1,127 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import com.att.research.xacml.util.StringUtils; +import com.att.research.xacml.util.XACMLProperties; +import com.att.research.xacmlatt.pdp.std.StdPolicyFinderFactory; + +/** + * ConformanceRepository represents one or more policies for a single policy test, which will include one or more root policies, and + * zero or more referenced policies. + * + * @version $Revision$ + */ +public class ConformanceRepository { + private List<File> rootPolicies = new ArrayList<>(); + private List<File> referencedPolicies = new ArrayList<>(); + + private void setXACMLProperty(String propertyName, List<File> listFiles) { + Iterator<File> iterFiles = listFiles.iterator(); + StringBuilder stringBuilderIdList = new StringBuilder(); + while (iterFiles.hasNext()) { + File file = iterFiles.next(); + if (stringBuilderIdList.length() > 0) { + stringBuilderIdList.append(','); + } + stringBuilderIdList.append(file.getName()); + + XACMLProperties.setProperty(file.getName() + StdPolicyFinderFactory.PROP_FILE, file.getAbsolutePath()); + } + XACMLProperties.setProperty(propertyName, stringBuilderIdList.toString()); + } + + public ConformanceRepository() { + } + + public void setXACMLProperties() { + if (this.rootPolicies.size() > 0) { + this.setXACMLProperty(XACMLProperties.PROP_ROOTPOLICIES, this.rootPolicies); + } + if (this.referencedPolicies.size() > 0) { + this.setXACMLProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, this.referencedPolicies); + } + } + + private void loadProperty(File fileDir, Properties properties, String propertyName, List<File> listFiles) { + String fileNameList = properties.getProperty(propertyName); + if (fileNameList != null) { + String[] fileNameArray = fileNameList.split("[,]",0); + if (fileNameArray != null && fileNameArray.length > 0) { + for (String fileName : fileNameArray) { + File file = new File(fileDir, fileName); + if (file.exists() && file.canRead()) { + listFiles.add(file); + } + } + } + } + } + + public void load(File fileRepository) throws IOException { + Properties propertiesRepository = new Properties(); + try (InputStream is = new FileInputStream(fileRepository)) { + propertiesRepository.load(is); + } + this.loadProperty(fileRepository.getParentFile(), propertiesRepository, XACMLProperties.PROP_ROOTPOLICIES, this.rootPolicies); + this.loadProperty(fileRepository.getParentFile(), propertiesRepository, XACMLProperties.PROP_REFERENCEDPOLICIES, this.referencedPolicies); + } + + public void addRootPolicy(File filePolicy) { + this.rootPolicies.add(filePolicy); + } + + public boolean hasRootPolicy() { + return (this.rootPolicies.size() > 0); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder("{"); + boolean needComma = false; + + if (this.rootPolicies != null && this.rootPolicies.size() > 0) { + stringBuilder.append("rootPolicies="); + stringBuilder.append(StringUtils.toString(this.rootPolicies.iterator())); + needComma = true; + } + if (this.referencedPolicies != null && this.referencedPolicies.size() > 0) { + if (needComma) { + stringBuilder.append(','); + } + stringBuilder.append("referencedPolicies="); + stringBuilder.append(StringUtils.toString(this.referencedPolicies.iterator())); + needComma = true; + } + stringBuilder.append('}'); + return stringBuilder.toString(); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceScopeResolver.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceScopeResolver.java new file mode 100644 index 000000000..654145424 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceScopeResolver.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.pdp.ScopeQualifier; +import com.att.research.xacml.api.pdp.ScopeResolver; +import com.att.research.xacml.api.pdp.ScopeResolverException; +import com.att.research.xacml.api.pdp.ScopeResolverResult; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.StdScopeResolverResult; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; + +/** + * ConformanceScopeResolver implements {@link com.att.research.xacml.pdp.ScopeResolver} for the conformance tests + * using a fixed set of hierarchical resources defined in a map. + * + * @version $Revision$ + */ +public class ConformanceScopeResolver implements ScopeResolver { + private Logger logger = FlexLogger.getLogger(ConformanceScopeResolver.class); + private Map<URI, List<URI>> mapIdentifierToChildren = new HashMap<>(); + + public ConformanceScopeResolver() { + } + + public void add(URI identifierRoot, URI identifierChild) { + List<URI> listChildrenRoot = this.mapIdentifierToChildren.get(identifierRoot); + if (listChildrenRoot == null) { + listChildrenRoot = new ArrayList<>(); + this.mapIdentifierToChildren.put(identifierRoot, listChildrenRoot); + } + listChildrenRoot.add(identifierChild); + } + + private void addChildren(Attribute attributeResourceId, URI urnResourceIdValue, boolean bDescendants, List<Attribute> listAttributes) { + List<URI> listChildren = this.mapIdentifierToChildren.get(urnResourceIdValue); + if (listChildren != null) { + for (URI uriChild : listChildren) { + AttributeValue<URI> attributeValueURI = null; + try { + attributeValueURI = DataTypes.DT_ANYURI.createAttributeValue(uriChild); + if (attributeValueURI != null) { + listAttributes.add(new StdMutableAttribute(attributeResourceId.getCategory(), attributeResourceId.getAttributeId(), attributeValueURI, attributeResourceId.getIssuer(), attributeResourceId.getIncludeInResults())); + } + } catch (Exception ex) { + this.logger.error("Exception converting URI to an AttributeValue"); + } + if (bDescendants) { + this.addChildren(attributeResourceId, uriChild, bDescendants, listAttributes); + } + } + } + } + + private void addChildren(Attribute attributeResourceId, boolean bDescendants, List<Attribute> listAttributes) { + /* + * Iterate over the values that are URNs + */ + Iterator<AttributeValue<URI>> iterAttributeValueURNs = attributeResourceId.findValues(DataTypes.DT_ANYURI); + if (iterAttributeValueURNs != null) { + while (iterAttributeValueURNs.hasNext()) { + this.addChildren(attributeResourceId, iterAttributeValueURNs.next().getValue(), bDescendants, listAttributes); + } + } + } + + @Override + public ScopeResolverResult resolveScope(Attribute attributeResourceId, ScopeQualifier scopeQualifier) throws ScopeResolverException { + List<Attribute> listAttributes = new ArrayList<>(); + switch(scopeQualifier) { + case CHILDREN: + listAttributes.add(attributeResourceId); + this.addChildren(attributeResourceId, false, listAttributes); + break; + case DESCENDANTS: + listAttributes.add(attributeResourceId); + this.addChildren(attributeResourceId, true, listAttributes); + break; + case IMMEDIATE: + listAttributes.add(attributeResourceId); + break; + default: + this.logger.error("Unknown ScopeQualifier: " + scopeQualifier.name()); + return new StdScopeResolverResult(new StdStatus(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "Unknown ScopeQualifier " + scopeQualifier.name())); + } + return new StdScopeResolverResult(listAttributes); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTest.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTest.java new file mode 100644 index 000000000..a37d1c155 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTest.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.io.File; + +/** + * ConformanceTest represents a collection of XACML files with a root Policy document, optional referenced Policy documents, a Request, and a Response. + * + * @version $Revision: 1.2 $ + */ +public class ConformanceTest { + private String testName; + private File request; + private File response; + private ConformanceRepository repository; + + public ConformanceTest(String name, ConformanceRepository conformanceRepository, File fileRequest, File fileResponse) { + this.testName = name; + this.request = fileRequest; + this.response = fileResponse; + this.repository = conformanceRepository; + } + + public ConformanceTest(String name) { + this.testName = name; + } + + public String getTestName() { + return this.testName; + } + public void setTestName(String s) { + this.testName = s; + } + public ConformanceRepository getRepository() { + if (this.repository == null) { + this.repository = new ConformanceRepository(); + } + return this.repository; + } + public File getRequest() { + return this.request; + } + public void setRequest(File f) { + this.request = f; + } + public File getResponse() { + return this.response; + } + public void setResponse(File f) { + this.response = f; + } + + public boolean isComplete() { + return this.getTestName() != null && this.getRepository() != null && this.getRepository().hasRootPolicy() && this.getRequest() != null && this.getResponse() != null; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + boolean needColon = false; + if (this.getTestName() != null) { + stringBuilder.append(this.getTestName()); + needColon = true; + } + if (this.getRepository() != null) { + + } + if (this.getRequest() != null) { + if (needColon) { + stringBuilder.append(':'); + } + stringBuilder.append(this.getRequest().getName()); + needColon = true; + } + if (this.getResponse() != null) { + if (needColon) { + stringBuilder.append(':'); + } + stringBuilder.append(this.getResponse().getName()); + needColon = true; + } + return stringBuilder.toString(); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestEngine.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestEngine.java new file mode 100644 index 000000000..91e96cf1a --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestEngine.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPEngineFactory; +import com.att.research.xacml.api.pdp.ScopeResolver; +import com.att.research.xacml.std.dom.DOMProperties; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacml.std.dom.DOMResponse; +import com.att.research.xacml.util.FactoryException; + +/** + * ConformanceTestEngine handles the creation of the PDPEngine for a ConformanceTest instance. + * + * @version $Revision: 1.2 $ + */ +public class ConformanceTestEngine { + private Logger logger = FlexLogger.getLogger(ConformanceTestEngine.class); + + private PDPEngineFactory pdpEngineFactory; + private ScopeResolver scopeResolver; + private boolean lenientRequests; + private boolean lenientPolicies; + private int iterations = 1; + + // total of all first calls to decide() + private long firstDecideTime; + private int numberOfFirstDecides = 0; + + // total of all non-first-calls to decide() + private long decideTimeMultiple; + + // total of average time each test case uses for a Request + // (sum of : for each test case, average of all non-first-call calls to decide() ) + private long avgDecideTimeMultiple = 0; + + protected PDPEngineFactory getPDPEngineFactory() throws FactoryException { + if (this.pdpEngineFactory == null) { + this.pdpEngineFactory = PDPEngineFactory.newInstance(); + this.pdpEngineFactory.setScopeResolver(this.scopeResolver); + } + return this.pdpEngineFactory; + } + + public ConformanceTestEngine(ScopeResolver scopeResolverIn, boolean lenientRequestsIn, boolean lenientPoliciesIn, int iterationsIn) { + this.scopeResolver = scopeResolverIn; + this.lenientRequests = lenientRequestsIn; + this.lenientPolicies = lenientPoliciesIn; + this.iterations = iterationsIn; + } + + public ConformanceTestResult run(ConformanceTest conformanceTest) { + if (conformanceTest.getRequest() == null || conformanceTest.getResponse() == null || conformanceTest.getRepository() == null) { + logger.error("Incomplete Conformance Test: " + conformanceTest.getTestName()); + } + PDPEngineFactory thisPDPEngineFactory = null; + try { + thisPDPEngineFactory = this.getPDPEngineFactory(); + } catch (FactoryException ex) { + return new ConformanceTestResult(conformanceTest, ex); + } + + ConformanceTestResult conformanceTestResult = new ConformanceTestResult(conformanceTest, iterations); + + /* + * Load the request + */ + Request request = null; + boolean isLenient = DOMProperties.isLenient(); + try { + DOMProperties.setLenient(this.lenientRequests); + try { + request = DOMRequest.load(conformanceTest.getRequest()); + conformanceTestResult.setRequest(request); + } catch (Exception ex) { + logger.error("Exception loading Request file " + conformanceTest.getRequest().getAbsolutePath(), ex); + conformanceTestResult.setError(ex); + return conformanceTestResult; + + } + + /* + * Load the expected response + */ + Response response = null; + try { + response = DOMResponse.load(conformanceTest.getResponse()); + conformanceTestResult.setExpectedResponse(response); + } catch (Exception ex) { + logger.error("Exception loading Response file " + conformanceTest.getResponse().getAbsolutePath(), ex); + conformanceTestResult.setError(ex); + return conformanceTestResult; + } + + /* + * Set up the configuration for the policy finder + */ + conformanceTest.getRepository().setXACMLProperties(); + DOMProperties.setLenient(this.lenientPolicies); + + /* + * Create the engine + */ + PDPEngine pdpEngine = null; + try { + // pdpEngine = thisPDPEngineFactory.newEngine(conformanceTest.getRootPolicy(), conformanceTest.getReferencedPolicies(), pipFinderEngine); + pdpEngine = thisPDPEngineFactory.newEngine(); + } catch (Exception ex) { + logger.error("Exception getting PDP engine instance", ex); + conformanceTestResult.setError(ex); + return conformanceTestResult; + } + if (pdpEngine == null) { + logger.error("Null PDP engine"); + conformanceTestResult.setError(new NullPointerException("Null engine")); + return conformanceTestResult; + } + + /* + * Run the request + */ + long startTime, endTime; + long curDecideTime = this.firstDecideTime; + try { + startTime = System.nanoTime(); + response = pdpEngine.decide(request); + endTime = System.nanoTime(); +//System.out.println(endTime - startTime); + // add to total + this.firstDecideTime += endTime - startTime; + this.numberOfFirstDecides++; + // remember just this test + conformanceTestResult.setFirstCallTime(endTime - startTime); + conformanceTestResult.setActualResponse(response); + } catch (Exception ex) { + logger.error("Exception in decide", ex); + conformanceTestResult.setError(ex); + return conformanceTestResult; + } + if (response == null) { + logger.error("Null Response"); + conformanceTestResult.setError(new NullPointerException("Null Response")); + return conformanceTestResult; + } + + long localLoopTime = 0; + try { + // if user requested non-first-call calls to decide() to get performance info, run them now. + // We can ignore the result since we are only interested in how long they take to process the Request. + for (int i = 0 ; i < this.iterations ; i++) { + startTime = System.nanoTime(); + pdpEngine.decide(request); + endTime = System.nanoTime(); +//System.out.println(endTime - startTime); + // add to the global total for all tests + this.decideTimeMultiple += (endTime - startTime); + // remember just this one test's info + localLoopTime += (endTime - startTime); + } + } catch (Exception ex) { + logger.error("Exception in iterated decide", ex); + return conformanceTestResult; + } + + // add to total average for non-first-call times for all test cases + avgDecideTimeMultiple += (localLoopTime / iterations); +//System.out.println("localLoop="+localLoopTime + " it="+iterations + " avg=" + (localLoopTime / iterations) ); + // remember average time for just this test + conformanceTestResult.setAverageTotalLoopTime(localLoopTime/iterations); + + long elapsedDecideTime = this.firstDecideTime - curDecideTime; + logger.info("Decide Time: " + elapsedDecideTime + "ns"); + + return conformanceTestResult; + } finally { + DOMProperties.setLenient(isLenient); + } + } + + public long getFirstDecideTime() { + return this.firstDecideTime; + } + + public long getDecideTimeMultiple() { + return this.decideTimeMultiple; + } + + + public long getAvgFirstDecideTime() { + return this.firstDecideTime / numberOfFirstDecides; + } + public long getAvgDecideTimeMultiple() { + return this.avgDecideTimeMultiple / numberOfFirstDecides; + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestResult.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestResult.java new file mode 100644 index 000000000..65cfd55fe --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestResult.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; + +/** + * ConformanceTestResult holds all of the objects for a single conformance test run. + * + * @version $Revision: 1.1 $ + */ +public class ConformanceTestResult { + private ConformanceTest conformanceTest; + private Request request; + private Response expectedResponse; + private Response actualResponse; + private ResponseMatchResult responseMatchResult; + private Exception error; + + // performance timings + private long firstCallTime; + private long averageTotalLoopTime; + + // how many non-first-call times the decide() was called + private int iterations; + + public ConformanceTestResult(ConformanceTest conformanceTestIn, int iterations) { + this.conformanceTest = conformanceTestIn; + this.iterations = iterations; + } + + public ConformanceTestResult(ConformanceTest conformanceTestIn, Exception errorIn) { + this.conformanceTest = conformanceTestIn; + this.error = errorIn; + } + + public int getIterations() { + return this.iterations; + } + + public ConformanceTest getConformanceTest() { + return this.conformanceTest; + } + public void setConformanceTest(ConformanceTest conformanceTestIn) { + this.conformanceTest = conformanceTestIn; + } + + public Request getRequest() { + return this.request; + } + public void setRequest(Request requestIn) { + this.request = requestIn; + } + + public Response getExpectedResponse() { + return this.expectedResponse; + } + public void setExpectedResponse(Response response) { + this.expectedResponse = response; + this.responseMatchResult = null; + } + + public Response getActualResponse() { + return this.actualResponse; + } + public void setActualResponse(Response response) { + this.actualResponse = response; + this.responseMatchResult = null; + } + + public ResponseMatchResult getResponseMatchResult() { + if (this.responseMatchResult == null && (this.actualResponse != null && this.expectedResponse != null)) { + this.computeResponseMatchResult(); + } + return this.responseMatchResult; + } + public void computeResponseMatchResult() { + if (this.expectedResponse != null && this.actualResponse != null) { + this.responseMatchResult = ResponseMatchResult.newInstance(this.expectedResponse, this.actualResponse); + } + } + public Exception getError() { + return this.error; + } + public void setError(Exception ex) { + this.error = ex; + } + + public long getFirstCallTime() { + return firstCallTime; + } + public void setFirstCallTime(long t) { + firstCallTime = t; + } + public long getAverageTotalLoopTime(){ + return averageTotalLoopTime; + } + public void setAverageTotalLoopTime(long t) { + averageTotalLoopTime = t; + } + + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestSet.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestSet.java new file mode 100644 index 000000000..6fc6e8d3d --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ConformanceTestSet.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +/** + * ConformanceTestSet represents a collection of <code>ConformanceTest</code>s ordered by the test name. It has methods for + * scanning a directory to generate an ordered set. + * + * @version $Revision: 1.1 $ + */ +public class ConformanceTestSet { + private static final Logger logger = FlexLogger.getLogger(ConformanceTestSet.class); + private List<ConformanceTest> listConformanceTests = new ArrayList<>(); + + protected List<ConformanceTest> getListConformanceTests() { + return this.listConformanceTests; + } + + protected ConformanceTestSet() { + + } + + private static String getTestName(String fileName, int itemPos) { + return (itemPos == 0 ? "NULL" : fileName.substring(0, itemPos)); + } + + private static String getTestName(File file) { + String fileName = file.getName(); + int itemPos = fileName.indexOf("Policy"); + if (itemPos >= 0) { + return getTestName(fileName, itemPos); + } else if ((itemPos = fileName.indexOf("Request")) >= 0) { + return getTestName(fileName, itemPos); + } else if ((itemPos = fileName.indexOf("Response")) >= 0) { + return getTestName(fileName, itemPos); + } else if ((itemPos = fileName.indexOf("Repository")) >= 0) { + return getTestName(fileName, itemPos); + } else { + return null; + } + } + + public static ConformanceTestSet loadDirectory(File fileDir) throws IOException { + final Map<String,ConformanceTest> mapConformanceTests = new HashMap<String,ConformanceTest>(); + + Files.walkFileTree(fileDir.toPath(), new FileVisitor<Path>() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + logger.info("Scanning directory " + dir.getFileName()); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + File fileVisited = file.toFile(); + String fileName = fileVisited.getName(); + if (fileName.endsWith(".xml") || fileName.endsWith(".properties")) { + String testName = getTestName(fileVisited); + if (testName != null) { + ConformanceTest conformanceTest = mapConformanceTests.get(testName); + if (conformanceTest == null) { + logger.info("Added test " + testName); + conformanceTest = new ConformanceTest(testName); + mapConformanceTests.put(testName, conformanceTest); + } + if (fileName.endsWith("Policy.xml")) { + conformanceTest.getRepository().addRootPolicy(fileVisited); + } else if (fileName.endsWith("Repository.properties")) { + conformanceTest.getRepository().load(fileVisited); + } else if (fileName.endsWith("Request.xml")) { + conformanceTest.setRequest(fileVisited); + } else if (fileName.endsWith("Response.xml")) { + conformanceTest.setResponse(fileVisited); + } + } + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + logger.warn("Skipped " + file.getFileName()); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + }); + + /* + * Sort the keyset and pull out the tests that have the required components + */ + List<String> listTestNames = new ArrayList<>(); + listTestNames.addAll(mapConformanceTests.keySet()); + Collections.sort(listTestNames); + + ConformanceTestSet conformanceTestSet = new ConformanceTestSet(); + Iterator<String> iterTestNames = listTestNames.iterator(); + while (iterTestNames.hasNext()) { + ConformanceTest conformanceTest = mapConformanceTests.get(iterTestNames.next()); + if (conformanceTest.isComplete()) { + conformanceTestSet.addConformanceTest(conformanceTest); + logger.debug("Added conformance test " + conformanceTest.getTestName()); + } else { + logger.warn("Incomplete conformance test " + conformanceTest.getTestName()); + } + } + + return conformanceTestSet; + + } + + public Iterator<ConformanceTest> getConformanceTests() { + return this.listConformanceTests.iterator(); + } + + public void addConformanceTest(ConformanceTest conformanceTest) { + this.listConformanceTests.add(conformanceTest); + } + + public void addConformanceTestSet(ConformanceTestSet conformanceTestSet) { + this.listConformanceTests.addAll(conformanceTestSet.getListConformanceTests()); + } + + public static void main(String[] args) { + for (String dir : args) { + try { + ConformanceTestSet conformanceTestSet = ConformanceTestSet.loadDirectory(new File(dir)); + Iterator<ConformanceTest> iterConformanceTests = conformanceTestSet.getConformanceTests(); + if (iterConformanceTests == null) { + System.out.println("No tests found in " + dir); + } else { + System.out.println("Tests found in " + dir); + while (iterConformanceTests.hasNext()) { + System.out.println(iterConformanceTests.next().toString()); + } + } + } catch (Exception ex) { + ex.printStackTrace(System.err); + } + } + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResponseMatchResult.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResponseMatchResult.java new file mode 100644 index 000000000..4c7423022 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResponseMatchResult.java @@ -0,0 +1,137 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; + +/** + * ResponseMatchResult provides information about how a {@link com.att.research.xacml.api.Response} object matches + * another <code>Response</code> object. + * + * @version $Revision: 1.1 $ + */ +public class ResponseMatchResult { + private List<ResultMatchResult> resultMatchResults = new ArrayList<>(); + + private boolean bAssociatedAdviceMatches = true; + private boolean bAttributesMatch = true; + private boolean bDecisionsMatch = true; + private boolean bStatusCodesMatch = true; + private boolean bObligationsMatch = true; + private boolean bPolicyIdentifiersMatch = true; + private boolean bPolicySetIdentifiersMatch = true; + private boolean bNumResultsMatch = true; + private boolean bUnknownFunction; + + protected void addResultMatchResult(ResultMatchResult resultMatchResult) { + this.resultMatchResults.add(resultMatchResult); + this.bAssociatedAdviceMatches = resultMatchResult.associatedAdviceMatches() && this.bAssociatedAdviceMatches; + this.bAttributesMatch = resultMatchResult.attributesMatch() && this.bAttributesMatch; + this.bDecisionsMatch = resultMatchResult.decisionsMatch() && this.bDecisionsMatch; + this.bStatusCodesMatch = resultMatchResult.statusCodesMatch() && this.bStatusCodesMatch; + this.bObligationsMatch = resultMatchResult.obligationsMatch() && this.bObligationsMatch; + this.bPolicyIdentifiersMatch = resultMatchResult.policyIdentifiersMatch() && this.bPolicyIdentifiersMatch; + this.bPolicySetIdentifiersMatch = resultMatchResult.policySetIdentifiersMatch() && this.bPolicySetIdentifiersMatch; + this.bUnknownFunction = resultMatchResult.unknownFunction() || this.bUnknownFunction; + } + + protected void setNumResultsMatch(boolean b) { + this.bNumResultsMatch = b; + } + + public ResponseMatchResult() { + } + + public static ResponseMatchResult newInstance(Response response1, Response response2) { + ResponseMatchResult responseMatchResult = new ResponseMatchResult(); + + Collection<Result> listResultsResponse1 = response1.getResults(); + Collection<Result> listResultsResponse2 = response2.getResults(); + if (listResultsResponse1.size() == 1 && listResultsResponse2.size() == 1) { + /* + * Just add a single ResultMatchResult comparing the results in the two responses + */ + responseMatchResult.addResultMatchResult(ResultMatchResult.newInstance(listResultsResponse1.iterator().next(), listResultsResponse2.iterator().next())); + } else { + /* + * Iterate over all of the results in the two responses and match them + */ + Iterator<Result> iterResponse1Results = listResultsResponse1.iterator(); + Iterator<Result> iterResponse2Results = listResultsResponse2.iterator(); + while ((iterResponse1Results != null && iterResponse1Results.hasNext()) || (iterResponse2Results != null && iterResponse2Results.hasNext())) { + Result result1 = (iterResponse1Results != null && iterResponse1Results.hasNext() ? iterResponse1Results.next() : null); + Result result2 = (iterResponse2Results != null && iterResponse2Results.hasNext() ? iterResponse2Results.next() : null); + if ((result1 == null || result2 == null) && responseMatchResult.numResultsMatch()) { + responseMatchResult.setNumResultsMatch(false); + } + responseMatchResult.addResultMatchResult(ResultMatchResult.newInstance(result1, result2)); + } + } + return responseMatchResult; + } + + public Iterator<ResultMatchResult> getResultMatchResults() { + return this.resultMatchResults.iterator(); + } + + public boolean numResultsMatch() { + return this.bNumResultsMatch; + } + + public boolean associatedAdviceMatches() { + return this.bAssociatedAdviceMatches; + } + + public boolean attributesMatch() { + return this.bAttributesMatch; + } + + public boolean decisionsMatch() { + return this.bDecisionsMatch; + } + + public boolean obligationsMatch() { + return this.bObligationsMatch; + } + + public boolean policyIdentifiersMatch() { + return this.bPolicyIdentifiersMatch; + } + + public boolean policySetIdentifiersMatch() { + return this.bPolicySetIdentifiersMatch; + } + + public boolean statusCodesMatch() { + return this.bStatusCodesMatch; + } + + public boolean unknownFunction() { + return this.bUnknownFunction; + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResultMatchResult.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResultMatchResult.java new file mode 100644 index 000000000..fd6bf7103 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/conformance/ResultMatchResult.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.conformance; + +import com.att.research.xacml.api.Result; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.util.ListUtil; + +/** + * ResultMatchResult provides information about how well a {@link com.att.research.xacml.api.Result} object matches + * another <code>Result</code> object. + * + * @version $Revision: 1.1 $ + */ +public class ResultMatchResult { + private boolean bAssociatedAdviceMatches = true; + private boolean bAttributesMatch = true; + private boolean bDecisionsMatch = true; + private boolean bObligationsMatch = true; + private boolean bPolicyIdentifiersMatch = true; + private boolean bPolicySetIdentifiersMatch = true; + private boolean bStatusCodesMatch = true; + private boolean bUnknownFunction = false; + + protected void setAssociatedAdviceMatches(boolean b) { + this.bAssociatedAdviceMatches = b; + } + protected void setAttributesMatch(boolean b) { + this.bAttributesMatch = b; + } + protected void setDecisionsMatch(boolean b) { + this.bDecisionsMatch = b; + } + protected void setObligationsMatch(boolean b) { + this.bObligationsMatch = b; + } + protected void setPolicyIdentifiersMatch(boolean b) { + this.bPolicyIdentifiersMatch = b; + } + protected void setPolicySetIdentifiersMatch(boolean b) { + this.bPolicySetIdentifiersMatch = b; + } + protected void setStatusCodesMatch(boolean b) { + this.bStatusCodesMatch = b; + } + protected void setUnknownFunction(boolean b) { + this.bUnknownFunction = b; + } + + public ResultMatchResult() { + } + + public static ResultMatchResult newInstance(Result result1, Result result2) { + ResultMatchResult resultMatchResult = new ResultMatchResult(); + if (result2 != null && result2.getStatus() != null && + result2.getStatus().getStatusCode().equals(StdStatusCode.STATUS_CODE_PROCESSING_ERROR) && + result2.getStatus().getStatusMessage() != null && + result2.getStatus().getStatusMessage().contains("Unknown Function") + ) { + resultMatchResult.setUnknownFunction(true); + } + if (result1 == null || result2 == null) { + resultMatchResult.setAssociatedAdviceMatches(false); + resultMatchResult.setAttributesMatch(false); + resultMatchResult.setDecisionsMatch(false); + resultMatchResult.setObligationsMatch(false); + resultMatchResult.setPolicyIdentifiersMatch(false); + resultMatchResult.setPolicySetIdentifiersMatch(false); + resultMatchResult.setStatusCodesMatch(false); + } else { + resultMatchResult.setAssociatedAdviceMatches(ListUtil.equalsAllowNulls(result1.getAssociatedAdvice(), result2.getAssociatedAdvice())); + resultMatchResult.setAttributesMatch(ListUtil.equalsAllowNulls(result1.getAttributes(), result2.getAttributes())); + resultMatchResult.setDecisionsMatch(result1.getDecision() == result2.getDecision()); + resultMatchResult.setObligationsMatch(ListUtil.equalsAllowNulls(result1.getObligations(), result2.getObligations())); + resultMatchResult.setPolicyIdentifiersMatch(ListUtil.equalsAllowNulls(result1.getPolicyIdentifiers(), result2.getPolicyIdentifiers())); + resultMatchResult.setPolicySetIdentifiersMatch(ListUtil.equalsAllowNulls(result1.getPolicySetIdentifiers(), result2.getPolicySetIdentifiers())); + if (result1.getStatus() == null || result1.getStatus().getStatusCode() == null || result2.getStatus() == null || result2.getStatus().getStatusCode() == null) { + resultMatchResult.setStatusCodesMatch(false); + } else { + resultMatchResult.setStatusCodesMatch(result1.getStatus().getStatusCode().equals(result2.getStatus().getStatusCode())); + } + } + return resultMatchResult; + } + + public boolean associatedAdviceMatches() { + return this.bAssociatedAdviceMatches; + } + + public boolean attributesMatch() { + return this.bAttributesMatch; + } + + public boolean decisionsMatch() { + return this.bDecisionsMatch; + } + + public boolean obligationsMatch() { + return this.bObligationsMatch; + } + + public boolean policyIdentifiersMatch() { + return this.bPolicyIdentifiersMatch; + } + + public boolean policySetIdentifiersMatch() { + return this.bPolicySetIdentifiersMatch; + } + + public boolean statusCodesMatch() { + return this.bStatusCodesMatch; + } + + public boolean unknownFunction() { + return this.bUnknownFunction; + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomDataTypeFactory.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomDataTypeFactory.java new file mode 100644 index 000000000..82a2e3ec5 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomDataTypeFactory.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.util.HashMap; +import java.util.Map; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeFactory; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.datatypes.DataTypes; + +public class CustomDataTypeFactory extends DataTypeFactory { + private static final Map<Identifier,DataType<?>> mapIdentifiersToDataTypes = new HashMap<>(); + private static boolean mapNeedsInit = true; + + public static final DataTypePrivateKey DT_PRIVATEKEY = DataTypePrivateKey.newInstance(); + public static final DataTypePublicKey DT_PUBLICKEY = DataTypePublicKey.newInstance(); + + private static void registerDataType(DataType<?> dataType) { + if (dataType != null && dataType.getId() != null) { + mapIdentifiersToDataTypes.put(dataType.getId(), dataType); + } + } + + private static void initMap() { + if (mapNeedsInit) { + synchronized(mapIdentifiersToDataTypes) { + if (mapNeedsInit) { + registerDataType(DataTypes.DT_ANYURI); + registerDataType(DataTypes.DT_BASE64BINARY); + registerDataType(DataTypes.DT_BOOLEAN); + registerDataType(DataTypes.DT_DATE); + registerDataType(DataTypes.DT_DATETIME); + registerDataType(DataTypes.DT_DAYTIMEDURATION); + registerDataType(DataTypes.DT_DNSNAME); + registerDataType(DataTypes.DT_DOUBLE); + registerDataType(DataTypes.DT_HEXBINARY); + registerDataType(DataTypes.DT_INTEGER); + registerDataType(DataTypes.DT_IPADDRESS); + registerDataType(DataTypes.DT_RFC822NAME); + registerDataType(DataTypes.DT_STRING); + registerDataType(DataTypes.DT_TIME); + registerDataType(DataTypes.DT_X500NAME); + registerDataType(DataTypes.DT_XPATHEXPRESSION); + registerDataType(DataTypes.DT_YEARMONTHDURATION); + // + // These are the custom data types! + // + registerDataType(DT_PRIVATEKEY); + registerDataType(DT_PUBLICKEY); + // + // Done + // + mapNeedsInit = false; + } + } + } + } + + public CustomDataTypeFactory() { + initMap(); + } + + @Override + public DataType<?> getDataType(Identifier dataTypeId) { + return mapIdentifiersToDataTypes.get(dataTypeId); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomFunctionDefinitionFactory.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomFunctionDefinitionFactory.java new file mode 100644 index 000000000..017edad1a --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/CustomFunctionDefinitionFactory.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.HashMap; +import java.util.Map; + +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinitionFactory; +import com.att.research.xacmlatt.pdp.std.StdFunctions; +import com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionBagOneAndOnly; + +public class CustomFunctionDefinitionFactory extends FunctionDefinitionFactory { + private static Map<Identifier,FunctionDefinition> mapFunctionDefinitions = new HashMap<>(); + private static boolean needMapInit = true; + + public static final Identifier ID_FUNCTION_PRIVATEKEY_ONE_AND_ONLY = new IdentifierImpl("urn:com:att:research:xacml:custom:function:3.0:rsa:privatekey-one-and-only"); + public static final Identifier ID_FUNCTION_PUBLICKEY_ONE_AND_ONLY = new IdentifierImpl("urn:com:att:research:xacml:custom:function:3.0:rsa:publickey-one-and-only"); + + public static final FunctionDefinition FD_PRIVATEKEY_ONE_AND_ONLY = new FunctionDefinitionBagOneAndOnly<PrivateKey>(ID_FUNCTION_PRIVATEKEY_ONE_AND_ONLY, DataTypePrivateKey.newInstance()); + public static final FunctionDefinition FD_PUBLICKEY_ONE_AND_ONLY = new FunctionDefinitionBagOneAndOnly<PublicKey>(ID_FUNCTION_PUBLICKEY_ONE_AND_ONLY, DataTypePublicKey.newInstance()); + + private static void register(FunctionDefinition functionDefinition) { + mapFunctionDefinitions.put(functionDefinition.getId(), functionDefinition); + } + + private static void initMap() { + if (needMapInit) { + synchronized(mapFunctionDefinitions) { + if (needMapInit) { + needMapInit = false; + Field[] declaredFields = StdFunctions.class.getDeclaredFields(); + for (Field field : declaredFields) { + if (Modifier.isStatic(field.getModifiers()) && + field.getName().startsWith(StdFunctions.FD_PREFIX) && + FunctionDefinition.class.isAssignableFrom(field.getType()) && + Modifier.isPublic(field.getModifiers()) + ) { + try { + register((FunctionDefinition)(field.get(null))); + } catch (IllegalAccessException ex) { + + } + } + } + // + // Our custom function + // + register(FunctionDefinitionDecrypt.newInstance()); + register(FD_PRIVATEKEY_ONE_AND_ONLY); + register(FD_PUBLICKEY_ONE_AND_ONLY); + } + } + } + } + + public CustomFunctionDefinitionFactory() { + initMap(); + } + + @Override + public FunctionDefinition getFunctionDefinition(Identifier functionId) { + return mapFunctionDefinitions.get(functionId); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePrivateKey.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePrivateKey.java new file mode 100644 index 000000000..36fd9e725 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePrivateKey.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.security.PrivateKey; + +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.datatypes.DataTypeBase; + +public class DataTypePrivateKey extends DataTypeBase<PrivateKey> { + public static final Identifier DT_PRIVATEKEY = new IdentifierImpl("urn:com:att:research:xacml:custom:3.0:rsa:private"); + private static final DataTypePrivateKey singleInstance = new DataTypePrivateKey(); + + private DataTypePrivateKey() { + super(DT_PRIVATEKEY, PrivateKey.class); + } + + public static DataTypePrivateKey newInstance() { + return singleInstance; + } + + @Override + public PrivateKey convert(Object source) throws DataTypeException { + if (source == null || (source instanceof PrivateKey) ) { + return (PrivateKey) source; + } else if (source instanceof byte[]) { + return (PrivateKey) source; + } else if (source instanceof String) { + return (PrivateKey) (Object) ((String) source).getBytes(); + } + throw new DataTypeException(this, "Failed to convert \"" + source.getClass().getCanonicalName()); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePublicKey.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePublicKey.java new file mode 100644 index 000000000..b73274785 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/DataTypePublicKey.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.security.PublicKey; + +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.datatypes.DataTypeBase; + +public class DataTypePublicKey extends DataTypeBase<PublicKey> { + public static final Identifier DT_PUBLICKEY = new IdentifierImpl("urn:com:att:research:xacml:custom:3.0:rsa:public"); + private static final DataTypePublicKey singleInstance = new DataTypePublicKey(); + + public DataTypePublicKey() { + super(DT_PUBLICKEY, PublicKey.class); + } + + public static DataTypePublicKey newInstance() { + return singleInstance; + } + + @Override + public PublicKey convert(Object source) throws DataTypeException { + if (source == null || (source instanceof PublicKey) ) { + return (PublicKey) source; + } else if (source instanceof byte[]) { + return (PublicKey) source; + } else if (source instanceof String) { + return (PublicKey) (Object) ((String) source).getBytes(); + } + throw new DataTypeException(this, "Failed to convert \"" + source.getClass().getCanonicalName()); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/FunctionDefinitionDecrypt.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/FunctionDefinitionDecrypt.java new file mode 100644 index 000000000..6d34e6334 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/FunctionDefinitionDecrypt.java @@ -0,0 +1,162 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.List; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypeHexBinary; +import com.att.research.xacml.std.datatypes.DataTypeString; +import com.att.research.xacml.std.datatypes.HexBinary; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; +import com.att.research.xacmlatt.pdp.std.functions.ConvertedArgument; + +public class FunctionDefinitionDecrypt implements FunctionDefinition { + public static final Identifier FD_RSA_DECRYPT = new IdentifierImpl("urn:com:att:research:xacml:custom:function:3.0:rsa:decrypt"); + private static final FunctionDefinitionDecrypt singleInstance = new FunctionDefinitionDecrypt(); + + public static FunctionDefinitionDecrypt newInstance() { + return singleInstance; + } + + @Override + public Identifier getId() { + return FD_RSA_DECRYPT; + } + + @Override + public Identifier getDataTypeId() { + return XACML3.ID_DATATYPE_STRING; + } + + @Override + public boolean returnsBag() { + return false; + } + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + if (arguments == null || arguments.size() < 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expecting 2 arguments.")); + } + // + // What is the first argument? + // + FunctionArgument arg0 = arguments.get(0); + if (arg0.isBag()) { + // + // We don't support bags right now + // + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, not expecting a bag for argument 0.")); + } + if (arg0.getValue().getDataTypeId().equals(XACML3.ID_DATATYPE_HEXBINARY) == false) { + // + // Should be a String + // + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expected a Hex Binary for argument 0.")); + } + // + // Convert the argument + // + ConvertedArgument<HexBinary> data = new ConvertedArgument<HexBinary>(arg0, DataTypeHexBinary.newInstance(), false); + if (! data.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, argument 0 failed to convert to Hex Binary.")); + } + // + // Ok - check the 2nd argument + // + FunctionArgument arg1 = arguments.get(1); + if (arg1.isBag()) { + // + // We don't support bags right now + // + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, not expecting a bag for argument 1.")); + } + if (arg1.getValue().getDataTypeId().equals(DataTypePrivateKey.DT_PRIVATEKEY) || + arg1.getValue().getDataTypeId().equals(DataTypePublicKey.DT_PUBLICKEY)) { + // + // Ok - let's try to decrypt + // + Cipher cipher; + try { + cipher = Cipher.getInstance("RSA"); + if (arg1.getValue().getDataTypeId().equals(DataTypePrivateKey.DT_PRIVATEKEY)) { + // + // Using the private key + // + DataType<PrivateKey> pkDatatype = DataTypePrivateKey.newInstance(); + ConvertedArgument<PrivateKey> privateKey = new ConvertedArgument<PrivateKey>(arg1, pkDatatype, false); + if ( ! privateKey.isOk()) { + return ExpressionResult.newError(new StdStatus(privateKey.getStatus().getStatusCode(), "Decrypt: " + privateKey.getStatus().getStatusMessage())); + } + // + // Setup decryption + // + cipher.init(Cipher.DECRYPT_MODE, privateKey.getValue()); + } else if (arg1.getValue().getDataTypeId().equals(DataTypePublicKey.DT_PUBLICKEY)) { + // + // Using the private key + // + DataType<PublicKey> pkDatatype = DataTypePublicKey.newInstance(); + ConvertedArgument<PublicKey> publicKey = new ConvertedArgument<PublicKey>(arg1, pkDatatype, false); + if ( ! publicKey.isOk()) { + return ExpressionResult.newError(new StdStatus(publicKey.getStatus().getStatusCode(), "Decrypt: " + publicKey.getStatus().getStatusMessage())); + } + // + // Setup decryption + // + cipher.init(Cipher.DECRYPT_MODE, publicKey.getValue()); + } + // + // Do the decryption + // + byte[] decryptedData = cipher.doFinal(data.getValue().getData()); + String decryptedString = new String(decryptedData); + // + // All good, return the decrypted string + // + return ExpressionResult.newSingle(DataTypeString.newInstance().createAttributeValue(decryptedString)); + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | DataTypeException e) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed: " + e.getLocalizedMessage())); + } + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Decrypt failed, expecting public/private key datatype for argument 1.")); + } + +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestBase.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestBase.java new file mode 100644 index 000000000..2ccf15682 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestBase.java @@ -0,0 +1,1082 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.io.IOUtils; +import org.apache.http.entity.ContentType; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.DataTypeFactory; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.RequestAttributes; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.api.pdp.PDPEngineFactory; +import com.att.research.xacml.api.pdp.PDPException; +import com.att.research.xacml.api.pep.PEPException; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.StdMutableRequest; +import com.att.research.xacml.std.StdMutableRequestAttributes; +import com.att.research.xacml.std.dom.DOMRequest; +import com.att.research.xacml.std.dom.DOMResponse; +import com.att.research.xacml.std.dom.DOMStructureException; +import com.att.research.xacml.std.json.JSONRequest; +import com.att.research.xacml.std.json.JSONResponse; +import com.att.research.xacml.std.json.JSONStructureException; +import com.att.research.xacml.util.FactoryException; +import com.att.research.xacml.util.XACMLProperties; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; + +/** + * This is a base class for setting up a test environment. Using properties files, it contains the + * necessary information for + * 1. defining and providing attributes + * 2. defining and instantiating the PDP engine + * 3. creating PEP requests and calling the PDP engine + * + * + */ +public class TestBase extends SimpleFileVisitor<Path> { + private static final Logger logger = FlexLogger.getLogger(TestBase.class); + + public class HelpException extends Exception { + private static final long serialVersionUID = 1L; + + } + + /** + * This private class holds information for properties defined for attribute + * generation. The user can configure the properties file such that attributes + * can be automatically generated and added into each request. + * + * + */ + class Generator { + Path file; + InputStream is; + BufferedReader reader; + List<StdMutableAttribute> attributes = new ArrayList<>(); + + public Generator(Path path) { + this.file = path; + } + + /** + * read - reads in the next line of data + * + * @return String - a line from the csv containing attribute data + */ + public String read() { + String str = null; + if (is == null) { + try { + is = Files.newInputStream(file); + } catch (IOException e) { + logger.error(e); + return null; + } + } + if (reader == null) { + reader = new BufferedReader(new InputStreamReader(this.is)); + } + try { + str = reader.readLine(); + if (str == null) { + // + // No more strings, close up + // + this.close(); + } + if (logger.isDebugEnabled()) { + logger.debug(str); + } + } catch (IOException e) { + logger.error(e); + } + return str; + } + + public void close() { + if (this.reader != null) { + try { + this.reader.close(); + } catch (IOException idontcare) { + } finally { + this.reader = null; + this.is = null; + } + } + } + + } + + public static final String PROP_GENERATOR = "xacml.attribute.generator"; + + public static final String OPTION_HELP = "help"; + public static final String OPTION_TESTDIR = "dir"; + public static final String OPTION_TESTREST = "rest"; + public static final String OPTION_TESTURL = "url"; + public static final String OPTION_TESTOUTPUT = "output"; + public static final String OPTION_LOOP = "loop"; + public static final String OPTION_TESTNUMBERS = "testNumbers"; + + public static final String DEFAULT_RESTURL = "https://localhost:8080/pdp/"; // Modified for test purpose. Port no. 8443 to 8080 + + public static Options options = new Options(); + static { + options.addOption(new Option(OPTION_HELP, false, "Prints help.")); + options.addOption(new Option(OPTION_TESTDIR, true, "Directory path where all the test properties and data are located.")); + options.addOption(new Option(OPTION_TESTREST, false, "Test against RESTful PDP.")); + options.addOption(new Option(OPTION_TESTURL, true, "URL to the RESTful PDP. Default is " + DEFAULT_RESTURL)); + options.addOption(new Option(OPTION_TESTOUTPUT, true, "Specify a different location for dumping responses.")); + options.addOption(new Option(OPTION_LOOP, true, "Number of times to loop through the tests. Default is 1. A value of -1 runs indefinitely.")); + options.addOption(new Option(OPTION_TESTNUMBERS, true, "Comma-separated list of numbers found in the names of the test files to be run. Numbers must exactly match the file name, e.g. '02'. Used to limit testing to specific set of tests.")); + } + + protected String directory = null; + protected Path output = null; + protected boolean isREST; + protected URL restURL = null; + protected int loop = 1; + protected PDPEngine engine = null; + protected List<Generator> generators = new ArrayList<>(); + protected static DataTypeFactory dataTypeFactory = null; + + private long permits = 0; + private long denies = 0; + private long notapplicables = 0; + private long indeterminates = 0; + + private long expectedPermits = 0; + private long expectedDenies = 0; + private long expectedNotApplicables = 0; + private long expectedIndeterminates = 0; + + private long generatedpermits = 0; + private long generateddenies = 0; + private long generatednotapplicables = 0; + private long generatedindeterminates = 0; + + private long responseMatches = 0; + private long responseNotMatches = 0; + + private String[] testNumbersArray = null; + + protected final Pattern pattern = Pattern.compile("Request[.]\\d+[.](Permit|Deny|NA|Indeterminate|Generate|Unknown)\\.(json|xml)"); + + public static boolean isJSON(Path file) { + return file.toString().endsWith(".json"); + } + + public static boolean isXML(Path file) { + return file.toString().endsWith(".xml"); + } + + public TestBase(String[] args) throws ParseException, MalformedURLException, HelpException { + // + // Finish Initialization + // + this.restURL = new URL(DEFAULT_RESTURL); + // + // Parse arguments + // + this.parseCommands(args); + } + + /** + * Parse in the command line arguments that the following parameters: + * + * @param args - command line arguments + * @throws ParseException + * @throws MalformedURLException + * @throws HelpException + */ + protected void parseCommands(String[] args) throws ParseException, MalformedURLException, HelpException { + // + // Parse the command line options + // + CommandLine cl; + cl = new GnuParser().parse(options, args); + // + // Check for what we have + // + if (cl.hasOption(OPTION_HELP)) { + new HelpFormatter().printHelp("Usage: -dir testdirectory OPTIONS", + options); + throw new HelpException(); + } + if (cl.hasOption(OPTION_TESTDIR)) { + this.directory = cl.getOptionValue(OPTION_TESTDIR); + } else { + throw new IllegalArgumentException("You must specify a test directory. -dir path/to/some/where"); + } + if (cl.hasOption(OPTION_TESTREST)) { + this.isREST = true; + } else { + this.isREST = false; + } + if (cl.hasOption(OPTION_TESTURL)) { + this.restURL = new URL(cl.getOptionValue(OPTION_TESTURL)); + } + if (cl.hasOption(OPTION_TESTOUTPUT)) { + this.output = Paths.get(cl.getOptionValue(OPTION_TESTOUTPUT)); + } else { + this.output = Paths.get(this.directory, "results"); + } + if (cl.hasOption(OPTION_LOOP)) { + this.loop = Integer.parseInt(cl.getOptionValue(OPTION_LOOP)); + } + if (cl.hasOption(OPTION_TESTNUMBERS)) { + String testNumberString = cl.getOptionValue(OPTION_TESTNUMBERS); + testNumbersArray = testNumberString.split(","); + // + // reset strings to include dots so they exactly match pattern in file name + // + for (int i = 0; i < testNumbersArray.length; i++) { + testNumbersArray[i] = "." + testNumbersArray[i] + "."; + } + } + } + + /** + * Using the command line options that were parsed, configures our test instance. + * + * @throws FactoryException + */ + protected void configure() throws FactoryException { + // + // Setup the xacml.properties file + // + if (this.directory == null) { + throw new IllegalArgumentException("Must supply a path to a test directory."); + } + Path pathDir = Paths.get(this.directory, "xacml.properties"); + if (Files.notExists(pathDir)) { + throw new IllegalArgumentException(pathDir.toString() + " does not exist."); + } + // + // Set it as the System variable so the XACML factories know where the properties are + // loaded from. + // + System.setProperty(XACMLProperties.XACML_PROPERTIES_NAME, pathDir.toString()); + // + // Now we can create the data type factory + // + dataTypeFactory = DataTypeFactory.newInstance(); + // + // Load in what generators we are to create + // + String generators = XACMLProperties.getProperty(PROP_GENERATOR); + if (generators != null) { + // + // Parse the generators + // + for (String generator : Splitter.on(',').trimResults().omitEmptyStrings().split(generators)) { + this.configureGenerator(generator); + } + } + // + // If we are embedded, create our engine + // + if (this.isREST == false) { + PDPEngineFactory factory = PDPEngineFactory.newInstance(); + this.engine = factory.newEngine(); + } + // + // Remove all the responses from the results directory + // + this.removeResults(); + } + + /** + * Removes all the Response* files from the results directory. + * + */ + public void removeResults() { + try { + // + // Determine where the results are supposed to be written to + // + Path resultsPath; + if (this.output != null) { + resultsPath = this.output; + } else { + resultsPath = Paths.get(this.directory.toString(), "results"); + } + // + // Walk the files + // + Files.walkFileTree(resultsPath, new SimpleFileVisitor<Path>() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.getFileName().toString().startsWith("Response")) { + Files.delete(file); + } + return super.visitFile(file, attrs); + } + }); + } catch (IOException e) { + logger.error("Failed to removeRequests from " + this.directory + " " + e); + } + } + + /** + * Configure's a specific generator instance from the properties file. + * + * @param generator + */ + protected void configureGenerator(String generator) { + String prefix = PROP_GENERATOR + "." + generator; + String file = XACMLProperties.getProperty(prefix + ".file"); + // + // Create a generator object + // + Generator gen = new Generator(Paths.get(this.directory, file)); + this.generators.add(gen); + // + // Grab attributes + // + String attributes = XACMLProperties.getProperty(prefix + ".attributes"); + for (String attribute : Splitter.on(',').trimResults().omitEmptyStrings().split(attributes)) { + String attributePrefix = prefix + ".attributes." + attribute; + // + // Create an attribute value. It is simply a placeholder for the field within + // the CSV that contains the actual attribute value. It mainly holds the data type + // + Identifier datatype = new IdentifierImpl(XACMLProperties.getProperty(attributePrefix + ".datatype")); + Integer field = Integer.parseInt(XACMLProperties.getProperty(attributePrefix + ".field")); + StdAttributeValue<?> value = new StdAttributeValue<>(datatype, field); + // + // Get the rest of the attribute properties + // + Identifier category = new IdentifierImpl(XACMLProperties.getProperty(attributePrefix + ".category")); + Identifier id = new IdentifierImpl(XACMLProperties.getProperty(attributePrefix + ".id")); + String issuer = XACMLProperties.getProperty(attributePrefix + ".issuer"); + boolean include = Boolean.parseBoolean(XACMLProperties.getProperty(attributePrefix + ".include", "false")); + // + // Now we have a skeleton attribute + // + gen.attributes.add(new StdMutableAttribute(category, id, value, issuer, include)); + } + } + + /** + * This runs() the test instance. It first configure's itself and then walks the + * requests directory issue each request to the PDP engine. + * + * @throws IOException + * @throws FactoryException + * + */ + public void run() throws IOException, FactoryException { + // + // Configure ourselves + // + this.configure(); + // + // Loop and run + // + int runs = 1; + do { + long lTimeStart = System.currentTimeMillis(); + logger.info("Run number: " + runs); + // + // Walk the request directory + // + Files.walkFileTree(Paths.get(this.directory.toString(), "requests"), this); + long lTimeEnd = System.currentTimeMillis(); + logger.info("Run elapsed time: " + (lTimeEnd - lTimeStart) + "ms"); + // + // Dump the stats + // + this.dumpStats(); + this.resetStats(); + // + // Increment + // + runs++; + } while ((this.loop == -1 ? true : runs <= this.loop)); + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + // + // Sanity check the file name + // + Matcher matcher = this.pattern.matcher(file.getFileName().toString()); + if (matcher.matches()) { + // + // if user has limited which files to use, check that here + // + if (testNumbersArray != null) { + String fileNameString = file.getFileName().toString(); + boolean found = false; + for (String numberString : testNumbersArray) { + if (fileNameString.contains(numberString)) { + found = true; + break; + } + } + if (found == false) { + // + // this test is not in the list to be run, so skip it + // + return super.visitFile(file, attrs); + } + } + try { + // + // Pull what this request is supposed to be + // + String group = null; + int count = matcher.groupCount(); + if (count >= 1) { + group = matcher.group(count-1); + } + // + // Send it + // + this.sendRequest(file, group); + } catch (Exception e) { + logger.error(e); + logger.error("Exception Occured"+e); + } + } + return super.visitFile(file, attrs); + } + + /** + * When a request file is encountered, this method is called send the request to the PDP engine. It will also dump + * the response object. If the group equals "Generate", then it will loop and send the request with generated attributes + * until that list is empty. + * + * @param file - Request file. Eg. Request-01-Permit.json + * @param group - This is the parsed out string of the request file that defines if it is a Permit/Deny/Generate etc. + * @throws Exception + */ + protected void sendRequest(Path file, String group) throws Exception { + logger.info(file.toString()); + int requestCount = 0; + do { + // + // Generate the request + // + Request request = this.generateRequest(file, group); + // + // Was something generated? + // + if (request == null) { + // + // Get out of the loop + // + logger.info("NULL request generated."); + break; + } + logger.info(request); + // + // Call the PDP + // + Response response = this.callPDP(request); + // + // Process the response + // + this.processResponse(file, request, response, group, requestCount); + // + // Is this a generated request? + // + if (group.equals("Generate")) { + // + // Yes, increment counter and move + // on to the next generated request. + // + requestCount++; + } else { + // + // Nope, exit the loop + // + break; + } + } while (group.equals("Generate")); + } + + /** + * Sends the request object to the PDP engine. Either the embedded engine or the RESTful engine. + * + * @param request - XACML request object + * @return Response - returns the XACML response object + */ + protected Response callPDP(Request request) { + // + // Send it to the PDP + // + Response response = null; + if (this.isREST) { + try { + String jsonString = JSONRequest.toString(request, false); + // + // Call RESTful PDP + // + response = this.callRESTfulPDP(new ByteArrayInputStream(jsonString.getBytes())); + } catch (Exception e) { + logger.error("Error in sending RESTful request: " + e, e); + } + } else { + // + // Embedded call to PDP + // + long lTimeStart = System.currentTimeMillis(); + try { + response = this.engine.decide(request); + } catch (PDPException e) { + logger.error(e); + } + long lTimeEnd = System.currentTimeMillis(); + logger.info("Elapsed Time: " + (lTimeEnd - lTimeStart) + "ms"); + } + return response; + } + + /** + * Reads the request file into a Request object based on its type. + * + * If the request has "Generate" in its filename, then this function will add + * generated attributes into the request. + * + * @param file - Request file. Eg. Request-01-Permit.json + * @param group - This is the parsed out string of the request file that defines if it is a Permit/Deny/Generate etc. + * @return + * @throws JSONStructureException + * @throws DOMStructureException + * @throws PEPException + */ + protected Request generateRequest(Path file, String group) throws JSONStructureException, DOMStructureException, PEPException { + // + // Convert to a XACML Request Object + // + Request request = null; + if (TestBase.isJSON(file)) { + request = JSONRequest.load(file.toFile()); + } else if (TestBase.isXML(file)) { + request = DOMRequest.load(file.toFile()); + } + if (request == null) { + throw new PEPException("Invalid Request File: " + file.toString()); + } + // + // Only if this request has "Generate" + // Request.XX.Generate.[json|xml] + // + if (group.equals("Generate")) { + // + // Add attributes to it + // + request = this.onNextRequest(request); + } + // + // Done + // + return request; + } + + /** + * Called to add in generated attributes into the request. + * + * @param request + * @return + */ + protected Request onNextRequest(Request request) { + // + // If we have no generators, just return + // + if (this.generators.isEmpty()) { + return request; + } + // + // Copy the request attributes + // + List<StdMutableRequestAttributes> attributes = new ArrayList<>(); + for (RequestAttributes a : request.getRequestAttributes()) { + attributes.add(new StdMutableRequestAttributes(a)); + } + // + // Iterate the generators + // + for (Generator generator : this.generators) { + // + // Read a row in + // + String line = generator.read(); + // + // Was something read? + // + if (line == null) { + // + // No more rows to read, return null + // + return null; + } + // + // Split the line + // + List<String> fields = Lists.newArrayList(Splitter.on(',').trimResults().split(line)); + // + // Now work on the attributes + // + for (StdMutableAttribute attribute : generator.attributes) { + // + // Grab the attribute holder, which holds the datatype and field. There should + // be only ONE object in the collection. + // + AttributeValue<?> value = attribute.getValues().iterator().next(); + Integer field = (Integer) value.getValue(); + // + // Is the field number valid? + // + if (field >= fields.size()) { + logger.error("Not enough fields: " + field + "(" + fields.size() + ")"); + return null; + } + // + // Determine what datatype it is + // + DataType<?> dataTypeExtended = dataTypeFactory.getDataType(value.getDataTypeId()); + if (dataTypeExtended == null) { + logger.error("Failed to determine datatype"); + return null; + } + // + // Create the attribute value + // + try { + AttributeValue<?> attributeValue = dataTypeExtended.createAttributeValue(fields.get(field)); + // + // Create the attribute + // + StdMutableAttribute newAttribute = new StdMutableAttribute(attribute.getCategory(), + attribute.getAttributeId(), + attributeValue, + attribute.getIssuer(), + attribute.getIncludeInResults()); + boolean added = false; + for (StdMutableRequestAttributes a : attributes) { + // + // Does the category exist? + // + if (a.getCategory().equals(attribute.getCategory())) { + // + // Yes - add in the new attribute value + // + a.add(newAttribute); + added = true; + break; + } + } + if (added == false) { + // + // New category - create it and add it in + // + StdMutableRequestAttributes a = new StdMutableRequestAttributes(); + a.setCategory(newAttribute.getCategory()); + a.add(newAttribute); + attributes.add(a); + } + } catch (DataTypeException e) { + logger.error(e); + return null; + } + } + } + // + // Now form our final request + // + StdMutableRequest newRequest = new StdMutableRequest(); + newRequest.setCombinedDecision(request.getCombinedDecision()); + newRequest.setRequestDefaults(request.getRequestDefaults()); + newRequest.setReturnPolicyIdList(request.getReturnPolicyIdList()); + newRequest.setStatus(request.getStatus()); + for (StdMutableRequestAttributes a : attributes) { + newRequest.add(a); + } + return newRequest; + } + + /** + * This makes an HTTP POST call to a running PDP RESTful servlet to get a decision. + * + * @param file + * @return + */ + protected Response callRESTfulPDP(InputStream is) { + Response response = null; + HttpURLConnection connection = null; + try { + + // + // Open up the connection + // + connection = (HttpURLConnection) this.restURL.openConnection(); + connection.setRequestProperty("Content-Type", "application/json"); + // + // Setup our method and headers + // + connection.setRequestMethod("POST"); + connection.setUseCaches(false); + // + // Adding this in. It seems the HttpUrlConnection class does NOT + // properly forward our headers for POST re-direction. It does so + // for a GET re-direction. + // + // So we need to handle this ourselves. + // + connection.setInstanceFollowRedirects(false); + connection.setDoOutput(true); + connection.setDoInput(true); + // + // Send the request + // + try (OutputStream os = connection.getOutputStream()) { + IOUtils.copy(is, os); + } + // + // Do the connect + // + connection.connect(); + if (connection.getResponseCode() == 200) { + // + // Read the response + // + ContentType contentType = null; + try { + contentType = ContentType.parse(connection.getContentType()); + + if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) { + response = JSONResponse.load(connection.getInputStream()); + } else if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) || + contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) { + response = DOMResponse.load(connection.getInputStream()); + } else { + logger.error("unknown content-type: " + contentType); + } + + } catch (Exception e) { + String message = "Parsing Content-Type: " + connection.getContentType() + ", error=" + e.getMessage(); + logger.error(message, e); + } + + } else { + logger.error(connection.getResponseCode() + " " + connection.getResponseMessage()); + } + } catch (Exception e) { + logger.error(e); + } + + return response; + } + + /** + * This processes a response. Saves the response out to disk. If there is a corresponding response file for the request located + * in the "responses" sub-directory, then this method will compare that response file with what the engine returned to see if it + * matched. + * + * @param requestFile + * @param request + * @param response + * @param group + * @param count + * @throws Exception + */ + protected void processResponse(Path requestFile, Request request, Response response, String group, int count) throws Exception { + // + // Construct the output filename + // + Path responseFile = null; + Path resultFile = null; + int num = requestFile.getNameCount(); + if (num < 2) { + logger.error("Too few dir's in request filename."); + throw new Exception("Too few dir's in request filename. Format should be Request.[0-9]+.{Permit|Deny|NA|Indeterminate}.{json|xml}"); + } + String filename = requestFile.getFileName().toString(); + if (group.equals("Generate")) { + // + // Using count variable, construct a filename + // + // i.e. Response.03.Generate.{count}.json + // + filename = "Response" + filename.substring(filename.indexOf('.'), filename.lastIndexOf('.')) + String.format("%03d", count) + filename.substring(filename.lastIndexOf('.')); + } else { + // + // Construct filename + // + filename = "Response" + filename.substring(filename.indexOf('.')); + } + // + // Determine equivalent response file path + // + responseFile = Paths.get(requestFile.subpath(0, num - 2).toString(), "responses"); + if (Files.notExists(responseFile)) { + // + // Create it + // + logger.warn(responseFile.toString() + " does NOT exist, creating..."); + try { + Files.createDirectories(responseFile); + } catch (IOException e) { + logger.error(e); + throw new Exception("Cannot proceed without an output directory."); + } + } + responseFile = Paths.get(responseFile.toString(), filename); + // + // Determine path to write result file + // + if (this.output != null) { + // + // User specified an output path + // + resultFile = this.output; + } else { + // + // Default path + // + resultFile = Paths.get(requestFile.subpath(0, num - 2).toString(), "results"); + } + // + // Check if the path exists + // + if (Files.notExists(resultFile)) { + // + // Create it + // + logger.warn(resultFile.toString() + " does NOT exist, creating..."); + try { + Files.createDirectories(resultFile); + } catch (IOException e) { + logger.error(e); + throw new Exception("Cannot proceed without an output directory."); + } + } + // + // Add the filename to the path + // + resultFile = Paths.get(resultFile.toString(), filename); + // + // Check if there is an equivalent response in the response + // directory. If so, compare our response result with that one. + // + boolean succeeded = true; + if (responseFile != null && Files.exists(responseFile)) { + // + // Do comparison + // + Response expectedResponse = null; + if (TestBase.isJSON(responseFile)) { + expectedResponse = JSONResponse.load(responseFile); + } else if (TestBase.isXML(responseFile)) { + expectedResponse = DOMResponse.load(responseFile); + } + if (expectedResponse != null) { + // + // Do the compare + // + if (response == null) { + logger.error("NULL response returned."); + this.responseNotMatches++; + succeeded = false; + } else { + if (response.equals(expectedResponse)) { + logger.info("Response matches expected response."); + this.responseMatches++; + } else { + logger.error("Response does not match expected response."); + logger.error("Expected: "); + logger.error(expectedResponse.toString()); + this.responseNotMatches++; + succeeded = false; + } + } + } + } + // + // Write the response to the result file + // + logger.info("Request: " + requestFile.getFileName() + " response is: " + (response == null ? "null" : response.toString())); + if (resultFile != null && response != null) { + if (TestBase.isJSON(resultFile)) { + Files.write(resultFile, JSONResponse.toString(response, true).getBytes()); + } else if (TestBase.isXML(resultFile)) { + Files.write(resultFile, DOMResponse.toString(response, true).getBytes()); + } + } + // + // Stats + // + if (group.equals("Permit")) { + this.expectedPermits++; + } else if (group.equals("Deny")) { + this.expectedDenies++; + } else if (group.equals("NA")) { + this.expectedNotApplicables++; + } else if (group.equals("Indeterminate")) { + this.expectedIndeterminates++; + } + if (response != null) { + for (Result result : response.getResults()) { + Decision decision = result.getDecision(); + if (group.equals("Generate")) { + if (decision.equals(Decision.PERMIT)) { + this.generatedpermits++; + } else if (decision.equals(Decision.DENY)) { + this.generateddenies++; + } else if (decision.equals(Decision.NOTAPPLICABLE)) { + this.generatednotapplicables++; + } else if (decision.equals(Decision.INDETERMINATE)) { + this.generatedindeterminates++; + } + continue; + } + if (decision.equals(Decision.PERMIT)) { + this.permits++; + if (group.equals("Permit") == false) { + succeeded = false; + logger.error("Expected " + group + " got " + decision); + } + } else if (decision.equals(Decision.DENY)) { + this.denies++; + if (group.equals("Deny") == false) { + succeeded = false; + logger.error("Expected " + group + " got " + decision); + } + } else if (decision.equals(Decision.NOTAPPLICABLE)) { + this.notapplicables++; + if (group.equals("NA") == false) { + succeeded = false; + logger.error("Expected " + group + " got " + decision); + } + } else if (decision.equals(Decision.INDETERMINATE)) { + this.indeterminates++; + if (group.equals("Indeterminate") == false) { + succeeded = false; + logger.error("Expected " + group + " got " + decision); + } + } + } + } + if (succeeded) { + logger.info("REQUEST SUCCEEDED"); + } else { + logger.info("REQUEST FAILED"); + } + } + + protected void dumpStats() { + StringBuilder dump = new StringBuilder(); + dump.append(System.lineSeparator()); + dump.append("Permits: " + this.permits + " Expected: " + this.expectedPermits); + dump.append(System.lineSeparator()); + dump.append("Denies: " + this.denies + " Expected: " + this.expectedDenies); + dump.append(System.lineSeparator()); + dump.append("NA: " + this.notapplicables + " Expected: " + this.expectedNotApplicables); + dump.append(System.lineSeparator()); + dump.append("Indeterminates: " + this.indeterminates + " Expected: " + this.expectedIndeterminates); + dump.append(System.lineSeparator()); + dump.append("Generated Permits: " + this.generatedpermits); + dump.append(System.lineSeparator()); + dump.append("Generated Denies: " + this.generateddenies); + dump.append(System.lineSeparator()); + dump.append("Generated NA: " + this.generatednotapplicables); + dump.append(System.lineSeparator()); + dump.append("Generated Indeterminates: " + this.generatedindeterminates); + dump.append(System.lineSeparator()); + dump.append("Responses Matched: " + this.responseMatches); + dump.append(System.lineSeparator()); + dump.append("Responses NOT Matched: " + this.responseNotMatches); + + if (this.permits != this.expectedPermits || + this.denies != this.expectedDenies || + this.notapplicables != this.expectedNotApplicables || + this.indeterminates != this.expectedIndeterminates || + this.responseNotMatches > 0) { + logger.error(dump.toString()); + } else { + logger.info(dump.toString()); + } + } + + protected void resetStats() { + this.permits = 0; + this.denies = 0; + this.notapplicables = 0; + this.indeterminates = 0; + this.generatedpermits = 0; + this.generateddenies = 0; + this.generatednotapplicables = 0; + this.generatedindeterminates = 0; + this.responseMatches = 0; + this.responseNotMatches = 0; + } + + public static void main(String[] args) { + try { + new TestBase(args).run(); + } catch (ParseException | IOException | FactoryException e) { + logger.error(e); + } catch (HelpException e) { + } + } +} diff --git a/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestCustom.java b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestCustom.java new file mode 100644 index 000000000..e7a038814 --- /dev/null +++ b/ONAP-PDP/src/test/java/org/onap/policy/pdp/test/custom/TestCustom.java @@ -0,0 +1,392 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP-PDP + * ================================================================================ + * Copyright (C) 2017 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.pdp.test.custom; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.MalformedURLException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.List; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.ParseException; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.RequestAttributes; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.api.pep.PEPException; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.StdMutableRequest; +import com.att.research.xacml.std.StdMutableRequestAttributes; +import com.att.research.xacml.std.dom.DOMStructureException; +import com.att.research.xacml.std.json.JSONStructureException; +import com.att.research.xacml.util.FactoryException; + +/** + * TestCustom is an application that tests the extensibility and configurability of the AT&T XACML API. + * + * It creates a custom datatype definition factory that adds in custom data types for RSA + * PublicKey and PrivateKey. + * + * It creates a custom function definition factory that adds in custom decryption function for decrypting data. It + * also derives and loads custom functions for the RSA public/private key datatypes for the bag function: one-and-only. + * + * + */ +public class TestCustom extends TestBase { + private static final Logger logger = FlexLogger.getLogger(TestCustom.class); + + // + // Our public's + // + public static final String ALGORITHM = "RSA"; + public static final String PRIVATEKEY_FILE = "PrivateKey.key"; + public static final String PUBLICKEY_FILE = "PublicKey.key"; + + public static final String DECRYPTION_INPUT_STRING = "This is the SECRET value!"; + + public static final String DECRYPTION_INPUT_ID = "com:att:research:xacml:test:custom:encrypted-data"; + // + // Our keys + // + protected PublicKey publicKey = null; + protected PrivateKey privateKey = null; + // + // Our command line parameters + // + public static final String OPTION_GENERATE = "generate"; + + static { + options.addOption(new Option(OPTION_GENERATE, false, "Generate a private/public key pair.")); + } + + /** + * This function generates the public/private key pair. Should never have to call this again, this was + * called once to generate the keys. They were saved into the testsets/custom/datatype-function sub-directory. + */ + public void generateKeyPair() { + // + // Generate a RSA private/public key pair + // + KeyPairGenerator keyGen; + try { + keyGen = KeyPairGenerator.getInstance(ALGORITHM); + } catch (NoSuchAlgorithmException e) { + logger.error("failed to generate keypair: " + e); + return; + } + keyGen.initialize(1024); + final KeyPair key = keyGen.generateKeyPair(); + // + // Save the keys to disk + // + Path file = Paths.get(this.directory, PRIVATEKEY_FILE); + try (ObjectOutputStream os = new ObjectOutputStream(Files.newOutputStream(file))) { + os.writeObject(key.getPrivate()); + } catch (IOException e) { + logger.error("Exception Occured"+e); + } + file = Paths.get(this.directory, PUBLICKEY_FILE); + try (ObjectOutputStream os = new ObjectOutputStream(Files.newOutputStream(file))) { + os.writeObject(key.getPublic()); + } catch (IOException e) { + logger.error("Exception Occured"+e); + } + } + + public TestCustom(String[] args) throws ParseException, MalformedURLException, HelpException { + super(args); + } + + /* (non-Javadoc) + * + * Simply look for command line option: -generate + * This generates the public/private key. Shouldn't need to call it again, the keys have + * already been generated and saved. + * + * @see org.onap.policy.pdp.test.TestBase#parseCommands(java.lang.String[]) + */ + @Override + protected void parseCommands(String[] args) throws ParseException, MalformedURLException, HelpException { + // + // Have our parent class parse its options out + // + super.parseCommands(args); + // + // Parse the command line options + // + CommandLine cl; + cl = new GnuParser().parse(options, args); + if (cl.hasOption(OPTION_GENERATE)) { + // + // Really only need to do this once to setup the test. + // + this.generateKeyPair(); + } + } + + /* (non-Javadoc) + * + * After our parent class configure's itself, all this needs to do is read in + * the public/private key's into objects. + * + * @see org.onap.policy.pdp.test.TestBase#configure() + */ + @Override + protected void configure() throws FactoryException { + // + // Have our super do its thing + // + super.configure(); + // + // Read in the public key + // + try { + this.publicKey = (PublicKey) new ObjectInputStream(Files.newInputStream(Paths.get(this.directory, PUBLICKEY_FILE))).readObject(); + } catch (ClassNotFoundException | IOException e) { + logger.error(e); + } + // + // Read in the private key + // + try { + this.privateKey = (PrivateKey) new ObjectInputStream(Files.newInputStream(Paths.get(this.directory, PRIVATEKEY_FILE))).readObject(); + } catch (ClassNotFoundException | IOException e) { + logger.error(e); + } + } + + /* (non-Javadoc) + * + * Here we add 2 attributes into the request: 1) the private key, and 2) a String that was encrypted using the public key. + * + * The goal is to have the custom decrypt function use the private key to decrypt that string. + * + * @see org.onap.policy.pdp.test.TestBase#generateRequest(java.nio.file.Path, java.lang.String) + */ + @Override + protected Request generateRequest(Path file, String group) throws JSONStructureException, DOMStructureException, PEPException { + // + // Have our super class do its work + // + Request oldRequest = super.generateRequest(file, group); + // + // Copy the request attributes + // + List<StdMutableRequestAttributes> attributes = new ArrayList<>(); + for (RequestAttributes a : oldRequest.getRequestAttributes()) { + attributes.add(new StdMutableRequestAttributes(a)); + } + // + // We are supplying the private key as an attribute for the decryption function to use: + // + // (NOTE: Ideally this would be provided by a custom PIP provider, not the PEP) + // + // ID=com:att:research:xacml:test:custom:privatekey + // Issuer=com:att:research:xacml:test:custom + // Category=urn:oasis:names:tc:xacml:1.0:subject-category:access-subject + // Datatype=urn:com:att:research:xacml:custom:3.0:rsa:private + // + DataType<?> dtExtended = dataTypeFactory.getDataType(DataTypePrivateKey.DT_PRIVATEKEY); + if (dtExtended == null) { + logger.error("Failed to get private key datatype."); + return null; + } + // + // Create the attribute value + // + try { + AttributeValue<?> attributeValue = dtExtended.createAttributeValue(this.privateKey); + // + // Create the attribute + // + StdMutableAttribute newAttribute = new StdMutableAttribute(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT, + new IdentifierImpl("com:att:research:xacml:test:custom:privatekey"), + attributeValue, + "com:att:research:xacml:test:custom", + false); + boolean added = false; + for (StdMutableRequestAttributes a : attributes) { + // + // Does the category exist? + // + if (a.getCategory().equals(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT)) { + // + // Yes - add in the new attribute value + // + a.add(newAttribute); + added = true; + break; + } + } + if (added == false) { + // + // New category - create it and add it in + // + StdMutableRequestAttributes a = new StdMutableRequestAttributes(); + a.setCategory(newAttribute.getCategory()); + a.add(newAttribute); + attributes.add(a); + } + } catch (DataTypeException e) { + logger.error(e); + return null; + } + // + // We are also supplying this attribute which is the secret text encrypted with + // the public key. + // + // ID=com:att:research:xacml:test:custom:encrypted-data + // Issuer= + // Category=urn:oasis:names:tc:xacml:1.0:subject-category:access-subject + // Datatype=http://www.w3.org/2001/XMLSchema#hexBinary + // + // Encrypt it + // + byte[] encryptedData = null; + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, this.publicKey); + // + // This is just a hack to test a decryption of the wrong value. + // + if (group.equals("Permit")) { + encryptedData = cipher.doFinal(DECRYPTION_INPUT_STRING.getBytes()); + } else { + encryptedData = cipher.doFinal("This is NOT the secret".getBytes()); + } + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { + logger.error(e); + return null; + } + // + // Sanity check (for the Permit request) + // + try { + if (group.equals("Permit")) { + Cipher cipher = Cipher.getInstance(ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, this.privateKey); + byte[] decryptedData = cipher.doFinal(encryptedData); + if (new String(decryptedData).equals(DECRYPTION_INPUT_STRING)) { + logger.info("Sanity check passed: decrypted the encrypted data."); + } else { + logger.error("Sanity check failed to decrypt the encrypted data."); + return null; + } + } + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { + logger.error(e); + } + // + // Get our datatype factory + // + dtExtended = dataTypeFactory.getDataType(XACML3.ID_DATATYPE_HEXBINARY); + if (dtExtended == null) { + logger.error("Failed to get hex binary datatype."); + return null; + } + // + // Create the attribute value + // + try { + AttributeValue<?> attributeValue = dtExtended.createAttributeValue(encryptedData); + // + // Create the attribute + // + StdMutableAttribute newAttribute = new StdMutableAttribute(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT, + new IdentifierImpl("com:att:research:xacml:test:custom:encrypted-data"), + attributeValue, + null, + false); + boolean added = false; + for (StdMutableRequestAttributes a : attributes) { + // + // Does the category exist? + // + if (a.getCategory().equals(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT)) { + // + // Yes - add in the new attribute value + // + a.add(newAttribute); + added = true; + break; + } + } + if (added == false) { + // + // New category - create it and add it in + // + StdMutableRequestAttributes a = new StdMutableRequestAttributes(); + a.setCategory(newAttribute.getCategory()); + a.add(newAttribute); + attributes.add(a); + } + } catch (DataTypeException e) { + logger.error(e); + return null; + } + // + // Now form our final request + // + StdMutableRequest newRequest = new StdMutableRequest(); + newRequest.setCombinedDecision(oldRequest.getCombinedDecision()); + newRequest.setRequestDefaults(oldRequest.getRequestDefaults()); + newRequest.setReturnPolicyIdList(oldRequest.getReturnPolicyIdList()); + newRequest.setStatus(oldRequest.getStatus()); + for (StdMutableRequestAttributes a : attributes) { + newRequest.add(a); + } + return newRequest; + } + + public static void main(String[] args) { + try { + new TestCustom(args).run(); + } catch (ParseException | IOException | FactoryException e) { + logger.error(e); + } catch (HelpException e) { + } + } + +} diff --git a/ONAP-PDP/src/test/resources/CSVPolicy.xml b/ONAP-PDP/src/test/resources/CSVPolicy.xml new file mode 100644 index 000000000..10bb8579f --- /dev/null +++ b/ONAP-PDP/src/test/resources/CSVPolicy.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + ============LICENSE_START======================================================= + ONAP-PDP + ================================================================================ + Copyright (C) 2017 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========================================================= + --> + +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="urn:com:xacml:policy:id:fb9e6bed-b5dd-430c-acd4-1baed0c1f1cf" Version="1" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-unless-permit"> + <Description>This Policy handles the Take action and Advice action operations. </Description> + <Target /> + <!--<Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">VM</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> --> + <VariableDefinition VariableId="doesItRequireNewVM"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:or"> + <Description>Check the CPU Utilization or Network Load</Description> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than"> + <Description>Load</Description> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:labs:onap:resource:vm:load" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="true"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">95</AttributeValue> + <!--<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="com:att:research:xacml:test:pip:csv:category:server" AttributeId="com:att:research:xacml:test:pip:csv:server:loadval" DataType="http://www.w3.org/2001/XMLSchema#integer" Issuer="com:att:research:xacml:test:pip:csv" MustBePresent="false"/> + </Apply> --> + </Apply> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than"> + <Description>CPU</Description> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:labs:onap:resource:vm:cpu" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="true"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">95</AttributeValue> + <!-- <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="com:att:research:xacml:test:pip:csv:category:server" AttributeId="com:att:research:xacml:test:pip:csv:server:cpuval" DataType="http://www.w3.org/2001/XMLSchema#integer" Issuer="com:att:research:xacml:test:pip:csv" MustBePresent="false"/> + </Apply> --> + </Apply> + </Apply> + </VariableDefinition> + <Rule RuleId="urn:com:xacml:rule:id:9f8e2241-8205-4656-b6f6-143637cc0c66" Effect="Permit"> + <Description>Permit to create a new VM with Obligation</Description> + <Target /> + <!--<Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">create_Action</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> --> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:boolean-equal"> + <Description>If the Requirement has met create the VM</Description> + <VariableReference VariableId="doesItRequireNewVM"/> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#boolean">true</AttributeValue> + </Apply> + </Condition> + <ObligationExpressions> + <ObligationExpression ObligationId="com.att.research.nvp.test.obligation" FulfillOn="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.obligation.key" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Action_Info</AttributeValue> + </AttributeAssignmentExpression> + </ObligationExpression> + <ObligationExpression ObligationId="com.att.research.nvp.test.multiobligation" FulfillOn="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.obligation.value" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Create_NEW_VM</AttributeValue> + </AttributeAssignmentExpression> + </ObligationExpression> + </ObligationExpressions> + </Rule> + <Rule RuleId="urn:com:xacml:rule:id:6dd4c4b2-8864-4bae-b497-7472b464ffe7" Effect="Permit"> + <Description>Permit to create a new VM with Advice</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">create_adviceAction</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:boolean-equal"> + <Description>If the Requirement has met create the VM</Description> + <VariableReference VariableId="doesItRequireNewVM"/> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#boolean">true</AttributeValue> + </Apply> + </Condition> + <AdviceExpressions> + <AdviceExpression AdviceId="com.att.research.nvp.test.advice.multi" AppliesTo="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.key"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Action_Info</AttributeValue> + </AttributeAssignmentExpression> + </AdviceExpression> + <AdviceExpression AdviceId="com.att.research.nvp.test.advice.multiadvice" AppliesTo="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.multival"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Created New VM</AttributeValue> + </AttributeAssignmentExpression> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.val" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">http://localhost:8080/pdp/?type=hb</AttributeValue> + </AttributeAssignmentExpression> + </AdviceExpression> + </AdviceExpressions> + </Rule> + <VariableDefinition VariableId="removeVM"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-less-than"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:research:xacml:test:pip:csv:resource:cpu" DataType="http://www.w3.org/2001/XMLSchema#integer" MustBePresent="true"/> + </Apply> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="com:att:research:xacml:test:pip:csv:category:server" AttributeId="com:att:research:xacml:test:pip:csv:server:minval" DataType="http://www.w3.org/2001/XMLSchema#integer" Issuer="com:att:research:xacml:test:pip:csv" MustBePresent="false"/> + </Apply> + </Apply> + </VariableDefinition> + <Rule RuleId="urn:com:xacml:rule:id:262fc3fd-f3f3-4aaa-8b9c-504f89be5ba2" Effect="Permit"> + <Description>Permit to remove a VM with Obligation</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">remove_Action</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:boolean-equal"> + <Description>If the resource usage is low then remove the VM</Description> + <VariableReference VariableId="removeVM"/> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#boolean">true</AttributeValue> + </Apply> + </Condition> + <ObligationExpressions> + <ObligationExpression ObligationId="com.att.research.nvp.test.obligation" FulfillOn="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.obligation.key" Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Action_Info</AttributeValue> + </AttributeAssignmentExpression> + </ObligationExpression> + <ObligationExpression ObligationId="com.att.research.nvp.test.multiobligation" FulfillOn="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.obligation.value" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Remove_VM</AttributeValue> + </AttributeAssignmentExpression> + </ObligationExpression> + </ObligationExpressions> + </Rule> + <Rule RuleId="urn:com:xacml:rule:id:6b17c532-6b43-4577-b499-30c862bc7df3" Effect="Permit"> + <Description>Permit to remove a VM with Advice</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">remove_adviceAction</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:boolean-equal"> + <Description>If the resource usage is low then remove the VM</Description> + <VariableReference VariableId="removeVM"/> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#boolean">true</AttributeValue> + </Apply> + </Condition> + <AdviceExpressions> + <AdviceExpression AdviceId="com.att.research.nvp.test.advice.multi" AppliesTo="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.key"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Action_Info</AttributeValue> + </AttributeAssignmentExpression> + </AdviceExpression> + <AdviceExpression AdviceId="com.att.research.nvp.test.advice.multiadvice" AppliesTo="Permit"> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.multival"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Removed VM</AttributeValue> + </AttributeAssignmentExpression> + <AttributeAssignmentExpression AttributeId="com.att.research.nvp.test.advice.val" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">http://localhost:8080/pdp/?type=hb</AttributeValue> + </AttributeAssignmentExpression> + </AdviceExpression> + </AdviceExpressions> + </Rule> +</Policy> diff --git a/ONAP-PDP/src/test/resources/log4j.properties b/ONAP-PDP/src/test/resources/log4j.properties new file mode 100644 index 000000000..e498777bb --- /dev/null +++ b/ONAP-PDP/src/test/resources/log4j.properties @@ -0,0 +1,42 @@ +### +# ============LICENSE_START======================================================= +# ONAP-PDP +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# +# Use this properties for debugging and development. +# +# +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=INFO, MAIN_LOG + +# A1 is set to be a ConsoleAppender. +log4j.appender.MAIN_LOG=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.MAIN_LOG.layout=org.apache.log4j.PatternLayout +log4j.appender.MAIN_LOG.layout.ConversionPattern=%d{yyyy_MM_dd_HH_mm_ss_SSS} [%t] %-5p %l- %m%n + +# +# This is specifically for Xacml request/response logging +# +log4j.logger.xacml.request=INFO, REQUEST_LOG + +log4j.appender.REQUEST_LOG=org.apache.log4j.ConsoleAppender +log4j.appender.REQUEST_LOG.layout=org.apache.log4j.PatternLayout +log4j.appender.REQUEST_LOG.layout.ConversionPattern=%d{yyyy_MM_dd_HH_mm_ss_SSS} %m%n diff --git a/ONAP-PDP/src/test/resources/logback.xml b/ONAP-PDP/src/test/resources/logback.xml new file mode 100644 index 000000000..03e9c0442 --- /dev/null +++ b/ONAP-PDP/src/test/resources/logback.xml @@ -0,0 +1,253 @@ +<!-- + ============LICENSE_START======================================================= + ONAP-PDP + ================================================================================ + Copyright (C) 2017 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========================================================= + --> + +<configuration scan="true" scanPeriod="3 seconds" debug="true"> + <!--<jmxConfigurator /> --> + <!-- directory path for all other type logs --> + <property name="logDir" value="logs" /> + + <!-- directory path for debugging type logs --> + <property name="debugDir" value="logs" /> + + <!-- specify the component name + <ONAP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" --> + <property name="componentName" value="Policy"></property> + <property name="subComponentName" value="ONAP-PDP"></property> + + <!-- log file names --> + <property name="errorLogName" value="error" /> + <property name="metricsLogName" value="metrics" /> + <property name="auditLogName" value="audit" /> + <property name="debugLogName" value="debug" /> + + + <!-- modified time stamp format --> + + <!-- A U D I T + <property name="defaultAuditPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + <property name="defaultAuditPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{ElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + --> + <property name="defaultAuditPattern" value="%X{TransactionBeginTimestamp}|%X{TransactionEndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{partnerName}|%X{statusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{TransactionElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + + + + <!-- M E T R I C + <property name="defaultMetricPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + --> + <property name="defaultMetricPattern" value="%X{MetricBeginTimestamp}|%X{MetricEndTimestamp}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{partnerName}|%X{targetEntity}|%X{targetServiceName}|%X{statusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%p|%X{severity}|%X{serverIpAddress}|%X{MetricElapsedTime}|%X{server}|%X{clientIpAddress}|%c||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + + + + + <!-- E R R O R + <property name="defaultErrorPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%n" /> + --> + <property name="defaultErrorPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{requestId}|%t|%X{serviceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%n" /> + + + + <!-- D E B U G + <property name="debugLoggerPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{Timer}|[%caller{3}]|%msg%n" /> + <property name="debugLoggerPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> --> + --> + <property name="debugLoggerPattern" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestId}|%msg%n" /> + + + + <!-- D E F A U L T + <property name="defaultPatternOld" value="%d{MM/dd-HH:mm:ss.SSS}|%logger|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Timer}|%msg%n" /> + <property name="defaultPattern" value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" /> + --> + <property name="defaultPattern" value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}|%X{requestId}|%X{serviceInstanceId}|%t|%X{serverName}|%X{serviceName}|%X{instanceUuid}|%p|%X{severity}|%X{serverIpAddress}|%X{server}|%X{clientIpAddress}|%c||%msg%n" /> + + + + <!-- P A T H + <property name="logDirectory" value="${catalina.base}/${logDir}/${componentName}/${subComponentName}" /> + <property name="debugLogDirectory" value="${catalina.base}/${debugDir}/${componentName}/${subComponentName}" /> + --> + <property name="logDirectory" value="${logDir}/${componentName}/${subComponentName}" /> + <property name="debugLogDirectory" value="${debugDir}/${componentName}/${subComponentName}" /> + + + + + <!-- Example evaluator filter applied against console appender --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>${defaultPattern}</pattern> + </encoder> + </appender> + + <!-- ============================================================================ --> + <!-- EELF Appenders --> + <!-- ============================================================================ --> + + <!-- The EELFAppender is used to record events to the general application + log --> + + <!-- EELF Audit Appender. This appender is used to record audit engine + related logging events. The audit logger and appender are specializations + of the EELF application root logger and appender. This can be used to segregate + Policy engine events from other components, or it can be eliminated to record + these events as part of the application root log. --> + + <appender name="EELFAudit" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${auditLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultAuditPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFAudit" /> + </appender> + + + + +<appender name="EELFMetrics" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${metricsLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - + %msg%n"</pattern> --> + <pattern>${defaultMetricPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFMetrics"/> + </appender> + + + + + <appender name="EELFError" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDirectory}/${errorLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>ERROR</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${defaultErrorPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFError"/> + </appender> + + + + <appender name="EELFDebug" + class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${debugLogDirectory}/${debugLogName}.log</file> + <rollingPolicy + class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>9</maxIndex> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>DEBUG</level> + </filter> + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>5MB</maxFileSize> + </triggeringPolicy> + <encoder> + <pattern>${debugLoggerPattern}</pattern> + </encoder> + </appender> + + <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender"> + <queueSize>256</queueSize> + <appender-ref ref="EELFDebug" /> + <includeCallerData>true</includeCallerData> + </appender> + + + <!-- ============================================================================ --> + <!-- EELF loggers --> + <!-- ============================================================================ --> + + <logger name="com.att.eelf.audit" level="info" additivity="false"> + <appender-ref ref="asyncEELFAudit" /> + </logger> + + <logger name="com.att.eelf.metrics" level="info" additivity="false"> + <appender-ref ref="asyncEELFMetrics" /> + </logger> + + <logger name="com.att.eelf.error" level="error" additivity="false"> + <appender-ref ref="asyncEELFError" /> + </logger> + + <logger name="com.att.eelf.debug" level="info" additivity="false"> + <appender-ref ref="asyncEELFDebug" /> + </logger> + + + + <root level="INFO"> + <appender-ref ref="asyncEELFDebug" /> + <appender-ref ref="asyncEELFError" /> + </root> + +</configuration> diff --git a/ONAP-PDP/src/test/resources/logging.properties b/ONAP-PDP/src/test/resources/logging.properties new file mode 100644 index 000000000..699369639 --- /dev/null +++ b/ONAP-PDP/src/test/resources/logging.properties @@ -0,0 +1,32 @@ +### +# ============LICENSE_START======================================================= +# ONAP-PDP +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +handlers = java.util.logging.ConsoleHandler, java.util.logging.FileHandler + +.level = FINE + +java.util.logging.SimpleFormatter.format=%4$s: %5$s %n + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter + +java.util.logging.FileHandler.level = SEVERE +java.util.logging.FileHandler.pattern=%h/xacml_log%u.log +java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter diff --git a/ONAP-PDP/src/test/resources/xacml.pip.properties b/ONAP-PDP/src/test/resources/xacml.pip.properties new file mode 100644 index 000000000..728a48281 --- /dev/null +++ b/ONAP-PDP/src/test/resources/xacml.pip.properties @@ -0,0 +1,23 @@ +### +# ============LICENSE_START======================================================= +# ONAP-PDP +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# +#Fri Mar 06 12:06:30 EST 2015 +xacml.pip.engines= diff --git a/ONAP-PDP/src/test/resources/xacml.policy.properties b/ONAP-PDP/src/test/resources/xacml.policy.properties new file mode 100644 index 000000000..20e77188b --- /dev/null +++ b/ONAP-PDP/src/test/resources/xacml.policy.properties @@ -0,0 +1,25 @@ +### +# ============LICENSE_START======================================================= +# ONAP-PDP +# ================================================================================ +# Copyright (C) 2017 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========================================================= +### + +# +#Fri Mar 06 12:06:30 EST 2015 +xacml.referencedPolicies= +xacml.rootPolicies= + |