From c93a8eeeb0aa4278fcd8c945a77ee2a299121551 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Thu, 31 Jul 2014 14:40:25 +0200 Subject: [PATCH] Assignment conditions fixed, more tests, diag improvements. --- .../expression/script/ScriptExpression.java | 9 +- .../model/impl/lens/AssignmentEvaluator.java | 30 ++++- .../model/impl/lens/AssignmentPath.java | 16 ++- .../model/impl/lens/Construction.java | 8 +- .../midpoint/model/intest/TestRbac.java | 110 +++++++++++++++++- .../src/test/resources/common/user-jack.xml | 3 +- .../src/test/resources/logback-test.xml | 1 + 7 files changed, 161 insertions(+), 16 deletions(-) diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java index 6969aab65d2..780ff491735 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java @@ -32,6 +32,7 @@ import com.evolveum.midpoint.schema.util.ObjectResolver; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -65,6 +66,7 @@ public class ScriptExpression { private Collection functions; private static final Trace LOGGER = TraceManager.getTrace(ScriptExpression.class); + private static final int MAX_CODE_CHARS = 42; ScriptExpression(ScriptEvaluator evaluator, ScriptExpressionEvaluatorType scriptType) { this.scriptType = scriptType; @@ -166,7 +168,7 @@ private String formatVariables(ExpressionVariables variables) { } private String formatCode() { - return scriptType.getCode(); + return DebugUtil.excerpt(scriptType.getCode().replaceAll("[\\s\\r\\n]+", " "), MAX_CODE_CHARS); } public ItemPath parsePath(String path) { @@ -184,4 +186,9 @@ public ItemPath parsePath(String path) { // return xPathHolder.toItemPath(); } + @Override + public String toString() { + return "ScriptExpression(" + formatCode() + ")"; + } + } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index e69f0e3af97..09526c67c59 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -255,17 +255,22 @@ private void evaluateAssignment(EvaluatedAssignment evalAssignment, Assignmen MappingType conditionType = assignmentType.getCondition(); if (conditionType != null) { - PrismValueDeltaSetTriple> conditionTriple = evaluateMappingAsCondition(conditionType, source, task, result); + PrismValueDeltaSetTriple> conditionTriple = evaluateMappingAsCondition(conditionType, + assignmentType, source, task, result); boolean condOld = ExpressionUtil.computeConditionResult(conditionTriple.getNonPositiveValues()); boolean condNew = ExpressionUtil.computeConditionResult(conditionTriple.getNonNegativeValues()); PlusMinusZero condMode = ExpressionUtil.computeConditionResultMode(condOld, condNew); if (condMode == null || (condMode == PlusMinusZero.ZERO && !condNew)) { - LOGGER.trace("Skipping evaluation of "+assignmentType+" because of condition result"); + LOGGER.trace("Skipping evaluation of "+assignmentType+" because of condition result ({} -> {}: {})", + new Object[]{ condOld, condNew, condMode }); assignmentPath.remove(assignmentPathSegment); evalAssignment.setValid(false); return; } + PlusMinusZero origMode = mode; mode = PlusMinusZero.compute(mode, condMode); + LOGGER.trace("Evaluated condition in assignment {} -> {}: {} + {} = {}", new Object[]{ + condOld, condNew, origMode, condMode, mode }); } boolean isValid = LensUtil.isValid(assignmentType, now, activationComputer); @@ -426,15 +431,21 @@ private boolean evaluateAbstractRole(EvaluatedAssignment assignment, Assignme MappingType conditionType = roleType.getCondition(); if (conditionType != null) { - PrismValueDeltaSetTriple> conditionTriple = evaluateMappingAsCondition(conditionType, source, task, result); + PrismValueDeltaSetTriple> conditionTriple = evaluateMappingAsCondition(conditionType, + null, source, task, result); boolean condOld = ExpressionUtil.computeConditionResult(conditionTriple.getNonPositiveValues()); boolean condNew = ExpressionUtil.computeConditionResult(conditionTriple.getNonNegativeValues()); PlusMinusZero condMode = ExpressionUtil.computeConditionResultMode(condOld, condNew); if (condMode == null || (condMode == PlusMinusZero.ZERO && !condNew)) { - LOGGER.trace("Skipping evaluation of "+roleType+" because of condition result"); + LOGGER.trace("Skipping evaluation of "+roleType+" because of condition result ({} -> {}: {})", + new Object[]{ condOld, condNew, condMode }); return false; } + PlusMinusZero origMode = mode; mode = PlusMinusZero.compute(mode, condMode); + LOGGER.trace("Evaluated condition in {}: {} -> {}: {} + {} = {}", new Object[]{ + roleType, condOld, condNew, origMode, condMode, mode }); + } int evaluationOrder = assignmentPath.getEvaluationOrder(); @@ -560,9 +571,16 @@ private void checkSchema(AssignmentType assignmentType, String sourceDescription } } - public PrismValueDeltaSetTriple> evaluateMappingAsCondition(MappingType conditionType, ObjectType source, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + public PrismValueDeltaSetTriple> evaluateMappingAsCondition(MappingType conditionType, + AssignmentType sourceAssignment, ObjectType source, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { + String desc; + if (sourceAssignment == null) { + desc = "condition in " + source; + } else { + desc = "condition in assignment in " + source; + } Mapping> mapping = mappingFactory.createMapping(conditionType, - "condition in " + source); + desc); mapping.addVariableDefinition(ExpressionConstants.VAR_USER, focusOdo); mapping.addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusOdo); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPath.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPath.java index 876b021572f..ebf4a0f7e2d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPath.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentPath.java @@ -127,8 +127,20 @@ public String debugDump() { public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); DebugUtil.debugDumpLabel(sb, "AssignmentPath", indent); - sb.append("\n"); - DebugUtil.debugDump(segments, indent + 1); + if (segments == null || segments.isEmpty()) { + sb.append(" (empty)"); + } else { + sb.append(" (").append(segments.size()).append(")"); + if (DebugUtil.isDetailedDebugDump()) { + DebugUtil.debugDump(sb, segments, indent + 1, false); + } else { + for (AssignmentPathSegment segment: segments) { + sb.append("\n"); + DebugUtil.indentDebugDump(sb, indent + 1); + sb.append(segment.toString()); + } + } + } return sb.toString(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java index d8e6540b303..4f63a37c5bc 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Construction.java @@ -546,7 +546,7 @@ public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); DebugUtil.debugDumpLabel(sb, "Construction", indent); if (refinedObjectClassDefinition == null) { - sb.append("null"); + sb.append(" (no object class definition)"); } else { sb.append(refinedObjectClassDefinition.getShadowDiscriminator()); } @@ -566,8 +566,10 @@ public String debugDump(int indent) { sb.append(mapping.debugDump(indent+2)); } } - sb.append("\n"); - DebugUtil.debugDumpWithLabel(sb, "assignmentPath", assignmentPath, indent + 1); + if (assignmentPath != null) { + sb.append("\n"); + sb.append(assignmentPath.debugDump(indent+1)); + } return sb.toString(); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRbac.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRbac.java index cdfea21c353..2dbc2fad62f 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRbac.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRbac.java @@ -1065,6 +1065,32 @@ public void test540JackAssignRoleWannabe() throws Exception { result.computeStatus(); TestUtil.assertSuccess(result); + assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result); + assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); + } + + /** + * Remove honorifixSuffix. This triggers a condition in Wannabe role inducement. + * But as the whole role has false condition nothing should happen. + */ + @Test + public void test541JackRemoveHonorificSuffixWannabe() throws Exception { + final String TEST_NAME = "test541JackRemoveHonorificSuffixWannabe"; + TestUtil.displayTestTile(this, TEST_NAME); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_SUFFIX, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result); assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); } @@ -1073,8 +1099,8 @@ public void test540JackAssignRoleWannabe() throws Exception { * Modify employeeType. This triggers a condition in Wannabe role. */ @Test - public void test541JackModifyEmployeeTypeWannabe() throws Exception { - final String TEST_NAME = "test541JackModifyEmployeeTypeWannabe"; + public void test542JackModifyEmployeeTypeWannabe() throws Exception { + final String TEST_NAME = "test542JackModifyEmployeeTypeWannabe"; TestUtil.displayTestTile(this, TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -1095,6 +1121,86 @@ public void test541JackModifyEmployeeTypeWannabe() throws Exception { assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME, "title", "Wannabe Cpt. Where's the rum?"); } + /** + * Remove honorifixPrefix. This triggers a condition in Wannabe role and should remove an account. + */ + @Test + public void test543JackRemoveHonorificPrefixWannabe() throws Exception { + final String TEST_NAME = "test543JackRemoveHonorificPrefixWannabe"; + TestUtil.displayTestTile(this, TEST_NAME); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_PREFIX, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result); + assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME); + } + + /** + * Set honorifixSuffix. This triggers conditions and adds a sub-role Honorable Wannabe. + */ + @Test + public void test544JackSetHonorificSuffixWannabe() throws Exception { + final String TEST_NAME = "test544JackSetHonorificSuffixWannabe"; + TestUtil.displayTestTile(this, TEST_NAME); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_SUFFIX, task, result, + PrismTestUtil.createPolyString("PhD.")); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result); + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_QUOTE_NAME, "Arr!", "Whatever. -- jack"); + } + + /** + * Restore honorifixPrefix. The title should be replaced again. + */ + @Test + public void test545JackRestoreHonorificPrefixWannabe() throws Exception { + final String TEST_NAME = "test545JackRestoreHonorificPrefixWannabe"; + TestUtil.displayTestTile(this, TEST_NAME); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); + + Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + modifyUserReplace(USER_JACK_OID, UserType.F_HONORIFIC_PREFIX, task, result, + PrismTestUtil.createPolyString("captain")); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertAssignedRole(USER_JACK_OID, ROLE_WANNABE_OID, task, result); + assertDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); + assertDefaultDummyAccountAttribute(ACCOUNT_JACK_DUMMY_USERNAME, "title", "Wannabe captain Where's the rum?"); + } + /** * The account should be gone - regardless of the condition state. */ diff --git a/model/model-intest/src/test/resources/common/user-jack.xml b/model/model-intest/src/test/resources/common/user-jack.xml index c119dd1822c..c12293c02cd 100644 --- a/model/model-intest/src/test/resources/common/user-jack.xml +++ b/model/model-intest/src/test/resources/common/user-jack.xml @@ -1,6 +1,6 @@