Commit caff5b79 authored by cdanger's avatar cdanger

- Fixed issue 6 on OW2's GitLab:

#6

- Added new unit and conformance tests for map function
parent 8ffcaea5
This diff is collapsed.
......@@ -22,7 +22,9 @@ import java.util.Set;
import org.ow2.authzforce.core.pdp.api.Decidable;
import org.ow2.authzforce.core.pdp.api.combining.CombiningAlg;
import org.ow2.authzforce.core.pdp.api.combining.CombiningAlgRegistry;
import org.ow2.authzforce.core.pdp.api.policy.PolicyEvaluator;
import org.ow2.authzforce.core.pdp.impl.BasePdpExtensionRegistry;
import org.ow2.authzforce.core.pdp.impl.rule.RuleEvaluator;
import com.google.common.base.Preconditions;
......@@ -31,8 +33,7 @@ import com.google.common.base.Preconditions;
*
* @version $Id: $
*/
public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistry<CombiningAlg<?>>
implements CombiningAlgRegistry
public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistry<CombiningAlg<?>> implements CombiningAlgRegistry
{
/**
* <p>
......@@ -44,15 +45,16 @@ public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistr
*/
public ImmutableCombiningAlgRegistry(Set<CombiningAlg<?>> algorithms)
{
super(CombiningAlg.class,
Preconditions.checkNotNull(algorithms, "Input Combining Algorithms undefined (algorithms == null)"));
super(CombiningAlg.class, Preconditions.checkNotNull(algorithms, "Input Combining Algorithms undefined (algorithms == null)"));
}
private static String toString(Class<? extends Decidable> combinedElementType) {
return combinedElementType == PolicyEvaluator.class ? "Policy(Set)" : combinedElementType == RuleEvaluator.class ? "Rule" : combinedElementType.getCanonicalName();
}
/** {@inheritDoc} */
@Override
public <T extends Decidable> CombiningAlg<T> getAlgorithm(String algId, Class<T> combinedEltType)
throws IllegalArgumentException
{
public <T extends Decidable> CombiningAlg<T> getAlgorithm(String algId, Class<T> combinedEltType) throws IllegalArgumentException {
final CombiningAlg<? extends Decidable> alg = this.getExtension(algId);
if (alg == null)
{
......@@ -65,10 +67,9 @@ public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistr
}
// wrong type of alg
throw new IllegalArgumentException("Registered combining algorithm for ID=" + algId
+ " combines instances of type '" + alg.getCombinedElementType()
+ "' which is not compatible (not same or supertype) with requested type of combined elements : "
+ combinedEltType);
alg.getCombinedElementType();
throw new IllegalArgumentException(
"Combining algorithm '" + algId + "': invalid type of input elements (to be combined): " + toString(combinedEltType) + "; expected: " + toString(alg.getCombinedElementType()) + ".");
}
}
......@@ -54,8 +54,7 @@ import org.ow2.authzforce.xacml.identifiers.XacmlStatusCode;
*/
final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<BooleanValue>
{
private static String getInvalidArg0MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg0MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #0 (number of required Trues): expected: 0 <= (integer) <= number_of_remaining_arguments; actual: ";
}
......@@ -81,8 +80,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
protected BooleanValue evaluate(final EvaluationContext context, final int requiredMinOfTrues, final Iterator<? extends Expression<?>> remainingArgExpsIterator,
final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException
{
final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException {
assert requiredMinOfTrues <= this.numOfArgsAfterFirst;
int nOfRequiredTrues = requiredMinOfTrues;
......@@ -111,8 +109,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
return BooleanValue.TRUE;
}
}
}
catch (final IndeterminateEvaluationException e)
} catch (final IndeterminateEvaluationException e)
{
/*
* Keep the indeterminate arg error to throw it later in exception, in case there was not enough TRUEs in the remaining args.
......@@ -174,8 +171,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
try
{
attrVal = BooleanValue.class.cast(arg);
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
/*
* Indicate arg index to help troubleshooting: argIndex (starting at 0) = max_index - number_of_args_remaining_to_evaluate = (totalArgCount - 1) - nOfRemainingArgs =
......@@ -253,8 +249,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
@Override
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... remainingArgs) throws IndeterminateEvaluationException
{
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... remainingArgs) throws IndeterminateEvaluationException {
return super.evaluate(context, requiredMinOfTrues, checkedArgExpressionsAfterFirst.iterator(), remainingArgs);
}
......@@ -274,8 +269,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
@Override
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException
{
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException {
/*
* Arg datatypes and number is already checked in superclass but we need to do further checks specific to this function such as the first argument which must be a positive integer
*/
......@@ -290,8 +284,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
try
{
intAttrVal = Expressions.eval(input0, context, StandardDatatypes.INTEGER);
}
catch (final IndeterminateEvaluationException e)
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException(indeterminateArgMsgPrefix + 0, e.getStatusCode(), e);
}
......@@ -334,13 +327,19 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<BooleanValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException
{
public FirstOrderFunctionCall<BooleanValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException {
/*
* Optimization: check whether the first arg ('n' = number of Trues to reach) is constant
*/
final Iterator<? extends Expression<?>> argExpsIterator = argExpressions.iterator();
// Evaluate the first argument
/*
* Evaluate the first argument if not in remainingArgTypes
*/
if (!argExpsIterator.hasNext())
{
return new CallWithVarArg0(functionSignature, argExpressions, remainingArgTypes);
}
final Optional<? extends Value> arg0 = argExpsIterator.next().getValue();
if (arg0.isPresent())
{
......
......@@ -24,6 +24,7 @@ import java.util.List;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.Expression;
import org.ow2.authzforce.core.pdp.api.expression.Expressions;
import org.ow2.authzforce.core.pdp.api.func.FirstOrderFunction;
import org.ow2.authzforce.core.pdp.api.func.GenericHigherOrderFunctionFactory;
import org.ow2.authzforce.core.pdp.api.func.HigherOrderBagFunction;
......@@ -62,28 +63,57 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
private final Datatype<SUB_RETURN> returnBagElementType;
private final String indeterminateSubFuncEvalMessagePrefix;
private Call(final String functionId, final Datatype<Bag<SUB_RETURN>> returnType, final FirstOrderFunction<SUB_RETURN> subFunction, final List<Expression<?>> primitiveInputs,
final Expression<? extends Bag<?>> lastInputBag)
private Call(final String functionId, final Datatype<Bag<SUB_RETURN>> returnType, final FirstOrderFunction<SUB_RETURN> subFunction, final List<Expression<?>> primitiveInputsBeforeBag,
final Expression<? extends Bag<?>> bagInput, List<Expression<?>> primitiveInputsAfterBag)
{
super(functionId, returnType, subFunction, primitiveInputs, lastInputBag);
super(functionId, returnType, subFunction, primitiveInputsBeforeBag, bagInput, primitiveInputsAfterBag);
this.returnBagElementType = subFunction.getReturnType();
this.indeterminateSubFuncEvalMessagePrefix = "Function " + functionId + ": Error calling sub-function (first argument) with last arg=";
this.indeterminateSubFuncEvalMessagePrefix = "Function '" + functionId + "': Error calling sub-function (first argument) with bag arg (#" + this.bagArgIndex + ") = ";
}
@Override
protected Bag<SUB_RETURN> evaluate(final Bag<?> lastArgBag, final EvaluationContext context) throws IndeterminateEvaluationException
{
final Collection<SUB_RETURN> results = new ArrayDeque<>(lastArgBag.size());
for (final AttributeValue lastArgBagVal : lastArgBag)
protected Bag<SUB_RETURN> evaluate(final Bag<?> bagArg, final EvaluationContext context) throws IndeterminateEvaluationException {
/*
* Prepare sub-function call's remaining args (bag arg and subsequent ones if any)
*/
final AttributeValue[] argsAfterBagInclusive = new AttributeValue[this.numOfArgsAfterBagInclusive];
/*
* Index i=0 is for the bag element value, resolved in the second for loop below.
*/
int i = 1;
/*
* See BaseFirstOrderFunctionCall#evalPrimitiveArgs(...)
*/
for (final Expression<?> primitiveArgExprAfterBag : this.primitiveArgExprsAfterBag)
{
final SUB_RETURN subResult;
// get and evaluate the next parameter
/*
* The types of arguments have already been checked with checkInputs(), so casting to returnType should work.
*/
final AttributeValue argVal;
try
{
subResult = subFuncCall.evaluate(context, lastArgBagVal);
argVal = Expressions.evalPrimitive(primitiveArgExprAfterBag, context);
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException("Indeterminate arg #" + (this.bagArgIndex + i), e.getStatusCode(), e);
}
catch (final IndeterminateEvaluationException e)
argsAfterBagInclusive[i] = argVal;
i++;
}
final Collection<SUB_RETURN> results = new ArrayDeque<>(bagArg.size());
for (final AttributeValue bagElement : bagArg)
{
argsAfterBagInclusive[0] = bagElement;
final SUB_RETURN subResult;
try
{
subResult = subFuncCall.evaluate(context, argsAfterBagInclusive);
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException(indeterminateSubFuncEvalMessagePrefix + lastArgBagVal, e.getStatusCode(), e);
throw new IndeterminateEvaluationException(indeterminateSubFuncEvalMessagePrefix + bagElement, e.getStatusCode(), e);
}
results.add(subResult);
......@@ -105,10 +135,9 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
}
@Override
protected OneBagOnlyHigherOrderFunction.Call<Bag<SUB_RETURN_T>, SUB_RETURN_T> newFunctionCall(final FirstOrderFunction<SUB_RETURN_T> subFunc, final List<Expression<?>> primitiveInputs,
final Expression<? extends Bag<?>> lastInputBag)
{
return new Call<>(this.getId(), this.getReturnType(), subFunc, primitiveInputs, lastInputBag);
protected OneBagOnlyHigherOrderFunction.Call<Bag<SUB_RETURN_T>, SUB_RETURN_T> newFunctionCall(final FirstOrderFunction<SUB_RETURN_T> subFunc,
final List<Expression<?>> primitiveInputsBeforeBag, final Expression<? extends Bag<?>> bagInput, final List<Expression<?>> primitiveInputsAfterBag) {
return new Call<>(this.getId(), this.getReturnType(), subFunc, primitiveInputsBeforeBag, bagInput, primitiveInputsAfterBag);
}
}
......@@ -121,14 +150,12 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
}
@Override
public String getId()
{
public String getId() {
return functionId;
}
@Override
public <SUB_RETURN extends AttributeValue> HigherOrderBagFunction<?, SUB_RETURN> getInstance(final Datatype<SUB_RETURN> subFunctionReturnType) throws IllegalArgumentException
{
public <SUB_RETURN extends AttributeValue> HigherOrderBagFunction<?, SUB_RETURN> getInstance(final Datatype<SUB_RETURN> subFunctionReturnType) throws IllegalArgumentException {
if (subFunctionReturnType == null)
{
throw NULL_SUB_FUNCTION_RETURN_TYPE_ARG_EXCEPTION;
......@@ -136,8 +163,8 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
if (!(subFunctionReturnType instanceof AttributeDatatype<?>))
{
throw new IllegalArgumentException("Invalid sub-function's return type specified for function '" + functionId + "': " + subFunctionReturnType
+ ". Expected: any primitive attribute datatype.");
throw new IllegalArgumentException(
"Invalid sub-function's return type specified for function '" + functionId + "': " + subFunctionReturnType + ". Expected: any primitive attribute datatype.");
}
return new MapFunction<>(functionId, (AttributeDatatype<SUB_RETURN>) subFunctionReturnType);
......
......@@ -52,8 +52,7 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
private static final IllegalArgumentException UNDEF_PARAMETER_TYPES_EXCEPTION = new IllegalArgumentException("Undefined function parameter types");
private static <AV extends Value> List<Datatype<AV>> validate(final List<Datatype<AV>> paramTypes)
{
private static <AV extends Value> List<Datatype<AV>> validate(final List<Datatype<AV>> paramTypes) {
if (paramTypes == null || paramTypes.isEmpty())
{
throw UNDEF_PARAMETER_TYPES_EXCEPTION;
......@@ -93,13 +92,11 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
}
@Override
protected V evaluate(final Deque<V> args) throws IndeterminateEvaluationException
{
protected V evaluate(final Deque<V> args) throws IndeterminateEvaluationException {
try
{
return op.eval(args);
}
catch (IllegalArgumentException | ArithmeticException e)
} catch (IllegalArgumentException | ArithmeticException e)
{
throw new IndeterminateEvaluationException(invalidArgsErrMsg, XacmlStatusCode.PROCESSING_ERROR.value(), e);
}
......@@ -128,12 +125,11 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<AV> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException
{
public FirstOrderFunctionCall<AV> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException {
/**
* If this.op is a commutative function (e.g. add or multiply function), we can simplify arguments if there are multiple constants. Indeed, if C1,...Cm are constants, then:
* <p>
* op(x1,..., x_{n1-1}, C1, x_n1, ..., x_{n2-1} C2, x_n2, ..., Cm, x_nm...) = op( C, x1.., x_{n1-1}, x_n1, x_{n2-2}, x_n2...), where C (constant) = op(C1, C2..., Cm)
* op(x1,..., x_{n1-1}, C1, x_n1, ..., x_{n2-1}, C2, x_n2, ..., Cm, x_nm...) = op( C, x1.., x_{n1-1}, x_n1, x_{n2-2}, x_n2...), where C (constant) = op(C1, C2..., Cm)
* </p>
* In this case, we can pre-compute constant C and replace all constant args with one: C
*
......@@ -159,18 +155,16 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
{
// variable
finalArgExpressions.add(argExp);
}
else
} else
{
// constant
try
{
constants.add(paramType.cast(v.get()));
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
throw new IllegalArgumentException("Function " + this.functionSignature + ": invalid arg #" + argIndex + ": bad type: " + argExp.getReturnType() + ". Expected type: "
+ paramType, e);
throw new IllegalArgumentException(
"Function " + this.functionSignature + ": invalid arg #" + argIndex + ": bad type: " + argExp.getReturnType() + ". Expected type: " + paramType, e);
}
}
......
......@@ -71,8 +71,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
}
@Override
protected StringValue evaluate(final Deque<AttributeValue> args) throws IndeterminateEvaluationException
{
protected StringValue evaluate(final Deque<AttributeValue> args) throws IndeterminateEvaluationException {
final AttributeValue rawArg0 = args.poll();
final AttributeValue rawArg1 = args.poll();
final AttributeValue rawArg2 = args.poll();
......@@ -85,8 +84,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
arg0 = param0Type.cast(rawArg0);
beginIndex = (IntegerValue) rawArg1;
endIndex = (IntegerValue) rawArg2;
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
throw new IndeterminateEvaluationException(invalidArgTypesErrorMsg + rawArg0.getDataType() + "," + rawArg1.getDataType() + "," + rawArg2.getDataType(),
XacmlStatusCode.PROCESSING_ERROR.value(), e);
......@@ -115,8 +113,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
final int beginIndexInt = beginIndex.intValueExact();
final int endIndexInt = endIndex.intValueExact();
substring = endIndexInt == -1 ? arg0.getUnderlyingValue().substring(beginIndexInt) : arg0.getUnderlyingValue().substring(beginIndexInt, endIndexInt);
}
catch (ArithmeticException | IndexOutOfBoundsException e)
} catch (ArithmeticException | IndexOutOfBoundsException e)
{
throw new IndeterminateEvaluationException(argsOutOfBoundsErrorMessage, XacmlStatusCode.PROCESSING_ERROR.value(), e);
}
......@@ -141,23 +138,21 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
this.param0Type = param0Type;
}
private static String getInvalidArg1MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg1MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #1 (beginIndex): expected: positive integer; actual: ";
}
private static String getInvalidArg2MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg2MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #2 (endIndex): expected: -1 or positive integer >= beginIndex; actual: ";
}
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<StringValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes)
{
if (argExpressions.size() != 3)
public FirstOrderFunctionCall<StringValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) {
final int numOfArgs = argExpressions.size() + remainingArgTypes.length;
if (numOfArgs != 3)
{
throw new IllegalArgumentException("Function " + functionSignature.getName() + ": Invalid number of args: expected: 3; actual: " + argExpressions.size());
throw new IllegalArgumentException("Function " + functionSignature.getName() + ": Invalid number of args: expected: 3; actual: " + numOfArgs);
}
/*
......@@ -165,10 +160,20 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
* error
*/
final Iterator<? extends Expression<?>> argExpsIterator = argExpressions.iterator();
// Skip the first argument which is the string
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
// Skip the first argument (arg #0) which is the string
argExpsIterator.next();
// Second arg
// Second arg (arg #1)
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
final Expression<?> arg1Exp = argExpsIterator.next();
final Optional<? extends Value> arg1 = arg1Exp.getValue();
final int beginIndex;
......@@ -185,13 +190,17 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
{
throw new IllegalArgumentException(getInvalidArg1MessagePrefix(functionSignature) + beginIndex);
}
}
else
} else
{
beginIndex = -1; // undefined
}
// Third arg
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
final Expression<?> arg2Exp = argExpsIterator.next();
final Optional<? extends Value> arg2 = arg2Exp.getValue();
if (arg2.isPresent())
......
......@@ -66,10 +66,9 @@ public abstract class StandardFunctionTest
{
try
{
STD_EXPRESSION_FACTORY = new DepthLimitingExpressionFactory(StandardAttributeValueFactories.getRegistry(true, Optional.empty()), StandardFunction.getRegistry(true,
StandardAttributeValueFactories.BIG_INTEGER), null, 0, false, false);
}
catch (IllegalArgumentException | IOException e)
STD_EXPRESSION_FACTORY = new DepthLimitingExpressionFactory(StandardAttributeValueFactories.getRegistry(true, Optional.empty()),
StandardFunction.getRegistry(true, StandardAttributeValueFactories.BIG_INTEGER), null, 0, false, false);
} catch (IllegalArgumentException | IOException e)
{
throw new RuntimeException(e);
}
......@@ -79,7 +78,7 @@ public abstract class StandardFunctionTest
private final Value expectedResult;
private final String toString;
private final boolean areBagsComparedAsSets;
private boolean syntaxErrorRaised = false;
private boolean isTestOkBeforeFuncCall = false;
/**
* Creates instance
......@@ -101,15 +100,13 @@ public abstract class StandardFunctionTest
if (inputs.isEmpty())
{
subFuncReturnType = null;
}
else
} else
{
final Expression<?> xpr0 = inputs.get(0);
if (xpr0 instanceof FunctionExpression)
{
subFuncReturnType = ((FunctionExpression) xpr0).getValue().get().getReturnType();
}
else
} else
{
subFuncReturnType = null;
}
......@@ -127,21 +124,30 @@ public abstract class StandardFunctionTest
try
{
funcCall = function.newCall(inputs);
}
catch (final IllegalArgumentException e)
} catch (final IllegalArgumentException e)
{
/*
* Some syntax errors might be caught at initialization time, which is expected if expectedResult == null
*/
if(expectedResult != null) {
if (expectedResult != null)
{
/*
* IllegalArgumentException should not have been thrown, since we expect a result of the function call
*/
throw new RuntimeException("expectedResult != null but invalid args in test definition prevented the function call", e);
}
funcCall = null;
syntaxErrorRaised = true;
// expectedResult == null
isTestOkBeforeFuncCall = true;
}
/*
* If test not yet OK, we need to run the function call (funcCall.evaluate(...)), so funcCall must be defined
*/
if (!isTestOkBeforeFuncCall && funcCall == null)
{
throw new RuntimeException("Failed to initialize function call for unknown reason");
}
this.expectedResult = expectedResult;
......@@ -157,14 +163,12 @@ public abstract class StandardFunctionTest
// org.junit.Assume.assumeTrue(function == null);
// }
private static <V extends AttributeValue> Expression<?> createValueExpression(final Datatype<V> datatype, final AttributeValue rawValue)
{
private static <V extends AttributeValue> Expression<?> createValueExpression(final Datatype<V> datatype, final AttributeValue rawValue) {
// static expression only if not xpathExpression
return new ConstantPrimitiveAttributeValueExpression<>(datatype, datatype.cast(rawValue));
}
private static <V extends Bag<?>> Expression<?> createValueExpression(final Datatype<V> datatype, final Bag<?> rawValue)
{
private static <V extends Bag<?>> Expression<?> createValueExpression(final Datatype<V> datatype, final Bag<?> rawValue) {
return new BagValueExpression<>(datatype, datatype.cast(rawValue));
}
......@@ -178,20 +182,17 @@ public abstract class StandardFunctionTest
}
@Override
public Datatype<V> getReturnType()
{
public Datatype<V> getReturnType() {
return returnType;
}
@Override
public V evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
{
public V evaluate(final EvaluationContext context) throws IndeterminateEvaluationException {
throw new IndeterminateEvaluationException("Missing attribute", XacmlStatusCode.MISSING_ATTRIBUTE.value());
}
@Override
public Optional<V> getValue()
{
public Optional<V> getValue() {
throw new UnsupportedOperationException("No constant defined for Indeterminate expression");
}
......@@ -199,8 +200,7 @@ public abstract class StandardFunctionTest
// private static <V extends Value> IndeterminateExpression<V> newIndeterminateExpression
private static final List<Expression<?>> toExpressions(final String subFunctionName, final List<Value> values)
{
private static final List<Expression<?>> toExpressions(final String subFunctionName, final List<Value> values) {
final List<Expression<?>> inputExpressions = new ArrayList<>();
if (subFunctionName != null)
{
......@@ -232,20 +232,17 @@ public abstract class StandardFunctionTest
}
valExpr = nullVal.isBag() ? new IndeterminateExpression<>(datatypeFactory.getDatatype().getBagDatatype()) : new IndeterminateExpression<>(datatypeFactory.getDatatype());
}
else if (val instanceof AttributeValue)
} else if (val instanceof AttributeValue)
{
final AttributeValue primVal = (AttributeValue) val;
final AttributeValueFactory<?> datatypeFactory = stdDatatypeFactoryRegistry.getExtension(primVal.getDataType());
valExpr = createValueExpression(datatypeFactory.getDatatype(), primVal);
}
else if (val instanceof Bag)
} else if (val instanceof Bag)
{
final Bag<?> bagVal = (Bag<?>) val;
final AttributeValueFactory<?> datatypeFactory = stdDatatypeFactoryRegistry.getExtension(bagVal.getElementDatatype().getId());
valExpr = createValueExpression(datatypeFactory.getDatatype().getBagDatatype(), bagVal);
}
else
} else
{
throw new UnsupportedOperationException("Unsupported type of Value: " + val.getClass());
}
......@@ -294,8 +291,7 @@ public abstract class StandardFunctionTest
this(functionName, subFunctionName, inputs, false, expectedResult);
}
private static final Set<PrimitiveValue> bagToSet(final Bag<?> bag)
{
private static final Set<PrimitiveValue> bagToSet(final Bag<?> bag) {
final Set<PrimitiveValue> set = new HashSet<>();
for (final PrimitiveValue val : bag)
{
......@@ -306,43 +302,34 @@ public abstract class StandardFunctionTest
}
@Test
public void testEvaluate() throws IndeterminateEvaluationException
{
/*
* expectedResult == null means that we expect IllegalArgumentException thrown when validating function inputs (syntaxErrorRaised = true)
*/
if (expectedResult == null)
public void testEvaluate() throws IndeterminateEvaluationException {
if (isTestOkBeforeFuncCall)
{
Assert.assertTrue("expectedResult = null, but no syntax error (invalid inputs) raised as expected", syntaxErrorRaised);
// syntax error already detected as expected -> test success
/*
* Test already OK (syntax error was expected and occured when creating the function call already), no need to carry on the function call
*/
return;
}
/*
* expectedResult != null
*/
if(funcCall == null) {
Assert.fail("expectedResult != null but function call undefined (failed to initialize)");
}
/*
* Use null context as all inputs given as values in function tests, therefore already provided as inputs to function call
*/
try
{
/*