From 1b8bc5b691d1a250d3e63b8262a5544a9500f1d0 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 25 Mar 2019 15:29:52 +0100 Subject: [PATCH] More tests for Groovy "sandbox". Some fixes. --- .../midpoint/prism/PrimitiveType.java | 2 + .../prism/impl/xjc/PrismForJAXBUtil.java | 12 +- .../ExpressionPermissionProfile.java | 33 +- .../schema/expression/TypedValue.java | 19 +- .../schema/expression/VariablesMap.java | 9 +- .../xml/ns/public/common/common-core-3.xsd | 130 ++++- .../expression/ExpressionProfileCompiler.java | 12 + ...alueTransformationExpressionEvaluator.java | 15 +- .../groovy/SandboxTypeCheckingExtension.java | 2 +- .../common/expression/ExpressionTestUtil.java | 19 +- .../common/expression/TestExpression.java | 472 +++++++++++++++++- .../expression/TestExpressionProfileSafe.java | 140 ++++++ .../resources/common/system-configuration.xml | 84 +++- .../expression/expression/expression-asis.xml | 28 ++ .../expression/expression-const.xml | 28 ++ ...xml => expression-iteration-condition.xml} | 6 +- .../expression/expression/expression-path.xml | 28 ++ .../expression-script-groovy-simple.xml | 32 ++ .../expression-script-groovy-system-allow.xml | 36 ++ .../expression-script-groovy-system-deny.xml | 34 ++ .../expression-script-javascript.xml | 33 ++ .../expression/expression-value.xml | 28 ++ .../src/test/resources/logback-test.xml | 1 + model/model-common/testng-unit.xml | 1 + .../expression/ExpressionVariables.java | 6 +- .../prism/DeltaSetTripleAsserter.java | 141 ++++++ .../prism/DeltaSetTripleSetAsserter.java | 88 ++++ .../prism/PrismPropertyValueAsserter.java | 77 +++ .../PrismValueDeltaSetTripleAsserter.java | 133 +++++ .../PrismValueDeltaSetTripleSetAsserter.java | 119 +++++ 30 files changed, 1693 insertions(+), 75 deletions(-) create mode 100644 model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionProfileSafe.java create mode 100644 model/model-common/src/test/resources/expression/expression/expression-asis.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-const.xml rename model/model-common/src/test/resources/expression/expression/{iteration-condition.xml => expression-iteration-condition.xml} (87%) create mode 100644 model/model-common/src/test/resources/expression/expression/expression-path.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-script-groovy-simple.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-allow.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-deny.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-script-javascript.xml create mode 100644 model/model-common/src/test/resources/expression/expression/expression-value.xml create mode 100644 repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleAsserter.java create mode 100644 repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleSetAsserter.java create mode 100644 repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java create mode 100644 repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleAsserter.java create mode 100644 repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleSetAsserter.java diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/PrimitiveType.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/PrimitiveType.java index bcde5b08eb2..7024338e5ed 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/PrimitiveType.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/PrimitiveType.java @@ -34,6 +34,7 @@ public enum PrimitiveType { SHORT("short"), FLOAT("float"), DOUBLE("double"), + BOOLEAN("boolean"), BASE64BINARY("base64binary"), DATETIME("dateTime"), DURATION("duration"), @@ -61,6 +62,7 @@ public QName getQname() { public static final QName XSD_SHORT = SHORT.getQname(); public static final QName XSD_FLOAT = FLOAT.getQname(); public static final QName XSD_DOUBLE = DOUBLE.getQname(); + public static final QName XSD_BOOLEAN = BOOLEAN.getQname(); public static final QName XSD_BASE64BINARY = BASE64BINARY.getQname(); public static final QName XSD_DATETIME = DATETIME.getQname(); public static final QName XSD_DURATION = DURATION.getQname(); diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java index 6ba1cb99491..22310a4ad03 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2018 Evolveum + * Copyright (c) 2010-2019 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,10 +38,13 @@ /** * @author lazyman + * @author semancik */ public final class PrismForJAXBUtil { - private PrismForJAXBUtil() { + private static final Object JAXB_CLASS_MANGLED = "clazz"; + + private PrismForJAXBUtil() { } public static T getPropertyValue(PrismContainerValue container, QName name, Class clazz) { @@ -163,6 +166,11 @@ public static T getFieldSingleContainerable(PrismConta public static > T getContainer(PrismContainerValue parentValue, QName name) { Validate.notNull(parentValue, "Parent container value must not be null."); Validate.notNull(name, "QName must not be null."); + + // This is how JAXB compiler handles elements of name "class". + if (JAXB_CLASS_MANGLED.equals(name.getLocalPart())) { + name = new QName(name.getNamespaceURI(), "class"); + } try { PrismContainer container = parentValue.findContainer(name); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/ExpressionPermissionProfile.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/ExpressionPermissionProfile.java index 02d0e619d6b..ff002e810d7 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/ExpressionPermissionProfile.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/ExpressionPermissionProfile.java @@ -21,6 +21,7 @@ import com.evolveum.midpoint.schema.AccessDecision; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionPermissionClassProfileType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionPermissionMethodProfileType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionPermissionPackageProfileType; /** * Compiled expression permission profile. @@ -32,7 +33,8 @@ public class ExpressionPermissionProfile { private final String identifier; private AccessDecision decision; - private List classProfiles = new ArrayList<>(); + private final List packageProfiles = new ArrayList<>(); + private final List classProfiles = new ArrayList<>(); public ExpressionPermissionProfile(String identifier) { super(); @@ -50,19 +52,28 @@ public AccessDecision getDecision() { public void setDecision(AccessDecision decision) { this.decision = decision; } + + public List getPackageProfiles() { + return packageProfiles; + } public List getClassProfiles() { return classProfiles; } public boolean hasRestrictions() { - return !classProfiles.isEmpty(); + return !classProfiles.isEmpty() || !packageProfiles.isEmpty() || decision != AccessDecision.ALLOW; } public AccessDecision decideClassAccess(String className, String methodName) { ExpressionPermissionClassProfileType classProfile = getClassProfile(className); if (classProfile == null) { - return decision; + ExpressionPermissionPackageProfileType packageProfile = getPackageProfileByClassName(className); + if (packageProfile == null) { + return decision; + } else { + return AccessDecision.translate(packageProfile.getDecision()); + } } ExpressionPermissionMethodProfileType methodProfile = getMethodProfile(classProfile, methodName); if (methodProfile == null) { @@ -72,6 +83,22 @@ public AccessDecision decideClassAccess(String className, String methodName) { } } + private ExpressionPermissionPackageProfileType getPackageProfileByClassName(String className) { + for (ExpressionPermissionPackageProfileType packageProfile : packageProfiles) { + if (isMemeberClass(packageProfile, className)) { + return packageProfile; + } + } + return null; + } + + + + private boolean isMemeberClass(ExpressionPermissionPackageProfileType packageProfile, String className) { + // TODO Maybe too simple. But this will do for now. + return className.startsWith(packageProfile.getName()); + } + private ExpressionPermissionClassProfileType getClassProfile(String className) { for (ExpressionPermissionClassProfileType classProfile : classProfiles) { if (className.equals(classProfile.getName())) { diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/TypedValue.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/TypedValue.java index ca55e4a15a1..89645c8eb8f 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/TypedValue.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/TypedValue.java @@ -84,6 +84,13 @@ public TypedValue(Object value, Class typeClass) { this.value = value; this.typeClass = typeClass; } + + public TypedValue(Object value, ItemDefinition definition, Class typeClass) { + super(); + this.value = value; + this.definition = definition; + this.typeClass = typeClass; + } public Object getValue() { return value; @@ -110,6 +117,9 @@ public void setTypeClass(Class typeClass) { this.typeClass = typeClass; } + public boolean canDetermineType() { + return definition != null || typeClass != null; + } public Class determineClass() throws SchemaException { if (definition == null) { @@ -134,6 +144,13 @@ public Class determineClass() throws SchemaException { return determinedClass; } } + + /** + * Returns new TypedValue that has a new (transformed) value, but has the same definition. + */ + public TypedValue createTransformed(Object newValue) { + return new TypedValue(newValue, definition, typeClass); + } @Override public int hashCode() { @@ -200,7 +217,7 @@ public void shortDump(StringBuilder sb) { sb.append(", class=").append(typeClass.getSimpleName()); } if (definition == null && typeClass == null) { - sb.append("definition/class=null"); + sb.append(", definition/class=null"); } } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/VariablesMap.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/VariablesMap.java index 50bec31e08b..c7569f65801 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/VariablesMap.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/expression/VariablesMap.java @@ -79,14 +79,17 @@ public TypedValue get(Object key) { public TypedValue put(String key, TypedValue typedValue) { if (typedValue == null) { - throw new IllegalArgumentException("Attempt to variable '"+key+"' with null typed value"); + throw new IllegalArgumentException("Attempt to set variable '"+key+"' with null typed value"); + } + if (!typedValue.canDetermineType()) { + throw new IllegalArgumentException("Attempt to set variable '"+key+"' without determinable type"); } return variables.put(key, typedValue); } @SuppressWarnings("rawtypes") public TypedValue put(String key, Object value, D definition) { - return variables.put(key, new TypedValue(value, definition)); + return variables.put(key, new TypedValue<>(value, definition)); } /** @@ -95,7 +98,7 @@ public TypedValue put(String key, Object value, D def * of the value precisely. */ public TypedValue put(String key, Object value, Class typeClass) { - return variables.put(key, new TypedValue(value, typeClass)); + return variables.put(key, new TypedValue<>(value, typeClass)); } /** diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index 2c35f7a671d..f5939840946 100755 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -15412,6 +15412,16 @@ + + + + Free-form description (comment). + + + SystemConfigurationExpressionsType.name + + + @@ -15459,6 +15469,16 @@ + + + + Free-form description (comment). + + + ExpressionProfileType.name + + + @@ -15504,6 +15524,16 @@ + + + + Free-form description (comment). + + + ExpressionEvaluatorProfileType.name + + + @@ -15551,6 +15581,16 @@ + + + + Free-form description (comment). + + + ScriptExpressionProfileType.name + + + @@ -15617,6 +15657,16 @@ + + + + Free-form description (comment). + + + ExpressionPermissionProfileType.name + + + @@ -15628,6 +15678,16 @@ + + + + Detailed specification for access to a class. + + + ExpressionPermissionProfileType.class + + + @@ -15638,11 +15698,59 @@ - + + + + Specifies restrictions and permissions for a package. + For now package definitions MUST NOT OVERLAP. Therefore there must not be + a definiton of a superpackage and subpackage at the same time. + + + + 4.0 + true + + + + + + + Full name of the class (including package). + + + ExpressionPermissionPackageProfileType.name + + + + + + + Free-form description (comment). + + + ExpressionPermissionPackageProfileType.name + + + + + + + Default decision for the profile. I.e. decision of those aspects of the profile + (e.g. classes, permissions) that are not explicitly enumerated. + + + ExpressionPermissionPackageProfileType.decision + + + + + + + @@ -15665,6 +15773,16 @@ + + + + Free-form description (comment). + + + ExpressionPermissionClassProfileType.name + + + @@ -15711,6 +15829,16 @@ + + + + Free-form description (comment). + + + "ExpressionPermissionMethodProfileType".name + + + diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionProfileCompiler.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionProfileCompiler.java index c1bf24da64b..90e115fa5b2 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionProfileCompiler.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionProfileCompiler.java @@ -56,6 +56,7 @@ private ExpressionPermissionProfile compilePermissionProfile(ExpressionPermissio ExpressionPermissionProfile profile = new ExpressionPermissionProfile(permissionProfileType.getIdentifier()); profile.setDecision(AccessDecision.translate(permissionProfileType.getDecision())); + profile.getPackageProfiles().addAll(permissionProfileType.getPackage()); profile.getClassProfiles().addAll(permissionProfileType.getClazz()); return profile; @@ -116,5 +117,16 @@ private ExpressionPermissionProfile findPermissionProfile(List profiles, String identifier) { + if (identifier == null) { + return null; + } + for (ExpressionProfile profile : profiles) { + if (identifier.equals(profile.getIdentifier())) { + return profile; + } + } + return null; + } } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractValueTransformationExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractValueTransformationExpressionEvaluator.java index b2dfe53b050..eab684ef944 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractValueTransformationExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AbstractValueTransformationExpressionEvaluator.java @@ -459,12 +459,15 @@ private PrismValueDeltaSetTriple evaluateRelativeExpression(final List> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(INPUT_VALUE); + + assertScriptExecutionIncrement(0); + } + @Test - public void testIterationCondition() throws Exception { - final String TEST_NAME = "testIterationCondition"; - TestUtil.displayTestTitle(TEST_NAME); + public void test110Path() throws Exception { + final String TEST_NAME = "test110Path"; + displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); rememberScriptExecutionCount(); - ExpressionType expressionType = PrismTestUtil.parseAtomicValue( - EXPRESSION_ITERATION_CONDITION_FILE, ExpressionType.COMPLEX_TYPE); + ExpressionType expressionType = parseExpression(EXPRESSION_PATH_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); - PrismPropertyDefinition outputDefinition = prismContext.definitionFactory().createPropertyDefinition( - ExpressionConstants.OUTPUT_ELEMENT_NAME, DOMUtil.XSD_BOOLEAN); - Expression,PrismPropertyDefinition> expression = expressionFactory.makeExpression(expressionType, outputDefinition , MiscSchemaUtil.getExpressionProfile(), TEST_NAME, null, result); + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); - ExpressionVariables variables = new ExpressionVariables(); - PrismObject user = PrismTestUtil.parseObject(USER_JACK_FILE); - variables.addVariableDefinition(ExpressionConstants.VAR_FOCUS, user, user.getDefinition()); - variables.addVariableDefinition(ExpressionConstants.VAR_USER, user, user.getDefinition()); + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(USER_JACK_NAME); + + assertScriptExecutionIncrement(0); + } + + @Test + public void test120Value() throws Exception { + final String TEST_NAME = "test120Value"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_VALUE_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(EXPRESSION_VALUE_OUTPUT); + + assertScriptExecutionIncrement(0); + } + + @Test + public void test130Const() throws Exception { + final String TEST_NAME = "test130Const"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_CONST_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(ExpressionTestUtil.CONST_FOO_VALUE); + + assertScriptExecutionIncrement(0); + } + + @Test + public void test150ScriptGroovySimple() throws Exception { + final String TEST_NAME = "test150ScriptGroovySimple"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_GROOVY_SIMPLE_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(VAR_FOO_VALUE + VAR_BAR_VALUE); + + assertScriptExecutionIncrement(1); + } + + @Test + public void test152ScriptGroovySystemAllow() throws Exception { + final String TEST_NAME = "test152ScriptGroovySystemAllow"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_GROOVY_SYSTEM_ALLOW_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(GROOVY_SCRIPT_OUTPUT_SUCCESS); + + assertScriptExecutionIncrement(1); + } + + @Test + public void test154ScriptGroovySystemDeny() throws Exception { + final String TEST_NAME = "test154ScriptGroovySystemDeny"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_GROOVY_SYSTEM_DENY_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(GROOVY_SCRIPT_OUTPUT_SUCCESS); + + assertScriptExecutionIncrement(1); + } + + @Test + public void test160ScriptJavaScript() throws Exception { + final String TEST_NAME = "test160ScriptJavaScript"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_JAVASCRIPT_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(VAR_FOO_VALUE + VAR_BAR_VALUE); + + assertScriptExecutionIncrement(1); + } + + @Test + public void test200IterationCondition() throws Exception { + final String TEST_NAME = "test200IterationCondition"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_ITERATION_CONDITION_FILE); + + ExpressionVariables variables = prepareBasicVariables(); PrismObject account = PrismTestUtil.parseObject(ACCOUNT_JACK_DUMMYFILE); - variables.addVariableDefinition(ExpressionConstants.VAR_SHADOW, account, account.getDefinition()); - variables.addVariableDefinition(ExpressionConstants.VAR_ITERATION, 1, + variables.put(ExpressionConstants.VAR_SHADOW, account, account.getDefinition()); + variables.put(ExpressionConstants.VAR_ITERATION, 1, TestUtil.createPrimitivePropertyDefinition(prismContext, ExpressionConstants.VAR_ITERATION, PrimitiveType.INT)); - variables.addVariableDefinition(ExpressionConstants.VAR_ITERATION_TOKEN, "001", + variables.put(ExpressionConstants.VAR_ITERATION_TOKEN, "001", TestUtil.createPrimitivePropertyDefinition(prismContext, ExpressionConstants.VAR_ITERATION_TOKEN, PrimitiveType.STRING)); ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null , variables, TEST_NAME, null, result); // WHEN - PrismValueDeltaSetTriple> outputTriple = expression.evaluate(expressionContext); + PrismValueDeltaSetTriple> outputTriple = evaluatePropertyExpression(expressionType, PrimitiveType.BOOLEAN, expressionContext); // THEN - assertNotNull(outputTriple); - outputTriple.checkConsistence(); + assertOutputTriple(outputTriple) + .assertEmptyMinus() + .assertEmptyPlus() + .zeroSet() + .assertSinglePropertyValue(Boolean.TRUE); // Make sure that the script is executed only once. There is no delta in the variables, no need to do it twice. assertScriptExecutionIncrement(1); } + + protected ExpressionType parseExpression(File file) throws SchemaException, IOException { + return PrismTestUtil.parseAtomicValue(file, ExpressionType.COMPLEX_TYPE); + } + + protected void displayTestTitle(final String TEST_NAME) { + TestUtil.displayTestTitle(this, TEST_NAME); + } + + protected Source,PrismPropertyDefinition> prepareStringSource(String value) throws SchemaException { + PrismPropertyDefinition propDef = prismContext.definitionFactory().createPropertyDefinition(ExpressionConstants.VAR_INPUT_QNAME, PrimitiveType.STRING.getQname()); + PrismProperty inputProp = prismContext.itemFactory().createProperty(ExpressionConstants.VAR_INPUT_QNAME, propDef); + PrismPropertyValue pval = prismContext.itemFactory().createPropertyValue(INPUT_VALUE); + inputProp.add(pval); + return new Source<>(inputProp, null, inputProp, ExpressionConstants.VAR_INPUT_QNAME); + } + + protected Collection> prepareStringSources(String value) throws SchemaException { + Collection> sources = new ArrayList<>(); + sources.add(prepareStringSource(value)); + return sources; + } + + protected ExpressionVariables prepareBasicVariables() throws SchemaException, IOException { + ExpressionVariables variables = new ExpressionVariables(); + PrismObject user = PrismTestUtil.parseObject(USER_JACK_FILE); + variables.put(ExpressionConstants.VAR_FOCUS, user, user.getDefinition()); + variables.put(VAR_FOO_NAME, VAR_FOO_VALUE, String.class); + variables.put(VAR_BAR_NAME, VAR_BAR_VALUE, String.class); + return variables; + } + + protected PrismValueDeltaSetTriple evaluateExpression( + ExpressionType expressionType, D outputDefinition, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + Expression expression = expressionFactory.makeExpression(expressionType, outputDefinition , getExpressionProfile(), + expressionContext.getContextDescription(), expressionContext.getTask(), expressionContext.getResult()); + LOGGER.debug("Starting evaluation of expression: {}", expression); + return expression.evaluate(expressionContext); + } + + protected PrismValueDeltaSetTriple> evaluatePropertyExpression( + ExpressionType expressionType, QName outputType, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + PrismPropertyDefinition outputDefinition = prismContext.definitionFactory().createPropertyDefinition( + ExpressionConstants.OUTPUT_ELEMENT_NAME, outputType); + return evaluateExpression(expressionType, outputDefinition, expressionContext); + } + + protected PrismValueDeltaSetTriple> evaluatePropertyExpression( + ExpressionType expressionType, PrimitiveType outputType, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + return evaluatePropertyExpression(expressionType, outputType.getQname(), expressionContext); + } + + protected void evaluateExpressionRestricted( + ExpressionType expressionType, D outputDefinition, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + Expression expression; + try { + + expression = expressionFactory.makeExpression(expressionType, outputDefinition , getExpressionProfile(), + expressionContext.getContextDescription(), expressionContext.getTask(), expressionContext.getResult()); + + } catch (SecurityViolationException e) { + // Exception may happen here, or it may happen later. + // Expected + LOGGER.debug("Expected exception", e); + assertTrue("Wrong exception message: " + e.getMessage(), e.getMessage().contains("Access to script language")); + return; + } + + LOGGER.debug("Starting evaluation of expression (expecting security violation): {}", expression); + try { + + expression.evaluate(expressionContext); + + AssertJUnit.fail("Unexpected success of expression evaluation"); + + } catch (SecurityViolationException e) { + // Expected + LOGGER.debug("Expected exception", e); + assertTrue("Wrong exception message: " + e.getMessage(), + e.getMessage().contains("Access to expression evaluator") + || e.getMessage().contains("Access to Groovy method")); + } + } + + protected void evaluatePropertyExpressionRestricted( + ExpressionType expressionType, QName outputType, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + PrismPropertyDefinition outputDefinition = prismContext.definitionFactory().createPropertyDefinition( + ExpressionConstants.OUTPUT_ELEMENT_NAME, outputType); + evaluateExpressionRestricted(expressionType, outputDefinition, expressionContext); + } + + protected void evaluatePropertyExpressionRestricted( + ExpressionType expressionType, PrimitiveType outputType, ExpressionEvaluationContext expressionContext) + throws SchemaException, ObjectNotFoundException, SecurityViolationException, ExpressionEvaluationException, CommunicationException, ConfigurationException { + evaluatePropertyExpressionRestricted(expressionType, outputType.getQname(), expressionContext); + } protected void rememberScriptExecutionCount() { lastScriptExecutionCount = InternalMonitor.getCount(InternalCounters.SCRIPT_EXECUTION_COUNT); @@ -134,5 +515,44 @@ protected void assertScriptExecutionIncrement(int expectedIncrement) { assertEquals("Unexpected increment in script execution count", (long)expectedIncrement, actualIncrement); lastScriptExecutionCount = currentScriptExecutionCount; } + + protected ExpressionProfile getExpressionProfile() { + return expressionProfile; + } + + protected String getExpressionProfileName() { + // Default "null" expression profile, no restrictions. + return null; + } + + protected ExpressionProfile compileExpressionProfile(String profileName) throws SchemaException, IOException { + if (profileName == null) { + return null; + } + PrismObject systemConfig = PrismTestUtil.parseObject(getSystemConfigurationFile()); + SystemConfigurationExpressionsType expressions = systemConfig.asObjectable().getExpressions(); + if (expressions == null) { + throw new SchemaException("No expressions in system config"); + } + ExpressionProfileCompiler compiler = new ExpressionProfileCompiler(); + List profiles = compiler.compile(expressions); + ExpressionProfile profile = ExpressionProfileCompiler.findProfile(profiles, profileName); + if (profile == null) { + throw new SchemaException("Profile '"+profile+"' not found in system config"); + } + return profile; + } + + protected File getSystemConfigurationFile() { + return SYSTEM_CONFIGURATION_FILE; + } + protected PrismValueDeltaSetTripleAsserter assertOutputTriple(PrismValueDeltaSetTriple triple) { + assertNotNull(triple); + triple.checkConsistence(); + PrismValueDeltaSetTripleAsserter asserter = new PrismValueDeltaSetTripleAsserter<>(triple, "expression output triple"); + asserter.setPrismContext(prismContext); + asserter.display(); + return asserter; + } } diff --git a/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionProfileSafe.java b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionProfileSafe.java new file mode 100644 index 00000000000..3e1329070fb --- /dev/null +++ b/model/model-common/src/test/java/com/evolveum/midpoint/model/common/expression/TestExpressionProfileSafe.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013-2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.model.common.expression; + +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; + +import com.evolveum.midpoint.prism.crypto.Protector; +import com.evolveum.midpoint.repo.common.DirectoryFileObjectResolver; +import com.evolveum.midpoint.repo.common.ObjectResolver; +import com.evolveum.midpoint.repo.common.expression.Expression; +import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; +import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import com.evolveum.midpoint.repo.common.expression.Source; +import com.evolveum.midpoint.common.Clock; +import com.evolveum.midpoint.prism.*; + +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.MidPointPrismContextFactory; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.expression.ExpressionProfile; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.internals.InternalMonitor; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + +/** + * @author Radovan Semancik + */ +public class TestExpressionProfileSafe extends TestExpression { + + @Override + protected String getExpressionProfileName() { + return EXPRESSION_PROFILE_SAFE_NAME; + } + + @Test + @Override + public void test130Const() throws Exception { + final String TEST_NAME = "test130Const"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_CONST_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + evaluatePropertyExpressionRestricted(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + + assertScriptExecutionIncrement(0); + } + + @Test + @Override + public void test154ScriptGroovySystemDeny() throws Exception { + final String TEST_NAME = "test154ScriptGroovySystemDeny"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_GROOVY_SYSTEM_DENY_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + evaluatePropertyExpressionRestricted(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + + assertScriptExecutionIncrement(0); + } + + @Test + @Override + public void test160ScriptJavaScript() throws Exception { + final String TEST_NAME = "test160ScriptJavaScript"; + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestExpression.class.getName()+"."+TEST_NAME); + + rememberScriptExecutionCount(); + + ExpressionType expressionType = parseExpression(EXPRESSION_SCRIPT_JAVASCRIPT_FILE); + Collection> sources = prepareStringSources(INPUT_VALUE); + ExpressionVariables variables = prepareBasicVariables(); + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(sources , variables, TEST_NAME, null, result); + + // WHEN + evaluatePropertyExpressionRestricted(expressionType, PrimitiveType.STRING, expressionContext); + + // THEN + + assertScriptExecutionIncrement(0); + } +} diff --git a/model/model-common/src/test/resources/common/system-configuration.xml b/model/model-common/src/test/resources/common/system-configuration.xml index 7ceace1c3c3..e76d7b179b3 100644 --- a/model/model-common/src/test/resources/common/system-configuration.xml +++ b/model/model-common/src/test/resources/common/system-configuration.xml @@ -37,10 +37,12 @@ value allow + script deny @@ -52,25 +54,65 @@ + + script-safe + deny + + com.evolveum.midpoint.xml.ns._public.common.common_3 + MidPoint common schema - generated bean classes + allow + + + com.evolveum.prism.xml.ns._public.types_3 + Prism schema - bean classes + allow + + + java.lang.String + String operations are generally safe. But Groovy is adding execute() method which is very dangerous. + allow + + execute + deny + + + + java.lang.CharSequence + allow + + + java.util.List + List operations are generally safe. But Groovy is adding execute() method which is very dangerous. + allow + + execute + deny + + + + java.lang.System + Just a few methods of System are safe enough. + deny + + currentTimeMillis + allow + + + + java.lang.IllegalStateException + Basic Java exception. Also used in test. + allow + + + java.lang.IllegalArgumentException + Basic Java exception. + allow + + + com.evolveum.midpoint.model.common.expression.functions.LogExpressionFunctions + MidPoint logging functions library + allow + + - - script-safe - deny - - java.lang.String - allow - - execute - deny - - - - java.util.List - allow - - execute - deny - - - diff --git a/model/model-common/src/test/resources/expression/expression/expression-asis.xml b/model/model-common/src/test/resources/expression/expression/expression-asis.xml new file mode 100644 index 00000000000..23283a9419c --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-asis.xml @@ -0,0 +1,28 @@ + + + + + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-const.xml b/model/model-common/src/test/resources/expression/expression/expression-const.xml new file mode 100644 index 00000000000..7d4679ef04d --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-const.xml @@ -0,0 +1,28 @@ + + + + foo + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/iteration-condition.xml b/model/model-common/src/test/resources/expression/expression/expression-iteration-condition.xml similarity index 87% rename from model/model-common/src/test/resources/expression/expression/iteration-condition.xml rename to model/model-common/src/test/resources/expression/expression/expression-iteration-condition.xml index e816d4cc212..d5de5d1f2b7 100644 --- a/model/model-common/src/test/resources/expression/expression/iteration-condition.xml +++ b/model/model-common/src/test/resources/expression/expression/expression-iteration-condition.xml @@ -1,6 +1,6 @@ + + $focus/name + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-script-groovy-simple.xml b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-simple.xml new file mode 100644 index 00000000000..bfedcbb7150 --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-simple.xml @@ -0,0 +1,32 @@ + + + + + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-allow.xml b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-allow.xml new file mode 100644 index 00000000000..ca740e40de3 --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-allow.xml @@ -0,0 +1,36 @@ + + + + + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-deny.xml b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-deny.xml new file mode 100644 index 00000000000..b3acb3cce1a --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-script-groovy-system-deny.xml @@ -0,0 +1,34 @@ + + + + + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-script-javascript.xml b/model/model-common/src/test/resources/expression/expression/expression-script-javascript.xml new file mode 100644 index 00000000000..059ecf3ce8c --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-script-javascript.xml @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/model/model-common/src/test/resources/expression/expression/expression-value.xml b/model/model-common/src/test/resources/expression/expression/expression-value.xml new file mode 100644 index 00000000000..25797e6f93f --- /dev/null +++ b/model/model-common/src/test/resources/expression/expression/expression-value.xml @@ -0,0 +1,28 @@ + + + + GARBAGE OUT + \ No newline at end of file diff --git a/model/model-common/src/test/resources/logback-test.xml b/model/model-common/src/test/resources/logback-test.xml index c9e6859622f..8a4313aee43 100644 --- a/model/model-common/src/test/resources/logback-test.xml +++ b/model/model-common/src/test/resources/logback-test.xml @@ -25,6 +25,7 @@ + diff --git a/model/model-common/testng-unit.xml b/model/model-common/testng-unit.xml index 25b7787a39d..403372df714 100644 --- a/model/model-common/testng-unit.xml +++ b/model/model-common/testng-unit.xml @@ -32,6 +32,7 @@ + diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionVariables.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionVariables.java index d917d714084..c7052fc568a 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionVariables.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/expression/ExpressionVariables.java @@ -65,7 +65,7 @@ public void addVariableDefinitions(VariablesMap extraVariables, @NotNull Collect } value = odo.getOldObject(); } - put(entry.getKey(), new TypedValue(value, valueDef.getDefinition())); + put(entry.getKey(), valueDef.createTransformed(value)); } } @@ -93,7 +93,7 @@ public void addVariableDefinitionsOld(VariablesMap extraVariables) { ItemDeltaItem idi = (ItemDeltaItem)value; value = idi.getItemOld(); } - put(entry.getKey(), new TypedValue(value, valueDef.getDefinition())); + put(entry.getKey(), valueDef.createTransformed(value)); } } @@ -113,7 +113,7 @@ public void addVariableDefinitionsNew(VariablesMap extraVariables) { ItemDeltaItem idi = (ItemDeltaItem)value; value = idi.getItemNew(); } - put(entry.getKey(), new TypedValue(value, valueDef.getDefinition())); + put(entry.getKey(), valueDef.createTransformed(value)); } } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleAsserter.java new file mode 100644 index 00000000000..928b3ece7a4 --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleAsserter.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Collection; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.asserter.AbstractAsserter; +import com.evolveum.midpoint.test.asserter.ContainerDeltaAsserter; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; + +/** + * @author semancik + * + */ +public class DeltaSetTripleAsserter,RA> extends AbstractAsserter { + + private D triple; + + public DeltaSetTripleAsserter(D triple) { + super(); + this.triple = triple; + } + + public DeltaSetTripleAsserter(D triple, String detail) { + super(detail); + this.triple = triple; + } + + public DeltaSetTripleAsserter(D triple, RA returnAsserter, String detail) { + super(returnAsserter, detail); + this.triple = triple; + } + + public static DeltaSetTripleAsserter,Void> forDeltaSetTriple(DeltaSetTriple triple) { + return new DeltaSetTripleAsserter<>(triple); + } + + public D getTriple() { + return triple; + } + + public DeltaSetTripleSetAsserter> zeroSet() { + return createSetAsserter(triple.getZeroSet(), "zero"); + } + + public DeltaSetTripleSetAsserter> plusSet() { + return createSetAsserter(triple.getPlusSet(), "plus"); + } + + public DeltaSetTripleSetAsserter> minusSet() { + return createSetAsserter(triple.getMinusSet(), "minus"); + } + + private DeltaSetTripleSetAsserter> createSetAsserter(Collection set, String name) { + DeltaSetTripleSetAsserter> setAsserter = new DeltaSetTripleSetAsserter<>(set, this, name+" set of "+desc()); + copySetupTo(setAsserter); + return setAsserter; + } + + public DeltaSetTripleAsserter assertNullZero() { + assertNullSet(triple.getZeroSet(), "zero"); + return this; + } + + public DeltaSetTripleAsserter assertNullPlus() { + assertNullSet(triple.getPlusSet(), "plus"); + return this; + } + + public DeltaSetTripleAsserter assertNullMinus() { + assertNullSet(triple.getMinusSet(), "minus"); + return this; + } + + private void assertNullSet(Collection set, String name) { + assertNull("Non-null "+name+" set in "+desc(), set); + } + + public DeltaSetTripleAsserter assertEmptyZero() { + assertEmptySet(triple.getZeroSet(), "zero"); + return this; + } + + public DeltaSetTripleAsserter assertEmptyPlus() { + assertEmptySet(triple.getPlusSet(), "plus"); + return this; + } + + public DeltaSetTripleAsserter assertEmptyMinus() { + assertEmptySet(triple.getMinusSet(), "minus"); + return this; + } + + private void assertEmptySet(Collection set, String name) { + assertTrue("Non-empty "+name+" set in "+desc(), set.isEmpty()); + } + + protected String desc() { + return descWithDetails(triple); + } + + public DeltaSetTripleAsserter display() { + display(desc()); + return this; + } + + public DeltaSetTripleAsserter display(String message) { + IntegrationTestTools.display(message, triple); + return this; + } +} diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleSetAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleSetAsserter.java new file mode 100644 index 00000000000..09219fc4be4 --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/DeltaSetTripleSetAsserter.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.Collection; + +import org.testng.AssertJUnit; + +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.asserter.AbstractAsserter; + +/** + * @author semancik + * + */ +public class DeltaSetTripleSetAsserter extends AbstractAsserter { + + private Collection set; + + public DeltaSetTripleSetAsserter(Collection set) { + super(); + this.set = set; + } + + public DeltaSetTripleSetAsserter(Collection set, String detail) { + super(detail); + this.set = set; + } + + public DeltaSetTripleSetAsserter(Collection set, RA returnAsserter, String detail) { + super(returnAsserter, detail); + this.set = set; + } + + public static DeltaSetTripleSetAsserter forSet(Collection set) { + return new DeltaSetTripleSetAsserter<>(set); + } + + public Collection getSet() { + return set; + } + + public DeltaSetTripleSetAsserter assertSize(int expected) { + assertEquals("Wrong number of values in " + desc(), expected, set.size()); + return this; + } + + public DeltaSetTripleSetAsserter assertNone() { + assertSize(0); + return this; + } + + public DeltaSetTripleSetAsserter assertNull() { + AssertJUnit.assertNull("Expected null, but found non-null set in " + desc(), set); + return this; + } + + // TODO + + protected String desc() { + return descWithDetails(set); + } + + public DeltaSetTripleSetAsserter display() { + display(desc()); + return this; + } + + public DeltaSetTripleSetAsserter display(String message) { + IntegrationTestTools.display(message, set); + return this; + } +} diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java new file mode 100644 index 00000000000..c6e6bcac883 --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Iterator; +import java.util.List; + +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReference; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.prism.xml.ns._public.types_3.RawType; + +/** + * @author semancik + * + */ +public class PrismPropertyValueAsserter extends PrismValueAsserter, RA> { + + public PrismPropertyValueAsserter(PrismPropertyValue prismValue) { + super(prismValue); + } + + public PrismPropertyValueAsserter(PrismPropertyValue prismValue, String detail) { + super(prismValue, detail); + } + + public PrismPropertyValueAsserter(PrismPropertyValue prismValue, RA returnAsserter, String detail) { + super(prismValue, returnAsserter, detail); + } + + public PrismPropertyValueAsserter assertValue(T expectedValue) { + assertEquals("Wrong property value in "+desc(), expectedValue, getPrismValue().getValue()); + return this; + } + + // TODO + + protected String desc() { + return getDetails(); + } + +} diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleAsserter.java new file mode 100644 index 00000000000..7adef0ab71c --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleAsserter.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Collection; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.asserter.AbstractAsserter; +import com.evolveum.midpoint.test.asserter.ContainerDeltaAsserter; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; + +/** + * @author semancik + * + */ +public class PrismValueDeltaSetTripleAsserter extends DeltaSetTripleAsserter,RA> { + + public PrismValueDeltaSetTripleAsserter(PrismValueDeltaSetTriple triple) { + super(triple); + } + + public PrismValueDeltaSetTripleAsserter(PrismValueDeltaSetTriple triple, String detail) { + super(triple, detail); + } + + public PrismValueDeltaSetTripleAsserter(PrismValueDeltaSetTriple triple, RA returnAsserter, String detail) { + super(triple, returnAsserter, detail); + } + + public static PrismValueDeltaSetTripleAsserter forPrismValueDeltaSetTriple(PrismValueDeltaSetTriple triple) { + return new PrismValueDeltaSetTripleAsserter<>(triple); + } + + @Override + public PrismValueDeltaSetTripleSetAsserter> zeroSet() { + return createSetAsserter(getTriple().getZeroSet(), "zero"); + } + + @Override + public PrismValueDeltaSetTripleSetAsserter> plusSet() { + return createSetAsserter(getTriple().getPlusSet(), "plus"); + } + + @Override + public PrismValueDeltaSetTripleSetAsserter> minusSet() { + return createSetAsserter(getTriple().getMinusSet(), "minus"); + } + + private PrismValueDeltaSetTripleSetAsserter> createSetAsserter(Collection set, String name) { + PrismValueDeltaSetTripleSetAsserter> setAsserter = new PrismValueDeltaSetTripleSetAsserter<>(set, this, name+" set of "+desc()); + copySetupTo(setAsserter); + return setAsserter; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertNullZero() { + super.assertNullZero(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertNullPlus() { + super.assertNullPlus(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertNullMinus() { + super.assertNullMinus(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertEmptyZero() { + super.assertEmptyZero(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertEmptyPlus() { + super.assertEmptyPlus(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter assertEmptyMinus() { + super.assertEmptyMinus(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter display() { + super.display(); + return this; + } + + @Override + public PrismValueDeltaSetTripleAsserter display(String message) { + super.display(message); + return this; + } +} diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleSetAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleSetAsserter.java new file mode 100644 index 00000000000..d409d32bb7e --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismValueDeltaSetTripleSetAsserter.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2019 Evolveum + * + * 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. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Collection; + +import javax.xml.namespace.QName; + +import org.testng.AssertJUnit; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.asserter.AbstractAsserter; +import com.evolveum.midpoint.test.asserter.ContainerDeltaAsserter; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; + +/** + * @author semancik + * + */ +public class PrismValueDeltaSetTripleSetAsserter extends DeltaSetTripleSetAsserter { + + public PrismValueDeltaSetTripleSetAsserter(Collection set) { + super(set); + } + + public PrismValueDeltaSetTripleSetAsserter(Collection set, String detail) { + super(set,detail); + } + + public PrismValueDeltaSetTripleSetAsserter(Collection set, RA returnAsserter, String detail) { + super(set,returnAsserter, detail); + } + + public static PrismValueDeltaSetTripleSetAsserter forSPrismValueet(Collection set) { + return new PrismValueDeltaSetTripleSetAsserter<>(set); + } + + @Override + public PrismValueDeltaSetTripleSetAsserter assertSize(int expected) { + super.assertSize(expected); + return this; + } + + @Override + public PrismValueDeltaSetTripleSetAsserter assertNone() { + super.assertNone(); + return this; + } + + @Override + public PrismValueDeltaSetTripleSetAsserter assertNull() { + super.assertNull(); + return this; + } + + public PrismPropertyValueAsserter> singlePropertyValue(Class type) { + assertSize(1); + V val = getSet().iterator().next(); + if (!(val instanceof PrismPropertyValue)) { + fail("Expected that a single value of set will be a property value, but it was "+val+", in " + desc()); + } + PrismPropertyValueAsserter> vAsserter = new PrismPropertyValueAsserter<>((PrismPropertyValue)val, this, "single property value in " + desc()); + copySetupTo(vAsserter); + return vAsserter; + } + + public PrismValueDeltaSetTripleSetAsserter assertSinglePropertyValue(T expectedValue) { + assertSize(1); + V val = getSet().iterator().next(); + if (!(val instanceof PrismPropertyValue)) { + fail("Expected that a single value of set will be a property value, but it was "+val+", in " + desc()); + } + T value = ((PrismPropertyValue)val).getValue(); + assertEquals("Wrong property value in "+desc(), expectedValue, value); + return this; + } + + @Override + public PrismValueDeltaSetTripleSetAsserter display() { + super.display(); + return this; + } + + @Override + public PrismValueDeltaSetTripleSetAsserter display(String message) { + super.display(message); + return this; + } +}