diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/Clock.java b/infra/common/src/main/java/com/evolveum/midpoint/common/Clock.java index e90cf1c27f0..bc0579e90ac 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/Clock.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/Clock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Evolveum + * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,13 +37,19 @@ public class Clock { private static final Trace LOGGER = TraceManager.getTrace(Clock.class); private Long override = null; - // TODO: more sophisticated functions + private Long overrideOffset = null; public long currentTimeMillis() { - if (override != null) { - return override; + long time; + if (override == null) { + time = System.currentTimeMillis(); + } else { + time = override; } - return System.currentTimeMillis(); + if (overrideOffset != null) { + time = time + overrideOffset; + } + return time; } public XMLGregorianCalendar currentTimeXMLGregorianCalendar() { @@ -80,19 +86,43 @@ public void override(XMLGregorianCalendar overrideTimestamp) { override(XmlTypeConverter.toMillis(overrideTimestamp)); } + /** + * Extends offset on top of existing offset. + */ public void overrideDuration(String durationString) { overrideDuration(XmlTypeConverter.createDuration(durationString)); } + /** + * Extends offset on top of existing offset. + */ public void overrideDuration(Duration duration) { - XMLGregorianCalendar time = currentTimeXMLGregorianCalendar(); + long millis = currentTimeMillis(); + XMLGregorianCalendar time = XmlTypeConverter.createXMLGregorianCalendar(millis); time.add(duration); - override(time); + long offset = XmlTypeConverter.toMillis(time) - millis; + overrideDuration(offset); + } + + /** + * Extends offset on top of existing offset. + */ + public void overrideDuration(Long offsetMillis) { + if (overrideOffset == null) { + overrideOffset = offsetMillis; + } else { + overrideOffset = overrideOffset + offsetMillis; + } + } + + public void overrideOffset(Long offsetMillis) { + this.overrideOffset = offsetMillis; } public void resetOverride() { LOGGER.info("Clock override reset"); this.override = null; + this.overrideOffset = null; if (LOGGER.isDebugEnabled()) { LOGGER.debug("Clock current time: {}", currentTimeXMLGregorianCalendar()); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java index eac837d965b..b3d8f436e42 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/ItemDelta.java @@ -1293,7 +1293,7 @@ public static void applyTo(Collection deltas, PrismContaine delta.applyTo(propertyContainerValue); } } - + public static void applyToMatchingPath(Collection deltas, PrismContainer propertyContainer) throws SchemaException { for (ItemDelta delta : deltas) { diff --git a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/PolyStringType.java b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/PolyStringType.java index 26106c9baa9..2ee74aedbb2 100644 --- a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/PolyStringType.java +++ b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/PolyStringType.java @@ -494,7 +494,7 @@ private static JAXBElement copyOfStringElement(final JAXBElement public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((any == null) ? 0 : any.hashCode()); + result = prime * result + ((any == null || any.isEmpty()) ? 0 : any.hashCode()); result = prime * result + ((norm == null) ? 0 : norm.hashCode()); result = prime * result + ((orig == null) ? 0 : orig.hashCode()); return result; 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 b2ad079a93c..e6f6d19fef8 100644 --- 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 @@ -923,6 +923,30 @@ + + + +

+ The timestamp last provisioning operation that was based on this object. + E.g. the timestamp of last modificaiton od any account based on the + data from the user. This valus is only updated if there was any + real change in the resource. +

+

+ This meta-datum is used as an informational property that tells when + the data were last synchronized in outbound direction. But it has another + imporatant role. It is used indirectly to trigger optimistic locking + conflicts that are used to detect a "clean" recompute (i.e. recompute + that is processing data without any outside interaction). +

+
+ + true + 3.6.1 + +
+
+ + + + TODO + EXPERIMENTAL. + + + 3.7 + true + + + + + + + TODO + + + + + + + Number of tasks within the group that can be executed at once (clusterwide). Default is "unlimited". + This parameter will be moved into separate task group object in a later version of midPoint. + + + + + + @@ -11825,6 +11887,7 @@ 3.6.1 + true @@ -11839,6 +11902,7 @@ 3.6.1 + true @@ -11877,6 +11941,7 @@ 3.6.1 + true @@ -11900,6 +11965,28 @@ + + + + Operation should be end with an error. + This is a recoverable error (precondition failed). + TODO: align with "fail" + + + + + + + + + + Operation should be restarted. + + + + + + @@ -11910,11 +11997,23 @@ + + + + The focus object should be recomputed and all projections reconciled. + + + + + + The whole operation should fail. This is to be used mainly for testing purposes, to check if conflict detection algorithm does not yield false positive results. + This fails with a system error. This is a definitive, non-recoverable fauilure. + TODO: align with "error" @@ -14353,6 +14452,21 @@ + + + + A method to resolve conflicts on focus objects. This specifies how will the + processors handle optimistic locking conflicts - and whether they even try + to detect them. The default value is null, which means that there is no reaction + to conflicts and that the conflicts are not even detected. + Note that different default conflict resolution may be specified in system configuration. + + + 3.6.1 + true + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd index 6a3dd601cea..9a5c77e35f5 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd @@ -635,12 +635,92 @@ + + + + TODO + EXPERIMENTAL + + + true + 3.6.1 + + + - + + + + TODO + EXPERIMENTAL + + + true + 3.6.1 + + + + + + + TODO + + + + + + + TODO + + + 3.7 + + + + + + + + + + TODO + EXPERIMENTAL + + + true + 3.6.1 + + + + + + + Whether this feature is enabled. Default is true if "serialization" element is present; false otherwise. + + + + + + + Interval after which the execution task is to be rescheduled in case of conflict. Default is 10 seconds. + + + + + + + TODO + + + + + + + How to deal with legacy approvers specifications, i.e. approvalRef, approvalExpression, approvalSchema, diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java index fe27db9d7e5..7e22e8ace5a 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/util/SchemaTestUtil.java @@ -101,7 +101,7 @@ public static void assertFocusDefinition(ComplexTypeDefinition complexTypeDefini assertFalse("Metadata is runtime", metadataContainer.isRuntimeSchema()); assertFalse("Metadata is dynamic", metadataContainer.isDynamic()); assertTrue("Metadata is NOT operational", metadataContainer.isOperational()); - assertEquals("Metadata size", 12, metadataContainer.getDefinitions().size()); + assertEquals("Metadata size", 13, metadataContainer.getDefinitions().size()); PrismReferenceDefinition tenantRefDef = complexTypeDefinition.findItemDefinition(UserType.F_TENANT_REF, PrismReferenceDefinition.class); PrismAsserts.assertDefinition(tenantRefDef, UserType.F_TENANT_REF, ObjectReferenceType.COMPLEX_TYPE, 0, 1); diff --git a/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/TestUtil.java b/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/TestUtil.java index f7878dde525..30f57ccf20a 100644 --- a/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/TestUtil.java +++ b/infra/test-util/src/main/java/com/evolveum/midpoint/test/util/TestUtil.java @@ -198,6 +198,11 @@ public static void displayCleanup(String testName) { System.out.println(TEST_OUT_SECTION_PREFIX + " CLEANUP " + testName + TEST_OUT_SECTION_SUFFIX); LOGGER.info(TEST_LOG_SECTION_PREFIX + " CLEANUP " + testName + TEST_LOG_SECTION_SUFFIX); } + + public static void displaySkip(String testName) { + System.out.println(TEST_OUT_SECTION_PREFIX + " SKIP " + testName + TEST_OUT_SECTION_SUFFIX); + LOGGER.info(TEST_LOG_SECTION_PREFIX + " SKIP " + testName + TEST_LOG_SECTION_SUFFIX); + } public static void info(String message) { System.out.println(TEST_OUT_SECTION_PREFIX + message + TEST_OUT_SECTION_SUFFIX); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java index 07c46f4990a..60e09c95b19 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java @@ -17,6 +17,7 @@ import com.evolveum.midpoint.schema.AbstractOptions; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConflictResolutionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationBusinessContextType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingOptionsType; @@ -134,6 +135,18 @@ public class ModelExecuteOptions extends AbstractOptions implements Serializable * this option only if there is reasonable assumption that the request will stop after INITIAL phase. */ private PartialProcessingOptionsType initialPartialProcessing; + + /** + * A method to resolve conflicts on focus objects. This specifies how will the processors handle + * optimistic locking conflicts - and whether they even try to detect them. The default value is + * null, which means that there is no reaction to conflicts and that the conflicts are not even + * detected. + * + * Note that different default conflict resolution may be specified in system configuration. + * + * EXPERIMENTAL + */ + private ConflictResolutionType focusConflictResolution; public Boolean getForce() { return force; @@ -536,6 +549,28 @@ public static ModelExecuteOptions createInitialPartialProcessing(PartialProcessi return opts; } + public ConflictResolutionType getFocusConflictResolution() { + return focusConflictResolution; + } + + public void setFocusConflictResolution(ConflictResolutionType focusConflictResolution) { + this.focusConflictResolution = focusConflictResolution; + } + + public static ConflictResolutionType getFocusConflictResolution(ModelExecuteOptions options) { + if (options == null) { + return null; + } + return options.getFocusConflictResolution(); + } + + public static ModelExecuteOptions createFocusConflictResolution(ConflictResolutionType focusConflictResolution) { + ModelExecuteOptions opts = new ModelExecuteOptions(); + opts.setFocusConflictResolution(focusConflictResolution); + return opts; + } + + public ModelExecuteOptionsType toModelExecutionOptionsType() { ModelExecuteOptionsType retval = new ModelExecuteOptionsType(); retval.setForce(force); @@ -551,6 +586,7 @@ public ModelExecuteOptionsType toModelExecutionOptionsType() { // preAuthorized is purposefully omitted (security reasons) retval.setRequestBusinessContext(requestBusinessContext); retval.setPartialProcessing(partialProcessing); + retval.setFocusConflictResolution(focusConflictResolution); return retval; } @@ -572,6 +608,7 @@ public static ModelExecuteOptions fromModelExecutionOptionsType(ModelExecuteOpti // preAuthorized is purposefully omitted (security reasons) retval.setRequestBusinessContext(type.getRequestBusinessContext()); retval.setPartialProcessing(type.getPartialProcessing()); + retval.setFocusConflictResolution(type.getFocusConflictResolution()); return retval; } @@ -633,6 +670,7 @@ public String toString() { appendFlag(sb, "requestBusinessContext", requestBusinessContext == null ? null : true); appendVal(sb, "partialProcessing", format(partialProcessing)); appendVal(sb, "initialPartialProcessing", format(initialPartialProcessing)); + appendVal(sb, "focusConflictResolution", focusConflictResolution); removeLastComma(sb); sb.append(")"); return sb.toString(); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java index fdc62bf87d3..be3b7eefd8e 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/AssociationFromLinkExpressionEvaluator.java @@ -164,8 +164,9 @@ private void gatherAssociationsFromAbstractRoleRecurse(OrgType thisOrg, private boolean matchesForRecursion(OrgType thisOrg) { for (String recurseUpOrgType: evaluatorType.getRecurseUpOrgType()) { - thisOrg.getOrgType().contains(recurseUpOrgType); - return true; + if (thisOrg.getOrgType().contains(recurseUpOrgType)) { + return true; + } } return false; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java index a6852844d57..2d91b474444 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelController.java @@ -47,6 +47,7 @@ import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.repo.cache.RepositoryCache; @@ -604,6 +605,15 @@ public Collection> executeChanges(fin CommunicationException|ConfigurationException|PolicyViolationException|SecurityViolationException|RuntimeException e) { ModelUtils.recordFatalError(result, e); throw e; + + } catch (PreconditionViolationException e) { + ModelUtils.recordFatalError(result, e); + // TODO: Temporary fix for 3.6.1 + // We do not want to propagate PreconditionViolationException to model API as that might break compatiblity + // ... and we do not really need that in 3.6.1 + // TODO: expose PreconditionViolationException in 3.7 + throw new SystemException(e); + } finally { task.markObjectActionExecutedBoundary(); } @@ -720,33 +730,20 @@ public void recompute(Class type, String oid, ModelExe result.cleanupResult(); - } catch (ExpressionEvaluationException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (SchemaException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (PolicyViolationException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (ObjectNotFoundException e) { + } catch (ExpressionEvaluationException | SchemaException | PolicyViolationException | ObjectNotFoundException | + ObjectAlreadyExistsException | CommunicationException | ConfigurationException | SecurityViolationException | + RuntimeException | Error e) { ModelUtils.recordFatalError(result, e); throw e; - } catch (ObjectAlreadyExistsException e) { + + } catch (PreconditionViolationException e) { ModelUtils.recordFatalError(result, e); - throw e; - } catch (CommunicationException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (ConfigurationException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (SecurityViolationException e) { - ModelUtils.recordFatalError(result, e); - throw e; - } catch (RuntimeException e) { - ModelUtils.recordFatalError(result, e); - throw e; + // TODO: Temporary fix for 3.6.1 + // We do not want to propagate PreconditionViolationException to model API as that might break compatiblity + // ... and we do not really need that in 3.6.1 + // TODO: expose PreconditionViolationException in 3.7 + throw new SystemException(e); + } finally { RepositoryCache.exit(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java index 8f90e6d3580..d9613f16c32 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java @@ -87,6 +87,7 @@ import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.query.TypeFilter; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; @@ -195,6 +196,15 @@ public ModelContext previewChanges( ExpressionEvaluationException e) { ModelUtils.recordFatalError(result, e); throw e; + + } catch (PreconditionViolationException e) { + ModelUtils.recordFatalError(result, e); + // TODO: Temporary fix for 3.6.1 + // We do not want to propagate PreconditionViolationException to model API as that might break compatiblity + // ... and we do not really need that in 3.6.1 + // TODO: expose PreconditionViolationException in 3.7 + throw new SystemException(e); + } finally { RepositoryCache.exit(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelOperationTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelOperationTaskHandler.java index 5a3c795beb6..7fb45b0d3a6 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelOperationTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelOperationTaskHandler.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskCategory; @@ -122,7 +123,7 @@ public TaskRunResult run(Task task) { result.computeStatus(); } runResult.setRunResultStatus(TaskRunResult.TaskRunResultStatus.FINISHED); - } catch (RuntimeException|CommonException e) { + } catch (CommonException | PreconditionViolationException | RuntimeException | Error e) { String message = "An exception occurred within model operation, in task " + task; LoggingUtils.logUnexpectedException(LOGGER, message, e); result.recordPartialError(message, e); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index a2e651d32b8..1bbf8b47789 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyStateRecorder; import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.repo.api.ConflictWatcher; +import com.evolveum.midpoint.repo.api.ModificationPrecondition; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.common.expression.Expression; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; @@ -49,7 +51,9 @@ import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions; import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.repo.api.RepoAddOptions; +import com.evolveum.midpoint.repo.api.RepoModifyOptions; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.api.VersionPrecondition; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.PointInTimeType; @@ -88,6 +92,7 @@ import javax.annotation.PostConstruct; import javax.xml.bind.JAXBElement; +import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; /** @@ -134,7 +139,7 @@ private void locateDefinitions() { public boolean executeChanges(LensContext context, Task task, OperationResult parentResult) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, - SecurityViolationException, ExpressionEvaluationException { + SecurityViolationException, ExpressionEvaluationException, PreconditionViolationException { OperationResult result = parentResult.createSubresult(OPERATION_EXECUTE); @@ -149,7 +154,13 @@ public boolean executeChanges(LensContext context, Tas focusDelta = applyPendingObjectPolicyStateModifications(focusContext, focusDelta); focusDelta = applyPendingAssignmentPolicyStateModifications(focusContext, focusDelta); - if (focusDelta != null) { + if (focusDelta == null && !context.hasProjectionChange()) { + LOGGER.trace("Skipping focus change execute, because user delta is null"); + } else { + + if (focusDelta == null) { + focusDelta = focusContext.getObjectAny().createModifyDelta(); + } ObjectPolicyConfigurationType objectPolicyConfigurationType = focusContext .getObjectPolicyConfigurationType(); @@ -166,9 +177,17 @@ public boolean executeChanges(LensContext context, Tas result.computeStatus(); throw new SystemException(e.getMessage(), e); } + + applyLastProvisioningTimestamp(context, focusDelta); + try { + context.reportProgress(new ProgressInformation(FOCUS_OPERATION, ENTERING)); - executeDelta(focusDelta, focusContext, context, null, null, task, subResult); + + ConflictResolutionType conflictResolution = ModelExecuteOptions.getFocusConflictResolution(context.getOptions()); + + executeDelta(focusDelta, focusContext, context, null, conflictResolution, null, task, subResult); + if (focusDelta.isAdd() && focusDelta.getOid() != null) { ConflictWatcher watcher = context.createAndRegisterConflictWatcher(focusDelta.getOid(), cacheRepositoryService); watcher.setExpectedVersion(focusDelta.getObjectToAdd().getVersion()); @@ -178,6 +197,16 @@ public boolean executeChanges(LensContext context, Tas } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException | RuntimeException e) { recordFatalError(subResult, result, null, e); throw e; + + } catch (PreconditionViolationException e) { + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Modification precondition failed for {}: {}", focusContext.getHumanReadableName(), e.getMessage()); + } +// TODO: fatal error if the conflict resolution is "error" (later) + result.recordHandledError(e); + throw e; + } catch (ObjectAlreadyExistsException e) { subResult.computeStatus(); if (!subResult.isSuccess() && !subResult.isHandledError()) { @@ -188,8 +217,6 @@ public boolean executeChanges(LensContext context, Tas } finally { context.reportProgress(new ProgressInformation(FOCUS_OPERATION, subResult)); } - } else { - LOGGER.trace("Skipping focus change execute, because user delta is null"); } } @@ -207,7 +234,7 @@ public boolean executeChanges(LensContext context, Tas if (!projCtx.isCanProject()) { continue; } - + // we should not get here, but just to be sure if (projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.IGNORE) { LOGGER.trace("Skipping ignored projection context {}", projCtx.toHumanReadableString()); @@ -249,7 +276,7 @@ public boolean executeChanges(LensContext context, Tas } if (projDelta != null && projDelta.isDelete()) { - executeDelta(projDelta, projCtx, context, null, projCtx.getResource(), task, + executeDelta(projDelta, projCtx, context, null, null, projCtx.getResource(), task, subResult); } @@ -271,7 +298,7 @@ public boolean executeChanges(LensContext context, Tas subResult.computeStatus(); subResult.recordNotApplicableIfUnknown(); continue; - + } else if (projDelta.isDelete() && projCtx.getResourceShadowDiscriminator() != null && projCtx.getResourceShadowDiscriminator().getOrder() > 0) { // HACK ... for higher-order context check if this was @@ -285,7 +312,7 @@ public boolean executeChanges(LensContext context, Tas } } - executeDelta(projDelta, projCtx, context, null, projCtx.getResource(), task, subResult); + executeDelta(projDelta, projCtx, context, null, null, projCtx.getResource(), task, subResult); } @@ -299,14 +326,11 @@ public boolean executeChanges(LensContext context, Tas subResult.computeStatus(); subResult.recordNotApplicableIfUnknown(); - } catch (SchemaException e) { - recordProjectionExecutionException(e, projCtx, subResult, - SynchronizationPolicyDecision.BROKEN); - continue; - } catch (ObjectNotFoundException e) { + } catch (SchemaException | ObjectNotFoundException | PreconditionViolationException e) { recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN); continue; + } catch (ObjectAlreadyExistsException e) { // check if this is a repeated attempt - OAEE was not handled @@ -333,26 +357,12 @@ public boolean executeChanges(LensContext context, Tas restartRequested = true; break; // we will process remaining projections when retrying // the wave - } catch (CommunicationException e) { - recordProjectionExecutionException(e, projCtx, subResult, - SynchronizationPolicyDecision.BROKEN); - continue; - } catch (ConfigurationException e) { - recordProjectionExecutionException(e, projCtx, subResult, - SynchronizationPolicyDecision.BROKEN); - continue; - } catch (SecurityViolationException e) { - recordProjectionExecutionException(e, projCtx, subResult, - SynchronizationPolicyDecision.BROKEN); - continue; - } catch (ExpressionEvaluationException e) { - recordProjectionExecutionException(e, projCtx, subResult, - SynchronizationPolicyDecision.BROKEN); - continue; - } catch (RuntimeException e) { + + } catch (CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | Error e) { recordProjectionExecutionException(e, projCtx, subResult, SynchronizationPolicyDecision.BROKEN); continue; + } finally { context.reportProgress(new ProgressInformation(RESOURCE_OBJECT_OPERATION, projCtx.getResourceShadowDiscriminator(), subResult)); @@ -445,6 +455,27 @@ private void swallowIntoValues(Collection assignments, Assignmen // TODO change to warning throw new IllegalStateException("We have 'plus' assignment to modify but it couldn't be found in assignment delta. Assignment=" + assignmentToFind + ", new assignments=" + assignments); } + + private void applyLastProvisioningTimestamp(LensContext context, ObjectDelta focusDelta) throws SchemaException { + if (!context.hasProjectionChange()) { + return; + } + if (focusDelta.isAdd()) { + + PrismObject objectToAdd = focusDelta.getObjectToAdd(); + PrismContainer metadataContainer = objectToAdd.findOrCreateContainer(ObjectType.F_METADATA); + metadataContainer.getValue().asContainerable().setLastProvisioningTimestamp(clock.currentTimeXMLGregorianCalendar()); + + } else if (focusDelta.isModify()) { + + PropertyDelta provTimestampDelta = PropertyDelta.createModificationReplaceProperty( + new ItemPath(ObjectType.F_METADATA, MetadataType.F_LAST_PROVISIONING_TIMESTAMP), + context.getFocusContext().getObjectDefinition(), + clock.currentTimeXMLGregorianCalendar()); + focusDelta.addModification(provTimestampDelta); + + } + } private boolean shouldBeDeleted(ObjectDelta accDelta, LensProjectionContext accCtx) { return (accDelta == null || accDelta.isEmpty()) @@ -525,7 +556,7 @@ private void applyObjectPolicy(LensFocusContext focusC } } - private

void recordProjectionExecutionException(Exception e, + private

void recordProjectionExecutionException(Throwable e, LensProjectionContext accCtx, OperationResult subResult, SynchronizationPolicyDecision decision) { subResult.recordFatalError(e); LOGGER.error("Error executing changes for {}: {}", @@ -589,7 +620,7 @@ private void updateLinks( // Already linked, nothing to do, only be sure, the // situation is set with the good value LOGGER.trace("Updating situation in already linked shadow."); - updateSituationInShadow(task, SynchronizationSituationType.LINKED, focusObjectContext, + updateSituationInShadow(task, SynchronizationSituationType.LINKED, null, focusObjectContext, projCtx, result); return; } @@ -599,7 +630,7 @@ private void updateLinks( linkShadow(focusContext.getOid(), projOid, focusObjectContext, projCtx, task, result); // be sure, that the situation is set correctly LOGGER.trace("Updating situation after shadow was linked."); - updateSituationInShadow(task, SynchronizationSituationType.LINKED, focusObjectContext, projCtx, + updateSituationInShadow(task, SynchronizationSituationType.LINKED, null, focusObjectContext, projCtx, result); } else { // Link should NOT exist @@ -626,7 +657,7 @@ private void updateLinks( LOGGER.trace("Resource object {} deleted, updating also situation in shadow.", projOid); // HACK HACK? try { - updateSituationInShadow(task, SynchronizationSituationType.DELETED, focusObjectContext, + updateSituationInShadow(task, SynchronizationSituationType.DELETED, true, focusObjectContext, projCtx, result); } catch (ObjectNotFoundException e) { // HACK HACK? @@ -640,7 +671,7 @@ private void updateLinks( // situation here. Reflect that in the shadow. LOGGER.trace("Resource object {} unlinked from the user, updating also situation in shadow.", projOid); - updateSituationInShadow(task, null, focusObjectContext, projCtx, result); + updateSituationInShadow(task, null, null, focusObjectContext, projCtx, result); } // Not linked, that's OK } @@ -765,7 +796,7 @@ private void unlinkShadow(String focusOid, PrismReference } private void updateSituationInShadow(Task task, - SynchronizationSituationType situation, LensFocusContext focusContext, + SynchronizationSituationType situation, Boolean dead, LensFocusContext focusContext, LensProjectionContext projectionCtx, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { @@ -788,6 +819,11 @@ private void updateSituationInShadow(Task task, List> syncSituationDeltas = SynchronizationUtils .createSynchronizationSituationAndDescriptionDelta(account, situation, task.getChannel(), projectionCtx.hasFullShadow()); + + if (dead != null) { + PropertyDelta deadDelta = PropertyDelta.createModificationReplaceProperty(ShadowType.F_DEAD, account.getDefinition(), dead); + syncSituationDeltas.add(deadDelta); + } try { Utils.setRequestee(task, focusContext); @@ -823,10 +859,10 @@ private void updateSituationInShadow(Task task, private void executeDelta(ObjectDelta objectDelta, LensElementContext objectContext, LensContext context, ModelExecuteOptions options, - ResourceType resource, Task task, OperationResult parentResult) + ConflictResolutionType conflictResolution, ResourceType resource, Task task, OperationResult parentResult) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, - ExpressionEvaluationException { + ExpressionEvaluationException, PreconditionViolationException { if (objectDelta == null) { throw new IllegalArgumentException("Null change"); @@ -870,7 +906,7 @@ private void executeDelta(ObjectDel if (objectDelta.getChangeType() == ChangeType.ADD) { executeAddition(objectDelta, context, objectContext, options, resource, task, result); } else if (objectDelta.getChangeType() == ChangeType.MODIFY) { - executeModification(objectDelta, context, objectContext, options, resource, task, result); + executeModification(objectDelta, context, objectContext, options, conflictResolution, resource, task, result); } else if (objectDelta.getChangeType() == ChangeType.DELETE) { executeDeletion(objectDelta, context, objectContext, options, resource, task, result); } @@ -1303,48 +1339,58 @@ private void executeDeletion(Object } } - private void executeModification(ObjectDelta change, - LensContext context, LensElementContext objectContext, ModelExecuteOptions options, - ResourceType resource, Task task, OperationResult result) throws ObjectNotFoundException, - SchemaException, ObjectAlreadyExistsException, CommunicationException, - ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - Class objectTypeClass = change.getObjectTypeClass(); + private void executeModification(ObjectDelta delta, + LensContext context, LensElementContext objectContext, ModelExecuteOptions options, + ConflictResolutionType conflictResolution, ResourceType resource, Task task, OperationResult result) + throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, CommunicationException, + ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PreconditionViolationException { + Class objectTypeClass = delta.getObjectTypeClass(); PrismObject objectNew = objectContext.getObjectNew(); OwnerResolver ownerResolver = createOwnerResolver(context, task, result); try { securityEnforcer.authorize(ModelAuthorizationAction.MODIFY.getUrl(), - AuthorizationPhaseType.EXECUTION, objectNew, change, null, ownerResolver, result); + AuthorizationPhaseType.EXECUTION, objectNew, delta, null, ownerResolver, result); - metadataManager.applyMetadataModify(change, objectContext, objectTypeClass, + metadataManager.applyMetadataModify(delta, objectContext, objectTypeClass, clock.currentTimeXMLGregorianCalendar(), task, context, result); - if (change.isEmpty()) { + if (delta.isEmpty()) { // Nothing to do return; } if (TaskType.class.isAssignableFrom(objectTypeClass)) { - taskManager.modifyTask(change.getOid(), change.getModifications(), result); + taskManager.modifyTask(delta.getOid(), delta.getModifications(), result); } else if (NodeType.class.isAssignableFrom(objectTypeClass)) { throw new UnsupportedOperationException("NodeType is not modifiable using model interface"); } else if (ObjectTypes.isClassManagedByProvisioning(objectTypeClass)) { ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options); - String oid = modifyProvisioningObject(objectTypeClass, change.getOid(), - change.getModifications(), context, objectContext, provisioningOptions, resource, + String oid = modifyProvisioningObject(objectTypeClass, delta.getOid(), + delta.getModifications(), context, objectContext, provisioningOptions, resource, task, result); - if (!oid.equals(change.getOid())) { - change.setOid(oid); + if (!oid.equals(delta.getOid())) { + delta.setOid(oid); } } else { - FocusConstraintsChecker.clearCacheForDelta(change.getModifications()); - cacheRepositoryService.modifyObject(objectTypeClass, change.getOid(), - change.getModifications(), result); + FocusConstraintsChecker.clearCacheForDelta(delta.getModifications()); + ModificationPrecondition precondition = null; + if (conflictResolution != null) { + String readVersion = objectContext.getObjectReadVersion(); + if (readVersion != null) { + LOGGER.trace("Modification with precondition, readVersion={}", readVersion); + precondition = new VersionPrecondition<>(readVersion); + } else { + LOGGER.warn("Requested careful modification of {}, but there is no read version", objectContext.getHumanReadableName()); + } + } + cacheRepositoryService.modifyObject(objectTypeClass, delta.getOid(), + delta.getModifications(), precondition, null, result); } - task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, + task.recordObjectActionExecuted(objectNew, objectTypeClass, delta.getOid(), ChangeType.MODIFY, context.getChannel(), null); } catch (Throwable t) { - task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, + task.recordObjectActionExecuted(objectNew, objectTypeClass, delta.getOid(), ChangeType.MODIFY, context.getChannel(), t); throw t; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java index 0c17da9269e..235badf8f46 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/Clockwork.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.common.Clock; import com.evolveum.midpoint.model.api.ProgressInformation; import com.evolveum.midpoint.repo.api.ConflictWatcher; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; import com.evolveum.midpoint.model.api.ModelAuthorizationAction; import com.evolveum.midpoint.model.api.ModelExecuteOptions; @@ -121,6 +122,7 @@ public class Clockwork { private static final int DEFAULT_MAX_CONFLICT_RESOLUTION_ATTEMPTS = 1; // synchronize with common-core-3.xsd private static final int DEFAULT_CONFLICT_RESOLUTION_DELAY_UNIT = 5000; // synchronize with common-core-3.xsd + private static final int MAX_PRECONDITION_CONFLICT_RESOLUTION_ATTEMPTS = 3; private static final Trace LOGGER = TraceManager.getTrace(Clockwork.class); @@ -162,7 +164,9 @@ public void setDebugListener(LensDebugListener debugListener) { private static final int DEFAULT_MAX_CLICKS = 200; - public HookOperationMode run(LensContext context, Task task, OperationResult result) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + public HookOperationMode run(LensContext context, Task task, OperationResult result) + throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { LOGGER.trace("Running clockwork for context {}", context); if (InternalsConfig.consistencyChecks) { context.checkConsistence(); @@ -240,6 +244,7 @@ private HookOperationMode resolveFocusConflict(LensContex return HookOperationMode.FOREGROUND; } PrismObject focusObject = context.getFocusContext() != null ? context.getFocusContext().getObjectAny() : null; + ModelExecuteOptions options = new ModelExecuteOptions(); switch (resolutionPolicy.getAction()) { case FAIL: throw new SystemException("Conflict detected while updating " + focusObject); case LOG: @@ -247,11 +252,15 @@ private HookOperationMode resolveFocusConflict(LensContex return HookOperationMode.FOREGROUND; case RECOMPUTE: break; + case RECONCILE: + options.setReconcile(); + break; default: throw new IllegalStateException("Unsupported conflict resolution action: " + resolutionPolicy.getAction()); } // so, recompute is the action + LOGGER.debug("CONFLICT: Conflict detected while updating {}, recomputing (options={})", focusObject, options); if (context.getFocusContext() == null) { LOGGER.warn("No focus context, not possible to resolve conflict by focus recomputation"); // should really never occur @@ -274,35 +283,71 @@ private HookOperationMode resolveFocusConflict(LensContex LOGGER.warn("Focus is not of FocusType (it is {}); not possible to resolve conflict by focus recomputation", focusClass.getName()); return HookOperationMode.FOREGROUND; } - - PrismObject focus = repositoryService.getObject(focusClass, oid, null, result); - LensContext contextNew = contextFactory.createRecomputeContext(focus, null, task, result); - contextNew.setProgressListeners(new ArrayList<>(emptyIfNull(context.getProgressListeners()))); - int attemptOld = context.getConflictResolutionAttemptNumber(); - int attemptNew = attemptOld + 1; - boolean shouldExecuteAttempt = shouldExecuteAttempt(resolutionPolicy, attemptNew, context); - if (shouldExecuteAttempt) { + + ConflictResolutionType focusConflictResolution = new ConflictResolutionType(); + focusConflictResolution.setAction(ConflictResolutionActionType.ERROR); + options.setFocusConflictResolution(focusConflictResolution); + + int preconditionAttempts = 0; + while (true) { + + int attemptOld = context.getConflictResolutionAttemptNumber(); + int attemptNew = attemptOld + 1; + boolean shouldExecuteAttempt = shouldExecuteAttempt(context, resolutionPolicy, attemptNew); + if (!shouldExecuteAttempt) { + LOGGER.warn("CONFLICT: Couldn't resolve conflict even after {} resolution attempt(s), giving up.", attemptOld); + return HookOperationMode.FOREGROUND; + } + + delay(context, resolutionPolicy, attemptNew + preconditionAttempts); + + PrismObject focus = repositoryService.getObject(focusClass, oid, null, result); + LensContext contextNew = contextFactory.createRecomputeContext(focus, options, task, result); + contextNew.setProgressListeners(new ArrayList<>(emptyIfNull(context.getProgressListeners()))); contextNew.setConflictResolutionAttemptNumber(attemptNew); - // this is a recursion; but limited to max attempts which should not be a large number - return run(contextNew, task, result); - } else { - LOGGER.warn("Couldn't resolve conflict even after {} resolution attempt(s), giving up.", attemptOld); - return HookOperationMode.FOREGROUND; + + LOGGER.debug("CONFLICT: Recomputing {} as reaction to conflict (options={}, attempts={},{}, readVersion={})", + context.getFocusContext().getHumanReadableName(), options, attemptNew, preconditionAttempts, contextNew.getFocusContext().getObjectReadVersion()); + + try { + + // this is a recursion; but limited to max attempts which should not be a large number + HookOperationMode hookOperationMode = run(contextNew, task, result); + + // This may be in fact a giveup after recompute that was not able to cleanly proceed. + LOGGER.debug("CONFLICT: Clean recompute (or giveup) of {} achieved (options={}, attempts={},{})", + context.getFocusContext().getHumanReadableName(), options, attemptNew, preconditionAttempts); + + return hookOperationMode; + + } catch (PreconditionViolationException e) { + preconditionAttempts++; + LOGGER.debug("CONFLICT: Recompute precondition failed (attempt {}, precondition attempt {}), trying again", attemptNew, preconditionAttempts); + if (preconditionAttempts < MAX_PRECONDITION_CONFLICT_RESOLUTION_ATTEMPTS) { + continue; + } + LOGGER.warn("CONFLICT: Couldn't resolve conflict even after {} resolution attempt(s) and {} precondition attempts, giving up.", + attemptOld, preconditionAttempts); + return HookOperationMode.FOREGROUND; + } } } - private boolean shouldExecuteAttempt(@NotNull ConflictResolutionType resolutionPolicy, int attemptNew, - LensContext context) { + private boolean shouldExecuteAttempt(LensContext context, @NotNull ConflictResolutionType resolutionPolicy, int attemptNew) { int maxAttempts = defaultIfNull(resolutionPolicy.getMaxAttempts(), DEFAULT_MAX_CONFLICT_RESOLUTION_ATTEMPTS); if (attemptNew > maxAttempts) { return false; } + return true; + } + + private void delay(LensContext context, @NotNull ConflictResolutionType resolutionPolicy, int attempts) { long delayUnit = defaultIfNull(resolutionPolicy.getDelayUnit(), DEFAULT_CONFLICT_RESOLUTION_DELAY_UNIT); - for (int i = 0; i < attemptNew; i++) { + for (int i = 0; i < attempts; i++) { delayUnit *= 2; } long delay = (long) (Math.random() * delayUnit); - String message = "Waiting "+delay+" milliseconds before starting conflict resolution attempt "+attemptNew+" of "+maxAttempts; + String message = "CONFLICT: Waiting "+delay+" milliseconds before starting conflict resolution (delay exponent: "+attempts+")"; // TODO convey information about waiting time after some GUI mechanism for displaying it is available // (showing text messages is currently really ugly) context.reportProgress(new ProgressInformation(WAITING, EXITING)); @@ -313,7 +358,6 @@ private boolean shouldExecuteAttempt(@NotNull ConflictRes // ignore } context.reportProgress(new ProgressInformation(WAITING, EXITING)); - return true; } private void enterAssociationSearchExpressionEvaluatorCache() { @@ -347,7 +391,9 @@ private int getMaxClicks(LensContext context, Operatio } } - public HookOperationMode click(LensContext context, Task task, OperationResult result) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + public HookOperationMode click(LensContext context, Task task, OperationResult result) + throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { // DO NOT CHECK CONSISTENCY of the context here. The context may not be fresh and consistent yet. Project will fix // that. Check consistency afterwards (and it is also checked inside projector several times). @@ -440,7 +486,7 @@ public HookOperationMode click(LensContext context, Ta } catch (CommunicationException | ConfigurationException | ExpressionEvaluationException | ObjectNotFoundException | PolicyViolationException | SchemaException | SecurityViolationException | RuntimeException | - ObjectAlreadyExistsException e) { + ObjectAlreadyExistsException | PreconditionViolationException e) { processClockworkException(context, e, task, result); throw e; } @@ -569,7 +615,9 @@ private void processPrimaryToSecondary(LensContext con context.setState(ModelState.SECONDARY); } - private void processSecondary(LensContext context, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException { + private void processSecondary(LensContext context, Task task, OperationResult result) + throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, + SecurityViolationException, ExpressionEvaluationException, PolicyViolationException, PreconditionViolationException { if (context.getExecutionWave() > context.getMaxWave() + 1) { context.setState(ModelState.FINAL); return; @@ -578,7 +626,7 @@ private void processSecondary(LensContext context, Tas Holder restartRequestedHolder = new Holder<>(); LensUtil.partialExecute("execution", - () -> { + () -> { boolean restartRequested = changeExecutor.executeChanges(context, task, result); restartRequestedHolder.setValue(restartRequested); }, @@ -679,7 +727,9 @@ private

boolean isShadowDeltaSignificant(ObjectDelta

d return false; } - private HookOperationMode processFinal(LensContext context, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException { + private HookOperationMode processFinal(LensContext context, Task task, OperationResult result) + throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, + SecurityViolationException, ExpressionEvaluationException, PolicyViolationException, PreconditionViolationException { auditFinalExecution(context, task, result); logFinalReadable(context, task, result); recordOperationExecution(context, null, task, result); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java index e438a685e99..a43259ecccc 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java @@ -1368,4 +1368,22 @@ public void unregisterConflictWatchers(RepositoryService repositoryService) { conflictWatchers.forEach(w -> repositoryService.unregisterConflictWatcher(w)); conflictWatchers.clear(); } + + public boolean hasProjectionChange() { + for (LensProjectionContext projectionContext: getProjectionContexts()) { + if (projectionContext.getWave() != getExecutionWave()) { + continue; + } + if (!projectionContext.isCanProject()) { + continue; + } + if (projectionContext.isThombstone()) { + continue; + } + if (projectionContext.hasPrimaryDelta() || projectionContext.hasSecondaryDelta()) { + return true; + } + } + return false; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java index e06c9609b68..d0a9c587915 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java @@ -216,6 +216,10 @@ public void setObjectNew(PrismObject objectNew) { public ObjectDelta getPrimaryDelta() { return primaryDelta; } + + public boolean hasPrimaryDelta() { + return primaryDelta != null && !primaryDelta.isEmpty(); + } /** * As getPrimaryDelta() but caters for the possibility that an object already exists. @@ -762,5 +766,17 @@ protected String getDebugDumpTitle(String suffix) { } public abstract String getHumanReadableName(); - + + public String getObjectReadVersion() { + // Do NOT use version from object current. + // Current object may be re-read, but the computation + // might be based on older data (objectOld). +// if (getObjectCurrent() != null) { +// return getObjectCurrent().getVersion(); +// } + if (getObjectOld() != null) { + return getObjectOld().getVersion(); + } + return null; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java index c85343d4eba..762c6bfa54a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java @@ -220,12 +220,15 @@ public void setSyncDelta(ObjectDelta syncDelta) { public ObjectDelta getSecondaryDelta() { return secondaryDelta; } - + @Override public ObjectDeltaObject getObjectDeltaObject() throws SchemaException { return new ObjectDeltaObject<>(getObjectCurrent(), getDelta(), getObjectNew()); } + public boolean hasSecondaryDelta() { + return secondaryDelta != null && !secondaryDelta.isEmpty(); + } @Override public void setSecondaryDelta(ObjectDelta secondaryDelta) { @@ -1405,4 +1408,5 @@ public boolean hasPendingOperations() { } return !current.asObjectable().getPendingOperation().isEmpty(); } + } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java index 37ba88f412a..d01439351d8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java @@ -63,6 +63,7 @@ import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.common.expression.Expression; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; @@ -1231,14 +1232,14 @@ public static void processRuleWithException(@NotNull EvaluatedPolicyRule rule, C public static void partialExecute(String componentName, ProjectorComponentRunnable runnable, Supplier optionSupplier) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, - PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException { + PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException { partialExecute(componentName, runnable, optionSupplier, null); } public static void partialExecute(String componentName, ProjectorComponentRunnable runnable, Supplier optionSupplier, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, - PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException { + PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException { PartialProcessingTypeType option = optionSupplier.get(); if (option == PartialProcessingTypeType.SKIP) { LOGGER.debug("Skipping projector component {} because partial execution option is set to {}", componentName, option); @@ -1248,7 +1249,7 @@ public static void partialExecute(String componentName, ProjectorComponentRunnab runnable.run(); LOGGER.trace("Projector component finished: {}", componentName); } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException - | PolicyViolationException | ExpressionEvaluationException | ObjectAlreadyExistsException | RuntimeException | Error e) { + | PolicyViolationException | ExpressionEvaluationException | ObjectAlreadyExistsException | PreconditionViolationException | RuntimeException | Error e) { LOGGER.trace("Projector component error: {}: {}: {}", componentName, e.getClass().getSimpleName(), e.getMessage()); if (result != null) { result.recordFatalError(e); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/PersonaProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/PersonaProcessor.java index acfecb83250..b5563a21c32 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/PersonaProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/PersonaProcessor.java @@ -41,6 +41,7 @@ import com.evolveum.midpoint.prism.delta.DeltaSetTriple; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.FocusTypeUtil; @@ -105,7 +106,9 @@ public class PersonaProcessor { private PrismContext prismContext; @SuppressWarnings({ "unchecked", "rawtypes" }) - public HookOperationMode processPersonaChanges(LensContext context, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException { + public HookOperationMode processPersonaChanges(LensContext context, Task task, OperationResult result) + throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, + ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException, PreconditionViolationException { LensFocusContext focusContext = context.getFocusContext(); if (focusContext == null) { @@ -127,7 +130,9 @@ public HookOperationMode processPersonaChanges(LensContex return processPersonaChangesFocus((LensContext) context, task, result); } - public HookOperationMode processPersonaChangesFocus(LensContext context, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException { + public HookOperationMode processPersonaChangesFocus(LensContext context, Task task, OperationResult result) + throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, CommunicationException, + ConfigurationException, SecurityViolationException, ExpressionEvaluationException, PolicyViolationException, PreconditionViolationException { DeltaSetTriple> evaluatedAssignmentTriple = (DeltaSetTriple)context.getEvaluatedAssignmentTriple(); if (evaluatedAssignmentTriple == null || evaluatedAssignmentTriple.isEmpty()) { return HookOperationMode.FOREGROUND; @@ -262,7 +267,8 @@ private boolean personaMatches(FocusType persona, PersonaKey key) { public void personaAdd(LensContext context, PersonaKey key, PersonaConstruction construction, Task task, OperationResult result) - throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, + CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { PrismObject focus = context.getFocusContext().getObjectNew(); LOGGER.debug("Adding persona {} for {} using construction {}", key, focus, construction); PersonaConstructionType constructionType = construction.getConstructionType(); @@ -302,7 +308,8 @@ public void personaAdd(LensContext public void personaModify(LensContext context, PersonaKey key, PersonaConstruction construction, PrismObject existingPersona, Task task, OperationResult result) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { PrismObject focus = context.getFocusContext().getObjectNew(); LOGGER.debug("Modifying persona {} for {} using construction {}", key, focus, construction); PersonaConstructionType constructionType = construction.getConstructionType(); @@ -328,7 +335,10 @@ public void personaModify(LensContext executePersonaDelta(targetDelta, task, result); } - public void personaDelete(LensContext context, PersonaKey key, FocusType existingPersona, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException { + public void personaDelete(LensContext context, PersonaKey key, FocusType existingPersona, + Task task, OperationResult result) + throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, + CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException, PreconditionViolationException { PrismObject focus = context.getFocusContext().getObjectOld(); LOGGER.debug("Deleting persona {} for {}: ", key, focus, existingPersona); ObjectDelta targetDelta = existingPersona.asPrismObject().createDeleteDelta(); @@ -358,7 +368,9 @@ private void unlink(LensContext context, FocusType per repositoryService.modifyObject(delta.getObjectTypeClass(), delta.getOid(), delta.getModifications(), result); } - private void executePersonaDelta(ObjectDelta delta, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException { + private void executePersonaDelta(ObjectDelta delta, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, + PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException, PreconditionViolationException { Collection> deltas = MiscSchemaUtil.createCollection(delta); LensContext context = contextFactory.createContext(deltas, null, task, result); // Persona changes are all "secondary" changes, trigerred by roles and policies. We do not want to authorize diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ProjectorComponentRunnable.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ProjectorComponentRunnable.java index a20226a39ae..65898c787d7 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ProjectorComponentRunnable.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ProjectorComponentRunnable.java @@ -15,6 +15,7 @@ */ package com.evolveum.midpoint.model.impl.lens; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; @@ -33,6 +34,6 @@ public interface ProjectorComponentRunnable { void run() throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, - SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException; + SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java index 0a769b559a8..dc383c1d266 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ActivationProcessor.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.model.impl.lens.SynchronizationIntent; import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; import com.evolveum.midpoint.prism.delta.PropertyDelta; @@ -38,6 +39,7 @@ import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; @@ -71,8 +73,12 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; /** * The processor that takes care of user activation mapping to an account (outbound direction). @@ -89,18 +95,14 @@ public class ActivationProcessor { private static final QName ASSIGNED_PROPERTY_NAME = new QName(SchemaConstants.NS_C, "assigned"); private static final QName FOCUS_EXISTS_PROPERTY_NAME = new QName(SchemaConstants.NS_C, "focusExists"); + @Autowired private ContextLoader contextLoader; + @Autowired private PrismContext prismContext; + @Autowired private MappingEvaluator mappingEvaluator; + @Autowired private MidpointFunctions midpointFunctions; + private PrismObjectDefinition userDefinition; private PrismContainerDefinition activationDefinition; - @Autowired(required=true) - private PrismContext prismContext; - - @Autowired(required=true) - private MappingEvaluator mappingEvaluator; - - @Autowired(required=true) - private MidpointFunctions midpointFunctions; - public void processActivation(LensContext context, LensProjectionContext projectionContext, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException { @@ -120,9 +122,20 @@ private void processActivationFocal(LensContext context processActivationMetadata(context, projectionContext, now, result); return; } - processActivationUserCurrent(context, projectionContext, now, task, result); - processActivationMetadata(context, projectionContext, now, result); - processActivationUserFuture(context, projectionContext, now, task, result); + try { + + processActivationUserCurrent(context, projectionContext, now, task, result); + processActivationMetadata(context, projectionContext, now, result); + processActivationUserFuture(context, projectionContext, now, task, result); + + } catch (ObjectNotFoundException e) { + if (projectionContext.isThombstone()) { + // This is not critical. The projection is marked as thombstone and we can go on with processing + // No extra action is needed. + } else { + throw e; + } + } } public void processActivationUserCurrent(LensContext context, LensProjectionContext projCtx, @@ -355,7 +368,7 @@ public void processActivationMetadata(LensContext conte ActivationStatusType statusNew = statusPropNew.getRealValue(); if (statusNew == statusOld) { - LOGGER.trace("Administrative status not changed ({}), timestamp and/or reason will be recorded", statusNew); + LOGGER.trace("Administrative status not changed ({}), timestamp and/or reason will not be recorded", statusNew); } else { // timestamps PropertyDelta timestampDelta = LensUtil.createActivationTimestampDelta(statusNew, @@ -667,7 +680,7 @@ private void evaluateOutboundMapping(final LensContext< params.setMappingDesc(desc + " in projection " + projCtxDesc); params.setNow(now); params.setInitializer(internalInitializer); - // do NOT set loader here. We do not want loading at this stage. we do not yet know whether we care at all. + params.setTargetLoader(new ProjectionMappingLoader<>(context, projCtx, contextLoader)); params.setAPrioriTargetObject(shadowNew); params.setAPrioriTargetDelta(LensUtil.findAPrioriDelta(context, projCtx)); if (context.getFocusContext() != null) { @@ -679,10 +692,100 @@ private void evaluateOutboundMapping(final LensContext< params.setEvaluateWeak(true); params.setContext(context); params.setHasFullTargetObject(projCtx.hasFullShadow()); - mappingEvaluator.evaluateMappingSetProjection(params, task, result); + + Map>> outputTripleMap = mappingEvaluator.evaluateMappingSetProjection(params, task, result); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Mapping processing output after {}:\n{}", desc, DebugUtil.debugDump(outputTripleMap, 1)); + } + + if (projCtx.isDoReconciliation()) { + reconcileOutboundValue(context, projCtx, outputTripleMap, desc); + } } + /** + * TODO: can we align this with ReconciliationProcessor? + */ + private void reconcileOutboundValue(LensContext context, LensProjectionContext projCtx, + Map>> outputTripleMap, String desc) throws SchemaException { + + // TODO: check for full shadow? + + for (Entry>> entry: outputTripleMap.entrySet()) { + ItemPath mappingOutputPath = entry.getKey(); + MappingOutputStruct> mappingOutputStruct = entry.getValue(); + if (mappingOutputStruct.isWeakMappingWasUsed()) { + // Thing to do. All deltas should already be in context + LOGGER.trace("Skip reconciliation of {} in {} because of weak", mappingOutputPath, desc); + continue; + } + if (!mappingOutputStruct.isStrongMappingWasUsed()) { + // Normal mappings are not processed for reconciliation + LOGGER.trace("Skip reconciliation of {} in {} because not strong", mappingOutputPath, desc); + continue; + } + LOGGER.trace("reconciliation of {} for {}", mappingOutputPath, desc); + + PrismObjectDefinition targetObjectDefinition = projCtx.getObjectDefinition(); + PrismPropertyDefinition targetItemDefinition = targetObjectDefinition.findPropertyDefinition(mappingOutputPath); + if (targetItemDefinition == null) { + throw new SchemaException("No definition for item "+mappingOutputPath+" in "+targetObjectDefinition); + } + PropertyDelta targetItemDelta = targetItemDefinition.createEmptyDelta(mappingOutputPath); + + PrismValueDeltaSetTriple> outputTriple = mappingOutputStruct.getOutputTriple(); + + PrismProperty currentTargetItem = null; + PrismObject shadowCurrent = projCtx.getObjectCurrent(); + if (shadowCurrent != null) { + currentTargetItem = shadowCurrent.findProperty(mappingOutputPath); + } + Collection> hasValues = new ArrayList<>(); + if (currentTargetItem != null) { + hasValues.addAll(currentTargetItem.getValues()); + } + + Collection> shouldHaveValues = outputTriple.getNonNegativeValues(); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Reconciliation of {}:\n hasValues:\n{}\n shouldHaveValues\n{}", + mappingOutputPath, DebugUtil.debugDump(hasValues, 2), DebugUtil.debugDump(shouldHaveValues, 2)); + } + + for (PrismPropertyValue shouldHaveValue: shouldHaveValues) { + if (!PrismPropertyValue.containsRealValue(hasValues, shouldHaveValue)) { + if (targetItemDefinition.isSingleValue()) { + targetItemDelta.setValueToReplace(shouldHaveValue.clone()); + } else { + targetItemDelta.addValueToAdd(shouldHaveValue.clone()); + } + } + } + + if (targetItemDefinition.isSingleValue()) { + if (!targetItemDelta.isReplace() && shouldHaveValues.isEmpty()) { + targetItemDelta.setValueToReplace(); + } + } else { + for (PrismPropertyValue hasValue: hasValues) { + if (!PrismPropertyValue.containsRealValue(shouldHaveValues, hasValue)) { + targetItemDelta.addValueToDelete(hasValue.clone()); + } + } + } + + if (!targetItemDelta.isEmpty()) { + LOGGER.trace("Reconciliation delta:\n{}", targetItemDelta.debugDumpLazily(1)); + projCtx.swallowToSecondaryDelta(targetItemDelta); + } + } + + } + + + private ItemDeltaItem,PrismPropertyDefinition> getLegalIdi(LensProjectionContext accCtx) throws SchemaException { Boolean legal = accCtx.isLegal(); Boolean legalOld = accCtx.isLegalOld(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java index 32653c97e11..7e56d7f5793 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java @@ -1277,7 +1277,7 @@ public void loadFullShadow(LensContext context, LensPr projCtx.setOid(objectCurrent.getOid()); } catch (ObjectNotFoundException ex) { - LOGGER.trace("Load of full resource object {} ended with ObjectNotFoundException (options={})", projCtx, getOptions); + LOGGER.debug("Load of full resource object {} ended with ObjectNotFoundException (options={})", projCtx, getOptions); if (projCtx.isDelete()){ //this is OK, shadow was deleted, but we will continue in processing with old shadow..and set it as full so prevent from other full loading projCtx.setFullShadow(true); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java index 394435a633f..59a500c03e3 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/FocusProcessor.java @@ -57,6 +57,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; @@ -113,9 +114,6 @@ public class FocusProcessor { @Autowired private ObjectTemplateProcessor objectTemplateProcessor; - @Autowired - private MappingFactory mappingFactory; - @Autowired private PrismContext prismContext; @@ -145,8 +143,9 @@ public class FocusProcessor { private PolicyRuleProcessor policyRuleProcessor; void processFocus(LensContext context, String activityDescription, - XMLGregorianCalendar now, Task task, OperationResult result) throws ObjectNotFoundException, - SchemaException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + XMLGregorianCalendar now, Task task, OperationResult result) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { LensFocusContext focusContext = context.getFocusContext(); if (focusContext == null) { @@ -163,8 +162,8 @@ void processFocus(LensContext con private void processFocusFocus(LensContext context, String activityDescription, XMLGregorianCalendar now, Task task, OperationResult result) - throws ObjectNotFoundException, - SchemaException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { LensFocusContext focusContext = context.getFocusContext(); ObjectTemplateType objectTemplate = context.getFocusTemplate(); PartialProcessingOptionsType partialProcessingOptions = context.getPartialProcessingOptions(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java index 5fd799078e8..57d1dd758bb 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java @@ -175,15 +175,13 @@ public void evaluateOutboundMapping(final LensContext loader = new ProjectionMappingLoader<>(context, projCtx, contextLoader); - MappingEvaluatorParams, PrismPropertyDefinition, ShadowType, F> params = new MappingEvaluatorParams<>(); params.setMappingTypes(outboundMappings); params.setMappingDesc(desc + " in projection " + projCtxDesc); params.setNow(now); params.setInitializer(internalInitializer); params.setProcessor(processor); - params.setTargetLoader(loader); + params.setTargetLoader(new ProjectionMappingLoader<>(context, projCtx, contextLoader)); params.setAPrioriTargetObject(shadowNew); params.setAPrioriTargetDelta(LensUtil.findAPrioriDelta(context, projCtx)); params.setTargetContext(projCtx); @@ -198,7 +196,7 @@ public void evaluateOutboundMapping(final LensContext void evaluateMappingSetProjection( + public Map> evaluateMappingSetProjection( MappingEvaluatorParams params, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { @@ -285,7 +283,7 @@ public mappingOutputTriple = mapping.getOutputTriple(); @@ -305,13 +303,13 @@ public outputTriple = mappingOutputStruct.getOutputTriple(); @@ -375,7 +373,7 @@ public boolean isMeaningful(PrismValueDeltaSetTriple mappingOutputTriple) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingOutputStruct.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingOutputStruct.java index 2dd422317b4..66cb1e9522f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingOutputStruct.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingOutputStruct.java @@ -17,12 +17,14 @@ import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.DebugUtil; /** * @author semancik * */ -public class MappingOutputStruct { +public class MappingOutputStruct implements DebugDumpable { private PrismValueDeltaSetTriple outputTriple = null; private boolean strongMappingWasUsed = false; @@ -52,4 +54,13 @@ public void setWeakMappingWasUsed(boolean weakMappingWasUsed) { this.weakMappingWasUsed = weakMappingWasUsed; } + @Override + public String debugDump(int indent) { + StringBuilder sb = DebugUtil.createTitleStringBuilderLn(MappingOutputStruct.class, indent); + DebugUtil.debugDumpWithLabelLn(sb, "outputTriple", outputTriple, indent + 1); + DebugUtil.debugDumpWithLabelLn(sb, "strongMappingWasUsed", strongMappingWasUsed, indent + 1); + DebugUtil.debugDumpWithLabel(sb, "weakMappingWasUsed", weakMappingWasUsed, indent + 1); + return sb.toString(); + } + } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionMappingLoader.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionMappingLoader.java index 0dc21f33851..0c0dcc2c870 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionMappingLoader.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionMappingLoader.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; @@ -35,6 +37,8 @@ * */ public class ProjectionMappingLoader implements MappingLoader { + + private static final Trace LOGGER = TraceManager.getTrace(ProjectionMappingLoader.class); private LensProjectionContext projectionContext; private ContextLoader contextLoader; @@ -55,9 +59,14 @@ public boolean isLoaded() { @Override public PrismObject load(String loadReason, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { contextLoader.loadFullShadow(context, projectionContext, loadReason, task, result); - if (projectionContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) { - // TODO - } + if (SynchronizationPolicyDecision.BROKEN.equals(projectionContext.getSynchronizationPolicyDecision())) { + LOGGER.debug("Attempt to load full object for {} failed, projection context is broken", projectionContext.getHumanReadableName()); + throw new ObjectNotFoundException("Projection loading failed, projection broken"); + } + if (projectionContext.isThombstone()) { + LOGGER.debug("Projection {} got thombstoned", projectionContext.getHumanReadableName()); + throw new ObjectNotFoundException("Projection loading failed, projection thombstoned"); + } return projectionContext.getObjectCurrent(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java index 6f03a50bb31..c45afe99b16 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java @@ -57,6 +57,7 @@ import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; @@ -67,6 +68,7 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.IterationSpecificationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; @@ -242,7 +244,7 @@ private void processProjections(LensContext context, wasResetIterationCounter = true; iteration = 0; iterationToken = null; - cleanupContext(projContext); + cleanupContext(projContext, null); LOGGER.trace("Resetting iteration counter and token because we have rename"); if (consistencyChecks) context.checkConsistence(); continue; @@ -307,10 +309,11 @@ private void processProjections(LensContext context, if (focus != null && focus.getOid().equals(context.getFocusContext().getOid())) { LOGGER.trace("Conflicting projection already linked to the current focus, no recompute needed, continue processing with conflicting projection."); // accountContext.setSecondaryDelta(null); - cleanupContext(projContext); + cleanupContext(projContext, fullConflictingShadow); projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP); projContext.setObjectOld(fullConflictingShadow.clone()); projContext.setObjectCurrent(fullConflictingShadow); + projContext.setOid(fullConflictingShadow.getOid()); projContext.setFullShadow(true); ObjectDelta secondaryDelta = projContext.getSecondaryDelta(); if (secondaryDelta != null && projContext.getOid() != null) { @@ -376,9 +379,10 @@ private void processProjections(LensContext context, } //found shadow belongs to the current user..need to link it and replace current shadow with the found shadow.. - cleanupContext(projContext); + cleanupContext(projContext, fullConflictingShadow); projContext.setObjectOld(fullConflictingShadow.clone()); projContext.setObjectCurrent(fullConflictingShadow); + projContext.setOid(fullConflictingShadow.getOid()); projContext.setFullShadow(true); projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP); ObjectDelta secondaryDelta = projContext.getSecondaryDelta(); @@ -422,7 +426,7 @@ private void processProjections(LensContext context, iterationToken = null; LensUtil.checkMaxIterations(iteration, maxIterations, conflictMessage, projContext.getHumanReadableName()); - cleanupContext(projContext); + cleanupContext(projContext, null); if (consistencyChecks) context.checkConsistence(); } @@ -570,20 +574,47 @@ public void checkSchemaAndPolicies(LensContext context /** * Remove the intermediate results of values processing such as secondary deltas. */ - private void cleanupContext(LensProjectionContext accountContext) throws SchemaException { - // We must NOT clean up activation computation. This has happened before, it will not happen again - // and it does not depend on iteration + private void cleanupContext(LensProjectionContext accountContext, PrismObject fullConflictingShadow) throws SchemaException { + // We must NOT clean up activation computation here. This has happened before, it will not happen again + // and it does not depend on iteration. But, in fact we want to cleaup up activation changes if they + // are already applied to the new shadow. ObjectDelta secondaryDelta = accountContext.getSecondaryDelta(); if (secondaryDelta != null) { + boolean administrativeStatusDeltaRemoved = false; Collection modifications = secondaryDelta.getModifications(); if (modifications != null) { Iterator iterator = modifications.iterator(); while (iterator.hasNext()) { ItemDelta modification = iterator.next(); - if (! new ItemPath(FocusType.F_ACTIVATION).equivalent(modification.getParentPath())) { + if (SchemaConstants.PATH_ACTIVATION.equivalent(modification.getParentPath())) { + if (fullConflictingShadow != null) { + if (QNameUtil.match(ActivationType.F_ADMINISTRATIVE_STATUS,modification.getElementName())) { + if (modification.isRedundant(fullConflictingShadow)) { + LOGGER.trace("Removing redundant secondary activation delta: {}", modification); + iterator.remove(); + } + administrativeStatusDeltaRemoved = true; + } + } + } else { iterator.remove(); } } + if (administrativeStatusDeltaRemoved) { + iterator = modifications.iterator(); + while (iterator.hasNext()) { + ItemDelta modification = iterator.next(); + if (SchemaConstants.PATH_ACTIVATION.equivalent(modification.getParentPath())) { + if (QNameUtil.match(ActivationType.F_ENABLE_TIMESTAMP, modification.getElementName()) || + QNameUtil.match(ActivationType.F_DISABLE_TIMESTAMP, modification.getElementName()) || + QNameUtil.match(ActivationType.F_DISABLE_REASON, modification.getElementName()) || + QNameUtil.match(ActivationType.F_ARCHIVE_TIMESTAMP, modification.getElementName())) { + LOGGER.trace("Removing secondary activation delta because redundant delta was removed before: {}", modification); + iterator.remove(); + } + } + } + } } if (secondaryDelta.isEmpty()) { accountContext.setSecondaryDelta(null); @@ -592,6 +623,7 @@ private void cleanupContext(LensProjectionContext accountContext) throws SchemaE accountContext.clearIntermediateResults(); accountContext.recompute(); } + /** * Adds deltas for iteration and iterationToken to the shadow if needed. diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java index 17d4e7ecb11..f2a611ea237 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java @@ -36,6 +36,7 @@ import com.evolveum.midpoint.model.impl.lens.LensUtil; import com.evolveum.midpoint.model.impl.lens.projector.credentials.ProjectionCredentialsProcessor; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; import com.evolveum.midpoint.schema.internals.InternalCounters; import com.evolveum.midpoint.schema.internals.InternalMonitor; @@ -109,7 +110,7 @@ public class Projector { public void project(LensContext context, String activityDescription, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, - ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { projectInternal(context, activityDescription, true, false, task, parentResult); } @@ -119,7 +120,7 @@ public void project(LensContext context, String activi public void resume(LensContext context, String activityDescription, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, - ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { if (context.getProjectionWave() != context.getExecutionWave()) { throw new IllegalStateException("Projector.resume called in illegal wave state: execution wave = " + context.getExecutionWave() + @@ -139,14 +140,14 @@ public void resume(LensContext context, String activit public void projectAllWaves(LensContext context, String activityDescription, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, - ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { projectInternal(context, activityDescription, true, true, task, parentResult); } private void projectInternal(LensContext context, String activityDescription, boolean fromStart, boolean allWaves, Task task, OperationResult parentResult) throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, - ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { context.checkAbortRequested(); @@ -290,7 +291,7 @@ private void projectInternal(LensContext context, Stri computeResultStatus(now, result); } catch (SchemaException | PolicyViolationException | ExpressionEvaluationException | ObjectAlreadyExistsException | - ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException e) { + ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException | PreconditionViolationException e) { recordFatalError(e, now, result); throw e; } catch (RuntimeException e) { @@ -310,7 +311,9 @@ private void projectInternal(LensContext context, Stri private void projectProjection(LensContext context, LensProjectionContext projectionContext, PartialProcessingOptionsType partialProcessingOptions, - XMLGregorianCalendar now, String activityDescription, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException { + XMLGregorianCalendar now, String activityDescription, Task task, OperationResult parentResult) + throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, + SecurityViolationException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PreconditionViolationException { if (projectionContext.getWave() != context.getProjectionWave()) { // Let's skip accounts that do not belong into this wave. @@ -364,6 +367,10 @@ private void projectProjection(LensContext context, Le }, partialProcessingOptions::getProjectionValues); + if (projectionContext.isThombstone()) { + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Skipping projection because it is a thombstone"); + return; + } LensUtil.partialExecute("projectionCredentials", () -> { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java index b9f0fee8833..7bf10737576 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java @@ -126,9 +126,7 @@ private ComputationResult compute(@NotNull List rulesToReco cr.oldPolicySituations.addAll(existingPolicySituation); cr.oldTriggeredRules.addAll(existingTriggeredPolicyRule); cr.situationsNeedUpdate = !Objects.equals(cr.oldPolicySituations, cr.newPolicySituations); - // we do not use Objects.equal, because it uses hashCode, that is (for some reason) wrongly computed - //cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); - cr.rulesNeedUpdate = !MiscUtil.unorderedCollectionEquals(cr.oldTriggeredRules, cr.newTriggeredRules); + cr.rulesNeedUpdate = !Objects.equals(cr.oldTriggeredRules, cr.newTriggeredRules); // hope hashCode is computed well return cr; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java index 6e9b2fadc8f..01e87efbe80 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/FocusValidityScannerTaskHandler.java @@ -31,6 +31,7 @@ import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.builder.QueryBuilder; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; @@ -238,7 +239,7 @@ protected AbstractScannerResultHandler createHandler(TaskRunResult run AbstractScannerResultHandler handler = new AbstractScannerResultHandler( coordinatorTask, FocusValidityScannerTaskHandler.class.getName(), "recompute", "recompute task", taskManager) { @Override - protected boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException { + protected boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException, PreconditionViolationException { if (oidAlreadySeen(coordinatorTask, object.getOid())) { LOGGER.trace("Recomputation already executed for {}", ObjectTypeUtil.toShortString(object)); } else { @@ -253,7 +254,7 @@ protected boolean handleObject(PrismObject object, Task workerTask, Op private void reconcileUser(PrismObject user, Task workerTask, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ObjectAlreadyExistsException, - ConfigurationException, PolicyViolationException, SecurityViolationException { + ConfigurationException, PolicyViolationException, SecurityViolationException, PreconditionViolationException { LOGGER.trace("Recomputing user {}", user); // We want reconcile option here. There may be accounts that are in wrong activation state. // We will not notice that unless we go with reconcile. diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java index b4f4a4d6698..9e7cc220a15 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java @@ -36,6 +36,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; @@ -111,7 +112,7 @@ protected AbstractSearchIterativeResultHandler createHandler(TaskRunR AbstractSearchIterativeResultHandler handler = new AbstractSearchIterativeResultHandler( coordinatorTask, RecomputeTaskHandler.class.getName(), "recompute", "recompute task", taskManager) { @Override - protected boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException { + protected boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException, PreconditionViolationException { recompute(object, getOptions(coordinatorTask), workerTask, result); return true; } @@ -134,7 +135,7 @@ private ModelExecuteOptions getOptions(Task coordinatorTask) throws SchemaExcept private void recompute(PrismObject focalObject, ModelExecuteOptions options, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ObjectAlreadyExistsException, - ConfigurationException, PolicyViolationException, SecurityViolationException { + ConfigurationException, PolicyViolationException, SecurityViolationException, PreconditionViolationException { LOGGER.trace("Recomputing object {}", focalObject); LensContext syncContext = contextFactory.createRecomputeContext(focalObject, options, task, result); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java index a793f87b584..0e74029c857 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java @@ -56,6 +56,7 @@ import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; @@ -781,7 +782,7 @@ private SynchronizationSituationType reactToChange(Class void handle(PrismObject object, TriggerType tri clockwork.run(lensContext, task, result); LOGGER.trace("Recomputing of {}: {}", object, result.getStatus()); - } catch (SchemaException e) { - LOGGER.error(e.getMessage(), e); - } catch (ObjectNotFoundException e) { - LOGGER.error(e.getMessage(), e); - } catch (ExpressionEvaluationException e) { - LOGGER.error(e.getMessage(), e); - } catch (CommunicationException e) { - LOGGER.error(e.getMessage(), e); - } catch (ObjectAlreadyExistsException e) { - LOGGER.error(e.getMessage(), e); - } catch (ConfigurationException e) { - LOGGER.error(e.getMessage(), e); - } catch (PolicyViolationException e) { - LOGGER.error(e.getMessage(), e); - } catch (SecurityViolationException e) { + } catch (CommonException | PreconditionViolationException | RuntimeException | Error e) { LOGGER.error(e.getMessage(), e); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeResultHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeResultHandler.java index ef2de0be915..58d1308cc8f 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeResultHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeResultHandler.java @@ -17,6 +17,7 @@ import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.repo.cache.RepositoryCache; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResultStatus; @@ -353,7 +354,7 @@ private void processRequest(ProcessingRequest request, Task workerTask, Operatio } } - } catch (CommonException|RuntimeException e) { + } catch (CommonException | PreconditionViolationException | Error | RuntimeException e) { if (isRecordIterationStatistics()) { workerTask.recordIterativeOperationEnd(objectName, objectDisplayName, null /* TODO */, object.getOid(), startTime, e); @@ -430,7 +431,7 @@ private boolean shouldReportProgress() { } } - private boolean processError(PrismObject object, Exception ex, OperationResult result) { + private boolean processError(PrismObject object, Throwable ex, OperationResult result) { int errorsCount = errors.incrementAndGet(); LOGGER.trace("Processing error, count: {}", errorsCount); @@ -480,7 +481,7 @@ public void setLogErrors(boolean logErrors) { this.logErrors = logErrors; } - protected abstract boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException; + protected abstract boolean handleObject(PrismObject object, Task workerTask, OperationResult result) throws CommonException, PreconditionViolationException; public class ProcessingRequest { public PrismObject object; diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestClockwork.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestClockwork.java index 8fec5f5df04..2f17ae28ff3 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestClockwork.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestClockwork.java @@ -60,6 +60,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.repo.api.PreconditionViolationException; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.schema.util.SchemaTestConstants; @@ -402,7 +403,7 @@ private LensContext createJackAssignAccountContext(OperationResult res return context; } - private void unassignJackAccount() throws SchemaException, ObjectNotFoundException, IOException, JAXBException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { + private void unassignJackAccount() throws SchemaException, ObjectNotFoundException, IOException, JAXBException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PreconditionViolationException { Task task = taskManager.createTaskInstance(TestClockwork.class.getName() + ".unassignJackAccount"); LensContext context = createUserLensContext(); OperationResult result = task.getResult(); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestActivation.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestActivation.java index ba9c1a7237d..48883376cfd 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestActivation.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestActivation.java @@ -155,7 +155,7 @@ public void initSystem(Task initTask, OperationResult initResult) @Test public void test050CheckJackEnabled() throws Exception { final String TEST_NAME = "test050CheckJackEnabled"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN, WHEN // this happens during test initialization when user-jack.xml is added @@ -172,7 +172,7 @@ public void test050CheckJackEnabled() throws Exception { @Test public void test051ModifyUserJackDisable() throws Exception { final String TEST_NAME = "test051ModifyUserJackDisable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -204,7 +204,7 @@ public void test051ModifyUserJackDisable() throws Exception { @Test public void test052ModifyUserJackNull() throws Exception { final String TEST_NAME = "test052ModifyUserJackNull"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -235,7 +235,7 @@ public void test052ModifyUserJackNull() throws Exception { @Test public void test055ModifyUserJackEnable() throws Exception { final String TEST_NAME = "test055ModifyUserJackEnable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -267,7 +267,7 @@ public void test055ModifyUserJackEnable() throws Exception { @Test public void test056RecomputeUserJackEffectiveEnable() throws Exception { final String TEST_NAME = "test056RecomputeUserJackEffectiveEnable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -320,7 +320,7 @@ public void test056RecomputeUserJackEffectiveEnable() throws Exception { @Test public void test060ModifyUserJackLifecycleActive() throws Exception { final String TEST_NAME = "test060ModifyUserJackLifecycleActive"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -352,7 +352,7 @@ public void test060ModifyUserJackLifecycleActive() throws Exception { @Test public void test061ModifyUserJackLifecycleDraft() throws Exception { final String TEST_NAME = "test061ModifyUserJackLifecycleDraft"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -384,7 +384,7 @@ public void test061ModifyUserJackLifecycleDraft() throws Exception { @Test public void test065ModifyUserJackLifecycleDeprecated() throws Exception { final String TEST_NAME = "test065ModifyUserJackLifecycleDeprecated"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -416,7 +416,7 @@ public void test065ModifyUserJackLifecycleDeprecated() throws Exception { @Test public void test068ModifyUserJackLifecycleArchived() throws Exception { final String TEST_NAME = "test068ModifyUserJackLifecycleArchived"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -447,7 +447,7 @@ public void test068ModifyUserJackLifecycleArchived() throws Exception { @Test public void test069ModifyUserJackLifecycleNull() throws Exception { final String TEST_NAME = "test069ModifyUserJackLifecycleNull"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -478,7 +478,7 @@ public void test069ModifyUserJackLifecycleNull() throws Exception { @Test public void test100ModifyUserJackAssignAccount() throws Exception { final String TEST_NAME = "test100ModifyUserJackAssignAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -553,7 +553,7 @@ public void test100ModifyUserJackAssignAccount() throws Exception { @Test public void test101ModifyUserJackDisable() throws Exception { final String TEST_NAME = "test101ModifyUserJackDisable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -652,7 +652,7 @@ public void test111ModifyAccountJackDisable() throws Exception { @Test public void test112UserJackRecompute() throws Exception { final String TEST_NAME = "test112UserJackRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -692,7 +692,7 @@ public void test112UserJackRecompute() throws Exception { @Test public void test114ModifyUserJackEnable() throws Exception { final String TEST_NAME = "test114ModifyUserJackEnable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -730,7 +730,7 @@ public void test114ModifyUserJackEnable() throws Exception { @Test public void test115ModifyUserJackAdministrativeStatusNull() throws Exception { final String TEST_NAME = "test115ModifyUserJackAdministrativeStatusNull"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -771,7 +771,7 @@ public void test115ModifyUserJackAdministrativeStatusNull() throws Exception { @Test public void test118ModifyJackActivationUserAndAccount() throws Exception { final String TEST_NAME = "test118ModifyJackActivationUserAndAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -787,11 +787,11 @@ public void test118ModifyJackActivationUserAndAccount() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); @@ -818,7 +818,7 @@ public void test118ModifyJackActivationUserAndAccount() throws Exception { @Test public void test120ModifyUserJackAssignAccountDummyRed() throws Exception { final String TEST_NAME = "test120ModifyUserJackAssignAccountDummyRed"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -828,11 +828,11 @@ public void test120ModifyUserJackAssignAccountDummyRed() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignAccount(USER_JACK_OID, RESOURCE_DUMMY_RED_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); @@ -870,7 +870,7 @@ public void test120ModifyUserJackAssignAccountDummyRed() throws Exception { @Test public void test121ModifyJackUserAndAccountRed() throws Exception { final String TEST_NAME = "test121ModifyJackUserAndAccountRed"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -887,11 +887,11 @@ public void test121ModifyJackUserAndAccountRed() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); @@ -951,7 +951,7 @@ public void test130ModifyAccountDefaultAndRed() throws Exception { @Test public void test138ModifyJackEnabled() throws Exception { final String TEST_NAME = "test138ModifyJackEnabled"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -959,11 +959,11 @@ public void test138ModifyJackEnabled() throws Exception { assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, ACTIVATION_ADMINISTRATIVE_STATUS_PATH, task, result, ActivationStatusType.ENABLED); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); @@ -982,7 +982,7 @@ public void test138ModifyJackEnabled() throws Exception { @Test public void test139ModifyUserJackUnAssignAccountDummyRed() throws Exception { final String TEST_NAME = "test139ModifyUserJackUnAssignAccountDummyRed"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -993,8 +993,7 @@ public void test139ModifyUserJackUnAssignAccountDummyRed() throws Exception { unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_RED_OID, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); PrismObject userJack = getUser(USER_JACK_OID); display("User after change execution", userJack); @@ -1007,13 +1006,160 @@ public void test139ModifyUserJackUnAssignAccountDummyRed() throws Exception { assertAdministrativeStatusDisabled(accountRed); assertDisableReasonShadow(accountRed, SchemaConstants.MODEL_DISABLE_REASON_DEPROVISION); - // Check account in dummy resource + // Red resource has disabled-instead-of-delete, therefore the account should exists and be disabled assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false); assertAdministrativeStatusEnabled(userJack); assertDummyEnabled("jack"); assertDummyDisabled(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME); } + + /** + * Assign account red again. The account should be re-enabled. + */ + @Test + public void test140ModifyUserJackAssignAccountDummyRed() throws Exception { + final String TEST_NAME = "test140ModifyUserJackAssignAccountDummyRed"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); + + // WHEN + displayWhen(TEST_NAME); + assignAccount(USER_JACK_OID, RESOURCE_DUMMY_RED_OID, null, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); + + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertUserJack(userJack); + assertAccounts(USER_JACK_OID, 2); + accountRedOid = getLinkRefOid(userJack, RESOURCE_DUMMY_RED_OID); + + PrismObject accountRedRepo = repositoryService.getObject(ShadowType.class, accountRedOid, null, result); + display("Account red (repo)", accountRedRepo); + assertEnableTimestampShadow(accountRedRepo, startTime, endTime); + + PrismObject accountRed = getShadowModel(accountRedOid); + display("Account red (model)", accountRed); + assertAccountShadowModel(accountRed, accountRedOid, ACCOUNT_JACK_DUMMY_USERNAME, + getDummyResourceType(RESOURCE_DUMMY_RED_NAME)); + assertAdministrativeStatusEnabled(accountRed); + assertEnableTimestampShadow(accountRed, startTime, endTime); + + // Red account should be re-enabled + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, "jack", "Jack Sparrow", true); + + assertAdministrativeStatusEnabled(userJack); + assertDummyEnabled("jack"); + assertDummyEnabled(RESOURCE_DUMMY_RED_NAME, "jack"); + } + + /** + * Unassign red account. But do it raw, so the account activation is not affected. + * MID-4154 + */ + @Test + public void test147ModifyUserJackUnassignAccountDummyRedRaw() throws Exception { + final String TEST_NAME = "test147ModifyUserJackUnassignAccountDummyRedRaw"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + ObjectDelta userDelta = createAccountAssignmentUserDelta(USER_JACK_OID, RESOURCE_DUMMY_RED_OID, null, false); + + // WHEN + displayWhen(TEST_NAME); + modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), ModelExecuteOptions.createRaw(), task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertUserJack(userJack); + assertAccounts(USER_JACK_OID, 2); + accountRedOid = getLinkRefOid(userJack, RESOURCE_DUMMY_RED_OID); + + PrismObject accountRedRepo = repositoryService.getObject(ShadowType.class, accountRedOid, null, result); + display("Account red (repo)", accountRedRepo); + + PrismObject accountRed = getShadowModel(accountRedOid); + display("Account red (model)", accountRed); + assertAccountShadowModel(accountRed, accountRedOid, ACCOUNT_JACK_DUMMY_USERNAME, + getDummyResourceType(RESOURCE_DUMMY_RED_NAME)); + assertAdministrativeStatusEnabled(accountRed); + + // Red account should not be touched (yet) + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, "jack", "Jack Sparrow", true); + + assertAdministrativeStatusEnabled(userJack); + assertDummyEnabled("jack"); + assertDummyEnabled(RESOURCE_DUMMY_RED_NAME, "jack"); + } + + /** + * Recompute jack. There are no assignments for red resource. + * But the account is enabled. It should be disabled after recompute. + * MID-4154 + */ + @Test + public void test149RecomputeJack() throws Exception { + final String TEST_NAME = "test149RecomputeJack"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + + XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); + + // WHEN + displayWhen(TEST_NAME); + reconcileUser(USER_JACK_OID, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); + + PrismObject userJack = getUser(USER_JACK_OID); + display("User after change execution", userJack); + assertUserJack(userJack); + assertAccounts(USER_JACK_OID, 2); + accountRedOid = getLinkRefOid(userJack, RESOURCE_DUMMY_RED_OID); + + PrismObject accountRedRepo = repositoryService.getObject(ShadowType.class, accountRedOid, null, result); + display("Account red (repo)", accountRedRepo); + assertDisableTimestampShadow(accountRedRepo, startTime, endTime); + + PrismObject accountRed = getShadowModel(accountRedOid); + display("Account red (model)", accountRed); + assertAccountShadowModel(accountRed, accountRedOid, ACCOUNT_JACK_DUMMY_USERNAME, + getDummyResourceType(RESOURCE_DUMMY_RED_NAME)); + assertAdministrativeStatusDisabled(accountRed); + assertDisableTimestampShadow(accountRed, startTime, endTime); + + // Red account should be disabled now + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, "jack", "Jack Sparrow", false); + + assertAdministrativeStatusEnabled(userJack); + assertDummyEnabled("jack"); + assertDummyDisabled(RESOURCE_DUMMY_RED_NAME, "jack"); + } /** * Assign yellow account. @@ -1158,7 +1304,7 @@ public void test152ModifyAccountsJackDisable() throws Exception { @Test public void test153ModifyAccountsJackEnable() throws Exception { final String TEST_NAME = "test153ModifyAccountsJackEnable"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1310,7 +1456,7 @@ public void test160ModifyUserJackAssignAccountKhaki() throws Exception { @Test public void test170GetAccountUnlocked() throws Exception { final String TEST_NAME = "test170GetAccountUnlocked"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1334,7 +1480,7 @@ public void test170GetAccountUnlocked() throws Exception { @Test public void test172GetAccountLocked() throws Exception { final String TEST_NAME = "test172GetAccountLocked"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1362,7 +1508,7 @@ public void test172GetAccountLocked() throws Exception { @Test public void test174ModifyAccountUnlock() throws Exception { final String TEST_NAME = "test174ModifyAccountUnlock"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1397,7 +1543,7 @@ public void test174ModifyAccountUnlock() throws Exception { @Test public void test176ModifyUserUnlock() throws Exception { final String TEST_NAME = "test176ModifyUserUnlock"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1433,7 +1579,7 @@ public void test176ModifyUserUnlock() throws Exception { @Test public void test199DeleteUserJack() throws Exception { final String TEST_NAME = "test199DeleteUserJack"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1466,7 +1612,7 @@ public void test199DeleteUserJack() throws Exception { @Test public void test200AddUserLargo() throws Exception { final String TEST_NAME = "test200AddUserLargo"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = System.currentTimeMillis(); @@ -1492,7 +1638,7 @@ public void test200AddUserLargo() throws Exception { @Test public void test205ModifyUserLargoAssignAccount() throws Exception { final String TEST_NAME = "test205ModifyUserLargoAssignAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1531,7 +1677,7 @@ public void test205ModifyUserLargoAssignAccount() throws Exception { @Test public void test210ModifyLargoValidTo10MinsAgo() throws Exception { final String TEST_NAME = "test210ModifyLargoValidTo10MinsAgo"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = System.currentTimeMillis(); @@ -1569,7 +1715,7 @@ public void test210ModifyLargoValidTo10MinsAgo() throws Exception { @Test public void test211ModifyLargoValidToManana() throws Exception { final String TEST_NAME = "test211ModifyLargoValidToManana"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = System.currentTimeMillis(); @@ -1611,7 +1757,7 @@ public void test211ModifyLargoValidToManana() throws Exception { @Test public void test212SeeLargoTomorrow() throws Exception { final String TEST_NAME = "test212SeeLargoTomorrow"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = System.currentTimeMillis(); @@ -1654,7 +1800,7 @@ public void test212SeeLargoTomorrow() throws Exception { @Test public void test213HastaLaMananaLargo() throws Exception { final String TEST_NAME = "test213HastaLaMananaLargo"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = System.currentTimeMillis(); @@ -1694,7 +1840,7 @@ public void test213HastaLaMananaLargo() throws Exception { @Test public void test215ModifyLargoRemoveValidTo() throws Exception { final String TEST_NAME = "test215ModifyLargoRemoveValidTo"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = clock.currentTimeMillis(); @@ -1731,7 +1877,7 @@ public void test215ModifyLargoRemoveValidTo() throws Exception { @Test public void test217ModifyLargoRemoveValidFrom() throws Exception { final String TEST_NAME = "test217ModifyLargoRemoveValidFrom"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN long startMillis = clock.currentTimeMillis(); @@ -1767,13 +1913,13 @@ public void test217ModifyLargoRemoveValidFrom() throws Exception { /** * Delete assignment from repo. Model should not notice. - * The change should be NOT applied after recompute. - * Accounts are not retrieved, therefore the change is not noticed. + * The change should be applied after recompute, because RED resource has + * strong mappings, which trigger account to be loaded. */ @Test public void test230JackUnassignRepoRecompute() throws Exception { final String TEST_NAME = "test230JackUnassignRepoRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -1789,38 +1935,35 @@ public void test230JackUnassignRepoRecompute() throws Exception { assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); - assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true); + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false); } /** - * Deleted assignment from the repo (previous test). Model haven't noticed. * Now recompute with reconcile. The change should be applied after recompute. */ @Test public void test231JackRecomputeReconcile() throws Exception { final String TEST_NAME = "test231JackRecomputeReconcile"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, ModelExecuteOptions.createReconcile(), task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false); } @@ -1834,7 +1977,7 @@ public void test231JackRecomputeReconcile() throws Exception { @Test public void test240AddUserRappDraft() throws Exception { final String TEST_NAME = "test240AddUserRappDraft"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); @@ -1856,11 +1999,11 @@ public void test240AddUserRappDraft() throws Exception { display("User before", userBefore); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); addObject(userBefore, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1892,17 +2035,17 @@ public void test240AddUserRappDraft() throws Exception { @Test public void test241RecomputeRappDraft() throws Exception { final String TEST_NAME = "test240AddUserRappDraft"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_RAPP_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1935,17 +2078,17 @@ public void test241RecomputeRappDraft() throws Exception { @Test public void test242RappAssignCaptain() throws Exception { final String TEST_NAME = "test242RappAssignCaptain"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(USER_RAPP_OID, ROLE_CAPTAIN_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1973,18 +2116,18 @@ public void test242RappAssignCaptain() throws Exception { @Test public void test245ActivateRapp() throws Exception { final String TEST_NAME = "test245ActivateRapp"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_RAPP_OID, UserType.F_LIFECYCLE_STATE, task, result, SchemaConstants.LIFECYCLE_ACTIVE); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2016,18 +2159,18 @@ public void test245ActivateRapp() throws Exception { @Test public void test248DeactivateRapp() throws Exception { final String TEST_NAME = "test248DeactivateRapp"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_RAPP_OID, UserType.F_LIFECYCLE_STATE, task, result, SchemaConstants.LIFECYCLE_ARCHIVED); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2053,17 +2196,17 @@ public void test248DeactivateRapp() throws Exception { @Test public void test249DeleteUserRapp() throws Exception { final String TEST_NAME = "test249DeleteUserRapp"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); deleteObject(UserType.class, USER_RAPP_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2078,7 +2221,7 @@ public void test249DeleteUserRapp() throws Exception { @Test public void test300AddDummyGreenAccountMancomb() throws Exception { final String TEST_NAME = "test300AddDummyGreenAccountMancomb"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -2092,12 +2235,12 @@ public void test300AddDummyGreenAccountMancomb() throws Exception { account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Melee Island"); /// WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); dummyResourceGreen.addAccount(account); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); PrismObject accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyGreen); display("Account shadow after", accountMancomb); @@ -2119,7 +2262,7 @@ public void test300AddDummyGreenAccountMancomb() throws Exception { @Test public void test310ImportAccountsFromDummyGreen() throws Exception { final String TEST_NAME = "test310ImportAccountsFromDummyGreen"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); @@ -2131,17 +2274,17 @@ public void test310ImportAccountsFromDummyGreen() throws Exception { assertNull("Unexpected user mancomb before import", userMancomb); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.importFromResource(RESOURCE_DUMMY_GREEN_OID, new QName(dummyResourceCtlGreen.getNamespace(), "AccountObjectClass"), task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); OperationResult subresult = result.getLastSubresult(); TestUtil.assertInProgress("importAccountsFromResource result", subresult); waitForTaskFinish(task, true, 40000); - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); userMancomb = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); assertNotNull("No user mancomb after import", userMancomb); @@ -2157,7 +2300,7 @@ public void test310ImportAccountsFromDummyGreen() throws Exception { @Test public void test350AssignMancombBlueAccount() throws Exception { final String TEST_NAME = "test350AssignMancombBlueAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2184,7 +2327,7 @@ public void test350AssignMancombBlueAccount() throws Exception { @Test public void test352AssignMancombBlackAccount() throws Exception { final String TEST_NAME = "test352AssignMancombBlackAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2217,7 +2360,7 @@ public void test352AssignMancombBlackAccount() throws Exception { @Test public void test355MancombModifyAdministrativeStatusNull() throws Exception { final String TEST_NAME = "test355MancombModifyAdministrativeStatusNull"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2252,7 +2395,7 @@ public void test355MancombModifyAdministrativeStatusNull() throws Exception { @Test public void test400AddHerman() throws Exception { final String TEST_NAME = "test400AddHerman"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // WHEN addObject(USER_HERMAN_FILE); @@ -2269,7 +2412,7 @@ public void test400AddHerman() throws Exception { @Test public void test410AssignHermanKhakiAccount() throws Exception { final String TEST_NAME = "test410AssignHermanKhakiAccount"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2374,7 +2517,7 @@ public void test525SerivceSeaMonkeyRecompute() throws Exception { } private void test5X0CheckInitial(final String TEST_NAME, Class type, String oid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN, WHEN // this happens during test initialization when the role is added @@ -2392,7 +2535,7 @@ private void test5X0CheckInitial(final String TEST_NAME, C * MID-2877 */ private void test5X1Recompute(final String TEST_NAME, Class type, String oid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2419,7 +2562,7 @@ private void test5X1Recompute(final String TEST_NAME, Clas * MID-2877 */ private void test5X2ModifyDisable(final String TEST_NAME, Class type, String oid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2451,7 +2594,7 @@ private void test5X2ModifyDisable(final String TEST_NAME, * MID-2877 */ private void test5X4ModifyEnable(final String TEST_NAME, Class type, String oid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2483,7 +2626,7 @@ private void test5X4ModifyEnable(final String TEST_NAME, C * Make sure that recompute does not destroy anything. */ public void test5X5Recompute(final String TEST_NAME, Class type, String oid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2514,7 +2657,7 @@ public void test5X5Recompute(final String TEST_NAME, Class @Test public void test600AddUser1() throws Exception { final String TEST_NAME = "test600AddUser1"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2559,7 +2702,7 @@ private void checkSuspendedAttribute(DummyAccount dummyAccount, Boolean expected @Test public void test610EnableUser1() throws Exception { final String TEST_NAME = "test610EnableUser1"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN PrismObject user1 = findUserByUsername("user1"); @@ -2596,7 +2739,7 @@ public void test610EnableUser1() throws Exception { @Test public void test700ModifyJackRemoveAdministrativeStatus() throws Exception { final String TEST_NAME = "test700ModifyJackRemoveAdministrativeStatus"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2620,11 +2763,11 @@ public void test700ModifyJackRemoveAdministrativeStatus() throws Exception { PrismAsserts.assertNoItem(userBefore, SchemaConstants.PATH_ACTIVATION_VALID_TO); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2648,7 +2791,7 @@ public void test700ModifyJackRemoveAdministrativeStatus() throws Exception { @Test public void test702ModifyJackFuneralTimestampBeforeNow() throws Exception { final String TEST_NAME = "test702ModifyJackFuneralTimestampBeforeNow"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2665,11 +2808,11 @@ public void test702ModifyJackFuneralTimestampBeforeNow() throws Exception { XMLGregorianCalendar hourAgo = XmlTypeConverter.createXMLGregorianCalendar(clock.currentTimeMillis() - 60 * 60 * 1000); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, getExtensionPath(PIRACY_FUNERAL_TIMESTAMP), task, result, hourAgo); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2692,7 +2835,7 @@ public void test702ModifyJackFuneralTimestampBeforeNow() throws Exception { @Test public void test704ModifyJackFuneralTimestampAfterNow() throws Exception { final String TEST_NAME = "test704ModifyJackFuneralTimestampAfterNow"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestActivation.class.getName() + "." + TEST_NAME); @@ -2709,13 +2852,12 @@ public void test704ModifyJackFuneralTimestampAfterNow() throws Exception { XMLGregorianCalendar hourAhead = XmlTypeConverter.createXMLGregorianCalendar(clock.currentTimeMillis() + 60 * 60 * 1000); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, getExtensionPath(PIRACY_FUNERAL_TIMESTAMP), task, result, hourAhead); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject userAfter = getUser(USER_JACK_OID); display("User after", userAfter); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java index 65143b6b44d..8876fe371b7 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestAudit.java @@ -105,7 +105,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti @Test public void test000Sanity() throws Exception { final String TEST_NAME = "test000Sanity"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); assertTrue(modelAuditService.supportsRetrieval()); @@ -122,7 +122,7 @@ public void test000Sanity() throws Exception { @Test public void test010SanityJack() throws Exception { final String TEST_NAME = "test010SanityJack"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // WHEN List auditRecords = getObjectAuditRecords(USER_JACK_OID); @@ -136,20 +136,20 @@ public void test010SanityJack() throws Exception { @Test public void test100ModifyUserJackKid() throws Exception { final String TEST_NAME = "test100ModifyUserJackKid"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); initialTs = getTimeSafely(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, UserType.F_TITLE, task, result, createPolyString("Kid")); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -165,9 +165,9 @@ public void test100ModifyUserJackKid() throws Exception { @Test public void test105CreateUserHerman() throws Exception { final String TEST_NAME = "test105CreateUserHerman"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userHermanBefore = PrismTestUtil.parseObject(USER_HERMAN_FILE); @@ -177,12 +177,12 @@ public void test105CreateUserHerman() throws Exception { hermanInitialTs = getTimeSafely(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); addObject(userHermanBefore, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -197,9 +197,9 @@ public void test105CreateUserHerman() throws Exception { @Test public void test110ModifyUserJackSailor() throws Exception { final String TEST_NAME = "test110ModifyUserJackSailor"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); @@ -210,12 +210,12 @@ public void test110ModifyUserJackSailor() throws Exception { ActivationStatusType.DISABLED); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(objectDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -230,9 +230,9 @@ public void test110ModifyUserJackSailor() throws Exception { @Test public void test115ModifyUserHermanMarooned() throws Exception { final String TEST_NAME = "test115ModifyUserHermanMarooned"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_HERMAN_OID, UserType.F_TITLE, @@ -241,14 +241,13 @@ public void test115ModifyUserHermanMarooned() throws Exception { objectDelta.addModification(createAssignmentModification(RESOURCE_DUMMY_OID, ShadowKindType.ACCOUNT, null, true)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(objectDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject user = getUser(USER_HERMAN_OID); display("Herman (marooned)", user); @@ -262,9 +261,9 @@ public void test115ModifyUserHermanMarooned() throws Exception { @Test public void test120ModifyUserJackCaptain() throws Exception { final String TEST_NAME = "test120ModifyUserJackCaptain"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_JACK_OID, UserType.F_TITLE, @@ -274,14 +273,13 @@ public void test120ModifyUserJackCaptain() throws Exception { ActivationStatusType.ENABLED); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(objectDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); jackCaptainTs = getTimeSafely(); jackCaptainEid = assertObjectAuditRecords(USER_JACK_OID, 6); @@ -294,9 +292,9 @@ public void test120ModifyUserJackCaptain() throws Exception { @Test public void test125ModifyUserHermanHermit() throws Exception { final String TEST_NAME = "test125ModifyUserHermanHermit"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_HERMAN_OID, UserType.F_TITLE, @@ -311,15 +309,14 @@ public void test125ModifyUserHermanHermit() throws Exception { null, null, null, true)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(objectDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject user = getUser(USER_HERMAN_OID); display("Herman (hermit)", user); @@ -332,9 +329,9 @@ public void test125ModifyUserHermanHermit() throws Exception { @Test public void test135ModifyUserHermanCivilisedHermit() throws Exception { final String TEST_NAME = "test135ModifyUserHermanCivilisedHermit"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_HERMAN_OID, UserType.F_TITLE, @@ -344,15 +341,14 @@ public void test135ModifyUserHermanCivilisedHermit() throws Exception { null, null, null, false)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(objectDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject user = getUser(USER_HERMAN_OID); display("Herman (civilised hermit)", user); @@ -365,9 +361,9 @@ public void test135ModifyUserHermanCivilisedHermit() throws Exception { @Test public void test200ReconstructJackSailor() throws Exception { final String TEST_NAME = "test200ReconstructJackSailor"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = getUser(USER_JACK_OID); @@ -376,15 +372,14 @@ public void test200ReconstructJackSailor() throws Exception { PrismAsserts.assertPropertyValue(userBefore, UserType.F_TITLE, createPolyString("Captain")); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject jackReconstructed = modelAuditService.reconstructObject(UserType.class, USER_JACK_OID, jackSailorEid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); display("Reconstructed jack", jackReconstructed); @@ -397,9 +392,9 @@ public void test200ReconstructJackSailor() throws Exception { @Test public void test210ReconstructJackKid() throws Exception { final String TEST_NAME = "test210ReconstructJackKid"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = getUser(USER_JACK_OID); @@ -408,15 +403,14 @@ public void test210ReconstructJackKid() throws Exception { PrismAsserts.assertPropertyValue(userBefore, UserType.F_TITLE, createPolyString("Captain")); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject jackReconstructed = modelAuditService.reconstructObject(UserType.class, USER_JACK_OID, jackKidEid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); display("Reconstructed jack", jackReconstructed); @@ -431,9 +425,9 @@ public void test210ReconstructJackKid() throws Exception { @Test public void test250ReconstructHermanCreated() throws Exception { final String TEST_NAME = "test250ReconstructHermanCreated"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = getUser(USER_HERMAN_OID); @@ -445,15 +439,14 @@ public void test250ReconstructHermanCreated() throws Exception { assertAssignments(userBefore, 1); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject hermanReconstructed = modelAuditService.reconstructObject(UserType.class, USER_HERMAN_OID, hermanCreatedEid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); display("Reconstructed herman", hermanReconstructed); @@ -472,21 +465,20 @@ public void test250ReconstructHermanCreated() throws Exception { @Test public void test252ReconstructHermanMarooned() throws Exception { final String TEST_NAME = "test252ReconstructHermanMarooned"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject hermanReconstructed = modelAuditService.reconstructObject(UserType.class, USER_HERMAN_OID, hermanMaroonedEid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); display("Reconstructed herman", hermanReconstructed); @@ -506,21 +498,20 @@ public void test252ReconstructHermanMarooned() throws Exception { @Test public void test254ReconstructHermanHermit() throws Exception { final String TEST_NAME = "test254ReconstructHermanHermit"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); PrismObject hermanReconstructed = modelAuditService.reconstructObject(UserType.class, USER_HERMAN_OID, hermanHermitEid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); display("Reconstructed herman", hermanReconstructed); @@ -588,7 +579,7 @@ public void test300ConcurrentAudits() throws Exception { Thread thread = new Thread(() -> { try { login(userAdministrator); - Task threadTask = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task threadTask = createTask(TEST_NAME); OperationResult threadResult = threadTask.getResult(); for (int iteration = 0; iteration < ITERATIONS; iteration++) { display("Executing iteration " + iteration + " on user " + index); @@ -659,7 +650,7 @@ public void test310ConcurrentAuditsRaw() throws Exception { Thread thread = new Thread(() -> { try { login(userAdministrator); - Task threadTask = taskManager.createTaskInstance(TestAudit.class.getName() + "." + TEST_NAME); + Task threadTask = createTask(TEST_NAME); OperationResult threadResult = threadTask.getResult(); for (int iteration = 0; iteration < ITERATIONS; iteration++) { display("Executing iteration " + iteration + " in worker " + index); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestDeputy.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestDeputy.java index 87909e3b786..ca24db2d83c 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestDeputy.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestDeputy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Evolveum + * Copyright (c) 2016-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,7 +71,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti @Test public void test000Sanity() throws Exception { final String TEST_NAME = "test000Sanity"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); PrismObject userJack = getUser(USER_JACK_OID); display("User Jack", userJack); @@ -93,18 +93,18 @@ public void test000Sanity() throws Exception { @Test public void test100AssignDeputyNoBigDeal() throws Exception { final String TEST_NAME = "test100AssignDeputyNoBigDeal"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputy(USER_BARBOSSA_OID, USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -130,18 +130,18 @@ public void test100AssignDeputyNoBigDeal() throws Exception { @Test public void test109UnassignDeputyNoBigDeal() throws Exception { final String TEST_NAME = "test109UnassignDeputyNoBigDeal"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputy(USER_BARBOSSA_OID, USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -166,18 +166,18 @@ public void test109UnassignDeputyNoBigDeal() throws Exception { @Test public void test110AssignJackPirate() throws Exception { final String TEST_NAME = "test110AssignJackPirate"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(USER_JACK_OID, ROLE_PIRATE_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -204,18 +204,18 @@ public void test110AssignJackPirate() throws Exception { @Test public void test112AssignDeputyPirate() throws Exception { final String TEST_NAME = "test112AssignDeputyPirate"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputy(USER_BARBOSSA_OID, USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -247,18 +247,18 @@ public void test112AssignDeputyPirate() throws Exception { @Test public void test119UnassignDeputyPirate() throws Exception { final String TEST_NAME = "test119UnassignDeputyPirate"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputy(USER_BARBOSSA_OID, USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -285,9 +285,9 @@ public void test119UnassignDeputyPirate() throws Exception { @Test public void test120AssignbarbossaDeputyOfGuybrush() throws Exception { final String TEST_NAME = "test120AssignbarbossaDeputyOfGuybrush"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userGuybrushBefore = getUser(USER_GUYBRUSH_OID); @@ -295,12 +295,12 @@ public void test120AssignbarbossaDeputyOfGuybrush() throws Exception { assertLinks(userGuybrushBefore, 1); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputy(USER_BARBOSSA_OID, USER_GUYBRUSH_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -328,18 +328,18 @@ public void test120AssignbarbossaDeputyOfGuybrush() throws Exception { @Test public void test122AssignGuybrushPirate() throws Exception { final String TEST_NAME = "test122AssignGuybrushPirate"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(USER_GUYBRUSH_OID, ROLE_PIRATE_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -367,18 +367,18 @@ public void test122AssignGuybrushPirate() throws Exception { @Test public void test124RecomputeBarbossa() throws Exception { final String TEST_NAME = "test124RecomputeBarbossa"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_BARBOSSA_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -408,18 +408,18 @@ public void test124RecomputeBarbossa() throws Exception { @Test public void test126UnassignGuybrushPirate() throws Exception { final String TEST_NAME = "test126UnassignGuybrushPirate"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignRole(USER_GUYBRUSH_OID, ROLE_PIRATE_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -446,19 +446,19 @@ public void test126UnassignGuybrushPirate() throws Exception { @Test public void test128RecomputeBarbossa() throws Exception { final String TEST_NAME = "test128RecomputeBarbossa"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_BARBOSSA_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -480,18 +480,18 @@ public void test128RecomputeBarbossa() throws Exception { @Test public void test129UnassignBarbossaDeputyOfGuybrush() throws Exception { final String TEST_NAME = "test129UnassignBarbossaDeputyOfGuybrush"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputy(USER_BARBOSSA_OID, USER_GUYBRUSH_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -516,9 +516,9 @@ public void test129UnassignBarbossaDeputyOfGuybrush() throws Exception { @Test public void test150AssignJackMoreRoles() throws Exception { final String TEST_NAME = "test150AssignJackMoreRoles"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createAssignmentUserDelta(USER_JACK_OID, ROLE_PIRATE_OID, RoleType.COMPLEX_TYPE, @@ -538,12 +538,12 @@ public void test150AssignJackMoreRoles() throws Exception { null, null, (ActivationType) null, true))); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -570,20 +570,20 @@ public void test150AssignJackMoreRoles() throws Exception { @Test public void test152AssignbarbossaDeputyLimitedDeputy() throws Exception { final String TEST_NAME = "test152AssignbarbossaDeputyLimitedDeputy"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_PIRATE_OID), createOrgReference(ORG_MINISTRY_OF_RUM_OID, SchemaConstants.ORG_MANAGER)); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -607,20 +607,20 @@ public void test152AssignbarbossaDeputyLimitedDeputy() throws Exception { @Test public void test154UnassignbarbossaDeputyLimitedDeputy() throws Exception { final String TEST_NAME = "test154UnassignbarbossaDeputyLimitedDeputy"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_PIRATE_OID), createOrgReference(ORG_MINISTRY_OF_RUM_OID, SchemaConstants.ORG_MANAGER)); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -641,13 +641,13 @@ public void test154UnassignbarbossaDeputyLimitedDeputy() throws Exception { @Test public void test156AssignbarbossaDeputyLimitedDeputyRed() throws Exception { final String TEST_NAME = "test156AssignbarbossaDeputyLimitedDeputyRed"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_RED_SAILOR_OID), @@ -655,7 +655,7 @@ public void test156AssignbarbossaDeputyLimitedDeputyRed() throws Exception { ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -679,16 +679,16 @@ public void test156AssignbarbossaDeputyLimitedDeputyRed() throws Exception { @Test public void test159UnassignbarbossaDeputyLimitedDeputyRed() throws Exception { final String TEST_NAME = "test159UnassignbarbossaDeputyLimitedDeputyRed"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_RED_SAILOR_OID), @@ -696,7 +696,7 @@ public void test159UnassignbarbossaDeputyLimitedDeputyRed() throws Exception { ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -721,20 +721,20 @@ public void test159UnassignbarbossaDeputyLimitedDeputyRed() throws Exception { @Test public void test160AssignbarbossaDeputyLimitedDeputyEmpty() throws Exception { final String TEST_NAME = "test160AssignbarbossaDeputyLimitedDeputyEmpty"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_EMPTY_OID) ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -758,23 +758,23 @@ public void test160AssignbarbossaDeputyLimitedDeputyEmpty() throws Exception { @Test public void test162UnassignbarbossaDeputyLimitedDeputyEmpty() throws Exception { final String TEST_NAME = "test162UnassignbarbossaDeputyLimitedDeputyEmpty"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_EMPTY_OID) ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -799,20 +799,20 @@ public void test162UnassignbarbossaDeputyLimitedDeputyEmpty() throws Exception { @Test public void test170AddRoleDrinker() throws Exception { final String TEST_NAME = "test170AssignJackRoleDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject role = PrismTestUtil.parseObject(ROLE_DRINKER_FILE); display("Adding role", role); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); addObject(role, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -825,17 +825,17 @@ public void test170AddRoleDrinker() throws Exception { @Test public void test172AssignJackRoleDrinker() throws Exception { final String TEST_NAME = "test170AssignJackRoleDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(USER_JACK_OID, ROLE_DRINKER_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -856,20 +856,20 @@ public void test172AssignJackRoleDrinker() throws Exception { @Test public void test172AssignbarbossaDeputyLimitedDeputyDrinker() throws Exception { final String TEST_NAME = "test172AssignbarbossaDeputyLimitedDeputyDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_DRINKER_OID) ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -885,23 +885,23 @@ public void test172AssignbarbossaDeputyLimitedDeputyDrinker() throws Exception { @Test public void test178UnassignbarbossaDeputyLimitedDeputyDrinker() throws Exception { final String TEST_NAME = "test178UnassignbarbossaDeputyLimitedDeputyDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_DRINKER_OID) ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -926,13 +926,13 @@ public void test178UnassignbarbossaDeputyLimitedDeputyDrinker() throws Exception @Test public void test180AssignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Exception { final String TEST_NAME = "test180AssignbarbossaDeputyLimitedDeputyEmptyDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_EMPTY_OID), @@ -940,7 +940,7 @@ public void test180AssignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Except ); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -964,16 +964,16 @@ public void test180AssignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Except @Test public void test182UnassignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Exception { final String TEST_NAME = "test182UnassignbarbossaDeputyLimitedDeputyEmptyDrinker"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignDeputyLimits(USER_BARBOSSA_OID, USER_JACK_OID, task, result, createRoleReference(ROLE_EMPTY_OID), @@ -981,9 +981,8 @@ public void test182UnassignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Exce ); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); @@ -1007,7 +1006,7 @@ public void test182UnassignbarbossaDeputyLimitedDeputyEmptyDrinker() throws Exce @Test public void test800ImportValidityScannerTask() throws Exception { final String TEST_NAME = "test800ImportValidityScannerTask"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TestValidityRecomputeTask.class.getName() + "." + TEST_NAME); @@ -1016,14 +1015,14 @@ public void test800ImportValidityScannerTask() throws Exception { XMLGregorianCalendar startCal = clock.currentTimeXMLGregorianCalendar(); /// WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); importObjectFromFile(TASK_VALIDITY_SCANNER_FILENAME); waitForTaskStart(TASK_VALIDITY_SCANNER_OID, false); waitForTaskFinish(TASK_VALIDITY_SCANNER_OID, true); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); XMLGregorianCalendar endCal = clock.currentTimeXMLGregorianCalendar(); assertLastRecomputeTimestamp(TASK_VALIDITY_SCANNER_OID, startCal, endCal); } @@ -1035,9 +1034,9 @@ public void test800ImportValidityScannerTask() throws Exception { @Test public void test802AssignBarbossaDeputyOfJack() throws Exception { final String TEST_NAME = "test802AssignBarbossaDeputyOfJack"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userJackBefore = getUser(USER_JACK_OID); @@ -1052,15 +1051,14 @@ public void test802AssignBarbossaDeputyOfJack() throws Exception { activationType.setValidTo(XmlTypeConverter.addDuration(startTs, "PT2H")); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignDeputy(USER_BARBOSSA_OID, USER_JACK_OID, assignment -> assignment.setActivation(activationType), task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); @@ -1085,15 +1083,14 @@ public void test802AssignBarbossaDeputyOfJack() throws Exception { } /** - * Assign Barbossa as Jack's deputy. Barbossa should have all the privileges now. - * But they will expire soon ... + * Assign Barbossa as Jack's deputy. Barbossa privileges are about to expire. */ @Test public void test804BarbosaThreeHoursLater() throws Exception { final String TEST_NAME = "test804BarbosaThreeHoursLater"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestDeputy.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); clock.overrideDuration("PT3H"); @@ -1101,14 +1098,13 @@ public void test804BarbosaThreeHoursLater() throws Exception { XMLGregorianCalendar startTs = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); waitForTaskNextRunAssertSuccess(TASK_VALIDITY_SCANNER_OID, true); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); XMLGregorianCalendar endTs = clock.currentTimeXMLGregorianCalendar(); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestIntent.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestIntent.java index 00c3aeaf7f1..64cf9f33acd 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestIntent.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestIntent.java @@ -67,10 +67,10 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti @Test public void test131ModifyUserJackAssignAccountDefault() throws Exception { final String TEST_NAME="test131ModifyUserJackAssignAccountDefault"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestIntent.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -128,10 +128,10 @@ public void test131ModifyUserJackAssignAccountDefault() throws Exception { @Test public void test132ModifyUserJackAssignAccountTest() throws Exception { final String TEST_NAME="test132ModifyUserJackAssignAccountTest"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestIntent.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -202,10 +202,10 @@ public void test132ModifyUserJackAssignAccountTest() throws Exception { @Test public void test135ModifyUserJackFullName() throws Exception { final String TEST_NAME="test135ModifyUserJackFullName"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestIntent.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -265,10 +265,10 @@ public void test135ModifyUserJackFullName() throws Exception { @Test public void test147ModifyUserJackUnAssignAccountDefault() throws Exception { final String TEST_NAME="test147ModifyUserJackUnAssignAccountDefault"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestIntent.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -326,10 +326,10 @@ public void test147ModifyUserJackUnAssignAccountDefault() throws Exception { @Test public void test149ModifyUserJackUnassignAccountTest() throws Exception { final String TEST_NAME = "test149ModifyUserJackUnassignAccountTest"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestIntent.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -342,8 +342,7 @@ public void test149ModifyUserJackUnassignAccountTest() throws Exception { modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); PrismObject userJack = getUser(USER_JACK_OID); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMapping.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMapping.java index 0565e5318de..a454e33ee2d 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMapping.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMapping.java @@ -326,7 +326,8 @@ accountOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttributePat dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -371,7 +372,8 @@ accountOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttributePat dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -412,7 +414,8 @@ accountOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttributePat dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -457,7 +460,8 @@ accountOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttributePat dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -717,7 +721,8 @@ accountOid, getDummyResourceController(RESOURCE_DUMMY_RED_NAME).getAttributePath dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -907,7 +912,7 @@ public void test139DeleteAccountRed() throws Exception { dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.DELETE, ShadowType.class); dummyAuditService.assertExecutionSuccess(); @@ -1130,7 +1135,8 @@ public void test144ModifyAccountLocationReplaceEmpty() throws Exception { dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(1); + dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java index ac0d2bf9980..798190b5eae 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestModelServiceContract.java @@ -132,7 +132,7 @@ public void test050GetUserJack() throws Exception { final String TEST_NAME = "test050GetUserJack"; displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -155,7 +155,7 @@ public void test051GetUserBarbossa() throws Exception { final String TEST_NAME = "test051GetUserBarbossa"; displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -253,21 +253,20 @@ public void test100ModifyUserAddAccount() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserAddAccount(USER_JACK_OID, ACCOUNT_JACK_DUMMY_FILE, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); // Check accountRef - PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); - display("User jack after", userJack); - assertUserJack(userJack); - UserType userJackType = userJack.asObjectable(); + PrismObject userAfter = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); + display("User jack after", userAfter); + assertUserJack(userAfter); + UserType userJackType = userAfter.asObjectable(); assertEquals("Unexpected number of accountRefs", 1, userJackType.getLinkRef().size()); ObjectReferenceType accountRefType = userJackType.getLinkRef().get(0); accountJackOid = accountRefType.getOid(); @@ -288,14 +287,14 @@ public void test100ModifyUserAddAccount() throws Exception { // Check account in dummy resource assertDefaultDummyAccount("jack", "Jack Sparrow", true); - assertDummyScriptsAdd(userJack, accountModel, getDummyResourceType()); + assertDummyScriptsAdd(userAfter, accountModel, getDummyResourceType()); // Check audit display("Audit", dummyAuditService); dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, add account, link dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.ADD, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -334,7 +333,7 @@ public void test101GetAccount() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -358,8 +357,7 @@ public void test101GetAccount() throws Exception { display("Account attributes def complex type def", accountContainer.getDefinition().getComplexTypeDefinition()); assertDummyAccountShadowModel(account, accountJackOid, "jack", "Jack Sparrow"); - result.computeStatus(); - TestUtil.assertSuccess("getObject result", result); + assertSuccess("getObject result", result); account.checkConsistence(true, true, ConsistencyCheckScope.THOROUGH); @@ -414,8 +412,7 @@ public void test102GetAccountNoFetch() throws Exception { display("Account attributes def complex type def", accountContainer.getDefinition().getComplexTypeDefinition()); assertDummyAccountShadowRepo(account, accountJackOid, "jack"); - result.computeStatus(); - TestUtil.assertSuccess("getObject result", result); + assertSuccess("getObject result", result); assertSteadyResources(); } @@ -442,8 +439,7 @@ public void test103GetAccountRaw() throws Exception { display("Account attributes def complex type def", accountContainer.getDefinition().getComplexTypeDefinition()); assertDummyAccountShadowRepo(account, accountJackOid, "jack"); - result.computeStatus(); - TestUtil.assertSuccess("getObject result", result); + assertSuccess("getObject result", result); assertSteadyResources(); } @@ -739,7 +735,7 @@ public void test119ModifyUserDeleteAccount() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -752,11 +748,11 @@ public void test119ModifyUserDeleteAccount() throws Exception { Collection> deltas = MiscSchemaUtil.createCollection(userDelta); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result, 2); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); @@ -785,7 +781,7 @@ public void test119ModifyUserDeleteAccount() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, delete account, unlink dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.DELETE, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -898,8 +894,7 @@ public void test121ModifyUserAddAccountRef() throws Exception { modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); // There is strong mapping. Complete account is fetched. assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); @@ -924,7 +919,7 @@ public void test121ModifyUserAddAccountRef() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, modify account, link dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -1129,26 +1124,27 @@ public void test131ModifyUserJackAssignAccount() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignAccount(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); assertCounterIncrement(InternalCounters.PRISM_OBJECT_CLONE_COUNT, 66); - PrismObject userJack = getUser(USER_JACK_OID); - display("User after change execution", userJack); - assertUserJack(userJack); - AssignmentType assignmentType = assertAssignedAccount(userJack, RESOURCE_DUMMY_OID); - assertAssignments(userJack, 1); - assertModifyMetadata(userJack, startTime, endTime); + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after change execution", userAfter); + assertUserJack(userAfter); + AssignmentType assignmentType = assertAssignedAccount(userAfter, RESOURCE_DUMMY_OID); + assertAssignments(userAfter, 1); + assertModifyMetadata(userAfter, startTime, endTime); assertCreateMetadata(assignmentType, startTime, endTime); + assertLastProvisioningTimestamp(userAfter, startTime, endTime); - accountJackOid = getSingleLinkOid(userJack); + accountJackOid = getSingleLinkOid(userAfter); // Check shadow PrismObject accountShadow = repositoryService.getObject(ShadowType.class, accountJackOid, null, result); @@ -1163,7 +1159,7 @@ public void test131ModifyUserJackAssignAccount() throws Exception { // Check account in dummy resource assertDefaultDummyAccount("jack", "Jack Sparrow", true); - assertDummyScriptsAdd(userJack, accountModel, getDummyResourceType()); + assertDummyScriptsAdd(userAfter, accountModel, getDummyResourceType()); // Check audit display("Audit", dummyAuditService); @@ -1199,7 +1195,7 @@ public void test132ModifyAccountJackDummy() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -1215,8 +1211,7 @@ public void test132ModifyAccountJackDummy() throws Exception { modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); // There is strong mapping. Complete account is fetched. assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); @@ -1256,7 +1251,8 @@ public void test132ModifyAccountJackDummy() throws Exception { dummyAuditService.assertRecords(3); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(0, 1); + dummyAuditService.assertExecutionDeltas(0, 2); // lastProvisioningTimestamp, modify account + dummyAuditService.assertHasDelta(0, ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(0, ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertOldValue(0, ChangeType.MODIFY, ShadowType.class, dummyResourceCtl.getAttributeFullnamePath(), "Jack Sparrow"); @@ -1292,18 +1288,17 @@ public void test135ModifyUserJackAssignAccountAgain() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignAccount(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + displayThen(TEST_NAME); + assertSuccess("executeChanges result", result); PrismObject userJack = getUser(USER_JACK_OID); display("User after change execution", userJack); @@ -1346,6 +1341,66 @@ public void test135ModifyUserJackAssignAccountAgain() throws Exception { checkDummyTransportMessages("simpleUserNotifier", 1); checkDummyTransportMessages("simpleUserNotifier-ADD", 0); + assertSteadyResources(); + } + + @Test + public void test136JackRecomputeNoChange() throws Exception { + final String TEST_NAME="test136JackRecomputeNoChange"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + preTestCleanup(AssignmentPolicyEnforcementType.FULL); + + XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); + + // WHEN + displayWhen(TEST_NAME); + recomputeUser(USER_JACK_OID, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getUser(USER_JACK_OID); + display("User after change execution", userAfter); + assertUserJack(userAfter); + assertAssignedAccount(userAfter, RESOURCE_DUMMY_OID); + assertAssignments(userAfter, 1); + assertLastProvisioningTimestamp(userAfter, null, startTime); + + String accountJackOidAfter = getSingleLinkOid(userAfter); + assertEquals("Account OID changed", accountJackOid, accountJackOidAfter); + + // Check shadow + PrismObject accountShadow = repositoryService.getObject(ShadowType.class, accountJackOid, null, result); + assertDummyAccountShadowRepo(accountShadow, accountJackOid, "jack"); + + // Check account + PrismObject accountModel = modelService.getObject(ShadowType.class, accountJackOid, null, task, result); + assertDummyAccountShadowModel(accountModel, accountJackOid, "jack", "Cpt. Jack Sparrow"); + + // Check account in dummy resource + assertDefaultDummyAccount("jack", "Cpt. Jack Sparrow", true); + + // Check audit + display("Audit", dummyAuditService); + dummyAuditService.assertRecords(0); + dummyAuditService.assertSimpleRecordSanity(); + + // Check notifications + notificationManager.setDisabled(true); + checkDummyTransportMessages(NOTIFIER_ACCOUNT_PASSWORD_NAME, 0); + checkDummyTransportMessages("userPasswordNotifier", 0); + checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); + checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); + checkDummyTransportMessages("simpleAccountNotifier-DELETE-SUCCESS", 0); + checkDummyTransportMessages("simpleUserNotifier", 0); + checkDummyTransportMessages("simpleUserNotifier-ADD", 0); + assertSteadyResources(); } @@ -1355,7 +1410,7 @@ public void test139ModifyUserJackUnassignAccount() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -1418,7 +1473,7 @@ public void test141ModifyUserJackAssignAccountPositiveEnforcement() throws Excep displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -1522,11 +1577,11 @@ public void test148ModifyUserJackUnassignAccountPositiveEnforcement() throws Exc assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT, 1); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); // There is strong mapping. Complete account is fetched. @@ -1592,7 +1647,7 @@ public void test149ModifyUserJackDeleteAccount() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -1610,8 +1665,7 @@ public void test149ModifyUserJackDeleteAccount() throws Exception { modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); PrismObject userJack = getUser(USER_JACK_OID); @@ -1632,7 +1686,7 @@ public void test149ModifyUserJackDeleteAccount() throws Exception { dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, delete account, unlink dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.DELETE, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -1662,7 +1716,7 @@ public void test151ModifyUserJackAssignAccountRelativeEnforcement() throws Excep displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.RELATIVE); @@ -1804,7 +1858,7 @@ public void test161ModifyUserJackAssignAccountNoneEnforcement() throws Exception displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.NONE); @@ -1867,7 +1921,7 @@ public void test163ModifyUserJackAddAccountNoneEnforcement() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.NONE); @@ -1890,8 +1944,7 @@ public void test163ModifyUserJackAddAccountNoneEnforcement() throws Exception { modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); @@ -1920,7 +1973,7 @@ public void test163ModifyUserJackAddAccountNoneEnforcement() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, add account, link dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.ADD, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -2014,7 +2067,7 @@ public void test169ModifyUserJackDeleteAccountNoneEnforcement() throws Exception displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.NONE); @@ -2032,8 +2085,7 @@ public void test169ModifyUserJackDeleteAccountNoneEnforcement() throws Exception modelService.executeChanges(deltas, null, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); PrismObject userJack = getUser(USER_JACK_OID); @@ -2054,7 +2106,7 @@ public void test169ModifyUserJackDeleteAccountNoneEnforcement() throws Exception dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); // lastProvisioningTimestamp, delete account, unlink dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(ChangeType.DELETE, ShadowType.class); dummyAuditService.assertTarget(USER_JACK_OID); @@ -2081,7 +2133,7 @@ public void test180ModifyUserAddAccountFullEnforcement() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -2142,7 +2194,7 @@ public void test182ModifyUserAddAndAssignAccountPositiveEnforcement() throws Exc displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.POSITIVE); @@ -2358,7 +2410,7 @@ public void test191ModifyUserJackModifyAssignment() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); Collection> deltas = new ArrayList>(); @@ -2416,11 +2468,11 @@ public void test191ModifyUserJackModifyAssignment() throws Exception { display("Deltas to execute execution", deltas); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); @@ -2472,17 +2524,17 @@ public void test195ModifyUserJack() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, UserType.F_FULL_NAME, task, result, PrismTestUtil.createPolyString("Magnificent Captain Jack Sparrow")); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); // Strong mappings @@ -2545,7 +2597,7 @@ public void test196ModifyUserJackLocationEmpty() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -2609,7 +2661,7 @@ public void test197ModifyUserJackLocationNull() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -2855,11 +2907,11 @@ public void test210AddUserMorganWithAssignment() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); @@ -2927,16 +2979,16 @@ public void test212RenameUserMorgan() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_MORGAN_OID, UserType.F_NAME, task, result, PrismTestUtil.createPolyString("sirhenry")); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess("executeChanges result", result); // Strong mappings @@ -2973,7 +3025,7 @@ public void test212RenameUserMorgan() throws Exception { dummyAuditService.assertHasDelta(ChangeType.MODIFY, UserType.class); ObjectDeltaOperation auditShadowDelta = dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); - assertEquals("Unexpected number of modifications in shadow audit delta: "+auditShadowDelta.debugDump(), 3, auditShadowDelta.getObjectDelta().getModifications().size()); + assertEquals("Unexpected number of modifications in shadow audit delta: "+auditShadowDelta.debugDump(), 5, auditShadowDelta.getObjectDelta().getModifications().size()); dummyAuditService.assertOldValue(ChangeType.MODIFY, UserType.class, UserType.F_NAME, PrismTestUtil.createPolyString("morgan")); @@ -3013,7 +3065,7 @@ public void test240AddUserCharlesRaw() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -3058,7 +3110,7 @@ public void test241DeleteUserCharlesRaw() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestModelServiceContract.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); preTestCleanup(AssignmentPolicyEnforcementType.FULL); @@ -3069,8 +3121,7 @@ public void test241DeleteUserCharlesRaw() throws Exception { modelService.executeChanges(deltas, ModelExecuteOptions.createRaw(), task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); PrismObject userAfter = findUserByUsername("charles"); @@ -3119,7 +3170,8 @@ public void test300AddUserJackWithAssignmentBlue() throws Exception { assertSuccess(result); XMLGregorianCalendar endTime = clock.currentTimeXMLGregorianCalendar(); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); + // Weak activation mapping means account load + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 1); PrismObject userJackAfter = getUser(USER_JACK_OID); display("User after change execution", userJackAfter); @@ -3183,8 +3235,7 @@ accountJackBlueOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttr modelService.executeChanges(deltas, options, task, result); // THEN - result.computeStatus(); - TestUtil.assertSuccess("executeChanges result", result); + assertSuccess(result); // Not sure why 2 ... but this is not a big problem now assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 2); @@ -3212,7 +3263,8 @@ accountJackBlueOid, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttr dummyAuditService.assertRecords(2); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(0, 1); + dummyAuditService.assertExecutionDeltas(0, 2); // lastProvisioningTimestamp, modify account + dummyAuditService.assertHasDelta(0, ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(0, ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertOldValue(0, ChangeType.MODIFY, ShadowType.class, getDummyResourceController(RESOURCE_DUMMY_BLUE_NAME).getAttributeFullnamePath(), "Jack Sparrow"); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMultiResource.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMultiResource.java index 687578046c2..367371e8017 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMultiResource.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestMultiResource.java @@ -273,7 +273,7 @@ public void test120JackAssignRoleDummiesRelative() throws Exception { getDummyResource().resetBreakMode(); // Clean up user - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); modifyUserReplace(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result); @@ -292,7 +292,7 @@ public void test121JackTryDeleteAccount() throws Exception { getDummyResource().resetBreakMode(); // Clean up user - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userJack = getUser(USER_JACK_OID); String accountJackDummyOid = getLinkRefOid(userJack, RESOURCE_DUMMY_OID); @@ -333,7 +333,7 @@ public void test200JackAssignDummyIvory() throws Exception { final String TEST_NAME = "test200JackAssignDummyIvory"; // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -367,7 +367,7 @@ public void test209JackUnAssignDummyIvory() throws Exception { final String TEST_NAME = "test209JackUnAssignDummyIvory"; // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -397,10 +397,10 @@ public void test209JackUnAssignDummyIvory() throws Exception { @Test public void test210JackAssignDummyBeige() throws Exception { final String TEST_NAME = "test210JackAssignDummyBeige"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -408,11 +408,11 @@ public void test210JackAssignDummyBeige() throws Exception { modifyUserReplace(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignAccount(USER_JACK_OID, RESOURCE_DUMMY_BEIGE_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -435,10 +435,10 @@ public void test210JackAssignDummyBeige() throws Exception { @Test public void test219JackUnAssignDummyBeige() throws Exception { final String TEST_NAME = "test219JackUnAssignDummyBeige"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -446,11 +446,11 @@ public void test219JackUnAssignDummyBeige() throws Exception { modifyUserReplace(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_BEIGE_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -470,10 +470,10 @@ public void test219JackUnAssignDummyBeige() throws Exception { @Test public void test220JackAssignDummyBeigeAndDefault() throws Exception { final String TEST_NAME = "test220JackAssignDummyBeigeAndDefault"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -484,11 +484,11 @@ public void test220JackAssignDummyBeigeAndDefault() throws Exception { userDelta.addModification(createAssignmentModification(RESOURCE_DUMMY_OID, ShadowKindType.ACCOUNT, null, true)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); executeChanges(userDelta, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -510,18 +510,18 @@ public void test220JackAssignDummyBeigeAndDefault() throws Exception { @Test public void test221JackRecompute() throws Exception { final String TEST_NAME = "test221JackRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -539,27 +539,27 @@ public void test221JackRecompute() throws Exception { /** * Delete account on default dummy resource (but keep it assigned and keep the shadow). - * The recompute the user. The account should be re-created. + * Then recompute the user. The account should be re-created. * MID-2134, MID-3093 */ @Test public void test223JackKillDefaultDummyAccounAndRecompute() throws Exception { final String TEST_NAME = "test223JackKillDefaultDummyAccounAndRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); getDummyResource().deleteAccountByName(ACCOUNT_JACK_DUMMY_USERNAME); display("dummy resource before", getDummyResource()); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -586,21 +586,21 @@ public void test223JackKillDefaultDummyAccounAndRecompute() throws Exception { @Test public void test224JackKillBeigeAccounAndRecompute() throws Exception { final String TEST_NAME = "test224JackKillBeigeAccounAndRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); dummyResourceBeige.deleteAccountByName(ACCOUNT_JACK_DUMMY_USERNAME); display("beige dummy resource before", dummyResourceBeige); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, ModelExecuteOptions.createReconcile(), task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -620,16 +620,16 @@ public void test224JackKillBeigeAccounAndRecompute() throws Exception { /** * Delete both accounts on beige and default dummy resource (but keep it assigned and keep the shadows). - * The recompute the user. The accounts should be re-created. + * Then recompute the user. The accounts should be re-created. * MID-2134, MID-3093 */ @Test public void test225JackKillBothAccounsAndRecompute() throws Exception { final String TEST_NAME = "test225JackKillBothAccounsAndRecompute"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); getDummyResource().deleteAccountByName(ACCOUNT_JACK_DUMMY_USERNAME); @@ -639,13 +639,12 @@ public void test225JackKillBothAccounsAndRecompute() throws Exception { display("beige dummy resource before", dummyResourceBeige); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(USER_JACK_OID, ModelExecuteOptions.createReconcile(), task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject userJack = getUser(USER_JACK_OID); assertLinks(userJack, 2); @@ -671,7 +670,7 @@ public void test225JackKillBothAccounsAndRecompute() throws Exception { @Test public void test227ModifyUserJackDefaultDummyBrokenSchemaViolation() throws Exception { final String TEST_NAME = "test227ModifyUserJackDefaultDummyBrokenSchemaViolation"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestMultiResource.class.getName() + "." + TEST_NAME); @@ -681,12 +680,12 @@ public void test227ModifyUserJackDefaultDummyBrokenSchemaViolation() throws Exce getDummyResource().setModifyBreakMode(BreakMode.SCHEMA); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, UserType.F_FULL_NAME, task, result, new PolyString("Cpt. Jack Sparrow", null)); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); display("Result", result); TestUtil.assertPartialError(result); @@ -715,7 +714,7 @@ public void test227ModifyUserJackDefaultDummyBrokenSchemaViolation() throws Exce @Test public void test228ModifyUserJackDefaultDummyNoError() throws Exception { final String TEST_NAME = "test228ModifyUserJackDefaultDummyNoError"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestMultiResource.class.getName() + "." + TEST_NAME); @@ -724,12 +723,12 @@ public void test228ModifyUserJackDefaultDummyNoError() throws Exception { getDummyResource().resetBreakMode(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(USER_JACK_OID, UserType.F_FULL_NAME, task, result, new PolyString(USER_JACK_FULL_NAME, null)); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); display("Result", result); TestUtil.assertSuccess(result); @@ -756,10 +755,10 @@ public void test228ModifyUserJackDefaultDummyNoError() throws Exception { @Test public void test229JackUnassignDummyBeigeAndDefault() throws Exception { final String TEST_NAME = "test229JackUnassignDummyBeigeAndDefault"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); getDummyResource().resetBreakMode(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -768,11 +767,11 @@ public void test229JackUnassignDummyBeigeAndDefault() throws Exception { userDelta.addModification(createAssignmentModification(RESOURCE_DUMMY_OID, ShadowKindType.ACCOUNT, null, false)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); executeChanges(userDelta, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -792,10 +791,10 @@ public void test229JackUnassignDummyBeigeAndDefault() throws Exception { @Test public void test250JackAssignDummyLavender() throws Exception { final String TEST_NAME = "test250JackAssignDummyLavender"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); @@ -829,9 +828,9 @@ public void test250JackAssignDummyLavender() throws Exception { * resource through the user to the other resource. If dependency does not work then no value is propagated. */ public void jackAssignRoleDummies(final String TEST_NAME) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); clearJackOrganizationalUnit(task, result); @@ -874,9 +873,9 @@ public void jackAssignRoleDummies(final String TEST_NAME) throws Exception { } public void jackRename(final String TEST_NAME) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); jackRename(TEST_NAME, "jackie", "Jackie Sparrow", task, result); @@ -891,11 +890,11 @@ public void jackRename(final String TEST_NAME, String toName, String toFullName, Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -932,9 +931,9 @@ public void jackRename(final String TEST_NAME, String toName, String toFullName, } public void jackUnAssignRoleDummies(final String TEST_NAME) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN @@ -962,9 +961,9 @@ public void jackUnAssignRoleDummies(final String TEST_NAME) throws Exception { */ public void jackAssignRoleDummiesError(final String TEST_NAME, String roleOid, String dummyResourceName, boolean expectAccount) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); clearJackOrganizationalUnit(task, result); @@ -1003,17 +1002,17 @@ private void clearJackOrganizationalUnit(Task task, OperationResult result) thro } public void jackUnAssignRoleDummiesError(final String TEST_NAME, String roleOid) throws Exception { - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignRole(USER_JACK_OID, roleOid, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); display(result); // there is a failure while reading dummy account - it was not created @@ -1038,10 +1037,10 @@ public void jackUnAssignRoleDummiesError(final String TEST_NAME, String roleOid) @Test public void test300AddAndAssignRelative() throws Exception { final String TEST_NAME = "test300AddAndAssignRelative"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // Add default dummy account to jack without assigning it. @@ -1064,11 +1063,11 @@ public void test300AddAndAssignRelative() throws Exception { assertDefaultDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignAccount(USER_JACK_OID, RESOURCE_DUMMY_BLUE_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1096,18 +1095,18 @@ public void test300AddAndAssignRelative() throws Exception { @Test public void test310AddedAccountAndUnassignRelative() throws Exception { final String TEST_NAME = "test310AddedAccountAndUnassignRelative"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_BLUE_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1137,18 +1136,18 @@ public void test310AddedAccountAndUnassignRelative() throws Exception { @Test public void test319UnassignDummyRelative() throws Exception { final String TEST_NAME = "test319UnassignDummyRelative"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignAccount(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1173,17 +1172,17 @@ public void test319UnassignDummyRelative() throws Exception { @Test public void test350AddAccountLavender() throws Exception { final String TEST_NAME = "test350AddAccountLavender"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, resourceDummyLavender); // WHEN try { - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); AssertJUnit.fail("Unexpected success"); @@ -1193,7 +1192,7 @@ public void test350AddAccountLavender() throws Exception { } // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertFailure(result); @@ -1204,20 +1203,20 @@ public void test350AddAccountLavender() throws Exception { @Test public void test352AddAccountIvory() throws Exception { final String TEST_NAME = "test352AddAccountIvory"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, resourceDummyIvory); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1228,20 +1227,20 @@ public void test352AddAccountIvory() throws Exception { @Test public void test354AddAccountBeige() throws Exception { final String TEST_NAME = "test354AddAccountBeige"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, resourceDummyBeige); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1252,20 +1251,20 @@ public void test354AddAccountBeige() throws Exception { @Test public void test360AddAccountDummy() throws Exception { final String TEST_NAME = "test360AddAccountDummy"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, getDummyResourceObject()); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1279,20 +1278,20 @@ public void test360AddAccountDummy() throws Exception { @Test public void test362AddAccountLavender() throws Exception { final String TEST_NAME = "test362AddAccountLavender"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, resourceDummyLavender); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1306,17 +1305,17 @@ public void test362AddAccountLavender() throws Exception { @Test public void test370DeleteAccountDummy() throws Exception { final String TEST_NAME = "test370DeleteAccountDummy"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, getDummyResourceObject()); // WHEN try { - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); AssertJUnit.fail("Unexpected success"); @@ -1326,7 +1325,7 @@ public void test370DeleteAccountDummy() throws Exception { } // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertFailure(result); @@ -1343,17 +1342,17 @@ public void test370DeleteAccountDummy() throws Exception { @Test public void test372UnlinkAccountDummy() throws Exception { final String TEST_NAME = "test372UnlinkAccountDummy"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserUnlinkAccount(USER_JACK_OID, getDummyResourceObject()); // WHEN try { - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); AssertJUnit.fail("Unexpected success"); @@ -1363,9 +1362,8 @@ public void test372UnlinkAccountDummy() throws Exception { } // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertFailure(result); + displayThen(TEST_NAME); + assertFailure(result); PrismObject user = getUser(USER_JACK_OID); assertAccount(user, RESOURCE_DUMMY_OID); @@ -1377,21 +1375,20 @@ public void test372UnlinkAccountDummy() throws Exception { @Test public void test374DeleteAccountLavender() throws Exception { final String TEST_NAME = "test374DeleteAccountLavender"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, resourceDummyLavender); - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject user = getUser(USER_JACK_OID); assertAccount(user, RESOURCE_DUMMY_OID); @@ -1407,21 +1404,20 @@ public void test374DeleteAccountLavender() throws Exception { @Test public void test376DeleteAccountDummy() throws Exception { final String TEST_NAME = "test376DeleteAccountDummy"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, getDummyResourceObject()); - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertNoDummyAccount(RESOURCE_DUMMY_LAVENDER_NAME, ACCOUNT_JACK_DUMMY_USERNAME); assertNoDummyAccount(ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME); @@ -1434,21 +1430,20 @@ public void test376DeleteAccountDummy() throws Exception { @Test public void test378DeleteAccountBeige() throws Exception { final String TEST_NAME = "test378DeleteAccountBeige"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, resourceDummyBeige); - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertNoDummyAccount(RESOURCE_DUMMY_LAVENDER_NAME, ACCOUNT_JACK_DUMMY_USERNAME); assertNoDummyAccount(RESOURCE_DUMMY_BEIGE_NAME, ACCOUNT_JACK_DUMMY_USERNAME); @@ -1462,21 +1457,20 @@ public void test378DeleteAccountBeige() throws Exception { @Test public void test379DeleteAccountIvory() throws Exception { final String TEST_NAME = "test379DeleteAccountIvory"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, resourceDummyIvory); - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertNoDummyAccount(RESOURCE_DUMMY_LAVENDER_NAME, ACCOUNT_JACK_DUMMY_USERNAME); assertNoDummyAccount(RESOURCE_DUMMY_BEIGE_NAME, ACCOUNT_JACK_DUMMY_USERNAME); @@ -1491,26 +1485,25 @@ public void test379DeleteAccountIvory() throws Exception { @Test public void test380AddAccountPeru() throws Exception { final String TEST_NAME = "test380AddAccountPeru"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); getDummyResource().resetBreakMode(); // precondition assertEncryptedUserPassword(USER_JACK_OID, USER_JACK_PASSWORD); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, resourceDummyPeru); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDummyAccount(RESOURCE_DUMMY_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, ACCOUNT_JACK_DUMMY_FULLNAME, true); assertDummyPassword(RESOURCE_DUMMY_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_PASSWORD); @@ -1519,22 +1512,21 @@ public void test380AddAccountPeru() throws Exception { @Test public void test382AddAccountYellow() throws Exception { final String TEST_NAME = "test382AddAccountYellow"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserAddAccount(USER_JACK_OID, getDummyResourceObject(RESOURCE_DUMMY_YELLOW_NAME)); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); PrismObject userJack = getUser(USER_JACK_OID); display("User after change execution", userJack); @@ -1556,7 +1548,7 @@ public void test382AddAccountYellow() throws Exception { @Test public void test385ModifyUserJackPasswordA() throws Exception { final String TEST_NAME = "test385ModifyUserJackPasswordA"; - TestUtil.displayTestTitle(this, TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(AbstractPasswordTest.class.getName() + "." + TEST_NAME); @@ -1567,8 +1559,7 @@ public void test385ModifyUserJackPasswordA() throws Exception { modifyUserChangePassword(USER_JACK_OID, USER_PASSWORD_A_CLEAR, task, result); // THEN - result.computeStatus(); - TestUtil.assertPartialError(result); + assertPartialError(result); PrismObject userJack = getUser(USER_JACK_OID); display("User after change execution", userJack); @@ -1590,21 +1581,20 @@ public void test385ModifyUserJackPasswordA() throws Exception { @Test public void test389DeleteAccountPeru() throws Exception { final String TEST_NAME = "test389DeleteAccountPeru"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); ObjectDelta userDelta = createModifyUserDeleteAccount(USER_JACK_OID, resourceDummyPeru); - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modelService.executeChanges(MiscSchemaUtil.createCollection(userDelta), null, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertNoDummyAccount(RESOURCE_DUMMY_PERU_NAME, ACCOUNT_JACK_DUMMY_USERNAME); @@ -1618,12 +1608,12 @@ public void test389DeleteAccountPeru() throws Exception { @Test public void test400DavidAndGoliathAssignRole() throws Exception { final String TEST_NAME = "test400DavidAndGoliathAssignRole"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = createUser(USER_WORLD_NAME, USER_WORLD_FULL_NAME, true); @@ -1633,13 +1623,12 @@ public void test400DavidAndGoliathAssignRole() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "stone", USER_WORLD_NAME, true, true, true); @@ -1663,7 +1652,7 @@ public void test400DavidAndGoliathAssignRole() throws Exception { ObjectDeltaOperation executionDeltaOp = dummyAuditService.getExecutionDelta(2, ChangeType.MODIFY, ShadowType.class); ObjectDelta executionDelta = executionDeltaOp.getObjectDelta(); display("Last execution delta", executionDelta); - PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 2); + PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 4); } private void assertDavidGoliath(String userOid, String ou, String name, boolean userEnabled, boolean davidEnabled, boolean goliathEnabled) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, SchemaViolationException, ConflictException, ExpressionEvaluationException { @@ -1705,25 +1694,24 @@ private void assertDavidGoliath(String userOid, String ou, String name, boolean @Test public void test401DavidAndGoliathModifyOu() throws Exception { final String TEST_NAME = "test401DavidAndGoliathModifyOu"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(userBefore.getOid(), UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("rock")); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, true, true, true); @@ -1747,18 +1735,18 @@ public void test401DavidAndGoliathModifyOu() throws Exception { ObjectDeltaOperation executionDeltaOp = dummyAuditService.getExecutionDelta(2, ChangeType.MODIFY, ShadowType.class); ObjectDelta executionDelta = executionDeltaOp.getObjectDelta(); display("Last execution delta", executionDelta); - PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 2); + PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 4); } @Test public void test403DavidAndGoliathDisableUser() throws Exception { final String TEST_NAME = "test403DavidAndGoliathDisableUser"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); @@ -1766,13 +1754,12 @@ public void test403DavidAndGoliathDisableUser() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(userBefore.getOid(), ACTIVATION_ADMINISTRATIVE_STATUS_PATH, task, result, ActivationStatusType.DISABLED); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, false, false, false); @@ -1784,7 +1771,8 @@ public void test403DavidAndGoliathDisableUser() throws Exception { dummyAuditService.assertExecutionDeltas(0,2); dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, ShadowType.class); - dummyAuditService.assertExecutionDeltas(1,1); // user is again disabled here + dummyAuditService.assertExecutionDeltas(1,2); // user is again disabled here + dummyAuditService.assertHasDelta(1,ChangeType.MODIFY, UserType.class); // lastProvisioningTimestamp dummyAuditService.assertHasDelta(1,ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -1792,25 +1780,24 @@ public void test403DavidAndGoliathDisableUser() throws Exception { @Test public void test404DavidAndGoliathEnableUser() throws Exception { final String TEST_NAME = "test404DavidAndGoliathEnableUser"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(userBefore.getOid(), ACTIVATION_ADMINISTRATIVE_STATUS_PATH, task, result, ActivationStatusType.ENABLED); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, true, true, true); @@ -1822,7 +1809,8 @@ public void test404DavidAndGoliathEnableUser() throws Exception { dummyAuditService.assertExecutionDeltas(0,2); dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, UserType.class); dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, ShadowType.class); - dummyAuditService.assertExecutionDeltas(1,1); // user is again disabled here + dummyAuditService.assertExecutionDeltas(1,2); // user is again disabled here + dummyAuditService.assertHasDelta(1,ChangeType.MODIFY, UserType.class); // lastProvisioningTimestamp dummyAuditService.assertHasDelta(1,ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -1830,12 +1818,12 @@ public void test404DavidAndGoliathEnableUser() throws Exception { @Test public void test405DavidAndGoliathDisableAccountDavid() throws Exception { final String TEST_NAME = "test405DavidAndGoliathDisableAccountDavid"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); @@ -1844,13 +1832,12 @@ public void test405DavidAndGoliathDisableAccountDavid() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyAccountShadowReplace(accountDavidOid, ACTIVATION_ADMINISTRATIVE_STATUS_PATH, task, result, ActivationStatusType.DISABLED); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, true, false, true); @@ -1859,7 +1846,8 @@ public void test405DavidAndGoliathDisableAccountDavid() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(0,1); + dummyAuditService.assertExecutionDeltas(0,2); + dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, UserType.class); // lastProvisioningTimestamp dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -1870,12 +1858,12 @@ public void test405DavidAndGoliathDisableAccountDavid() throws Exception { @Test public void test406DavidAndGoliathRecompute() throws Exception { final String TEST_NAME = "test406DavidAndGoliathRecompute"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); @@ -1883,13 +1871,12 @@ public void test406DavidAndGoliathRecompute() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); recomputeUser(userBefore.getOid(), task, result); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, true, false, true); @@ -1901,12 +1888,12 @@ public void test406DavidAndGoliathRecompute() throws Exception { @Test public void test408DavidAndGoliathEnableAccountDavid() throws Exception { final String TEST_NAME = "test408DavidAndGoliathEnableAccountDavid"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); @@ -1915,13 +1902,12 @@ public void test408DavidAndGoliathEnableAccountDavid() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyAccountShadowReplace(accountDavidOid, ACTIVATION_ADMINISTRATIVE_STATUS_PATH, task, result, ActivationStatusType.ENABLED); // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_WORLD_NAME, true, true, true); @@ -1930,7 +1916,8 @@ public void test408DavidAndGoliathEnableAccountDavid() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(0,1); + dummyAuditService.assertExecutionDeltas(0,2); + dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, UserType.class); // lastProvisioningTimestamp dummyAuditService.assertHasDelta(0,ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionSuccess(); } @@ -1938,25 +1925,24 @@ public void test408DavidAndGoliathEnableAccountDavid() throws Exception { @Test public void test410DavidAndGoliathRename() throws Exception { final String TEST_NAME = "test410DavidAndGoliathRename"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_WORLD_NAME); dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); modifyUserReplace(userBefore.getOid(), UserType.F_NAME, task, result, PrismTestUtil.createPolyString(USER_FIELD_NAME)); - // THEN - TestUtil.displayThen(TEST_NAME); - result.computeStatus(); - TestUtil.assertSuccess(result); + // THEN + displayThen(TEST_NAME); + assertSuccess(result); assertDavidGoliath(userBefore.getOid(), "rock", USER_FIELD_NAME, true, true, true); @@ -1980,29 +1966,29 @@ public void test410DavidAndGoliathRename() throws Exception { ObjectDeltaOperation executionDeltaOp = dummyAuditService.getExecutionDelta(2, ChangeType.MODIFY, ShadowType.class); ObjectDelta executionDelta = executionDeltaOp.getObjectDelta(); display("Last execution delta", executionDelta); - PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 2); + PrismAsserts.assertModifications("Phantom changes in last delta:", executionDelta, 4); } @Test public void test419DavidAndGoliathUnassignRole() throws Exception { final String TEST_NAME = "test419DavidAndGoliathUnassignRole"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_FIELD_NAME); dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result, 2); @@ -2032,12 +2018,12 @@ public void test419DavidAndGoliathUnassignRole() throws Exception { @Test public void test420DavidAndGoliathAssignRoleGoliathDown() throws Exception { final String TEST_NAME = "test420DavidAndGoliathAssignRoleGoliathDown"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_FIELD_NAME); @@ -2056,11 +2042,11 @@ public void test420DavidAndGoliathAssignRoleGoliathDown() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); // Inner errors are expected TestUtil.assertPartialError(result); @@ -2100,12 +2086,12 @@ public void test420DavidAndGoliathAssignRoleGoliathDown() throws Exception { @Test(enabled=false) public void test422DavidAndGoliathAssignRoleGoliathUpRecompute() throws Exception { final String TEST_NAME = "test422DavidAndGoliathAssignRoleGoliathUpRecompute"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_FIELD_NAME); @@ -2116,7 +2102,7 @@ public void test422DavidAndGoliathAssignRoleGoliathUpRecompute() throws Exceptio recomputeUser(userBefore.getOid(), task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); @@ -2143,23 +2129,23 @@ public void test422DavidAndGoliathAssignRoleGoliathUpRecompute() throws Exceptio @Test public void test429DavidAndGoliathUnassignRole() throws Exception { final String TEST_NAME = "test429DavidAndGoliathUnassignRole"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_FIELD_NAME); dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); unassignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); // TestUtil.assertSuccess(result, 2); @@ -2191,12 +2177,12 @@ public void test429DavidAndGoliathUnassignRole() throws Exception { @Test public void test430DavidAndGoliathAssignRoleDavidDown() throws Exception { final String TEST_NAME = "test430DavidAndGoliathAssignRoleDavidDown"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); // GIVEN assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject userBefore = findUserByUsername(USER_FIELD_NAME); @@ -2216,11 +2202,11 @@ public void test430DavidAndGoliathAssignRoleDavidDown() throws Exception { dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); assignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); // Inner errors are expected TestUtil.assertPartialError(result); @@ -2256,12 +2242,12 @@ public void test430DavidAndGoliathAssignRoleDavidDown() throws Exception { @Test public void test440DavidAndGoliathAssignRoleAndCreateUserInOneStep() throws Exception { final String TEST_NAME = "test440DavidAndGoliathAssignRoleAndCreateUserInOneStep"; - TestUtil.displayTestTitle(TEST_NAME); + displayTestTitle(TEST_NAME); dummyResourceGoliath.setBreakMode(BreakMode.NONE); dummyResourceDavid.setBreakMode(BreakMode.NONE); try{ - Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // delete user and his roles which were added before @@ -2306,11 +2292,11 @@ public void test440DavidAndGoliathAssignRoleAndCreateUserInOneStep() throws Exce dummyAuditService.clear(); // WHEN - TestUtil.displayWhen(TEST_NAME); + displayWhen(TEST_NAME); // assignRole(userBefore.getOid(), ROLE_FIGHT_OID, task, result); // THEN - TestUtil.displayThen(TEST_NAME); + displayThen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java index 7f297aa93d6..10d08ef3d61 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestUserTemplate.java @@ -1019,7 +1019,7 @@ public void test160ModifyUserGivenNameAgain() throws Exception { dummyAuditService.assertTarget(USER_JACK_OID); dummyAuditService.assertExecutionSuccess(); ObjectDeltaOperation objectDeltaOperation = dummyAuditService.getExecutionDelta(0, ChangeType.MODIFY, UserType.class); - assertEquals("unexpected number of modifications in audited delta", 4, objectDeltaOperation.getObjectDelta().getModifications().size()); // givenName + badLuck + modifyTimestamp + assertEquals("unexpected number of modifications in audited delta", 5, objectDeltaOperation.getObjectDelta().getModifications().size()); // givenName + badLuck + modifyTimestamp PropertyDelta badLuckDelta = objectDeltaOperation.getObjectDelta().findPropertyDelta(new ItemPath(UserType.F_EXTENSION, PIRACY_BAD_LUCK)); assertNotNull("badLuck delta was not found", badLuckDelta); List oldValues = (List) badLuckDelta.getEstimatedOldValues(); @@ -1069,7 +1069,7 @@ public void test162ModifyUserGivenNameAgainPhantomChange() throws Exception { dummyAuditService.assertTarget(USER_JACK_OID); dummyAuditService.assertExecutionSuccess(); ObjectDeltaOperation objectDeltaOperation = dummyAuditService.getExecutionDelta(0, ChangeType.MODIFY, UserType.class); - assertEquals("unexpected number of modifications in audited delta", 4, objectDeltaOperation.getObjectDelta().getModifications().size()); // givenName + modifyTimestamp, modifyChannel, modifierRef + assertEquals("unexpected number of modifications in audited delta", 5, objectDeltaOperation.getObjectDelta().getModifications().size()); // givenName + modifyTimestamp, modifyChannel, modifierRef } @Test diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/gensync/TestRoleEntitlement.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/gensync/TestRoleEntitlement.java index 4d88ac79e4d..6d4b60ed91c 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/gensync/TestRoleEntitlement.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/gensync/TestRoleEntitlement.java @@ -434,7 +434,7 @@ public void test119ModifyRoleDeleteEntitlement() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); dummyAuditService.assertHasDelta(ChangeType.MODIFY, RoleType.class); dummyAuditService.assertHasDelta(ChangeType.DELETE, ShadowType.class); dummyAuditService.assertTarget(ROLE_PIRATE_OID); @@ -541,7 +541,7 @@ public void test121ModifyRoleLinkEntitlement() throws Exception { dummyAuditService.assertRecords(2); dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(2); + dummyAuditService.assertExecutionDeltas(3); dummyAuditService.assertHasDelta(ChangeType.MODIFY, RoleType.class); dummyAuditService.assertHasDelta(ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertTarget(ROLE_PIRATE_OID); @@ -761,7 +761,7 @@ public void test132ModifyEntitlement() throws Exception { dummyAuditService.assertSimpleRecordSanity(); dummyAuditService.assertRecords(3); dummyAuditService.assertAnyRequestDeltas(); - dummyAuditService.assertExecutionDeltas(0, 1); + dummyAuditService.assertExecutionDeltas(0, 2); dummyAuditService.assertHasDelta(0, ChangeType.MODIFY, ShadowType.class); dummyAuditService.assertExecutionDeltas(1, 1); dummyAuditService.assertHasDelta(1, ChangeType.MODIFY, RoleType.class); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java index 75ab497bdfe..bc5832c4100 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java @@ -19,7 +19,6 @@ */ package com.evolveum.midpoint.model.intest.manual; -import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; @@ -27,18 +26,13 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Random; -import java.util.function.Consumer; import javax.xml.bind.JAXBElement; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import com.evolveum.midpoint.util.FailableRunnable; -import com.evolveum.midpoint.util.exception.*; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -47,21 +41,17 @@ import org.w3c.dom.Element; import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.intest.AbstractConfiguredModelIntegrationTest; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.provisioning.ucf.impl.builtin.ManualConnectorInstance; -import com.evolveum.midpoint.repo.common.expression.evaluator.LiteralExpressionEvaluatorFactory; import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.PointInTimeType; @@ -74,19 +64,18 @@ import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.processor.ResourceSchemaImpl; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.test.util.ParallelTestThread; import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilitiesType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilityCollectionType; @@ -95,8 +84,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ConflictResolutionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceAttributeDefinitionType; @@ -114,7 +101,9 @@ import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; +import com.evolveum.prism.xml.ns._public.types_3.ObjectType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; +import com.evolveum.prism.xml.ns._public.types_3.RawType; /** * @author Radovan Semancik @@ -136,6 +125,9 @@ public abstract class AbstractManualResourceTest extends AbstractConfiguredModel protected static final File RESOURCE_SEMI_MANUAL_SLOW_PROPOSED_FILE = new File(TEST_DIR, "resource-semi-manual-slow-proposed.xml"); protected static final String RESOURCE_SEMI_MANUAL_SLOW_PROPOSED_OID = "512d749a-75ff-11e7-8176-8be7fb6f4e45"; + + protected static final File RESOURCE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE = new File(TEST_DIR, "resource-semi-manual-disable-slow-proposed.xml"); + protected static final String RESOURCE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID = "8ed29734-a1ed-11e7-b7f9-7bce8b17fd64"; protected static final File ROLE_ONE_MANUAL_FILE = new File(TEST_DIR, "role-one-manual.xml"); protected static final String ROLE_ONE_MANUAL_OID = "9149b3ca-5da1-11e7-8e84-130a91fb5876"; @@ -148,6 +140,9 @@ public abstract class AbstractManualResourceTest extends AbstractConfiguredModel protected static final File ROLE_ONE_SEMI_MANUAL_SLOW_PROPOSED_FILE = new File(TEST_DIR, "role-one-semi-manual-slow-proposed.xml"); protected static final String ROLE_ONE_SEMI_MANUAL_SLOW_PROPOSED_OID = "ca7fefc6-75ff-11e7-9833-572f6bf86a81"; + + protected static final File ROLE_ONE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE = new File(TEST_DIR, "role-one-semi-manual-disable-slow-proposed.xml"); + protected static final String ROLE_ONE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID = "38c9fc7a-a200-11e7-8157-2f9beeb541bc"; protected static final File ROLE_TWO_MANUAL_FILE = new File(TEST_DIR, "role-two-manual.xml"); protected static final String ROLE_TWO_MANUAL_OID = "414e3766-775e-11e7-b8cb-c7ca37c1dc9e"; @@ -161,6 +156,9 @@ public abstract class AbstractManualResourceTest extends AbstractConfiguredModel protected static final File ROLE_TWO_SEMI_MANUAL_SLOW_PROPOSED_FILE = new File(TEST_DIR, "role-two-semi-manual-slow-proposed.xml"); protected static final String ROLE_TWO_SEMI_MANUAL_SLOW_PROPOSED_OID = "eaf3569e-7776-11e7-93f3-3f1b853d6525"; + protected static final File ROLE_TWO_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE = new File(TEST_DIR, "role-two-semi-manual-disable-slow-proposed.xml"); + protected static final String ROLE_TWO_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID = "5ecd6fa6-a200-11e7-b0cb-af5e1792d327"; + public static final QName RESOURCE_ACCOUNT_OBJECTCLASS = new QName(MidPointConstants.NS_RI, "AccountObjectClass"); private static final Trace LOGGER = TraceManager.getTrace(AbstractManualResourceTest.class); @@ -231,6 +229,7 @@ public abstract class AbstractManualResourceTest extends AbstractConfiguredModel private XMLGregorianCalendar roleTwoValidFromTimestamp; protected String accountBarbossaOid; + protected String accountDrakeOid; @Override @@ -246,6 +245,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti addObject(USER_JACK_FILE); addObject(USER_BARBOSSA_FILE); + addObject(USER_DRAKE_FILE); PrismObject userWill = createUserWill(); addObject(userWill, initTask, initResult); @@ -254,9 +254,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); - ConflictResolutionType conflictResolutionType = new ConflictResolutionType(); - conflictResolutionType.action(ConflictResolutionActionType.RECOMPUTE); - setConflictResolution(UserType.COMPLEX_TYPE, null, conflictResolutionType, initResult); + setConflictResolutionAction(UserType.COMPLEX_TYPE, null, ConflictResolutionActionType.RECOMPUTE, initResult); // Turns on checks for connection in manual connector InternalsConfig.setSanityChecks(true); @@ -299,13 +297,19 @@ protected int getConcurrentTestNumberOfThreads() { return 4; } - protected int getConcurrentTestRandomStartDelayRange() { + protected int getConcurrentTestRandomStartDelayRangeAssign() { return 1000; } - protected int getConcurrentTestRandomStartDelayRangeDelete() { + protected int getConcurrentTestRandomStartDelayRangeUnassign() { return 5; } + + protected boolean are9xxTestsEnabled() { + // Disabled by default. These are intense parallel tests and they will fail for resources + // that do not have extra consistency checks and do not use proposed shadows. + return false; + } @Test public void test000Sanity() throws Exception { @@ -1553,17 +1557,17 @@ public void test260ClosePasswordChangeCaseAndRecomputeWill() throws Exception { } /** - * ff 10min. Refresh. Oldest delta should expire. + * ff 7min. Refresh. Oldest delta should expire. */ @Test - public void test270RecomputeWillAfter10min() throws Exception { - final String TEST_NAME = "test130RefreshAccountWillAfter10min"; + public void test270RecomputeWillAfter7min() throws Exception { + final String TEST_NAME = "test130RefreshAccountWillAfter7min"; displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); - clockForward("PT10M"); + clockForward("PT7M"); PrismObject shadowBefore = modelService.getObject(ShadowType.class, accountWillOid, null, task, result); display("Shadow before", shadowBefore); @@ -2441,7 +2445,7 @@ public void test515CloseCasesAndRecomputeWill() throws Exception { } /** - * ff 35min, grace period expired, shadow should be gone, linkRef shoud be gone. + * ff 35min, grace period expired, shadow should be gone, linkRef should be gone. * So we have clean state for next tests. * MID-4037 */ @@ -2457,7 +2461,7 @@ public void test517RecomputeWillAfter35min() throws Exception { // WHEN displayWhen(TEST_NAME); - recomputeUser(userWillOid, task, result); + reconcileUser(userWillOid, task, result); // THEN displayThen(TEST_NAME); @@ -2933,6 +2937,244 @@ public void test840AddToBackingStoreAndGetAccountWill() throws Exception { assertShadowExists(shadowRepo, true); } + /** + * Set up roles used in parallel tests. + */ + @Test + public void test900SetUpRoles() throws Exception { + final String TEST_NAME = "test900SetUpRoles"; + displayTestTitle(TEST_NAME); + if (!are9xxTestsEnabled()) { + displaySkip(TEST_NAME); + return; + } + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + SystemConfigurationType systemConfiguration = getSystemConfiguration(); + display("System config", systemConfiguration); + ConflictResolutionActionType conflictResolutionAction = systemConfiguration.getDefaultObjectPolicyConfiguration().get(0).getConflictResolution().getAction(); + if (!ConflictResolutionActionType.RECOMPUTE.equals(conflictResolutionAction) && !ConflictResolutionActionType.RECONCILE.equals(conflictResolutionAction)) { + fail("Wrong conflict resolution action: " + conflictResolutionAction); + } + + + for (int i = 0; i < getConcurrentTestNumberOfThreads(); i++) { + PrismObject role = parseObject(getRoleOneFile()); + role.setOid(getRoleOid(i)); + role.asObjectable().setName(createPolyStringType(getRoleName(i))); + List outboundAttributes = role.asObjectable().getInducement().get(0).getConstruction().getAttribute(); + if (hasMultivalueInterests()) { + ExpressionType outboundExpression = outboundAttributes.get(0).getOutbound().getExpression(); + JAXBElement jaxbElement = outboundExpression.getExpressionEvaluator().get(0); + jaxbElement.setValue(getRoleInterest(i)); + } else { + outboundAttributes.remove(0); + } + addObject(role); + } + } + + private String getRoleOid(int i) { + return String.format("f363260a-8d7a-11e7-bd67-%012d", i); + } + + private String getRoleName(int i) { + return String.format("role-%012d", i); + } + + private String getRoleInterest(int i) { + return String.format("i%012d", i); + } + + // MID-4047, MID-4112 + @Test + public void test910ConcurrentRolesAssign() throws Exception { + final String TEST_NAME = "test910ConcurrentRolesAssign"; + displayTestTitle(TEST_NAME); + if (!are9xxTestsEnabled()) { + displaySkip(TEST_NAME); + return; + } + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + int numberOfCasesBefore = getObjectCount(CaseType.class); + PrismObject userBefore = getUser(USER_DRAKE_OID); + display("user before", userBefore); + assertLinks(userBefore, 0); + + final long TIMEOUT = 60000L; + + // WHEN + displayWhen(TEST_NAME); + + ParallelTestThread[] threads = multithread(TEST_NAME, + (i) -> { + login(userAdministrator); + Task localTask = createTask(TEST_NAME + ".local"); + + assignRole(USER_DRAKE_OID, getRoleOid(i), localTask, localTask.getResult()); + + }, getConcurrentTestNumberOfThreads(), getConcurrentTestRandomStartDelayRangeAssign()); + + // THEN + displayThen(TEST_NAME); + waitForThreads(threads, TIMEOUT); + + PrismObject userAfter = getUser(USER_DRAKE_OID); + display("user after", userAfter); + assertAssignments(userAfter, getConcurrentTestNumberOfThreads()); + assertEquals("Wrong # of links", 1, userAfter.asObjectable().getLinkRef().size()); + accountDrakeOid = userAfter.asObjectable().getLinkRef().get(0).getOid(); + + PrismObject shadowRepo = repositoryService.getObject(ShadowType.class, accountDrakeOid, null, result); + display("Repo shadow", shadowRepo); + assertShadowNotDead(shadowRepo); + + assertTest910ShadowRepo(shadowRepo, task, result); + + Collection> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE)); + PrismObject shadowModel = modelService.getObject(ShadowType.class, accountDrakeOid, options, task, result); + display("Shadow after (model, future)", shadowModel); + +// assertObjects(CaseType.class, numberOfCasesBefore + getConcurrentTestNumberOfThreads()); + } + + protected void assertTest910ShadowRepo(PrismObject shadowRepo, Task task, OperationResult result) throws Exception { + assertShadowNotDead(shadowRepo); + ObjectDeltaType addPendingDelta = null; + for (PendingOperationType pendingOperation: shadowRepo.asObjectable().getPendingOperation()) { + ObjectDeltaType delta = pendingOperation.getDelta(); + if (delta.getChangeType() == ChangeTypeType.ADD) { + ObjectType objectToAdd = delta.getObjectToAdd(); + display("Pending ADD object", objectToAdd.asPrismObject()); + if (addPendingDelta != null) { + fail("More than one add pending delta found:\n"+addPendingDelta+"\n"+delta); + } + addPendingDelta = delta; + } + if (delta.getChangeType() == ChangeTypeType.DELETE) { + fail("Unexpected delete pending delta found:\n"+delta); + } + if (isActivationStatusModifyDelta(delta, ActivationStatusType.ENABLED)) { + fail("Unexpected enable pending delta found:\n"+delta); + } + } + assertNotNull("No add pending delta", addPendingDelta); + } + + // MID-4112 + @Test + public void test919ConcurrentRoleUnassign() throws Exception { + final String TEST_NAME = "test919ConcurrentRoleUnassign"; + displayTestTitle(TEST_NAME); + if (!are9xxTestsEnabled()) { + displaySkip(TEST_NAME); + return; + } + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + int numberOfCasesBefore = getObjectCount(CaseType.class); + PrismObject userBefore = getUser(USER_DRAKE_OID); + display("user before", userBefore); + assertAssignments(userBefore, getConcurrentTestNumberOfThreads()); + + final long TIMEOUT = 60000L; + + // WHEN + displayWhen(TEST_NAME); + + ParallelTestThread[] threads = multithread(TEST_NAME, + (i) -> { + display("Thread "+Thread.currentThread().getName()+" START"); + login(userAdministrator); + Task localTask = createTask(TEST_NAME + ".local"); + OperationResult localResult = localTask.getResult(); + + unassignRole(USER_DRAKE_OID, getRoleOid(i), localTask, localResult); + + localResult.computeStatus(); + + display("Thread "+Thread.currentThread().getName()+" DONE, result", localResult); + + }, getConcurrentTestNumberOfThreads(), getConcurrentTestRandomStartDelayRangeUnassign()); + + // THEN + displayThen(TEST_NAME); + waitForThreads(threads, TIMEOUT); + + PrismObject userAfter = getUser(USER_DRAKE_OID); + display("user after", userAfter); + assertAssignments(userAfter, 0); + assertEquals("Wrong # of links", 1, userAfter.asObjectable().getLinkRef().size()); + + PrismObject shadowRepo = repositoryService.getObject(ShadowType.class, accountDrakeOid, null, result); + display("Repo shadow", shadowRepo); + + PrismObject shadowModel = modelService.getObject(ShadowType.class, accountDrakeOid, null, task, result); + display("Shadow after (model)", shadowModel); + + Collection> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE)); + PrismObject shadowModelFuture = modelService.getObject(ShadowType.class, accountDrakeOid, options, task, result); + display("Shadow after (model, future)", shadowModelFuture); + + assertTest919ShadowRepo(shadowRepo, task, result); + + assertTest919ShadowFuture(shadowModelFuture, task, result); + +// assertObjects(CaseType.class, numberOfCasesBefore + getConcurrentTestNumberOfThreads() + 1); + } + + protected void assertTest919ShadowRepo(PrismObject shadowRepo, Task task, OperationResult result) throws Exception { + ObjectDeltaType deletePendingDelta = null; + for (PendingOperationType pendingOperation: shadowRepo.asObjectable().getPendingOperation()) { + ObjectDeltaType delta = pendingOperation.getDelta(); + if (delta.getChangeType() == ChangeTypeType.ADD) { + ObjectType objectToAdd = delta.getObjectToAdd(); + display("Pending ADD object", objectToAdd.asPrismObject()); + } + if (delta.getChangeType() == ChangeTypeType.DELETE) { + if (deletePendingDelta != null) { + fail("More than one delete pending delta found:\n"+deletePendingDelta+"\n"+delta); + } + deletePendingDelta = delta; + } + } + assertNotNull("No delete pending delta", deletePendingDelta); + } + + protected boolean isActivationStatusModifyDelta(ObjectDeltaType delta, ActivationStatusType expected) throws SchemaException { + if (delta.getChangeType() != ChangeTypeType.MODIFY) { + return false; + } + for (ItemDeltaType itemDelta: delta.getItemDelta()) { + ItemPath deltaPath = itemDelta.getPath().getItemPath(); + if (SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS.equivalent(deltaPath)) { + List value = itemDelta.getValue(); + PrismProperty parsedItem = (PrismProperty)(Item) + value.get(0).getParsedItem(getUserDefinition().findPropertyDefinition(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS)); + ActivationStatusType status = parsedItem.getRealValue(); + display("Delta status " + status, itemDelta); + if (expected.equals(status)) { + return true; + } + } + } + return false; + } + + protected void assertTest919ShadowFuture(PrismObject shadowModelFuture, Task task, + OperationResult result) { + assertShadowDead(shadowModelFuture); + } protected void backingStoreProvisionWill(String interest) throws IOException { diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualDisableSlowProposed.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualDisableSlowProposed.java new file mode 100644 index 00000000000..bae9963aafd --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualDisableSlowProposed.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2010-2017 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.intest.manual; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Listeners; + +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.PrismPropertyDefinition; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.provisioning.ucf.impl.builtin.ManualConnectorInstance; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.PointInTimeType; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConflictResolutionActionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; +import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; +import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; +import com.evolveum.prism.xml.ns._public.types_3.ObjectType; +import com.evolveum.prism.xml.ns._public.types_3.RawType; + +/** + * @author Radovan Semancik + */ +@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public class TestSemiManualDisableSlowProposed extends TestSemiManualDisable { + + private static final Trace LOGGER = TraceManager.getTrace(TestSemiManualDisableSlowProposed.class); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + initManualConnector(); + + // Recompute is not enough. It will not detect that account status is wrong and won't disable the account. + setConflictResolutionAction(UserType.COMPLEX_TYPE, null, ConflictResolutionActionType.RECONCILE, initResult); + } + + @Override + protected String getResourceOid() { + return RESOURCE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID; + } + + @Override + protected File getResourceFile() { + return RESOURCE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE; + } + + @Override + protected String getRoleOneOid() { + return ROLE_ONE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID; + } + + @Override + protected File getRoleOneFile() { + return ROLE_ONE_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE; + } + + @Override + protected String getRoleTwoOid() { + return ROLE_TWO_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_OID; + } + + @Override + protected File getRoleTwoFile() { + return ROLE_TWO_SEMI_MANUAL_DISABLE_SLOW_PROPOSED_FILE; + } + + + @Override + protected int getConcurrentTestRandomStartDelayRangeAssign() { + // Take it extra easy here. We do not have complete atomicity during shadow create. + // And this resource is really slow. + // MID-4166 + return 2000; + } + + // Make the test fast ... + @Override + protected int getConcurrentTestRandomStartDelayRangeUnassign() { + return 3; + } + + // ... and intense ... + @Override + protected int getConcurrentTestNumberOfThreads() { + return 10; + } + + @Override + protected boolean are9xxTestsEnabled() { + return true; + } + + // .. and make the resource slow. + protected void initManualConnector() { + ManualConnectorInstance.setRandomDelayRange(1000); + } + + @Override + protected void assertTest919ShadowRepo(PrismObject shadowRepo, Task task, OperationResult result) throws Exception { + ObjectDeltaType disablePendingDelta = null; + for (PendingOperationType pendingOperation: shadowRepo.asObjectable().getPendingOperation()) { + ObjectDeltaType delta = pendingOperation.getDelta(); + if (delta.getChangeType() == ChangeTypeType.ADD) { + ObjectType objectToAdd = delta.getObjectToAdd(); + display("Pending ADD object", objectToAdd.asPrismObject()); + } + if (isActivationStatusModifyDelta(delta, ActivationStatusType.DISABLED)) { + if (disablePendingDelta != null) { + fail("More than one disable pending delta found:\n"+disablePendingDelta+"\n"+delta); + } + disablePendingDelta = delta; + } + if (isActivationStatusModifyDelta(delta, ActivationStatusType.ENABLED)) { + fail("Unexpected enable pending delta found:\n"+delta); + } + if (delta.getChangeType() == ChangeTypeType.DELETE) { + fail("Unexpected delete pending delta found:\n"+disablePendingDelta+"\n"+delta); + } + + } + assertNotNull("No disable pending delta", disablePendingDelta); + } + + @Override + protected void assertTest919ShadowFuture(PrismObject shadowModelFuture, Task task, + OperationResult result) { + assertShadowNotDead(shadowModelFuture); + assertAdministrativeStatusDisabled(shadowModelFuture); + } +} \ No newline at end of file diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualSlowProposed.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualSlowProposed.java index a90e87dd4fa..c9169b23d1e 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualSlowProposed.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestSemiManualSlowProposed.java @@ -118,11 +118,12 @@ protected File getRoleTwoFile() { // Make the test fast ... @Override - protected int getConcurrentTestRandomStartDelayRange() { + protected int getConcurrentTestRandomStartDelayRangeAssign() { return 300; } - protected int getConcurrentTestRandomStartDelayRangeDelete() { + @Override + protected int getConcurrentTestRandomStartDelayRangeUnassign() { return 3; } @@ -132,165 +133,13 @@ protected int getConcurrentTestNumberOfThreads() { return 10; } - // TODO: .. and make the resource slow. - private void initManualConnector() { + // .. and make the resource slow. + protected void initManualConnector() { ManualConnectorInstance.setRandomDelayRange(1000); } - /** - * Set up roles used in parallel tests. - */ - @Test - public void test900SetUpRoles() throws Exception { - final String TEST_NAME = "test900SetUpRoles"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); - - SystemConfigurationType systemConfiguration = getSystemConfiguration(); - display("System config", systemConfiguration); - assertEquals("Wrong conflict resolution", ConflictResolutionActionType.RECOMPUTE, systemConfiguration.getDefaultObjectPolicyConfiguration().get(0).getConflictResolution().getAction()); - - for (int i = 0; i < getConcurrentTestNumberOfThreads(); i++) { - PrismObject role = parseObject(getRoleOneFile()); - role.setOid(getRoleOid(i)); - role.asObjectable().setName(createPolyStringType(getRoleName(i))); - List outboundAttributes = role.asObjectable().getInducement().get(0).getConstruction().getAttribute(); - if (hasMultivalueInterests()) { - ExpressionType outboundExpression = outboundAttributes.get(0).getOutbound().getExpression(); - JAXBElement jaxbElement = outboundExpression.getExpressionEvaluator().get(0); - jaxbElement.setValue(getRoleInterest(i)); - } else { - outboundAttributes.remove(0); - } - addObject(role); - } - } - - private String getRoleOid(int i) { - return String.format("f363260a-8d7a-11e7-bd67-%012d", i); - } - - private String getRoleName(int i) { - return String.format("role-%012d", i); - } - - private String getRoleInterest(int i) { - return String.format("i%012d", i); - } - - // MID-4047, MID-4112 - @Test - public void test910ConcurrentRolesAssign() throws Exception { - final String TEST_NAME = "test910ConcurrentRolesAssign"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); - - int numberOfCasesBefore = getObjectCount(CaseType.class); - PrismObject userBefore = getUser(USER_BARBOSSA_OID); - display("user before", userBefore); - - final long TIMEOUT = 60000L; - - // WHEN - displayWhen(TEST_NAME); - - ParallelTestThread[] threads = multithread(TEST_NAME, - (i) -> { - login(userAdministrator); - Task localTask = createTask(TEST_NAME + ".local"); - - assignRole(USER_BARBOSSA_OID, getRoleOid(i), localTask, localTask.getResult()); - - }, getConcurrentTestNumberOfThreads(), getConcurrentTestRandomStartDelayRange()); - - // THEN - displayThen(TEST_NAME); - waitForThreads(threads, TIMEOUT); - - PrismObject userAfter = getUser(USER_BARBOSSA_OID); - display("user after", userAfter); - assertAssignments(userAfter, getConcurrentTestNumberOfThreads()); - assertEquals("Wrong # of links", 1, userAfter.asObjectable().getLinkRef().size()); - accountBarbossaOid = userAfter.asObjectable().getLinkRef().get(0).getOid(); - - PrismObject shadowRepo = repositoryService.getObject(ShadowType.class, accountBarbossaOid, null, result); - display("Repo shadow", shadowRepo); - assertShadowNotDead(shadowRepo); - - Collection> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE)); - PrismObject shadowModel = modelService.getObject(ShadowType.class, accountBarbossaOid, options, task, result); - display("Shadow after (model, future)", shadowModel); - -// assertObjects(CaseType.class, numberOfCasesBefore + getConcurrentTestNumberOfThreads()); - } - - // MID-4112 - @Test - public void test919ConcurrentRoleUnassign() throws Exception { - final String TEST_NAME = "test919ConcurrentRoleUnassign"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); - - int numberOfCasesBefore = getObjectCount(CaseType.class); - PrismObject userBefore = getUser(USER_BARBOSSA_OID); - display("user before", userBefore); - assertAssignments(userBefore, getConcurrentTestNumberOfThreads()); - - final long TIMEOUT = 60000L; - - // WHEN - displayWhen(TEST_NAME); - - ParallelTestThread[] threads = multithread(TEST_NAME, - (i) -> { - display("Thread "+Thread.currentThread().getName()+" START"); - login(userAdministrator); - Task localTask = createTask(TEST_NAME + ".local"); - OperationResult localResult = localTask.getResult(); - - unassignRole(USER_BARBOSSA_OID, getRoleOid(i), localTask, localResult); - - localResult.computeStatus(); - - display("Thread "+Thread.currentThread().getName()+" DONE, result", localResult); - - }, getConcurrentTestNumberOfThreads(), getConcurrentTestRandomStartDelayRangeDelete()); - - // THEN - displayThen(TEST_NAME); - waitForThreads(threads, TIMEOUT); - - PrismObject userAfter = getUser(USER_BARBOSSA_OID); - display("user after", userAfter); - assertAssignments(userAfter, 0); - assertEquals("Wrong # of links", 1, userAfter.asObjectable().getLinkRef().size()); - - PrismObject shadowRepo = repositoryService.getObject(ShadowType.class, accountBarbossaOid, null, result); - display("Repo shadow", shadowRepo); - - ObjectDeltaType deletePendingDelta = null; - for (PendingOperationType pendingOperation: shadowRepo.asObjectable().getPendingOperation()) { - ObjectDeltaType delta = pendingOperation.getDelta(); - if (delta.getChangeType() == ChangeTypeType.DELETE) { - if (deletePendingDelta != null) { - fail("More than one delete pending delta found:\n"+deletePendingDelta+"\n"+delta); - } - deletePendingDelta = delta; - } - } - assertNotNull("No delete pending delta", deletePendingDelta); - - Collection> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE)); - PrismObject shadowModelFuture = modelService.getObject(ShadowType.class, accountBarbossaOid, options, task, result); - display("Shadow after (model, future)", shadowModelFuture); - assertShadowDead(shadowModelFuture); - -// assertObjects(CaseType.class, numberOfCasesBefore + getConcurrentTestNumberOfThreads() + 1); + @Override + protected boolean are9xxTestsEnabled() { + return true; } } \ No newline at end of file diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestImportRecon.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestImportRecon.java index c89e7c1f5c1..28c6441a0b8 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestImportRecon.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestImportRecon.java @@ -431,7 +431,7 @@ public void test150ImportFromResourceDummy() throws Exception { displayThen(TEST_NAME); TestUtil.assertSuccess(task.getResult()); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 3); + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 5); users = modelService.searchObjects(UserType.class, null, null, task, result); display("Users after import", users); diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml index 3fc62368c66..90d10261aeb 100644 --- a/model/model-intest/src/test/resources/logback-test.xml +++ b/model/model-intest/src/test/resources/logback-test.xml @@ -55,19 +55,19 @@ - + - - + + - + - + @@ -80,7 +80,7 @@ - + diff --git a/model/model-intest/src/test/resources/manual/resource-semi-manual-disable-slow-proposed.xml b/model/model-intest/src/test/resources/manual/resource-semi-manual-disable-slow-proposed.xml new file mode 100644 index 00000000000..c211e58fb66 --- /dev/null +++ b/model/model-intest/src/test/resources/manual/resource-semi-manual-disable-slow-proposed.xml @@ -0,0 +1,216 @@ + + + + + + Semi-Manual disable-on-delete slow proposed CSV Resource + + + + + c:connectorType + ManualConnector + + + + + + administrator + + + + csv + + + + c:connectorType + com.evolveum.polygon.connector.csv.CsvConnector + + + + + + target/semi-manual.csv + utf-8 + , + ; + username + password + + + + + + false + + + false + + + false + + + false + + + false + + + + ri:disabled + false + true + + + + + + + + + + + + account + default + true + ri:AccountObjectClass + + ri:username + + strong + + name + + + + + ri:fullname + + + fullName + + + + + + + + + default existence + weak + + $focusExists + + + + + + strong + true + + + + + + + + + + + + + + + + + + + + + ri:disabled + false + true + + + + + + + true + light + true + all + true + PT15M + + + + + ri:AccountObjectClass + account + default + true + + + name + + $projection/attributes/username + + + + + linked + true + + + deleted + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink + + + + unlinked + true + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link + + + + + + diff --git a/model/model-intest/src/test/resources/manual/role-one-semi-manual-disable-slow-proposed.xml b/model/model-intest/src/test/resources/manual/role-one-semi-manual-disable-slow-proposed.xml new file mode 100644 index 00000000000..58ea88f1042 --- /dev/null +++ b/model/model-intest/src/test/resources/manual/role-one-semi-manual-disable-slow-proposed.xml @@ -0,0 +1,35 @@ + + + One: Semi Manual Disable Slow Proposed + + + + account + + ri:interests + + + one + + + + + + diff --git a/model/model-intest/src/test/resources/manual/role-two-semi-manual-disable-slow-proposed.xml b/model/model-intest/src/test/resources/manual/role-two-semi-manual-disable-slow-proposed.xml new file mode 100644 index 00000000000..0650abc8cec --- /dev/null +++ b/model/model-intest/src/test/resources/manual/role-two-semi-manual-disable-slow-proposed.xml @@ -0,0 +1,36 @@ + + + Two: Semi Manual Disable Slow proposed + + + + account + + ri:interests + + strong + + two + + + + + + diff --git a/model/model-intest/src/test/resources/mapping/resource-dummy-crimson.xml b/model/model-intest/src/test/resources/mapping/resource-dummy-crimson.xml index 01b372e3064..393046152f8 100644 --- a/model/model-intest/src/test/resources/mapping/resource-dummy-crimson.xml +++ b/model/model-intest/src/test/resources/mapping/resource-dummy-crimson.xml @@ -190,9 +190,7 @@ - - strong - + diff --git a/model/model-intest/src/test/resources/mapping/resource-dummy-light-crimson.xml b/model/model-intest/src/test/resources/mapping/resource-dummy-light-crimson.xml index f905f957fed..dd4f5f858cf 100644 --- a/model/model-intest/src/test/resources/mapping/resource-dummy-light-crimson.xml +++ b/model/model-intest/src/test/resources/mapping/resource-dummy-light-crimson.xml @@ -181,9 +181,7 @@ - - strong - + diff --git a/model/model-intest/src/test/resources/security/role-self-accounts-partial-control-password.xml b/model/model-intest/src/test/resources/security/role-self-accounts-partial-control-password.xml index 070d258f667..9d347ba0825 100644 --- a/model/model-intest/src/test/resources/security/role-self-accounts-partial-control-password.xml +++ b/model/model-intest/src/test/resources/security/role-self-accounts-partial-control-password.xml @@ -77,6 +77,7 @@ self credentials + metadata http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#modify diff --git a/model/model-intest/testng-integration.xml b/model/model-intest/testng-integration.xml index cdfd75f677b..8b31c226ace 100644 --- a/model/model-intest/testng-integration.xml +++ b/model/model-intest/testng-integration.xml @@ -122,6 +122,7 @@ + diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index 772e3fdbc65..2e3ee15bd64 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -191,6 +191,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationDecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationPhaseType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConflictResolutionActionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConflictResolutionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsPolicyType; @@ -2411,6 +2412,13 @@ protected void setConflictResolution(QName objectType, String subType, ConflictR SystemObjectsType.SYSTEM_CONFIGURATION.value(), modifications, parentResult); } + + protected void setConflictResolutionAction(QName objectType, String subType, ConflictResolutionActionType conflictResolutionAction, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { + ConflictResolutionType conflictResolutionType = new ConflictResolutionType(); + conflictResolutionType.action(conflictResolutionAction); + setConflictResolution(objectType, subType, conflictResolutionType, parentResult); + } protected void setGlobalSecurityPolicy(String securityPolicyOid, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java index ea43ed10a90..3edb8cb0e57 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java @@ -23,6 +23,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.*; @@ -42,6 +43,7 @@ import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.lang.Validate; +import javax.xml.datatype.Duration; import java.util.*; import static com.evolveum.midpoint.prism.xml.XmlTypeConverter.createXMLGregorianCalendar; @@ -58,6 +60,8 @@ public class WfTaskCreationInstructionend() + .retryAfter(retryAfter); + LOGGER.trace("Setting group '{}' with a limit of 1 for task {}", groupName, task); + } + } return task; } diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/AbstractWfTestPolicy.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/AbstractWfTestPolicy.java index 6225b1ceb45..fc8e1c0bbba 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/AbstractWfTestPolicy.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/AbstractWfTestPolicy.java @@ -187,7 +187,10 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti super.initSystem(initTask, initResult); modelService.postInit(initResult); - repoAddObjectFromFile(getSystemConfigurationFile(), initResult); + PrismObject sysconfig = prismContext.parseObject(getSystemConfigurationFile()); + updateSystemConfiguration(sysconfig.asObjectable()); + repoAddObject(sysconfig, initResult); + repoAddObjectFromFile(ROLE_SUPERUSER_FILE, initResult); userAdministrator = repoAddObjectFromFile(USER_ADMINISTRATOR_FILE, initResult); login(userAdministrator); @@ -230,6 +233,10 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti userTemplateAssigningRole1aOidAfter = repoAddObjectFromFile(USER_TEMPLATE_ASSIGNING_ROLE_1A_AFTER, initResult).getOid(); } + protected void updateSystemConfiguration(SystemConfigurationType systemConfiguration) { + // nothing to do by default + } + protected File getSystemConfigurationFile() { return SYSTEM_CONFIGURATION_FILE; } diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestParallelApprovals.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestParallelApprovals.java new file mode 100644 index 00000000000..536f4b46869 --- /dev/null +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestParallelApprovals.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2010-2017 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.wf.impl.policy.other; + +import com.evolveum.midpoint.model.impl.controller.ModelOperationTaskHandler; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskListener; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.task.api.TaskRunResult; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.wf.impl.policy.AbstractWfTestPolicy; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +import static com.evolveum.midpoint.model.api.ModelExecuteOptions.createExecuteImmediatelyAfterApproval; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStatusType.CLOSED; + +/** + * @author mederly + */ +@ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +public class TestParallelApprovals extends AbstractWfTestPolicy { + + private static final File ROLE_ROLE51A_FILE = new File(TEST_RESOURCE_DIR, "role-role51a-slow.xml"); + private static final File ROLE_ROLE52A_FILE = new File(TEST_RESOURCE_DIR, "role-role52a-slow.xml"); + private static final File ROLE_ROLE53A_FILE = new File(TEST_RESOURCE_DIR, "role-role53a-slow.xml"); + + private String roleRole51aOid, roleRole52aOid, roleRole53aOid; + + @Override + protected PrismObject getDefaultActor() { + return userAdministrator; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + roleRole51aOid = repoAddObjectFromFile(ROLE_ROLE51A_FILE, initResult).getOid(); + roleRole52aOid = repoAddObjectFromFile(ROLE_ROLE52A_FILE, initResult).getOid(); + roleRole53aOid = repoAddObjectFromFile(ROLE_ROLE53A_FILE, initResult).getOid(); + + DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); + } + + @Override + protected void updateSystemConfiguration(SystemConfigurationType systemConfiguration) { + super.updateSystemConfiguration(systemConfiguration); + systemConfiguration.getWorkflowConfiguration() + .beginExecutionTasks() + .beginSerialization() + .retryAfter(XmlTypeConverter.createDuration(1000)); // makes tests run faster + } + + @Test + public void test100ParallelApprovals() throws Exception { + final String TEST_NAME = "test100ParallelApprovals"; + TestUtil.displayTestTitle(this, TEST_NAME); + login(userAdministrator); + + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + // WHEN + displayWhen(TEST_NAME); + ObjectDelta assignDelta = DeltaBuilder.deltaFor(UserType.class, prismContext) + .item(UserType.F_ASSIGNMENT).add( + ObjectTypeUtil.createAssignmentTo(roleRole51aOid, ObjectTypes.ROLE, prismContext), + ObjectTypeUtil.createAssignmentTo(roleRole52aOid, ObjectTypes.ROLE, prismContext), + ObjectTypeUtil.createAssignmentTo(roleRole53aOid, ObjectTypes.ROLE, prismContext)) + .asObjectDeltaCast(userJackOid); + executeChanges(assignDelta, createExecuteImmediatelyAfterApproval(), task, result); // should start approval processes + assertNotAssignedRole(userJackOid, roleRole51aOid, task, result); + assertNotAssignedRole(userJackOid, roleRole52aOid, task, result); + assertNotAssignedRole(userJackOid, roleRole53aOid, task, result); + + display("Task after operation", task); + String rootTaskOid = wfTaskUtil.getRootTaskOid(task); + display("root task", getTask(rootTaskOid)); + + CheckingTaskListener listener = new CheckingTaskListener(rootTaskOid); + taskManager.registerTaskListener(listener); + + List workItems = getWorkItems(task, result); + display("work items", workItems); + display("approving work items"); + for (WorkItemType workItem : workItems) { + workflowManager.completeWorkItem(workItem.getExternalId(), true, null, null, null, result); + } + + waitForTaskCloseOrSuspend(rootTaskOid, 120000, 1000); + + // THEN + + PrismObject rootTask = getTask(rootTaskOid); + if (listener.getException() != null || rootTask.asObjectable().getExecutionStatus() != CLOSED) { + fail("root task has not completed; recorded exception = " + listener.getException()); + } + + PrismObject jack = getUser(userJackOid); + assertAssignedRole(jack, roleRole51aOid); + assertAssignedRole(jack, roleRole52aOid); + assertAssignedRole(jack, roleRole53aOid); + } + + private class CheckingTaskListener implements TaskListener { + + private String rootTaskOid; + private Task executing; + private RuntimeException exception; + + public CheckingTaskListener(String rootTaskOid) { + this.rootTaskOid = rootTaskOid; + } + + public RuntimeException getException() { + return exception; + } + + @Override + public synchronized void onTaskStart(Task task) { + if (!ModelOperationTaskHandler.MODEL_OPERATION_TASK_URI.equals(task.getHandlerUri())) { + return; + } + System.out.println("Starting " + task + ", handler uri " + task.getHandlerUri()); + if (executing != null) { + exception = new IllegalStateException("Started task " + task + " but another one is already executing: " + executing); + System.out.println(exception.getMessage()); + // suspend root task in order to fail faster + taskManager.suspendTasks(Collections.singleton(rootTaskOid), TaskManager.DO_NOT_WAIT, new OperationResult("dummy")); + } + executing = task; + } + + @Override + public synchronized void onTaskFinish(Task task, TaskRunResult runResult) { + if (!ModelOperationTaskHandler.MODEL_OPERATION_TASK_URI.equals(task.getHandlerUri())) { + return; + } + System.out.println("Finishing " + task + ", handler uri " + task.getHandlerUri()); + assert executing.getOid().equals(task.getOid()); + executing = null; + } + + @Override + public void onTaskThreadStart(Task task, boolean isRecovering) { + // ignoring + } + + @Override + public void onTaskThreadFinish(Task task) { + // ignoring + } + } +} diff --git a/model/workflow-impl/src/test/resources/policy/role-role51a-slow.xml b/model/workflow-impl/src/test/resources/policy/role-role51a-slow.xml new file mode 100644 index 00000000000..e69219d918b --- /dev/null +++ b/model/workflow-impl/src/test/resources/policy/role-role51a-slow.xml @@ -0,0 +1,43 @@ + + + + Role51a-slow + + + + + description + + + + + + description + + + + + + diff --git a/model/workflow-impl/src/test/resources/policy/role-role52a-slow.xml b/model/workflow-impl/src/test/resources/policy/role-role52a-slow.xml new file mode 100644 index 00000000000..94e3ddff998 --- /dev/null +++ b/model/workflow-impl/src/test/resources/policy/role-role52a-slow.xml @@ -0,0 +1,43 @@ + + + + Role52a-slow + + + + + description + + + + + + description + + + + + + diff --git a/model/workflow-impl/src/test/resources/policy/role-role53a-slow.xml b/model/workflow-impl/src/test/resources/policy/role-role53a-slow.xml new file mode 100644 index 00000000000..39899cbc74d --- /dev/null +++ b/model/workflow-impl/src/test/resources/policy/role-role53a-slow.xml @@ -0,0 +1,43 @@ + + + + Role53a-slow + + + + + description + + + + + + description + + + + + + diff --git a/model/workflow-impl/testng-integration.xml b/model/workflow-impl/testng-integration.xml index b2466e6419c..40f976a6ab6 100644 --- a/model/workflow-impl/testng-integration.xml +++ b/model/workflow-impl/testng-integration.xml @@ -60,6 +60,7 @@ + diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConstraintsChecker.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConstraintsChecker.java index 06659ed7083..5e4d44eacfb 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConstraintsChecker.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConstraintsChecker.java @@ -194,8 +194,8 @@ private boolean checkUniqueness(String oid, PrismProperty identifier, ObjectQuer Collection> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch()); List> foundObjects = shadowCache.searchObjects(query, options, true, task, result); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Uniqueness check of {} resulted in {} results, using query:\n{}", - identifier, foundObjects.size(), query.debugDump()); + LOGGER.trace("Uniqueness check of {} resulted in {} results:\n{}\nquery:\n{}", + identifier, foundObjects.size(), foundObjects, query.debugDump(1)); } if (foundObjects.isEmpty()) { if (useCache) { @@ -204,8 +204,8 @@ private boolean checkUniqueness(String oid, PrismProperty identifier, ObjectQuer return true; } if (foundObjects.size() > 1) { + LOGGER.error("Found {} objects with attribute {}:\n{}", foundObjects.size() ,identifier.toHumanReadableString(), foundObjects); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Found {} objects with attribute {}", foundObjects.size() ,identifier.toHumanReadableString()); for (PrismObject foundObject: foundObjects) { LOGGER.debug("Conflicting object:\n{}", foundObject.debugDump()); } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index 966aea8422b..c26c477170d 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -895,19 +895,18 @@ public PrismObject refreshShadow(PrismObject repoShadow, for (PendingOperationType pendingOperation: sortedOperations) { ItemPath containerPath = pendingOperation.asPrismContainerValue().getPath(); - OperationResultStatusType statusType = pendingOperation.getResultStatus(); - XMLGregorianCalendar completionTimestamp = pendingOperation.getCompletionTimestamp(); - XMLGregorianCalendar now = null; + + if (!OperationResultStatusType.IN_PROGRESS.equals(pendingOperation.getResultStatus())) { + continue; + } String asyncRef = pendingOperation.getAsynchronousOperationReference(); if (asyncRef != null) { - OperationResultStatus newStaus = resouceObjectConverter.refreshOperationStatus(ctx, repoShadow, asyncRef, parentResult); - - now = clock.currentTimeXMLGregorianCalendar(); + OperationResultStatus newStatus = resouceObjectConverter.refreshOperationStatus(ctx, repoShadow, asyncRef, parentResult); - if (newStaus != null) { - OperationResultStatusType newStatusType = newStaus.createStatusType(); + if (newStatus != null) { + OperationResultStatusType newStatusType = newStatus.createStatusType(); if (!newStatusType.equals(pendingOperation.getResultStatus())) { @@ -924,14 +923,11 @@ public PrismObject refreshShadow(PrismObject repoShadow, shadowDelta.addModification(statusDelta); } - statusType = newStatusType; - if (operationCompleted) { // Operation completed PropertyDelta timestampDelta = shadowDelta.createPropertyModification(containerPath.subPath(PendingOperationType.F_COMPLETION_TIMESTAMP)); - timestampDelta.setValuesToReplace(new PrismPropertyValue<>(now)); + timestampDelta.setValuesToReplace(new PrismPropertyValue<>(clock.currentTimeXMLGregorianCalendar())); shadowDelta.addModification(timestampDelta); - completionTimestamp = now; ObjectDeltaType pendingDeltaType = pendingOperation.getDelta(); ObjectDelta pendingDelta = DeltaConvertor.createObjectDelta(pendingDeltaType, prismContext); @@ -975,10 +971,6 @@ public PrismObject refreshShadow(PrismObject repoShadow, } } } - - if (now == null) { - now = clock.currentTimeXMLGregorianCalendar(); - } } if (shadowDelta.isDelete()) { diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java index 01f09052515..412c27ead5f 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java @@ -778,11 +778,11 @@ public String addNewProposedShadow(ProvisioningContext ctx, PrismObject repoShadow = createRepositoryShadow(ctx, shadow); repoShadow.asObjectable().setLifecycleState(SchemaConstants.LIFECYCLE_PROPOSED); - addPendingOperationAdd(repoShadow, shadow, task.getTaskIdentifier()); + addPendingOperationAdd(repoShadow, shadow, null, task.getTaskIdentifier()); ConstraintsChecker.onShadowAddOperation(repoShadow.asObjectable()); String oid = repositoryService.addObject(repoShadow, null, result); - LOGGER.trace("Draft shadow added to the repository: {}", repoShadow); + LOGGER.trace("Proposed shadow added to the repository: {}", repoShadow); return oid; } @@ -805,13 +805,13 @@ public void handlePropesedShadowError(ProvisioningContext ctx, PrismObject> addResult, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException { if (existingShadowOid != null) { - // We know that we have draft shadow + // We know that we have proposed shadow updateProposedShadowAfterAdd(ctx, existingShadowOid, addResult, parentResult); return existingShadowOid; } - // TODO: check for proposed Shadow. There may be a draft shadow even if we do not have explicit draft shadow OID - // (e.g. in case that the add operation failed). If draft shadow is present do modify instead of add. + // TODO: check for proposed Shadow. There may be a proposed shadow even if we do not have explicit proposed shadow OID + // (e.g. in case that the add operation failed). If proposed shadow is present do modify instead of add. PrismObject resourceShadow = addResult.getReturnValue(); @@ -858,16 +858,14 @@ public String addNewActiveRepositoryShadow(ProvisioningContext ctx, String exist @SuppressWarnings("unchecked") private void updateProposedShadowAfterAdd(ProvisioningContext ctx, String existingShadowOid, AsynchronousOperationReturnValue> addResult, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException { PrismObject resourceShadow = addResult.getReturnValue(); - LOGGER.info("AAAAA resource:\n{}", resourceShadow.debugDumpLazily(1)); PrismObject proposedShadow = repositoryService.getObject(ShadowType.class, existingShadowOid, null, parentResult); - LOGGER.info("AAAAA repo:\n{}", proposedShadow.debugDumpLazily(1)); if (proposedShadow == null) { parentResult - .recordFatalError("Error while creating account shadow object to save in the reposiotory. Draft shadow is gone."); + .recordFatalError("Error while creating account shadow object to save in the reposiotory. Proposed shadow is gone."); throw new IllegalStateException( - "Error while creating account shadow object to save in the reposiotory. Draft shadow is gone."); + "Error while creating account shadow object to save in the reposiotory. Proposed shadow is gone."); } Collection shadowChanges = new ArrayList<>(); @@ -886,7 +884,8 @@ private void updateProposedShadowAfterAdd(ProvisioningContext ctx, String existi PrismContainerDefinition containerDefinition = proposedShadow.getDefinition().findContainerDefinition(ShadowType.F_PENDING_OPERATION); ContainerDelta pendingOperationDelta =containerDefinition.createEmptyDelta(new ItemPath(ShadowType.F_PENDING_OPERATION)); - pendingOperationDelta.addValuesToAdd(createPendingOperationAdd(proposedShadow, resourceShadow, addResult.getOperationResult().getAsynchronousOperationReference()).asPrismContainerValue()); + pendingOperationDelta.addValuesToAdd(createPendingOperationAdd(proposedShadow, resourceShadow, + OperationResultStatusType.IN_PROGRESS, addResult.getOperationResult().getAsynchronousOperationReference()).asPrismContainerValue()); shadowChanges.add(pendingOperationDelta); } @@ -899,12 +898,12 @@ private void updateProposedShadowAfterAdd(ProvisioningContext ctx, String existi computeUpdateShadowAttributeChanges(ctx, shadowChanges, resourceShadow, proposedShadow); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Updading draft repository shadow\n{}", DebugUtil.debugDump(shadowChanges, 1)); + LOGGER.trace("Updading proposed repository shadow\n{}", DebugUtil.debugDump(shadowChanges, 1)); } repositoryService.modifyObject(ShadowType.class, proposedShadow.getOid(), shadowChanges, parentResult); - LOGGER.trace("Draft shadow updated"); + LOGGER.trace("Proposed shadow updated"); parentResult.recordSuccess(); } @@ -915,22 +914,23 @@ private void addPendingOperationAdd(PrismObject repoShadow, return; } PrismObject resourceShadow = addResult.getReturnValue(); - addPendingOperationAdd(repoShadow, resourceShadow, addResult.getOperationResult().getAsynchronousOperationReference()); + addPendingOperationAdd(repoShadow, resourceShadow, + OperationResultStatusType.IN_PROGRESS, addResult.getOperationResult().getAsynchronousOperationReference()); } - private void addPendingOperationAdd(PrismObject repoShadow, PrismObject resourceShadow, String asyncOperationReference) throws SchemaException { + private void addPendingOperationAdd(PrismObject repoShadow, PrismObject resourceShadow, OperationResultStatusType status, String asyncOperationReference) throws SchemaException { ShadowType repoShadowType = repoShadow.asObjectable(); - repoShadowType.getPendingOperation().add(createPendingOperationAdd(repoShadow, resourceShadow, asyncOperationReference)); + repoShadowType.getPendingOperation().add(createPendingOperationAdd(repoShadow, resourceShadow, status, asyncOperationReference)); repoShadowType.setExists(false); } - private PendingOperationType createPendingOperationAdd(PrismObject repoShadow, PrismObject resourceShadow, String asyncOperationReference) throws SchemaException { + private PendingOperationType createPendingOperationAdd(PrismObject repoShadow, PrismObject resourceShadow, OperationResultStatusType status, String asyncOperationReference) throws SchemaException { ObjectDelta addDelta = resourceShadow.createAddDelta(); ObjectDeltaType addDeltaType = DeltaConvertor.toObjectDeltaType(addDelta); PendingOperationType pendingOperation = new PendingOperationType(); pendingOperation.setDelta(addDeltaType); pendingOperation.setRequestTimestamp(clock.currentTimeXMLGregorianCalendar()); - pendingOperation.setResultStatus(OperationResultStatusType.IN_PROGRESS); + pendingOperation.setResultStatus(status); if (asyncOperationReference != null) { pendingOperation.setAsynchronousOperationReference(asyncOperationReference); } @@ -1319,7 +1319,7 @@ public void modifyShadowAttributes(ProvisioningContext ctx, PrismObject shadowChanges = extractRepoShadowChanges(ctx, shadow, modifications); if (shadowChanges != null && !shadowChanges.isEmpty()) { LOGGER.trace( - "Detected shadow changes. Start to modify shadow in the repository, applying modifications {}", + "There are repository shadow changes, applying modifications {}", DebugUtil.debugDump(shadowChanges)); try { ConstraintsChecker.onShadowModifyOperation(shadowChanges); diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyParallelism.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyParallelism.java index c310c824c01..034b4856297 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyParallelism.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummyParallelism.java @@ -65,7 +65,7 @@ public class TestDummyParallelism extends AbstractBasicDummyTest { private static final long WAIT_TIMEOUT = 60000L; - private static final int DUMMY_OPERATION_DELAY_RANGE = 1000; + private static final int DUMMY_OPERATION_DELAY_RANGE = 1500; private String accountMorganOid; private String accountElizabethOid; @@ -79,7 +79,7 @@ protected int getConcurrentTestFastRandomStartDelayRange() { } protected int getConcurrentTestSlowRandomStartDelayRange() { - return 1000; + return 150; } @Override diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/manual/AbstractManualResourceTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/manual/AbstractManualResourceTest.java index 3aac919147f..5280e4af290 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/manual/AbstractManualResourceTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/manual/AbstractManualResourceTest.java @@ -1342,13 +1342,13 @@ public void test240CloseDisableCaseAndReadAccountWill() throws Exception { OperationResult result = task.getResult(); syncServiceMock.reset(); + accountWillCompletionTimestampStart = clock.currentTimeXMLGregorianCalendar(); + closeCase(willLastCaseOid); PrismObject shadowBefore = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, task, result); display("Shadow before", shadowBefore); - accountWillCompletionTimestampStart = clock.currentTimeXMLGregorianCalendar(); - // WHEN displayWhen(TEST_NAME); PrismObject shadowProvisioning = provisioningService.getObject(ShadowType.class, @@ -1678,18 +1678,18 @@ public void test260ClosePasswordChangeCaseAndRefreshAccountWill() throws Excepti } /** - * ff 10min. Refresh. Oldest delta should expire. + * ff 7min. Refresh. Oldest delta should expire. */ @Test - public void test270RefreshAccountWillAfter10min() throws Exception { - final String TEST_NAME = "test130RefreshAccountWillAfter10min"; + public void test270RefreshAccountWillAfter7min() throws Exception { + final String TEST_NAME = "test130RefreshAccountWillAfter7min"; displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); syncServiceMock.reset(); - clock.overrideDuration("PT10M"); + clock.overrideDuration("PT7M"); PrismObject shadowBefore = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, task, result); display("Shadow before", shadowBefore); @@ -2128,13 +2128,13 @@ public void test310CloseCaseAndRefreshAccountWill() throws Exception { OperationResult result = task.getResult(); syncServiceMock.reset(); + accountWillCompletionTimestampStart = clock.currentTimeXMLGregorianCalendar(); + closeCase(willLastCaseOid); PrismObject shadowBefore = provisioningService.getObject(ShadowType.class, ACCOUNT_WILL_OID, null, task, result); display("Shadow before", shadowBefore); - accountWillCompletionTimestampStart = clock.currentTimeXMLGregorianCalendar(); - // WHEN displayWhen(TEST_NAME); provisioningService.refreshShadow(shadowBefore, null, task, result); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java index 562fdb65f1c..918ef86d985 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/util/SimpleTaskAdapter.java @@ -45,10 +45,10 @@ import javax.xml.namespace.QName; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.emptySet; /** * @author lazyman @@ -828,6 +828,18 @@ public String getGroup() { return null; } + @NotNull + @Override + public Collection getGroups() { + return emptySet(); + } + + @NotNull + @Override + public Map getGroupsWithLimits() { + return emptyMap(); + } + @NotNull @Override public List getLastFailures() { diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java index 275ecc1dc9d..7625b1dff50 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java @@ -1558,13 +1558,13 @@ protected void assertMetadata(String message, MetadataType metadataType, boolean XMLGregorianCalendar start, XMLGregorianCalendar end, String actorOid, String channel) { assertNotNull("No metadata in " + message, metadataType); if (create) { - TestUtil.assertBetween("Wrong create timestamp in " + message, start, end, metadataType.getCreateTimestamp()); + assertBetween("Wrong create timestamp in " + message, start, end, metadataType.getCreateTimestamp()); if (actorOid != null) { ObjectReferenceType creatorRef = metadataType.getCreatorRef(); assertNotNull("No creatorRef in " + message, creatorRef); assertEquals("Wrong creatorRef OID in " + message, actorOid, creatorRef.getOid()); if (assertRequest) { - TestUtil.assertBetween("Wrong request timestamp in " + message, start, end, metadataType.getRequestTimestamp()); + assertBetween("Wrong request timestamp in " + message, start, end, metadataType.getRequestTimestamp()); ObjectReferenceType requestorRef = metadataType.getRequestorRef(); assertNotNull("No requestorRef in " + message, requestorRef); assertEquals("Wrong requestorRef OID in " + message, actorOid, requestorRef.getOid()); @@ -1577,7 +1577,7 @@ protected void assertMetadata(String message, MetadataType metadataType, boolean assertNotNull("No modifierRef in " + message, modifierRef); assertEquals("Wrong modifierRef OID in " + message, actorOid, modifierRef.getOid()); } - TestUtil.assertBetween("Wrong password modify timestamp in " + message, start, end, metadataType.getModifyTimestamp()); + assertBetween("Wrong password modify timestamp in " + message, start, end, metadataType.getModifyTimestamp()); assertEquals("Wrong modification channel in " + message, channel, metadataType.getModifyChannel()); } } @@ -1592,6 +1592,13 @@ protected void assertShadowPasswordMetadata(PrismObject shadow, bool assertNotNull("No metadata in shadow "+shadow, metadata); assertMetadata("Password metadata in "+shadow, metadata, passwordCreated, false, startCal, endCal, actorOid, channel); } + + protected void assertLastProvisioningTimestamp(PrismObject object, + XMLGregorianCalendar start, XMLGregorianCalendar end) { + MetadataType metadata = object.asObjectable().getMetadata(); + assertNotNull("No metadata in " + object); + assertBetween("Wrong last provisioning timestamp in " + object, start, end, metadata.getLastProvisioningTimestamp()); + } // Convenience @@ -1602,7 +1609,7 @@ protected PrismObject parseObject(File file) throws Sc protected void displayTestTitle(String testName) { TestUtil.displayTestTitle(this, testName); } - + protected void displayWhen(String testName) { TestUtil.displayWhen(testName); } @@ -1615,6 +1622,10 @@ protected void displayCleanup(String testName) { TestUtil.displayCleanup(testName); } + protected void displaySkip(String testName) { + TestUtil.displaySkip(testName); + } + protected void display(String str) { IntegrationTestTools.display(str); } @@ -1699,6 +1710,15 @@ public static void displayObjectTypeCollection(String message, Collection getGroups(); + + @NotNull + Map getGroupsWithLimits(); + + /** * Returns the schedule. */ public ScheduleType getSchedule(); diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java index 382eb172d70..aa9bea57d17 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java @@ -79,17 +79,12 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.Future; import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_MODEL_OPERATION_CONTEXT; import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_WORKFLOW_CONTEXT; +import static java.util.Collections.emptyMap; /** * Implementation of a Task. @@ -1222,7 +1217,32 @@ public String getGroup() { return executionConstraints != null ? executionConstraints.getGroup() : null; } - /* + @NotNull + @Override + public Collection getGroups() { + return getGroupsWithLimits().keySet(); + } + + @NotNull + @Override + public Map getGroupsWithLimits() { + TaskExecutionConstraintsType executionConstraints = getExecutionConstraints(); + if (executionConstraints == null) { + return emptyMap(); + } + Map rv = new HashMap<>(); + if (executionConstraints.getGroup() != null) { + rv.put(executionConstraints.getGroup(), executionConstraints.getGroupTaskLimit()); + } + for (TaskExecutionGroupConstraintType sg : executionConstraints.getSecondaryGroup()) { + if (sg.getGroup() != null) { // shouldn't occur but it's a user configurable field, so be prepared for the worst + rv.put(sg.getGroup(), sg.getGroupTaskLimit()); + } + } + return rv; + } + + /* * Schedule */ diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java index b17ae34a487..1421c410dbb 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java @@ -32,15 +32,16 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionConstraintsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ThreadStopActionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.commons.lang.Validate; +import org.jetbrains.annotations.NotNull; import org.quartz.*; import org.springframework.security.core.Authentication; import javax.xml.datatype.Duration; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import java.util.*; @DisallowConcurrentExecution public class JobExecutor implements InterruptableJob { @@ -60,6 +61,8 @@ public static void setTaskManagerQuartzImpl(TaskManagerQuartzImpl tmqi) { private static final long WATCHFUL_SLEEP_INCREMENT = 500; private static final int DEFAULT_RESCHEDULE_TIME_FOR_GROUP_LIMIT = 60; + private static final int RESCHEDULE_TIME_RANDOMIZATION_INTERVAL = 3; + private static final int RESCHEDULE_TIME_FOR_NO_SUITABLE_NODE = 60; /* * JobExecutor is instantiated at each execution of the task, so we can store @@ -206,6 +209,27 @@ public void execute(JobExecutionContext context) throws JobExecutionException { } + class GroupExecInfo { + int limit; + Set tasks = new HashSet<>(); + + GroupExecInfo(Integer l) { + limit = l != null ? l : Integer.MAX_VALUE; + } + + public void accept(Integer limit, Task task) { + if (limit != null && limit < this.limit) { + this.limit = limit; + } + this.tasks.add(task); + } + + @Override + public String toString() { + return "{limit=" + limit + ", tasks=" + tasks + "}"; + } + } + // returns false if constraints are not met (i.e. execution should finish immediately) private boolean checkExecutionConstraints(TaskQuartzImpl task, OperationResult result) throws JobExecutionException { TaskExecutionConstraintsType executionConstraints = task.getExecutionConstraints(); @@ -213,30 +237,13 @@ private boolean checkExecutionConstraints(TaskQuartzImpl task, OperationResult r return true; } - // group limit - String group = executionConstraints.getGroup(); - if (group != null && executionConstraints.getGroupTaskLimit() != null) { - List tasksInGroup = new ArrayList<>(); - ClusterStatusInformation clusterStatusInformation = taskManagerImpl.getExecutionManager() - .getClusterStatusInformation(true, false, result); - for (ClusterStatusInformation.TaskInfo taskInfo : clusterStatusInformation.getTasks()) { - Task runningTask; - try { - runningTask = taskManagerImpl.getTask(taskInfo.getOid(), result); - } catch (ObjectNotFoundException e) { - LOGGER.debug("Couldn't find running task {} when checking execution constraints: {}", taskInfo.getOid(), e.getMessage()); - continue; - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, - "Couldn't retrieve running task {} when checking execution constraints", e, taskInfo.getOid()); - continue; - } - if (group.equals(runningTask.getGroup()) && !task.getOid().equals(runningTask.getOid())) { - tasksInGroup.add(runningTask); - } - } - int limit = executionConstraints.getGroupTaskLimit(); - LOGGER.trace("Tasks in group {}: {}", group, tasksInGroup); + // group limits + Map groupMap = createGroupMap(task, result); + LOGGER.trace("groupMap = {}", groupMap); + for (Map.Entry entry : groupMap.entrySet()) { + String group = entry.getKey(); + int limit = entry.getValue().limit; + Set tasksInGroup = entry.getValue().tasks; if (tasksInGroup.size() >= limit) { RescheduleTime rescheduleTime = getRescheduleTime(executionConstraints, DEFAULT_RESCHEDULE_TIME_FOR_GROUP_LIMIT, task.getNextRunStartTime(result)); @@ -259,6 +266,47 @@ private boolean checkExecutionConstraints(TaskQuartzImpl task, OperationResult r return true; } + @NotNull + private Map createGroupMap(TaskQuartzImpl task, OperationResult result) { + Map groupMap = new HashMap<>(); + Map groupsWithLimits = task.getGroupsWithLimits(); + if (!groupsWithLimits.isEmpty()) { + groupsWithLimits.forEach((g, l) -> groupMap.put(g, new GroupExecInfo(l))); + ClusterStatusInformation csi = taskManagerImpl.getExecutionManager() + .getClusterStatusInformation(true, false, result); + for (ClusterStatusInformation.TaskInfo taskInfo : csi.getTasks()) { + if (task.getOid().equals(taskInfo.getOid())) { + continue; + } + Task otherTask; + try { + otherTask = taskManagerImpl.getTask(taskInfo.getOid(), result); + } catch (ObjectNotFoundException e) { + LOGGER.debug("Couldn't find running task {} when checking execution constraints: {}", taskInfo.getOid(), + e.getMessage()); + continue; + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, + "Couldn't retrieve running task {} when checking execution constraints", e, taskInfo.getOid()); + continue; + } + addToGroupMap(groupMap, otherTask); + } + } + return groupMap; + } + + private void addToGroupMap(Map groupMap, Task otherTask) { + for (Map.Entry otherGroupWithLimit : otherTask.getGroupsWithLimits().entrySet()) { + String otherGroup = otherGroupWithLimit.getKey(); + GroupExecInfo groupExecInfo = groupMap.get(otherGroup); + if (groupExecInfo != null) { + Integer otherLimit = otherGroupWithLimit.getValue(); + groupExecInfo.accept(otherLimit, otherTask); + } + } + } + private class RescheduleTime { private final long timestamp; private final boolean regular; @@ -281,6 +329,7 @@ private RescheduleTime getRescheduleTime(TaskExecutionConstraintsType executionC } else { retryAt = System.currentTimeMillis() + defaultInterval * 1000L; } + retryAt += Math.random() * RESCHEDULE_TIME_RANDOMIZATION_INTERVAL * 1000.0; // to avoid endless collisions if (nextTaskRunTime != null && nextTaskRunTime < retryAt) { return new RescheduleTime(nextTaskRunTime, true); } else { diff --git a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestQuartzTaskManagerContract.java b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestQuartzTaskManagerContract.java index f851ba4f16a..f7be988d952 100644 --- a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestQuartzTaskManagerContract.java +++ b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestQuartzTaskManagerContract.java @@ -1633,6 +1633,52 @@ public void timeout() { } } + @Test + public void test108SecondaryGroupLimit() throws Exception { + + final String TEST_NAME = "108SecondaryGroupLimit"; + final OperationResult result = createResult(TEST_NAME); + + TaskType task1 = (TaskType) addObjectFromFile(taskFilename(TEST_NAME)).asObjectable(); + waitForTaskStart(task1.getOid(), result); + + // import second task with the same group (expensive) + TaskType task2 = (TaskType) addObjectFromFile(taskFilename(TEST_NAME + "-2")).asObjectable(); + + Thread.sleep(10000); + task1 = getTaskType(task1.getOid(), result); + assertNull("First task should have no retry time", task1.getNextRetryTimestamp()); + + task2 = getTaskType(task2.getOid(), result); + assertNull("Second task was started even if it should not be", task2.getLastRunStartTimestamp()); + assertNotNull("Next retry time is not set for second task", task2.getNextRetryTimestamp()); + + // now finish first task and check the second one is started + boolean stopped = taskManager.suspendTasks(Collections.singleton(task1.getOid()), 20000L, result); + assertTrue("Task 1 was not suspended successfully", stopped); + + waitForTaskStart(task2.getOid(), result); + + // import third task that has another collision (large-ram) with the second one + TaskType task3 = (TaskType) addObjectFromFile(taskFilename(TEST_NAME + "-3")).asObjectable(); + + Thread.sleep(10000); + task2 = getTaskType(task2.getOid(), result); + assertNull("Second task should have no retry time", task2.getNextRetryTimestamp()); + + task3 = getTaskType(task3.getOid(), result); + assertNull("Third task was started even if it should not be", task3.getLastRunStartTimestamp()); + assertNotNull("Next retry time is not set for third task", task3.getNextRetryTimestamp()); + + // now finish second task and check the third one is started + stopped = taskManager.suspendTasks(Collections.singleton(task2.getOid()), 20000L, result); + assertTrue("Task 2 was not suspended successfully", stopped); + + waitForTaskStart(task3.getOid(), result); + + taskManager.suspendTasks(Collections.singleton(task3.getOid()), 20000L, result); + } + @Test public void test110GroupLimit() throws Exception { @@ -1727,6 +1773,9 @@ public void test999CheckingLeftovers() throws Exception { checkLeftover(leftovers, "022", result); checkLeftover(leftovers, "100", result); checkLeftover(leftovers, "105", result); + checkLeftover(leftovers, "108", result); + checkLeftover(leftovers, "108", "a", result); + checkLeftover(leftovers, "108", "b", result); checkLeftover(leftovers, "110", result); checkLeftover(leftovers, "110", "a", result); checkLeftover(leftovers, "120", result); diff --git a/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-2.xml b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-2.xml new file mode 100644 index 00000000000..43afd27dd22 --- /dev/null +++ b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-2.xml @@ -0,0 +1,42 @@ + + + + + + Testing task secondary group limit (2) + + 91919191-76e0-59e2-86d6-3d4f02d3a108 + + + runnable + + http://midpoint.evolveum.com/test/long-task-handler + single + + + + expensive + 1 + + + large-ram + 1 + + PT2S + + diff --git a/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-3.xml b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-3.xml new file mode 100644 index 00000000000..c6bbe46ad2a --- /dev/null +++ b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit-3.xml @@ -0,0 +1,38 @@ + + + + + + Testing task secondary group limit (3) + + 91919191-76e0-59e2-86d6-3d4f02d3b108 + + + runnable + + http://midpoint.evolveum.com/test/long-task-handler + single + + + + large-ram + + + PT2S + + diff --git a/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit.xml b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit.xml new file mode 100644 index 00000000000..cab3b014f5c --- /dev/null +++ b/repo/task-quartz-impl/src/test/resources/repo/task-108SecondaryGroupLimit.xml @@ -0,0 +1,38 @@ + + + + + + Testing task secondary group limit + + 91919191-76e0-59e2-86d6-3d4f02d30108 + + + runnable + + http://midpoint.evolveum.com/test/long-task-handler + single + + + + expensive + 1 + + PT2S + +