diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsPanel.java index a0e4fa60742..64fc94f3db7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsPanel.java @@ -8,11 +8,13 @@ package com.evolveum.midpoint.web.component.progress; import com.evolveum.midpoint.gui.api.component.BasePanel; +import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import java.util.List; @@ -81,6 +83,16 @@ public StatisticsPanel(String id, IModel model) { initLayout(); } + private Label createFailureLabel(String id, IModel text) { + Label label = new Label(id, text); + label.add(AttributeAppender.append("class", () -> { + Integer value = text != null ? text.getObject() : null; + + return value != null && value != 0 ? "text-danger" : null; + })); + return label; + } + protected void initLayout() { contentsPanel = new WebMarkupContainer(ID_CONTENTS_PANEL); contentsPanel.setOutputMarkupId(true); @@ -90,22 +102,22 @@ protected void initLayout() { protected void populateItem(final ListItem item) { item.add(new Label(ID_PROVISIONING_RESOURCE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_RESOURCE))); item.add(new Label(ID_PROVISIONING_OBJECT_CLASS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_OBJECT_CLASS))); - item.add(new Label(ID_PROVISIONING_GET_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_GET_SUCCESS))); - item.add(new Label(ID_PROVISIONING_GET_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_GET_FAILURE))); - item.add(new Label(ID_PROVISIONING_SEARCH_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SEARCH_SUCCESS))); - item.add(new Label(ID_PROVISIONING_SEARCH_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SEARCH_FAILURE))); - item.add(new Label(ID_PROVISIONING_CREATE_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_CREATE_SUCCESS))); - item.add(new Label(ID_PROVISIONING_CREATE_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_CREATE_FAILURE))); - item.add(new Label(ID_PROVISIONING_UPDATE_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_UPDATE_SUCCESS))); - item.add(new Label(ID_PROVISIONING_UPDATE_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_UPDATE_FAILURE))); - item.add(new Label(ID_PROVISIONING_DELETE_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_DELETE_SUCCESS))); - item.add(new Label(ID_PROVISIONING_DELETE_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_DELETE_FAILURE))); - item.add(new Label(ID_PROVISIONING_SYNC_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SYNC_SUCCESS))); - item.add(new Label(ID_PROVISIONING_SYNC_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SYNC_FAILURE))); - item.add(new Label(ID_PROVISIONING_SCRIPT_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SCRIPT_SUCCESS))); - item.add(new Label(ID_PROVISIONING_SCRIPT_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_SCRIPT_FAILURE))); - item.add(new Label(ID_PROVISIONING_OTHER_SUCCESS, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_OTHER_SUCCESS))); - item.add(new Label(ID_PROVISIONING_OTHER_FAILURE, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_OTHER_FAILURE))); + item.add(new Label(ID_PROVISIONING_GET_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_GET_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_GET_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_GET_FAILURE))); + item.add(new Label(ID_PROVISIONING_SEARCH_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SEARCH_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_SEARCH_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SEARCH_FAILURE))); + item.add(new Label(ID_PROVISIONING_CREATE_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_CREATE_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_CREATE_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_CREATE_FAILURE))); + item.add(new Label(ID_PROVISIONING_UPDATE_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_UPDATE_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_UPDATE_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_UPDATE_FAILURE))); + item.add(new Label(ID_PROVISIONING_DELETE_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_DELETE_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_DELETE_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_DELETE_FAILURE))); + item.add(new Label(ID_PROVISIONING_SYNC_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SYNC_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_SYNC_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SYNC_FAILURE))); + item.add(new Label(ID_PROVISIONING_SCRIPT_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SCRIPT_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_SCRIPT_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_SCRIPT_FAILURE))); + item.add(new Label(ID_PROVISIONING_OTHER_SUCCESS, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_OTHER_SUCCESS))); + item.add(createFailureLabel(ID_PROVISIONING_OTHER_FAILURE, new PropertyModel<>(item.getModel(), ProvisioningStatisticsLineDto.F_OTHER_FAILURE))); item.add(new Label(ID_PROVISIONING_TOTAL_OPERATIONS_COUNT, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_TOTAL_OPERATIONS_COUNT))); item.add(new Label(ID_PROVISIONING_AVERAGE_TIME, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_AVERAGE_TIME))); item.add(new Label(ID_PROVISIONING_MIN_TIME, new PropertyModel(item.getModel(), ProvisioningStatisticsLineDto.F_MIN_TIME))); diff --git a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java index 3476c3d27e4..30bd7b0704c 100644 --- a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java +++ b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java @@ -248,11 +248,12 @@ private void addAttributeValue(String attrName, Set currentValues, Objec } } - Set valuesToCheck = new HashSet<>(); - valuesToCheck.addAll(currentValues); - valuesToCheck.add(valueToAdd); - checkSchema(attrName, valuesToCheck, "add"); - + // an optimization: let's avoid attribute manipulation if we don't want to check the schema anyway + if (resource != null && resource.isEnforceSchema()) { + Set valuesToCheck = new HashSet<>(currentValues); + valuesToCheck.add(valueToAdd); + checkSchema(attrName, valuesToCheck, "add"); + } currentValues.add(valueToAdd); } diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Item.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Item.java index b60c256567a..32e65a4268a 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Item.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Item.java @@ -272,12 +272,20 @@ public interface Item extends It /** * Adds given values, with the same semantics as repeated add(..) calls. - * For equality testing uses give strategy. + * For equality testing uses given strategy. * * @return true if this item changed as a result of the call (i.e. if at least one value was really added) */ boolean addAll(Collection newValues, EquivalenceStrategy strategy) throws SchemaException; + /** + * Adds given values, with the same semantics as repeated add(..) calls. + * For equality testing uses given strategy. + * + * @return true if this item changed as a result of the call (i.e. if at least one value was really added) + */ + boolean addAll(Collection newValues, boolean checkUniqueness, EquivalenceStrategy strategy) throws SchemaException; + /** * Removes given value from the item. * diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/ItemImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/ItemImpl.java index 8b1e452d91b..e6f7c6d0a12 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/ItemImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/ItemImpl.java @@ -404,10 +404,14 @@ public boolean addAll(Collection newValues) throws SchemaException { } public boolean addAll(Collection newValues, EquivalenceStrategy strategy) throws SchemaException { + return addAll(newValues, true, strategy); + } + + public boolean addAll(Collection newValues, boolean checkUniqueness, EquivalenceStrategy strategy) throws SchemaException { checkMutability(); boolean changed = false; for (V val: newValues) { - if (add(val, strategy)) { + if (add(val, checkUniqueness, strategy)) { changed = true; } } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/delta/ItemDeltaImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/delta/ItemDeltaImpl.java index ae7fee744d6..fd73cb918ab 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/delta/ItemDeltaImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/delta/ItemDeltaImpl.java @@ -1270,8 +1270,13 @@ public void applyToMatchingPath(Item item, ParameterizedEquivalenceStrategy stra throw new SchemaException("Cannot apply delta "+this+" to "+item+" because the deltas is applicable only to "+getItemClass().getSimpleName()); } if (valuesToReplace != null) { + // FIXME This is a temporary solution (ugly hack). We do this to avoid O(n^2) comparisons when replacing + // a lot of values, like 100K members for a group. But the serious solution is to employ hashing in ItemImpl, + // and resolve this efficiency issue (1) for all cases - i.e. ADD+DELETE+REPLACE, (2) preserving uniqueness checking. + // See MID-5889. + item.clear(); //noinspection unchecked - item.replaceAll(PrismValueCollectionsUtil.cloneCollection(valuesToReplace), strategy); + item.addAll(PrismValueCollectionsUtil.cloneCollection(valuesToReplace), false, strategy); } else { if (valuesToDelete != null) { //noinspection unchecked diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyContainerImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyContainerImpl.java index 3f168e57b98..8ec62bdca48 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyContainerImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyContainerImpl.java @@ -399,6 +399,12 @@ public boolean addAll(Collection> newValues, EquivalenceS return realContainer.addAll(newValues, strategy); } + @Override + public boolean addAll(Collection> newValues, boolean checkUniqueness, EquivalenceStrategy strategy) + throws SchemaException { + return realContainer.addAll(newValues, checkUniqueness, strategy); + } + public String debugDump(int indent) { return realContainer.debugDump(indent); } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyPropertyImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyPropertyImpl.java index 3f372196bbd..5fd366c7c42 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyPropertyImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyPropertyImpl.java @@ -297,6 +297,12 @@ public boolean addAll(Collection> newValues, EquivalenceSt return realProperty.addAll(newValues, strategy); } + @Override + public boolean addAll(Collection> newValues, boolean checkUniqueness, EquivalenceStrategy strategy) + throws SchemaException { + return realProperty.addAll(newValues, checkUniqueness, strategy); + } + public boolean remove(PrismPropertyValue value) { return realProperty.remove(value); } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyReferenceImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyReferenceImpl.java index 3bdb4fe82f3..2232d5649ff 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyReferenceImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/item/DummyReferenceImpl.java @@ -225,6 +225,12 @@ public boolean addAll(Collection newValues, EquivalenceStra return realReference.addAll(newValues, strategy); } + @Override + public boolean addAll(Collection newValues, boolean checkUniqueness, EquivalenceStrategy strategy) + throws SchemaException { + return realReference.addAll(newValues, checkUniqueness, strategy); + } + public boolean remove(PrismReferenceValue value) { return realReference.remove(value); } diff --git a/infra/schema-pure-jaxb/src/compile/resources/catalog.xml b/infra/schema-pure-jaxb/src/compile/resources/catalog.xml index 47fded01238..296399de122 100644 --- a/infra/schema-pure-jaxb/src/compile/resources/catalog.xml +++ b/infra/schema-pure-jaxb/src/compile/resources/catalog.xml @@ -27,6 +27,7 @@ Used when building via xjc. + diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java index 9d89d377f5f..be9d168f065 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java @@ -1744,6 +1744,10 @@ public void summarize(boolean alsoSubresults) { // Already summarized continue; } + if (subresult.isTraced()) { + // We don't want to summarize traced subresults. + continue; + } if (subresult.isError() && summarizeErrors) { // go on } else if (subresult.isPartialError() && summarizePartialErrors) { @@ -1768,6 +1772,8 @@ public void summarize(boolean alsoSubresults) { // We implement quite a complex algorithm to ensure "incremental stripping", i.e. calling summarize() repeatedly // on an OperationResult to which new standard entries are continually added. The requirement is that there must // be at most one summarization record, and it must be placed after all standard records of given type. + // + // TODO consider tracing here Map recordsCounters = new HashMap<>(); iterator = getSubresults().iterator(); while (iterator.hasNext()) { diff --git a/infra/schema/src/main/resources/META-INF/schemas-in-this-module.xml b/infra/schema/src/main/resources/META-INF/schemas-in-this-module.xml index a8a30de042e..1aab1dec12e 100644 --- a/infra/schema/src/main/resources/META-INF/schemas-in-this-module.xml +++ b/infra/schema/src/main/resources/META-INF/schemas-in-this-module.xml @@ -44,6 +44,7 @@ Notes: + 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 395ad6ec984..b58fb0a05ae 100755 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -32,6 +32,7 @@ + @@ -14632,7 +14633,7 @@ - + Reference to the template. @@ -20846,977 +20847,6 @@ - - - - System that contains definitions of overall security policy. - It contains configuration of authentication mechanisms, credentials management - (such as password resets) and so on. - Please note that this NOT contain authorization and auditing. Authorization is - defined in roles (see RoleType) and auditing has a separate configuration. - - - - - - - - - - - - - true - - - - - - - 3.8 - - - - - - - - - - - - - - - Definition of the use of authentication mechanisms. This is in fact practically - applicable only in default security policy (the policy that is referenced from - system configuration). - - - - - - - - - - - - - - - - - - Credentials management policy. It specifies the management details for each supported - credentials type. It defines parameters such as credential lifetime. It may define even - a very complex schemes for some credential types. E.g. it may define a complete security - questions. - - - - - - - - - - Common setting applied to all other credentials type. Any of this - setting can be overridden in the individual credentials setting. - - - - - - - - - - - Nonce settings used to generate one-time random values. - Used in self-registration, e-mail-based password reset and possibly also - other scenarios. - - - - - - - - - - - Credentials management policy. It specifies the management details for each supported - credentials type. It defines parameters such as credential lifetime. It may define even - a very complex schemes for some credential types. E.g. it may define a complete security - questions. - - - - - - - - - - - - 3.8 - - - - - - - - - - - -

- Credentials reset management policy. It specifies the management details for each supported - credentials reset type. It defines parameters such as reset method. -

-

- The idea is that all the password reset mechanisms have the same parts: - request, authentication, credential source, delivery. - This data structure is meant to configure those steps. -

-
- - - -
- - - - - Name of the password reset scheme. This is a short name that acts both as an - identifier of the scheme and also as a short name used for diagnostics. - - - 3.7.1 - - - - - - - - Source of a new credential value. This setting specifies whether the new credential - value should be provided by the user, randomly generated, derived by a key-exchange - protocol and so on. - - - 3.7.1 - - - - - - - If set to true then the new credential will have the forceChange flag set. - Which usually means that the user will have to change the credential on next logon. - - - 3.7.1 - - - - - - - - - - - - - - -
- - - - - Source of a new credential value. This setting specifies whether the new credential - value should be provided by the user, randomly generated, derived by a key-exchange - protocol and so on. - - - - 3.7.1 - - - - - - - New credential value is entered by the user. - - - - - - - - - - - Specifies the details of a new credential entered manually by a user. - - - - 3.7.1 - - - - - - - - - - - - - - - - - - - - - Authentication management policy. It specifies configurations for different authentication methods - - - - - - - - - - A configuration for user notifications. In future, it might be overridden e.g. at a level - of a user. - - - - - - - - - - - - - - - Authentication management policy. It specifies configurations for different authentication methods - - - - - - - - - - - - - - - - Reference to form which is displayed for registration - - - tns:FormType - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - - - - - - - - - Credentials management policy. It specifies the management details for each supported - credentials type. It defines parameters such as credential lifetime. It may define even - a very complex schemes for some credential types. E.g. it may define a complete security - questions. - - - - - - - - - - - - - - - - - - - - Reference to the default roles which will be assigned to the user automatically after registration - - - tns:AbstractRoleType - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - - - - - - - - Reference to form which is displayed for registration - - - tns:FormType - - - - - - - - - - - - - Structure that specifies common elements to all the credential policies. - - - - - - - - - - Method used to store the values of this credential (encrypted, hashed, ...) - If storage method is not specified it defaults to encryption - (due to compatibility and convenience reasons). - - - 3.6 - - - - - - - - - Constraints that define how propagation of the credentials can be controlled by the - user. E.g. if user can choose where the password change will be propagated. - - - - - - - Minimal number of value occurrences. minOccurs set to zero means that the value - is optional. - E.g. when applied to passwords the minOccurs=0 means that the policy will - accept no password at all. But it will still validate the password using - stringPolicy if a password is present. - - - - - - - Maximal number of value occurrences. - If not specified then the default schema limitation is imposed. - - - - - - - Maximum age of the credential, counted from the last credential value update. - The credential must not be used after the age is exceeded (it is expired). - Any authentication with such credential must fail. - - - - - - - Minimum age of the credential, counted from the last credential value update. - The credential cannot be changed before its minimal age is reached. - - - - - - - The time interval before credential expiration (exceeded maxAge) that the user will be - warned that the credential is about to expire. - - - - - - - Maximum number of failed authentication attempts that can be tried before the credential - is locked-out. - - - - - - - The duration in which the failed attempts must happen for the credential to be locked-out. - The failed attempt counter is re-set after this duration (counted from the last failed attempt). - The credential is NOT locked-out during this duration. - - - - - - - The duration for which the credential remains locked-out. The credential is automatically - unlocked after this duration. - - - - - - - Reference to the value policy for the credential. - - - tns:ValuePolicyType - - - - - - - The number of entries to keep in the credential history. Also specifies the - number of past credential values that will be checked before accepting a new - credential change. - - - - - - - Method used to store historical values of the credential (encrypted, hashed, ...) - If storage type is not specified then it defaults to hashing. - - - 3.6 - - - - - - - - - - - Constraints that define how propagation of credentials can be controlled by the - user. E.g. if user can choose where the password change will be propagated. - - - - - - - - - - Credentials propagation will be determined by the mappings. - User cannot choose where the credentials will be propagated. - The credentials propagation dialog will not be shown. - - - - - - - - - - The user can choose where the credentials will be propagated. - The propagation dialog will be shown. - - - - - - - - - - - - - Specifies the method of resetting the credential. This usually applies to a - self-service credential reset. - - - - - - - - - - The type of credential reset. - - - - - - - - - - - - - - - - - Credential reset is disabled. - - - - - - - - - - Use security questions to reset the credential. - - - - - - - - - - Use security questions to reset the credential. - - - - - - - - - - Use security questions to reset the credential. - - - - - - - - - - Use security questions to reset the credential. - - - - - - - - - - - - - Specifies the method of storing the credential in midPoint. - - - - - - - - - - The type of credential storage. - - - - - - - - - - - - - - - - - - Credential will be stored in an encrypted form. - This is a symmetric (reversible) encryption. - MidPoint will be able to get a cleartext form of - the credential if needed. - - - - - - - - - - Credential will be stored in a hashed form. - One-way (irreversible) cryptographic hash or key derivation function - will be used to transform the credential before storage. - MidPoint will NOT be able to get a cleartext form of - the credential, but it can still compare credential values. - - - - - - - - - - MidPoint will not store the credential at all. - MidPoint will only work with credential in the memory - while it is needed to complete current operation. - The credential will be discarded after the operation. - - THIS IS ONLY PARTIALLY SUPPORTED - - MidPoint should be able not to store the credentials when - this setting is used. But there may be side effects - that are not completely addressed yet. - This is not entirely tested and not supported. - Use at your own risk. - - - - - - - - - - - - - Structure that specifies policy for password management. It is in fact only a simple reference - to a password policy. - - - - - tns:passwordPolicyRef - 4.0 - removed - - - tns:passwordHistoryLength - 4.0 - removed - - - - - - - - - - Additional security applied when changing a password. - This applies when user is changing his own password. It does NOT apply - when administrator changes password of other user. - - - - - - - - - - - - Additional security applied when changing a password. - - - - - - - - - - No additional security. Password can be changed by supplying new value. - - - - - - - - - - User must supply old password to change the password. - - - - - - - - - - - - - Structure that specifies policy for security questions. It actually contains text for the - questions (or rather a reference to localization catalog file). But it also contains a policy - how the questions can be used, e.g. how many questions to display to a user. - - - - - - - - - - - - Number of Questions in order to change the passwords - - - - - - - The set of all the security questions in this policy. - - - - - - - - - - - - Definition of a single security question. - - - - - - - - - - Unique identified of a security question. This can be used in the answer to refer to this - definition (see SecurityQuestionAnswerType). - - It is expected that midPoint will come with a pre-configured set of frequently used security - questions (such as "what is your mother's maiden name?"). Therefore URI is a good mechanism for - this identifier. URI has a natural namespacing. Which means that the identifiers of built-in - questions will not clash with identifiers of questions configured by midPoint administrators. - - - - - - - Simple flag that could be used to disable a use of a specific question without actually - deleting it. This may be used to select only some questions, e.g. to disable the low-security - built-in questions such as "what is your mother's maiden name?". - If not present at all then the question is assumed to be enabled. - - - - - - - The question itself, or the localization identifier to it. - - - - - - - - - - - - Structure that specifies policy for nonce management. - - - - - - - - - - - - TODO - - - - - - - - diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd index b7e455693c7..462856846f7 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-model-context-3.xsd @@ -2099,6 +2099,16 @@ + + + + Processing of object retrieved from a resource (e.g. when doing import or reconciliation). + + + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-security-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-security-3.xsd new file mode 100644 index 00000000000..5b0a5077fe3 --- /dev/null +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-security-3.xsd @@ -0,0 +1,1660 @@ + + + + + + + + + Security parts of common schema. + + + + + + + + + + + + + + + Object that contains definitions of overall security policy. + It contains configuration of authentication mechanisms, credentials management + (such as password resets) and so on. + Please note that this NOT contain authorization and auditing. Authorization is + defined in roles (see RoleType) and auditing has a separate configuration. + + + + + + + + + + + + + true + + + + + + + 3.8 + + + + + + + + + + + + + + +

+ Definition of the use of authentication mechanisms. This part specifies how midPoint + uses the credentials to authenticate users. This is also the place where SSO system + integrations are specified. +

+

+ This is in fact practically applicable only in default security policy + (the policy that is referenced from system configuration). +

+
+ + + +
+ + + + + 4.1 + + + + + + + 4.1 + + + + + + + + true + 4.1 + + + + + + + true + 4.1 + + + + +
+ + + + + Definition of authentication modules that midPoint is aware about. + Each element has a configuration of a particular authentication element instance. + Each modules specified in the container must have unique name. + + + + 4.1 + + + + + + + + + + + + + + + + + + + Common supertype for all authentication module definitions. + + + + 4.1 + + + + + + + Unique name of the authentication module. This name is fact a short identifier. + It is supposed to give some idea about nature of the module to system administrator. + But it is not supposed to be used as a user-friendly label for the module. + Module name must be unique. + + + + + + + Free form description of the module (administrator comment). + + + + + + + + + + Common definition for all authentication modules that use password. + + + + 4.1 + + + + + + + + + Name of credential definition that should be used when validating password. + This must point to a valid credential definition + in the "credential" section of a security policy. + If not specified then default password definition is used. + + + + + + + If set to true than an empty (all blank) password will be accepted as valid password. + Password is still compared with user's password. Therefore for the password to be accepted + an empty password must still be set as a credential for a user. + + + + + + + + + + + + Definition of "login form" module. The module is used for interactive log-in of a user by using + HTML forms. + + + + 4.1 + + + + + + + + + + + + + + + Definition of HTTP BASIC authentication module (RFC 7617). + + + + 4.1 + + + + + + + + + + + + + + + Pseudo-authentication for pre-authenticated users. Based on HTTP header values. + + + + 4.1 + + + + + + + + + Name of HTTP header that contains username. + + + + + + + + + + + + + SAML2 authentication module. + + + + 4.1 + + + + + + + + + + + + + + + + + SAML2 authentication module, network configuration. + + + + 4.1 + + + + + + + + + + + + SAML2 authentication module, service provider configuration. + + + + 4.1 + + + + + + + + + + + + OpenId Connect authentication module. + PLACEHOLDER. NOT SUPPORTED YET. + + + + 4.1 + + + + + + + + + + + + + + + Mail nonce authentication module. + Module that sends randomly generated nonce in URL in mail message. + + + + 4.1 + + + + + + + + + + + + + + + SMS (mobile text message) nonce authentication module. + Module that sends randomly generated nonce in mobile text message (SMS). + + + + 4.1 + + + + + + + + + Path of a user property that will be the source of a mobile telephone number. + This number will be the target of SMS message. + + + + + + + + + + + + Common definition for all authentication modules that use security questions. + + + + 4.1 + + + + + + + + + Name of credential definition that should be used when validating password. + This must point to a valid credential definition + in the "credential" section of a security policy. + If not specified then default password definition is used. + + + + + + + + + + + + + Definition of "security questions form" module. The module is used for interactive log-in of a user by + answering a set of security questions. + + + + 4.1 + + + + + + + + + + + + + + + Definition of HTTP SecQ module. The module is used for quasi-interative log-in of a user by + answering a set of security questions. The HTTP SecQ mechanism is similar to HTTP BASIC mechanism, + but it is using security questions instead of password. + + + + 4.1 + + + + + + + + + + + + + + + Authentication sequence. It is a sequence of authentication modules. The modules could be invoked + in order, or they may be invoked in parallel if the specific implementation allows such approach. + The purpose of the sequence is to guide user through a complete authentication process. + + + + 4.1 + + + + + + + Unique name of the authentication sequence. This name is fact a short identifier. + It is supposed to give some idea about purpose of the sequence to system administrator. + But it is not supposed to be used as a user-friendly label. + Sequence name must be unique. + + + + + + + Free form description of the sequence (administrator comment). + + + + + + + Specification of channel for authentication sequence. + + + + + + + Required assignment target. This authentication sequence is applicable only to users that + have active assignment with this target (and relation). If the sequence is attempted on a user + that does not have this assignment then the authentication will fail. + + + + + + + + + Specification of authentication module in the sequence. + + + + + + + + + + Channel specification for authentication sequence. It specifies whether this sequence is usable for + a specific channel (user/GUI, REST, etc.) + + + + 4.1 + + + + + + + Name (URI) of the channel. + + + + + + + Free form description (administrator comment). + + + + + + + Specifies whether this sequence is the default sequence for a specified channel. + The default sequence will be chosen in case that specific sequence was not requested, e.g. by using URL suffix. + If this element is not present and only a single sequence is defined for a channel, + then such sequence is considered to be the default. If more than one sequence is specified then + none of them is considered to be default. In that case this element must be used explicitly. + + + + + + + URL suffix that can be used to select this authentication sequence specifically. + + + + + + + + + + +

+ Specification of authentication module in the sequence. +

+

+ The authentication modules are evaluated in sequence (or in parallel if possible). + At least one authentication module must succeed for authentication to be successful. + If there are required or requisite modules in the sequence then all of them must succeed + for the sequence to be successful. +

+
+ + + 4.1 + +
+ + + + + Reference to the authentication module name. Value of this element must match name of + existing authentication module. + + + + + + + Free form description (administrator comment). + + + + + + + Ordering number for the module. The modules are sorted according to those numbers. + Modules that have the same value of "order" can be evaluated in parallel in case that + actual use of authentication mechanism allows that. + + + + + + + Necessity, i.e. the level of requirement, whether the module is mandatory or optional. + + + + + +
+ + + + + Necessity, i.e. the level of requirement, whether the module is mandatory or optional. + + + 4.1 + + + + + + + + The module is sufficient for authentication to succeed. It is NOT required to succeed. + If this module succeeds, the evaluation stops. The result is a success. Other modules are NOT evaluated. + (Except for the case when "required" module that was evaluated before has failed.) + If this module fails, the evaluation continues. Other modules are evaluated. + + + + + + + + + + + + + +

+ Credentials management policy. It specifies the management details for each supported + credentials type. It defines parameters such as credential lifetime. It may define even + a very complex schemes for some credential types. E.g. it may define a complete security + questions. +

+

+ This section is a definition of user credentials that midPoint can MANAGE. + Which mostly means writing/changing the credentials. This section is not directly concerned + with authentication or credential reset - at least not directly. + But there may be dependencies. E.g. password reset may use password policy to generate/validate new password. + Also, resource-side passwords need to be defined here to be used by authentication modules. +

+
+ + + +
+ + + + + Common setting applied to all other credentials type. Any of this + setting can be overridden in the individual credentials setting. + + + + + + + + + + Nonce settings used to generate one-time random values. + Used in self-registration, e-mail-based password reset and possibly also + other scenarios. + + + + + +
+ + + + + TODO + + + + + + + + + + + + 3.8 + + + + + + + + + + + +

+ Credentials reset management policy. It specifies the management details for each supported + credentials reset type. It defines parameters such as reset method. +

+

+ The idea is that all the password reset mechanisms have the same parts: + request, authentication, credential source, delivery. + This data structure is meant to configure those steps. +

+
+ + + +
+ + + + + Name of the password reset scheme. This is a short name that acts both as an + identifier of the scheme and also as a short name used for diagnostics. + + + 3.7.1 + + + + + + + Free form description of the credential reset method (administrator comment). + + + 4.1 + + + + + + + + Source of a new credential value. This setting specifies whether the new credential + value should be provided by the user, randomly generated, derived by a key-exchange + protocol and so on. + + + 3.7.1 + + + + + + + If set to true then the new credential will have the forceChange flag set. + Which usually means that the user will have to change the credential on next logon. + + + 3.7.1 + + + + + + + + + + + + + + +
+ + + + + Source of a new credential value. This setting specifies whether the new credential + value should be provided by the user, randomly generated, derived by a key-exchange + protocol and so on. + + + + 3.7.1 + + + + + + + New credential value is entered by the user. + + + + + + + + + + + Specifies the details of a new credential entered manually by a user. + + + + 3.7.1 + + + + + + + + + + + + + + + + + + + + + Authentication management policy. It specifies configurations for different authentication methods + + + + + + + + + + A configuration for user notifications. In future, it might be overridden e.g. at a level + of a user. + + + + + + + + + + + + + + + Authentication management policy. It specifies configurations for different authentication methods + + + + + + + + + + + + + + + + Reference to form which is displayed for registration + + + tns:FormType + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + + + + + + + + + TODO + + + + + + + + + + + + + + + + + + + + Reference to the default roles which will be assigned to the user automatically after registration + + + tns:AbstractRoleType + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + + + + + + + + Reference to form which is displayed for registration + + + tns:FormType + + + + + + + + + + + + + Structure that specifies common elements to all the credential policies. + + + + + + + + + +

+ Unique name of the credential. This name is fact a short identifier. + It is supposed to give some idea about purpose of the credential to system administrator. + It is also used for referencing the credential when needed (e.g. from authentication modules, credential reset specs, etc.) + The name may be stored in the user object together with the credential. + But it is not supposed to be used as a user-friendly label for credential. + Credential name must be unique. +

+

+ Credential name is optional, mostly due to historical/compatibility reasons. +

+
+ + 4.1 + +
+
+ + + + Free form description of the credential (administrator comment). + + + 4.1 + + + + + + + + + Method used to store the values of this credential (encrypted, hashed, ...) + If storage method is not specified it defaults to encryption + (due to compatibility and convenience reasons). + + + 3.6 + + + + + + + + + + Constraints that define how propagation of the credentials can be controlled by the + user. E.g. if user can choose where the password change will be propagated. + + + + + + + Minimal number of value occurrences. minOccurs set to zero means that the value + is optional. + E.g. when applied to passwords the minOccurs=0 means that the policy will + accept no password at all. But it will still validate the password using + stringPolicy if a password is present. + + + + + + + Maximal number of value occurrences. + If not specified then the default schema limitation is imposed. + + + + + + + Maximum age of the credential, counted from the last credential value update. + The credential must not be used after the age is exceeded (it is expired). + Any authentication with such credential must fail. + + + + + + + Minimum age of the credential, counted from the last credential value update. + The credential cannot be changed before its minimal age is reached. + + + + + + + The time interval before credential expiration (exceeded maxAge) that the user will be + warned that the credential is about to expire. + + + + + + + Maximum number of failed authentication attempts that can be tried before the credential + is locked-out. + + + + + + + The duration in which the failed attempts must happen for the credential to be locked-out. + The failed attempt counter is re-set after this duration (counted from the last failed attempt). + The credential is NOT locked-out during this duration. + + + + + + + The duration for which the credential remains locked-out. The credential is automatically + unlocked after this duration. + + + + + + + Reference to the value policy for the credential. + + + tns:ValuePolicyType + + + + + + + The number of entries to keep in the credential history. Also specifies the + number of past credential values that will be checked before accepting a new + credential change. + + + + + + + Method used to store historical values of the credential (encrypted, hashed, ...) + If storage type is not specified then it defaults to hashing. + + + 3.6 + + + + +
+
+ + + + + Constraints that define how propagation of credentials can be controlled by the + user. E.g. if user can choose where the password change will be propagated. + + + + + + + + + + Credentials propagation will be determined by the mappings. + User cannot choose where the credentials will be propagated. + The credentials propagation dialog will not be shown. + + + + + + + + + + The user can choose where the credentials will be propagated. + The propagation dialog will be shown. + + + + + + + + + + + + + Specifies the method of resetting the credential. This usually applies to a + self-service credential reset. + + + + + + + + + + The type of credential reset. + + + + + + + + + + + + + + + + + Credential reset is disabled. + + + + + + + + + + Use security questions to reset the credential. + + + + + + + + + + Use security questions to reset the credential. + + + + + + + + + + Use security questions to reset the credential. + + + + + + + + + + Use security questions to reset the credential. + + + + + + + + + + + + + Specifies the method of storing the credential in midPoint. + + + + + + + + + + The type of credential storage. + + + + + + + + + + + + + + + + + + Credential will be stored in an encrypted form. + This is a symmetric (reversible) encryption. + MidPoint will be able to get a cleartext form of + the credential if needed. + + + + + + + + + + Credential will be stored in a hashed form. + One-way (irreversible) cryptographic hash or key derivation function + will be used to transform the credential before storage. + MidPoint will NOT be able to get a cleartext form of + the credential, but it can still compare credential values. + + + + + + + + + + MidPoint will not store the credential at all. + MidPoint will only work with credential in the memory + while it is needed to complete current operation. + The credential will be discarded after the operation. + + THIS IS ONLY PARTIALLY SUPPORTED + + MidPoint should be able not to store the credentials when + this setting is used. But there may be side effects + that are not completely addressed yet. + This is not entirely tested and not supported. + Use at your own risk. + + + + + + + + + + + + + Structure that specifies policy for password management. It is in fact only a simple reference + to a password policy. + + + + + tns:passwordPolicyRef + 4.0 + removed + + + tns:passwordHistoryLength + 4.0 + removed + + + + + + + + + + Additional security applied when changing a password. + This applies when user is changing his own password. It does NOT apply + when administrator changes password of other user. + + + + + + + + + + + + Additional security applied when changing a password. + + + + + + + + + + No additional security. Password can be changed by supplying new value. + + + + + + + + + + User must supply old password to change the password. + + + + + + + + + + + + + Structure that specifies policy for security questions. It actually contains text for the + questions (or rather a reference to localization catalog file). But it also contains a policy + how the questions can be used, e.g. how many questions to display to a user. + + + + + + + + + + + + Number of Questions in order to change the passwords + + + + + + + The set of all the security questions in this policy. + + + + + + + + + + + + Definition of a single security question. + + + + + + + + + + Unique identified of a security question. This can be used in the answer to refer to this + definition (see SecurityQuestionAnswerType). + + It is expected that midPoint will come with a pre-configured set of frequently used security + questions (such as "what is your mother's maiden name?"). Therefore URI is a good mechanism for + this identifier. URI has a natural namespacing. Which means that the identifiers of built-in + questions will not clash with identifiers of questions configured by midPoint administrators. + + + + + + + Simple flag that could be used to disable a use of a specific question without actually + deleting it. This may be used to select only some questions, e.g. to disable the low-security + built-in questions such as "what is your mother's maiden name?". + If not present at all then the question is assumed to be enabled. + + + + + + + The question itself, or the localization identifier to it. + + + + + + + + + + + + Structure that specifies policy for nonce management. + + + + + + + + + + + + + + + +
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 db4acc6c163..07f7d112fd0 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 @@ -21,6 +21,7 @@ import com.evolveum.midpoint.prism.ItemFactory; import com.evolveum.midpoint.prism.delta.*; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.test.TestResource; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang3.StringUtils; @@ -76,12 +77,14 @@ public class TestUserTemplate extends AbstractInitializedModelIntegrationTest { protected static final File USER_TEMPLATE_USELESS_FILE = new File(TEST_DIR, "user-template-useless.xml"); protected static final String USER_TEMPLATE_USELESS_OID = "29b2936a-d1f6-4942-8e44-9ba44fc27423"; + protected static final TestResource USER_TEMPLATE_MID_5892 = new TestResource(TEST_DIR, "user-template-mid-5892.xml", "064993c0-34b4-4440-9331-e909fc923504"); private static final String ACCOUNT_STAN_USERNAME = "stan"; private static final String ACCOUNT_STAN_FULLNAME = "Stan the Salesman"; private static final String SUBTYPE_MAROONED = "marooned"; private static final String SUBTYPE_USELESS = "useless"; + private static final String SUBTYPE_MID_5892 = "mid-5892"; private static final int NUMBER_OF_IMPORTED_ROLES = 5; @@ -110,9 +113,17 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti repoAddObjectFromFile(USER_TEMPLATE_MAROONED_FILE, initResult); repoAddObjectFromFile(USER_TEMPLATE_USELESS_FILE, initResult); + repoAdd(USER_TEMPLATE_MID_5892, initResult); + setDefaultObjectTemplate(UserType.COMPLEX_TYPE, USER_TEMPLATE_COMPLEX_OID, initResult); setDefaultObjectTemplate(UserType.COMPLEX_TYPE, SUBTYPE_MAROONED, USER_TEMPLATE_MAROONED_OID, initResult); setDefaultObjectTemplate(UserType.COMPLEX_TYPE, SUBTYPE_USELESS, USER_TEMPLATE_USELESS_OID, initResult); + setDefaultObjectTemplate(UserType.COMPLEX_TYPE, SUBTYPE_MID_5892, USER_TEMPLATE_MID_5892.oid, initResult); + } + + @Override + protected boolean isAutoTaskManagementEnabled() { + return true; } protected int getNumberOfRoles() { @@ -121,14 +132,11 @@ protected int getNumberOfRoles() { @Test public void test000Sanity() throws Exception { - final String TEST_NAME = "test000Sanity"; - displayTestTitle(TEST_NAME); - - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN - displayWhen(TEST_NAME); + displayWhen(); PrismObject systemConfiguration = modelService.getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, task, result); @@ -140,10 +148,11 @@ public void test000Sanity() throws Exception { assertNotNull("no system config", systemConfiguration); List defaultObjectPolicyConfiguration = systemConfiguration.asObjectable().getDefaultObjectPolicyConfiguration(); assertNotNull("No object policy", defaultObjectPolicyConfiguration); - assertEquals("Wrong object policy size", 5, defaultObjectPolicyConfiguration.size()); // last two are conflict resolution rules + assertEquals("Wrong object policy size", 6, defaultObjectPolicyConfiguration.size()); // last two are conflict resolution rules assertObjectTemplate(defaultObjectPolicyConfiguration, UserType.COMPLEX_TYPE, null, USER_TEMPLATE_COMPLEX_OID); assertObjectTemplate(defaultObjectPolicyConfiguration, UserType.COMPLEX_TYPE, SUBTYPE_MAROONED, USER_TEMPLATE_MAROONED_OID); assertObjectTemplate(defaultObjectPolicyConfiguration, UserType.COMPLEX_TYPE, SUBTYPE_USELESS, USER_TEMPLATE_USELESS_OID); + assertObjectTemplate(defaultObjectPolicyConfiguration, UserType.COMPLEX_TYPE, SUBTYPE_MID_5892, USER_TEMPLATE_MID_5892.oid); assertRoles(getNumberOfRoles()); } @@ -162,12 +171,9 @@ private void assertObjectTemplate(List defaultObj @Test public void test100ModifyUserGivenName() throws Exception { - final String TEST_NAME = "test100ModifyUserGivenName"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -207,12 +213,9 @@ public void test100ModifyUserGivenName() throws Exception { @Test public void test101ModifyUserEmployeeTypePirate() throws Exception { - final String TEST_NAME = "test101ModifyUserEmployeeTypePirate"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -222,11 +225,11 @@ public void test101ModifyUserEmployeeTypePirate() throws Exception { deltas.add(userDelta); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modelService.executeChanges(deltas, null, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -258,12 +261,9 @@ public void test101ModifyUserEmployeeTypePirate() throws Exception { */ @Test public void test102ModifyUserEmployeeTypeBuccaneer() throws Exception { - final String TEST_NAME = "test102ModifyUserEmployeeTypeBuccaneer"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -299,12 +299,9 @@ public void test102ModifyUserEmployeeTypeBuccaneer() throws Exception { @Test public void test103ModifyUserEmployeeTypeBartender() throws Exception { - final String TEST_NAME = "test103ModifyUserEmployeeTypeBartender"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -342,12 +339,9 @@ public void test103ModifyUserEmployeeTypeBartender() throws Exception { */ @Test public void test104ModifyUserCostCenter() throws Exception { - final String TEST_NAME = "test104ModifyUserCostCenter"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -381,12 +375,9 @@ public void test104ModifyUserCostCenter() throws Exception { @Test public void test105ModifyUserTelephoneNumber() throws Exception { - final String TEST_NAME = "test105ModifyUserTelephoneNumber"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -422,12 +413,9 @@ public void test105ModifyUserTelephoneNumber() throws Exception { @Test public void test106ModifyUserRemoveTelephoneNumber() throws Exception { - final String TEST_NAME = "test106ModifyUserRemoveTelephoneNumber"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); Collection> deltas = new ArrayList<>(); ObjectDelta userDelta = prismContext.deltaFactory().object().createModificationReplaceProperty(UserType.class, @@ -463,12 +451,9 @@ public void test106ModifyUserRemoveTelephoneNumber() throws Exception { @Test public void test107ModifyUserSetTelephoneNumber() throws Exception { - final String TEST_NAME = "test107ModifyUserSetTelephoneNumber"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_TELEPHONE_NUMBER, task, result, "1 222 3456789"); @@ -503,12 +488,9 @@ public void test107ModifyUserSetTelephoneNumber() throws Exception { */ @Test public void test120ReconcileUser() throws Exception { - final String TEST_NAME = "test121ModifyUserReplaceLocality"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN reconcileUser(USER_JACK_OID, task, result); @@ -546,12 +528,9 @@ public void test120ReconcileUser() throws Exception { */ @Test public void test121ModifyUserReplaceLocality() throws Exception { - final String TEST_NAME = "test121ModifyUserReplaceLocality"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_LOCALITY, task, result, PrismTestUtil.createPolyString("Tortuga")); @@ -585,12 +564,9 @@ public void test121ModifyUserReplaceLocality() throws Exception { @Test public void test140AssignDummy() throws Exception { - final String TEST_NAME = "test140AssignDummy"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN assignAccountToUser(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); @@ -620,12 +596,9 @@ public void test140AssignDummy() throws Exception { @Test public void test149UnAssignDummy() throws Exception { - final String TEST_NAME = "test149UnAssignDummy"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN unassignAccountFromUser(USER_JACK_OID, RESOURCE_DUMMY_OID, null, task, result); @@ -654,12 +627,9 @@ public void test149UnAssignDummy() throws Exception { @Test public void test150ModifyJackOrganizationalUnitRum() throws Exception { - final String TEST_NAME = "test150ModifyJackOrganizationalUnitRum"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("F0004")); @@ -691,12 +661,9 @@ public void test150ModifyJackOrganizationalUnitRum() throws Exception { @Test public void test151ModifyJackOrganizationalUnitOffense() throws Exception { - final String TEST_NAME = "test151ModifyJackOrganizationalUnitOffense"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("F0003")); @@ -728,12 +695,9 @@ public void test151ModifyJackOrganizationalUnitOffense() throws Exception { @Test public void test152ModifyJackOrganizationalUnitAddRum() throws Exception { - final String TEST_NAME = "test152ModifyJackOrganizationalUnitAddRum"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserAdd(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("F0004")); @@ -768,12 +732,9 @@ public void test152ModifyJackOrganizationalUnitAddRum() throws Exception { @Test public void test153ModifyJackOrganizationalUnitDeleteOffense() throws Exception { - final String TEST_NAME = "test153ModifyJackOrganizationalUnitDeleteOffense"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserDelete(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("F0003")); @@ -807,12 +768,9 @@ public void test153ModifyJackOrganizationalUnitDeleteOffense() throws Exception */ @Test public void test155ModifyJackOrganizationalUnitFD001() throws Exception { - final String TEST_NAME = "test155ModifyJackOrganizationalUnitFD001"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserAdd(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("FD001")); @@ -849,12 +807,9 @@ public void test155ModifyJackOrganizationalUnitFD001() throws Exception { */ @Test public void test156ReconcileJack() throws Exception { - final String TEST_NAME = "test156ReconcileJack"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN reconcileUser(USER_JACK_OID, task, result); @@ -890,12 +845,9 @@ public void test156ReconcileJack() throws Exception { */ @Test public void test157ModifyJackOrganizationalUnitFD0023() throws Exception { - final String TEST_NAME = "test157ModifyJackOrganizationalUnitFD0023"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserAdd(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, @@ -933,12 +885,9 @@ public void test157ModifyJackOrganizationalUnitFD0023() throws Exception { @Test public void test159ModifyJackDeleteOrganizationalUnitFD002() throws Exception { - final String TEST_NAME = "test159ModifyJackDeleteOrganizationalUnitFD002"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserDelete(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, @@ -977,11 +926,9 @@ public void test159ModifyJackDeleteOrganizationalUnitFD002() throws Exception { @Test public void test160ModifyUserGivenNameAgain() throws Exception { - TestUtil.displayTestTitle(this, "test160ModifyUserGivenNameAgain"); - // GIVEN - Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + ".test160ModifyUserGivenNameAgain"); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); dummyAuditService.clear(); @@ -1012,6 +959,7 @@ public void test160ModifyUserGivenNameAgain() throws Exception { PropertyDelta badLuckDelta = objectDeltaOperation.getObjectDelta().findPropertyDelta( ItemPath.create(UserType.F_EXTENSION, PIRACY_BAD_LUCK)); assertNotNull("badLuck delta was not found", badLuckDelta); + //noinspection unchecked List oldValues = (List) badLuckDelta.getEstimatedOldValues(); assertNotNull("badLuck delta has null estimatedOldValues field", oldValues); ItemFactory factory = prismContext.itemFactory(); @@ -1021,12 +969,9 @@ public void test160ModifyUserGivenNameAgain() throws Exception { @Test public void test162ModifyUserGivenNameAgainPhantomChange() throws Exception { - final String TEST_NAME = "test162ModifyUserGivenNameAgainPhantomChange"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); display("User before", userBefore); @@ -1039,11 +984,11 @@ public void test162ModifyUserGivenNameAgainPhantomChange() throws Exception { deltas.add(userDelta); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modelService.executeChanges(deltas, null, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userJack = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); @@ -1062,12 +1007,9 @@ public void test162ModifyUserGivenNameAgainPhantomChange() throws Exception { @Test public void test165ModifyUserGivenNameAgainAgain() throws Exception { - final String TEST_NAME = "test165ModifyUserGivenNameAgainAgain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_JACK_OID, null, task, result); display("User before", userBefore); @@ -1112,23 +1054,20 @@ private void assertOnDemandOrgAssigned(String orgName, PrismObject use */ @Test public void test170ModifyUserGuybrushEmployeeTypeThief() throws Exception { - final String TEST_NAME = "test170ModifyUserGuybrushEmployeeTypeThief"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, "THIEF"); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1143,24 +1082,21 @@ public void test170ModifyUserGuybrushEmployeeTypeThief() throws Exception { */ @Test public void test172ModifyUserGuybrushHonorificPrefix() throws Exception { - final String TEST_NAME = "test172ModifyUserGuybrushHonorificPrefix"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_HONORIFIC_PREFIX, task, result, PrismTestUtil.createPolyString("Thf.")); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1176,23 +1112,20 @@ public void test172ModifyUserGuybrushHonorificPrefix() throws Exception { */ @Test public void test174ModifyUserGuybrushHonorificPrefixNone() throws Exception { - final String TEST_NAME = "test174ModifyUserGuybrushHonorificPrefixNone"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedRole(userBefore, ROLE_THIEF_OID); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_HONORIFIC_PREFIX, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1208,12 +1141,9 @@ public void test174ModifyUserGuybrushHonorificPrefixNone() throws Exception { */ @Test public void test180ModifyUserGuybrushEmployeeTypeMarooned() throws Exception { - final String TEST_NAME = "test180ModifyUserGuybrushEmployeeTypeMarooned"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); @@ -1221,11 +1151,11 @@ public void test180ModifyUserGuybrushEmployeeTypeMarooned() throws Exception { assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, SUBTYPE_MAROONED); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1241,23 +1171,20 @@ public void test180ModifyUserGuybrushEmployeeTypeMarooned() throws Exception { */ @Test public void test184ModifyUserGuybrushEmployeeTypeNone() throws Exception { - final String TEST_NAME = "test184ModifyUserGuybrushEmployeeTypeNone"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_COST_CENTER, task, result, "S321"); @@ -1276,23 +1203,20 @@ public void test184ModifyUserGuybrushEmployeeTypeNone() throws Exception { */ @Test public void test185ModifyUserGuybrushSubtypeMarooned() throws Exception { - final String TEST_NAME = "test185ModifyUserGuybrushSubtypeMarooned"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, SUBTYPE_MAROONED); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1305,23 +1229,20 @@ public void test185ModifyUserGuybrushSubtypeMarooned() throws Exception { @Test public void test189ModifyUserGuybrushSubtypeNone() throws Exception { - final String TEST_NAME = "test189ModifyUserGuybrushSubtypeNone"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_COST_CENTER, task, result, "S321"); @@ -1342,12 +1263,9 @@ public void test189ModifyUserGuybrushSubtypeNone() throws Exception { */ @Test public void test190ModifyUserGuybrushOrganizationWhateveric() throws Exception { - final String TEST_NAME = "test190ModifyUserGuybrushOrganizationWhateveric"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); @@ -1355,11 +1273,11 @@ public void test190ModifyUserGuybrushOrganizationWhateveric() throws Exception { assertAssignments(userBefore, 1); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("Whateveric")); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -1376,23 +1294,20 @@ public void test190ModifyUserGuybrushOrganizationWhateveric() throws Exception { */ @Test public void test191ModifyUserGuybrushOrganizationAutomatic() throws Exception { - final String TEST_NAME = "test191ModifyUserGuybrushOrganizationAutomatic"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserAdd(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("AUTO-matic")); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1415,19 +1330,16 @@ public void test191ModifyUserGuybrushOrganizationAutomatic() throws Exception { */ @Test public void test192ModifyUserGuybrushOrganizationAddMixed() throws Exception { - final String TEST_NAME = "test192ModifyUserGuybrushOrganizationAddMixed"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 2); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserAdd(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("DEMO-cratic"), createPolyString("AUTO-cratic"), @@ -1436,7 +1348,7 @@ public void test192ModifyUserGuybrushOrganizationAddMixed() throws Exception { ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1466,26 +1378,23 @@ public void test192ModifyUserGuybrushOrganizationAddMixed() throws Exception { */ @Test public void test193ModifyUserGuybrushOrganizationAddOutOfDomain() throws Exception { - final String TEST_NAME = "test193ModifyUserGuybrushOrganizationAddOutOfDomain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 4); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserAdd(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("meritocratic"), createPolyString("piratocratic") ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1517,19 +1426,16 @@ public void test193ModifyUserGuybrushOrganizationAddOutOfDomain() throws Excepti */ @Test public void test194ModifyUserGuybrushOrganizationDeleteMixed() throws Exception { - final String TEST_NAME = "test194ModifyUserGuybrushOrganizationDeleteMixed"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 4); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserDelete(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("AUTO-matic"), createPolyString("plutocratic"), @@ -1538,7 +1444,7 @@ public void test194ModifyUserGuybrushOrganizationDeleteMixed() throws Exception ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1564,26 +1470,23 @@ public void test194ModifyUserGuybrushOrganizationDeleteMixed() throws Exception */ @Test public void test195ModifyUserGuybrushOrganizationDeleteOutOfDomain() throws Exception { - final String TEST_NAME = "test195ModifyUserGuybrushOrganizationDeleteOutOfDomain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 2); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserDelete(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("piratocratic"), createPolyString("DEMO-cratic") ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1608,23 +1511,20 @@ public void test195ModifyUserGuybrushOrganizationDeleteOutOfDomain() throws Exce */ @Test public void test196GuybrushAssignCaptain() throws Exception { - final String TEST_NAME = "test196GuybrushAssignCaptain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 2); // WHEN - displayWhen(TEST_NAME); + displayWhen(); assignRole(USER_GUYBRUSH_OID, ROLE_CAPTAIN_OID, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1650,19 +1550,16 @@ public void test196GuybrushAssignCaptain() throws Exception { */ @Test public void test197ModifyGuybrushEmployeeTypePirate() throws Exception { - final String TEST_NAME = "test197ModifyGuybrushEmployeeTypePirate"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, "PIRATE"); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1689,26 +1586,23 @@ public void test197ModifyGuybrushEmployeeTypePirate() throws Exception { */ @Test public void test198AModifyUserGuybrushOrganizationAddInDomain() throws Exception { - final String TEST_NAME = "test198AModifyUserGuybrushOrganizationAddInDomain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 4); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserAdd(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("AUTO-graphic"), createPolyString("AUTO-matic") ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1739,26 +1633,23 @@ public void test198AModifyUserGuybrushOrganizationAddInDomain() throws Exception */ @Test public void test198BModifyUserGuybrushOrganizationDeleteMixed() throws Exception { - final String TEST_NAME = "test198BModifyUserGuybrushOrganizationDeleteMixed"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 6); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserDelete(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result, createPolyString("AUTO-cratic"), createPolyString("Whateveric") ); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1785,23 +1676,20 @@ public void test198BModifyUserGuybrushOrganizationDeleteMixed() throws Exception */ @Test public void test199AGuyBrushModifyEmployeeTypeWannabe() throws Exception { - final String TEST_NAME = "test199AGuyBrushModifyEmployeeTypeWannabe"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 5); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, "wannabe"); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1827,23 +1715,20 @@ public void test199AGuyBrushModifyEmployeeTypeWannabe() throws Exception { */ @Test public void test199BGuyBrushUnassignCaptain() throws Exception { - final String TEST_NAME = "test199BGuyBrushUnassignCaptain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignments(userBefore, 4); // WHEN - displayWhen(TEST_NAME); + displayWhen(); unassignRole(USER_GUYBRUSH_OID, ROLE_CAPTAIN_OID, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1868,22 +1753,19 @@ public void test199BGuyBrushUnassignCaptain() throws Exception { */ @Test public void test199CModifyUserGuybrushOrganizationCleanup() throws Exception { - final String TEST_NAME = "test199CModifyUserGuybrushOrganizationCleanup"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_ORGANIZATION, task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); TestUtil.assertSuccess(result); @@ -1899,12 +1781,9 @@ public void test199CModifyUserGuybrushOrganizationCleanup() throws Exception { @Test public void test200AddUserRapp() throws Exception { - final String TEST_NAME = "test200AddUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject user = PrismTestUtil.parseObject(USER_RAPP_FILE); Collection> deltas = new ArrayList<>(); @@ -1936,13 +1815,11 @@ public void test200AddUserRapp() throws Exception { @Test public void test201AddUserLargo() throws Exception { - TestUtil.displayTestTitle(this, "test201AddUserLargo"); - // GIVEN - Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + ".test201AddUserLargo"); + Task task = getTask(); + OperationResult result = getResult(); // This simulates IMPORT to trigger the channel-limited mapping task.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_IMPORT)); - OperationResult result = task.getResult(); PrismObject user = PrismTestUtil.parseObject(USER_LARGO_FILE); Collection> deltas = new ArrayList<>(); @@ -1983,11 +1860,9 @@ public void test201AddUserLargo() throws Exception { @Test public void test202AddUserMonkey() throws Exception { - TestUtil.displayTestTitle(this, "test202AddUserMonkey"); - // GIVEN - Task task = taskManager.createTaskInstance(TestUserTemplate.class.getName() + ".test202AddUserMonkey"); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject user = PrismTestUtil.parseObject(USER_THREE_HEADED_MONKEY_FILE); Collection> deltas = new ArrayList<>(); @@ -2023,12 +1898,9 @@ public void test202AddUserMonkey() throws Exception { */ @Test public void test204AddUserHerman() throws Exception { - final String TEST_NAME = "test204AddUserHerman"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject user = PrismTestUtil.parseObject(USER_HERMAN_FILE); Collection> deltas = new ArrayList<>(); @@ -2059,12 +1931,9 @@ public void test204AddUserHerman() throws Exception { @Test public void test220AssignRoleSailorToUserRapp() throws Exception { - final String TEST_NAME = "test220AssignRoleSailorToUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN assignRole(USER_RAPP_OID, ROLE_SAILOR_OID, task, result); @@ -2094,12 +1963,9 @@ public void test220AssignRoleSailorToUserRapp() throws Exception { */ @Test public void test229UnassignRoleSailorFromUserRapp() throws Exception { - final String TEST_NAME = "test220AssignRoleSailorToUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN unassignRole(USER_RAPP_OID, ROLE_SAILOR_OID, task, result); @@ -2131,12 +1997,9 @@ public void test229UnassignRoleSailorFromUserRapp() throws Exception { */ @Test public void test230AssignRoleCaptainToUserRapp() throws Exception { - final String TEST_NAME = "test230AssignRoleCaptainToUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN assignRole(USER_RAPP_OID, ROLE_CAPTAIN_OID, task, result); @@ -2166,12 +2029,9 @@ public void test230AssignRoleCaptainToUserRapp() throws Exception { */ @Test public void test232ModifyUserRappCostCenter() throws Exception { - final String TEST_NAME = "test232ModifyUserRappCostCenter"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_RAPP_OID, UserType.F_COST_CENTER, task, result, "CC-RAPP"); @@ -2202,12 +2062,9 @@ public void test232ModifyUserRappCostCenter() throws Exception { */ @Test public void test239UnassignRoleCaptainFromUserRapp() throws Exception { - final String TEST_NAME = "test239UnassignRoleCaptainFromUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN unassignRole(USER_RAPP_OID, ROLE_CAPTAIN_OID, task, result); @@ -2234,12 +2091,9 @@ public void test239UnassignRoleCaptainFromUserRapp() throws Exception { @Test public void test240ModifyUserRappLocalityScabb() throws Exception { - final String TEST_NAME = "test240ModifyUserRappLocalityScabb"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_RAPP_OID, null, task, result); display("User before", userBefore); @@ -2282,12 +2136,9 @@ public void test240ModifyUserRappLocalityScabb() throws Exception { */ @Test public void test242AssignRoleRastamanToUserRapp() throws Exception { - final String TEST_NAME = "test242AssignRoleRastamanToUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN assignRole(USER_RAPP_OID, ROLE_RASTAMAN_OID, task, result); @@ -2323,12 +2174,9 @@ public void test242AssignRoleRastamanToUserRapp() throws Exception { */ @Test public void test244ModifyUserRappLocalityCoffin() throws Exception { - final String TEST_NAME = "test244ModifyUserRappLocalityCoffin"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_RAPP_OID, null, task, result); display("User before", userBefore); @@ -2364,12 +2212,9 @@ public void test244ModifyUserRappLocalityCoffin() throws Exception { */ @Test public void test245ModifyUserRappLocalityUnderReconcile() throws Exception { - final String TEST_NAME = "test245ModifyUserRappLocalityUnderReconcile"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_RAPP_OID, null, task, result); display("User before", userBefore); @@ -2412,12 +2257,9 @@ public void test245ModifyUserRappLocalityUnderReconcile() throws Exception { */ @Test public void test246ModifyUserRappTimezoneMonkey() throws Exception { - final String TEST_NAME = "test246ModifyUserRappTimezoneMonkey"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_RAPP_OID, null, task, result); display("User before", userBefore); @@ -2455,12 +2297,9 @@ public void test246ModifyUserRappTimezoneMonkey() throws Exception { */ @Test public void test247ModifyUserRappLocaleMI() throws Exception { - final String TEST_NAME = "test247ModifyUserRappLocaleMI"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = modelService.getObject(UserType.class, USER_RAPP_OID, null, task, result); display("User before", userBefore); @@ -2495,12 +2334,9 @@ public void test247ModifyUserRappLocaleMI() throws Exception { @Test public void test249UnassignRoleRastamanFromUserRapp() throws Exception { - final String TEST_NAME = "test249UnassignRoleRastamanFromUserRapp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN unassignRole(USER_RAPP_OID, ROLE_RASTAMAN_OID, task, result); @@ -2535,12 +2371,9 @@ public void test249UnassignRoleRastamanFromUserRapp() throws Exception { */ @Test public void test300ImportStanFromEmeraldResource() throws Exception { - final String TEST_NAME = "test300ImportStanFromEmeraldResource"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); DummyAccount dummyAccountBefore = new DummyAccount(ACCOUNT_STAN_USERNAME); @@ -2554,11 +2387,11 @@ public void test300ImportStanFromEmeraldResource() throws Exception { display("Shadow before", shadowBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modelService.importFromResource(shadowBefore.getOid(), task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); display(result); TestUtil.assertSuccess(result); @@ -2580,12 +2413,9 @@ public void test300ImportStanFromEmeraldResource() throws Exception { */ @Test public void test302ModifyStanAccountAndReimport() throws Exception { - final String TEST_NAME = "test302ModifyStanAccountAndReimport"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); DummyAccount dummyAccountBefore = dummyResourceEmerald.getAccountByUsername(ACCOUNT_STAN_USERNAME); @@ -2596,11 +2426,11 @@ public void test302ModifyStanAccountAndReimport() throws Exception { display("Shadow before", shadowBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modelService.importFromResource(shadowBefore.getOid(), task, result); // THEN - displayThen(TEST_NAME); + displayThen(); result.computeStatus(); display(result); TestUtil.assertSuccess(result); @@ -2622,12 +2452,9 @@ public void test302ModifyStanAccountAndReimport() throws Exception { */ @Test public void test800NullTimeFrom() throws Exception { - final String TEST_NAME = "test800Kaboom"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); importObjectFromFile(TASK_TRIGGER_SCANNER_FILE); @@ -2651,12 +2478,9 @@ public void test800NullTimeFrom() throws Exception { */ @Test public void test802FuneralTimestamp() throws Exception { - final String TEST_NAME = "test802FuneralTimestamp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); funeralTimestamp = clock.currentTimeXMLGregorianCalendar(); modifyUserReplace(USER_JACK_OID, getExtensionPath(PIRACY_FUNERAL_TIMESTAMP), task, result, funeralTimestamp); @@ -2825,12 +2649,9 @@ public void test813TalesBoomRecompute() throws Exception { */ @Test public void test820TalesUnBoom() throws Exception { - final String TEST_NAME = "test820TalesUnBoom"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); modifyUserReplace(USER_JACK_OID, getExtensionPath(PIRACY_TALES), task, result /* no value */); @@ -2877,12 +2698,9 @@ public void test820TalesUnBoom() throws Exception { */ @Test public void test830PreLootBoom() throws Exception { - final String TEST_NAME = "test830PreLootBoom"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); modifyUserReplace(USER_JACK_OID, UserType.F_DESCRIPTION, task, result, "Rum is gone"); @@ -2976,12 +2794,9 @@ public void test832LootBoomConditionFalse() throws Exception { */ @Test public void test835LootBoom() throws Exception { - final String TEST_NAME = "test835LootBoom"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_GIVEN_NAME, task, result, createPolyString("Lootjack")); @@ -3013,12 +2828,9 @@ public void test835LootBoom() throws Exception { */ @Test public void test840ResetFuneralTimestamp() throws Exception { - final String TEST_NAME = "test840ResetFuneralTimestamp"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); modifyUserReplace(USER_JACK_OID, getExtensionPath(PIRACY_FUNERAL_TIMESTAMP), task, result /* no value */); @@ -3044,12 +2856,9 @@ public void test840ResetFuneralTimestamp() throws Exception { */ @Test public void test843UnLoot() throws Exception { - final String TEST_NAME = "test843UnLoot"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_GIVEN_NAME, task, result, createPolyString("Justjack")); @@ -3082,12 +2891,9 @@ public void test843UnLoot() throws Exception { */ @Test public void test845ReLoot() throws Exception { - final String TEST_NAME = "test845ReLoot"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserReplace(USER_JACK_OID, UserType.F_GIVEN_NAME, task, result, createPolyString("Lootjack")); @@ -3120,12 +2926,9 @@ public void test845ReLoot() throws Exception { */ @Test public void test850AddCannibalLemonhead() throws Exception { - final String TEST_NAME = "test850AddCannibalLemonhead"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_LEMONHEAD_USERNAME, null, false), task, result); @@ -3151,12 +2954,9 @@ public void test850AddCannibalLemonhead() throws Exception { */ @Test public void test852AddCanibalRedSkull() throws Exception { - final String TEST_NAME = "test852AddCanibalRedSkull"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_REDSKULL_USERNAME, "", false), task, result); @@ -3176,7 +2976,7 @@ public void test852AddCanibalRedSkull() throws Exception { .single() // Trigger from time bomb. There is no condition and the reference time is set. .assertHandlerUri(RecomputeTriggerHandler.HANDLER_URI) - .assertTimestampFuture(funeralTimestamp, "P1M", 1*24*60*60*1000L); + .assertTimestampFuture(funeralTimestamp, "P1M", 24*60*60*1000L); } /** @@ -3186,12 +2986,9 @@ public void test852AddCanibalRedSkull() throws Exception { */ @Test public void test854AddCanibalShaprtooth() throws Exception { - final String TEST_NAME = "test854AddCanibalShaprtooth"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_SHARPTOOTH_USERNAME, "-P1M1D", false), task, result); @@ -3212,7 +3009,7 @@ public void test854AddCanibalShaprtooth() throws Exception { .single() // Trigger from tales bomb. We have Kaboomed, the time constraint has activated .assertHandlerUri(RecomputeTriggerHandler.HANDLER_URI) - .assertTimestampFuture(funeralTimestamp, "P3M", 1*24*60*60*1000L); + .assertTimestampFuture(funeralTimestamp, "P3M", 24*60*60*1000L); } /** @@ -3222,12 +3019,9 @@ public void test854AddCanibalShaprtooth() throws Exception { */ @Test public void test856AddCanibalOrangeskin() throws Exception { - final String TEST_NAME = "test856AddCanibalOrangeskin"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_ORANGESKIN_USERNAME, "-P3M1D", false), task, result); @@ -3256,12 +3050,9 @@ public void test856AddCanibalOrangeskin() throws Exception { */ @Test public void test858AddCanibalCherrybrain() throws Exception { - final String TEST_NAME = "test858AddCanibalCherrybrain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_CHERRYBRAIN_USERNAME, "-P1Y1D", false), task, result); @@ -3292,12 +3083,9 @@ public void test858AddCanibalCherrybrain() throws Exception { */ @Test public void test859AddCanibalPineapplenose() throws Exception { - final String TEST_NAME = "test858AddCanibalCherrybrain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject( @@ -3329,12 +3117,9 @@ public void test859AddCanibalPineapplenose() throws Exception { */ @Test public void test860AddCannibalRottenLemonhead() throws Exception { - final String TEST_NAME = "test860AddCannibalRottenLemonhead"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_LEMONHEAD_USERNAME, null, true), task, result); @@ -3360,12 +3145,9 @@ public void test860AddCannibalRottenLemonhead() throws Exception { */ @Test public void test862AddCanibalRottenRedSkull() throws Exception { - final String TEST_NAME = "test862AddCanibalRottenRedSkull"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_REDSKULL_USERNAME, "", true), task, result); @@ -3395,12 +3177,9 @@ public void test862AddCanibalRottenRedSkull() throws Exception { */ @Test public void test864AddCanibalRottenShaprtooth() throws Exception { - final String TEST_NAME = "test864AddCanibalRottenShaprtooth"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_SHARPTOOTH_USERNAME, "-P1M1D", true), task, result); @@ -3441,12 +3220,9 @@ public void test864AddCanibalRottenShaprtooth() throws Exception { */ @Test public void test866AddCanibalRottenOrangeskin() throws Exception { - final String TEST_NAME = "test866AddCanibalRottenOrangeskin"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_ORANGESKIN_USERNAME, "-P3M1D", true), task, result); @@ -3478,12 +3254,9 @@ public void test866AddCanibalRottenOrangeskin() throws Exception { */ @Test public void test868AddCanibalRottenCherrybrain() throws Exception { - final String TEST_NAME = "test868AddCanibalRottenCherrybrain"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject(createCannibal(CANNIBAL_CHERRYBRAIN_USERNAME, "-P1Y1D", true), task, result); @@ -3512,12 +3285,9 @@ public void test868AddCanibalRottenCherrybrain() throws Exception { */ @Test public void test869AddCanibalRottenPineapplenose() throws Exception { - final String TEST_NAME = "test869AddCanibalRottenPineapplenose"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject( @@ -3550,12 +3320,9 @@ public void test869AddCanibalRottenPineapplenose() throws Exception { */ @Test public void test870AddCanibalRottenPotatoleg() throws Exception { - final String TEST_NAME = "test870AddCanibalRottenPotatoleg"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN String userOid = addObject( @@ -3605,12 +3372,9 @@ private PrismObject createCannibal(String name, String funeralDateOffs @Test public void test900DeleteUser() throws Exception { - final String TEST_NAME = "test900DeleteUser"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); Collection> deltas = new ArrayList<>(); @@ -3638,14 +3402,11 @@ public void test900DeleteUser() throws Exception { @Test public void test950CreateUserJackWithoutTemplate() throws Exception { - final String TEST_NAME = "test950CreateUserJackWithoutTemplate"; - displayTestTitle(TEST_NAME); - // GIVEN setDefaultUserTemplate(null); - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); // WHEN @@ -3673,12 +3434,9 @@ public void test950CreateUserJackWithoutTemplate() throws Exception { */ @Test public void test952ModifyJackOrganizationalUnitFD004() throws Exception { - final String TEST_NAME = "test952ModifyJackOrganizationalUnitFD004"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); // WHEN modifyUserAdd(USER_JACK_OID, UserType.F_ORGANIZATIONAL_UNIT, task, result, PrismTestUtil.createPolyString("FD004")); @@ -3705,14 +3463,11 @@ public void test952ModifyJackOrganizationalUnitFD004() throws Exception { */ @Test public void test960ReconcileUserJackWithTemplate() throws Exception { - final String TEST_NAME = "test960ModifyUserJackWithTemplate"; - displayTestTitle(TEST_NAME); - // GIVEN setDefaultUserTemplate(USER_TEMPLATE_COMPLEX_OID); - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE); // WHEN @@ -3737,23 +3492,20 @@ public void test960ReconcileUserJackWithTemplate() throws Exception { */ @Test public void test970ModifyUserGuybrushEmployeeTypeUseless() throws Exception { - final String TEST_NAME = "test970ModifyUserGuybrushEmployeeTypeUseless"; - displayTestTitle(TEST_NAME); - // GIVEN - Task task = createTask(TEST_NAME); - OperationResult result = task.getResult(); + Task task = getTask(); + OperationResult result = getResult(); PrismObject userBefore = getUser(USER_GUYBRUSH_OID); display("User before", userBefore); assertAssignedNoRole(userBefore); // WHEN - displayWhen(TEST_NAME); + displayWhen(); modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_SUBTYPE, task, result, SUBTYPE_USELESS); // THEN - displayThen(TEST_NAME); + displayThen(); assertSuccess(result); PrismObject userAfter = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, null, task, result); @@ -3763,4 +3515,44 @@ public void test970ModifyUserGuybrushEmployeeTypeUseless() throws Exception { assertEquals("Wrong originMappingName", "assignment-for-useless-role", uselessAssignment.getMetadata().getOriginMappingName()); } + /** + * MID-5892 + */ + @Test + public void test980DeleteUserGivenName() throws Exception { + // GIVEN + Task task = getTask(); + OperationResult result = getResult(); + + UserType user = new UserType(prismContext) + .name("test980DeleteUserGivenName") + .givenName("jim") + .subtype(SUBTYPE_MID_5892) + .beginAssignment() + .targetRef(SystemObjectsType.ROLE_SUPERUSER.value(), RoleType.COMPLEX_TYPE) + .end(); + repositoryService.addObject(user.asPrismObject(), null, result); + + // WHEN + displayWhen(); + ObjectDelta delta = prismContext.deltaFor(UserType.class) + .item(UserType.F_GIVEN_NAME).delete(new PolyString("jim")) + .asObjectDeltaCast(user.getOid()); + executeChanges(delta, null, task, result); + + // THEN + displayThen(); + assertSuccess(result); + + PrismObject userAfter = modelService.getObject(UserType.class, user.getOid(), null, task, result); + display("User after", userAfter); + + AssignmentType assignment = assertAssignedRole(userAfter, SystemObjectsType.ROLE_SUPERUSER.value()); + } + +// @Override +// protected TracingProfileType getTestMethodTracingProfile() { +// return createModelLoggingTracingProfile() +// .fileNamePattern(TEST_METHOD_TRACING_FILENAME_PATTERN); +// } } 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 0e126e1d13a..eb25565aca6 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 @@ -832,7 +832,7 @@ public void test200ReconcileDummy() throws Exception { // THEN displayThen(TEST_NAME); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 4); + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 6); reconciliationTaskResultListener.assertResult(RESOURCE_DUMMY_OID, 0, 7, 0, 0); @@ -995,7 +995,7 @@ public void test219ReconcileDummyFixed() throws Exception { // THEN displayThen(TEST_NAME); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 4); + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 6); reconciliationTaskResultListener.assertResult(RESOURCE_DUMMY_OID, 0, 7, 0, 0); @@ -1151,7 +1151,7 @@ public void test229ReconcileDummyFixed() throws Exception { // THEN displayThen(TEST_NAME); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 4); + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 6); reconciliationTaskResultListener.assertResult(RESOURCE_DUMMY_OID, 0, 7, 0, 0); @@ -1242,7 +1242,7 @@ public void test230ReconcileDummyRename() throws Exception { // THEN displayThen(TEST_NAME); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 4); + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 6); reconciliationTaskResultListener.assertResult(RESOURCE_DUMMY_OID, 0, 7, 0, 1); diff --git a/model/model-intest/src/test/resources/object-template/user-template-mid-5892.xml b/model/model-intest/src/test/resources/object-template/user-template-mid-5892.xml new file mode 100644 index 00000000000..179f70d78bf --- /dev/null +++ b/model/model-intest/src/test/resources/object-template/user-template-mid-5892.xml @@ -0,0 +1,32 @@ + + + + User Template 5892 + + + false + + name + + + givenName + + + + true + RoleType + 00000000-0000-0000-0000-000000000004 + + + + assignment + + + + diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java index a384dd817ad..632f34080eb 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java @@ -43,7 +43,7 @@ public class ProvisioningContext extends StateReporter { private static final Trace LOGGER = TraceManager.getTrace(ProvisioningContext.class); @NotNull private final ResourceManager resourceManager; - private OperationResult parentResult; + private OperationResult parentResult; // Use only when absolutely necessary! private Collection> getOperationOptions; private PrismObject originalShadow; diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java index c100adcde71..c6cdea11a48 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningServiceImpl.java @@ -950,9 +950,7 @@ public SearchResultMetadata searchObjectsIterative(Class< Validate.notNull(parentResult, "Operation result must not be null."); Validate.notNull(handler, "Handler must not be null."); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Start of (iterative) search objects. Query:\n{}", query != null ? query.debugDump(1) : " (null)"); - } + LOGGER.trace("Start of (iterative) search objects. Query:\n{}", DebugUtil.debugDumpLazily(query, 1)); OperationResult result = parentResult.createSubresult(ProvisioningService.class.getName() + ".searchObjectsIterative"); result.setSummarizeSuccesses(true); diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java index 53ce0d888c2..40ef7200ac7 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java @@ -1246,6 +1246,8 @@ public SearchResultMetadata searchResourceObjects(final ProvisioningContext ctx, ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, parentResult); + AtomicInteger objectCounter = new AtomicInteger(0); + SearchResultMetadata metadata; try { @@ -1253,37 +1255,59 @@ public SearchResultMetadata searchResourceObjects(final ProvisioningContext ctx, (shadow) -> { // in order to utilize the cache right from the beginning... RepositoryCache.enter(cacheConfigurationManager); + try { - OperationResult objResult = parentResult.createMinorSubresult(OperationConstants.OPERATION_SEARCH_RESULT); + int objectNumber = objectCounter.getAndIncrement(); - try { + Task task = ctx.getTask(); + boolean requestedTracingHere; + requestedTracingHere = task instanceof RunningTask && + ((RunningTask) task).requestTracingIfNeeded( + (RunningTask) task, objectNumber, + TracingRootType.RETRIEVED_RESOURCE_OBJECT_PROCESSING); try { - shadow = postProcessResourceObjectRead(ctx, shadow, fetchAssociations, objResult); - } catch (SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ObjectNotFoundException | ExpressionEvaluationException e) { - if (objResult.isUnknown()) { - objResult.recordFatalError(e); - } - throw new TunnelException(e); - } catch (Throwable t) { - if (objResult.isUnknown()) { + OperationResultBuilder resultBuilder = parentResult + .subresult(OperationConstants.OPERATION_SEARCH_RESULT) + .setMinor() + .addParam("number", objectNumber); + // TODO primary identifier (but it's not computed yet) + + // Here we request tracing if configured to do so. Note that this is only a partial solution: for multithreaded + // operations we currently do not trace the "worker" part of the processing. + boolean tracingRequested = setTracingInOperationResultIfRequested(resultBuilder, + TracingRootType.RETRIEVED_RESOURCE_OBJECT_PROCESSING, task, parentResult); + + OperationResult objResult = resultBuilder.build(); + try { + shadow = postProcessResourceObjectRead(ctx, shadow, fetchAssociations, objResult); + Validate.notNull(shadow, "null shadow"); + return resultHandler.handle(shadow, objResult); + } catch (Throwable t) { objResult.recordFatalError(t); + throw t; + } finally { + objResult.computeStatusIfUnknown(); + if (tracingRequested) { + tracer.storeTrace(task, objResult, parentResult); + } + // FIXME: hack. Hardcoded ugly summarization of successes. something like + // AbstractSummarizingResultHandler [lazyman] + if (objResult.isSuccess() && !tracingRequested && !objResult.isTraced()) { + objResult.getSubresults().clear(); + } + // TODO Reconsider this. It is quite dubious to touch parentResult from the inside. + parentResult.summarize(); } - throw t; - } - Validate.notNull(shadow, "null shadow"); - boolean doContinue; - try { - doContinue = resultHandler.handle(shadow, objResult); - objResult.computeStatus(); - } catch (Throwable t) { - if (objResult.isUnknown()) { - objResult.recordFatalError(t); + } finally { + RepositoryCache.exit(); + if (requestedTracingHere && task instanceof RunningTask) { + ((RunningTask) task).stopTracing(); } - throw t; } - return doContinue; - } finally { - RepositoryCache.exit(); + } catch (RuntimeException e) { + throw e; + } catch (Throwable t) { + throw new TunnelException(t); } }, attributesToReturn, objectClassDef.getPagedSearches(ctx.getResource()), searchHierarchyConstraints, @@ -1331,6 +1355,23 @@ public SearchResultMetadata searchResourceObjects(final ProvisioningContext ctx, return metadata; } + private boolean setTracingInOperationResultIfRequested(OperationResultBuilder resultBuilder, TracingRootType tracingRoot, + Task task, OperationResult parentResult) throws SchemaException { + boolean tracingRequested; + if (task != null && task.getTracingRequestedFor().contains(tracingRoot)) { + tracingRequested = true; + try { + resultBuilder.tracingProfile(tracer.compileProfile(task.getTracingProfile(), parentResult)); + } catch (SchemaException | RuntimeException e) { + parentResult.recordFatalError(e); + throw e; + } + } else { + tracingRequested = false; + } + return tracingRequested; + } + @SuppressWarnings("rawtypes") public PrismProperty fetchCurrentToken(ProvisioningContext ctx, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, ExpressionEvaluationException { @@ -1791,15 +1832,11 @@ public boolean handleChange(Change change, OperationResult parentResult) { // Here we request tracing if configured to do so. Note that this is only a partial solution: for multithreaded // livesync we currently do not trace the "worker" part of the processing. boolean tracingRequested; - if (task.getTracingRequestedFor().contains(TracingRootType.LIVE_SYNC_CHANGE_PROCESSING)) { - tracingRequested = true; - try { - resultBuilder.tracingProfile(tracer.compileProfile(task.getTracingProfile(), parentResult)); - } catch (SchemaException | RuntimeException e) { - return changeHandler.handleError(change.getToken(), change, e, parentResult); - } - } else { - tracingRequested = false; + try { + tracingRequested = setTracingInOperationResultIfRequested(resultBuilder, + TracingRootType.LIVE_SYNC_CHANGE_PROCESSING, task, parentResult); + } catch (Throwable t) { + return changeHandler.handleError(change.getToken(), change, t, parentResult); } OperationResult result = resultBuilder.build(); 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 d3818a618da..ebf829614f2 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 @@ -220,7 +220,7 @@ public PrismObject getShadow(String oid, PrismObject rep return resultShadow; } - PrismObject resourceShadow = null; + PrismObject resourceObject; Collection> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(repositoryShadow); if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) { @@ -257,7 +257,7 @@ public PrismObject getShadow(String oid, PrismObject rep try { - resourceShadow = resourceObjectConverter.getResourceObject(ctx, identifiers, true, parentResult); + resourceObject = resourceObjectConverter.getResourceObject(ctx, identifiers, true, parentResult); } catch (ObjectNotFoundException e) { // This may be OK, e.g. for connectors that have running async add operation. @@ -280,30 +280,30 @@ public PrismObject getShadow(String oid, PrismObject rep } } - LOGGER.trace("Shadow returned by ResourceObjectConverter:\n{}", resourceShadow.debugDumpLazily(1)); + LOGGER.trace("Shadow returned by ResourceObjectConverter:\n{}", resourceObject.debugDumpLazily(1)); // Resource shadow may have different auxiliary object classes than // the original repo shadow. Make sure we have the definition that // applies to resource shadow. We will fix repo shadow later. // BUT we need also information about kind/intent and these information is only // in repo shadow, therefore the following 2 lines.. - resourceShadow.asObjectable().setKind(repositoryShadow.asObjectable().getKind()); - resourceShadow.asObjectable().setIntent(repositoryShadow.asObjectable().getIntent()); - ProvisioningContext shadowCtx = ctx.spawn(resourceShadow); + resourceObject.asObjectable().setKind(repositoryShadow.asObjectable().getKind()); + resourceObject.asObjectable().setIntent(repositoryShadow.asObjectable().getIntent()); + ProvisioningContext shadowCtx = ctx.spawn(resourceObject); resourceManager.modifyResourceAvailabilityStatus(resource.asPrismObject(), AvailabilityStatusType.UP, parentResult); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Shadow from repository:\n{}", repositoryShadow.debugDump(1)); - LOGGER.trace("Resource object fetched from resource:\n{}", resourceShadow.debugDump(1)); + LOGGER.trace("Resource object fetched from resource:\n{}", resourceObject.debugDump(1)); } - repositoryShadow = shadowManager.updateShadow(shadowCtx, resourceShadow, null, repositoryShadow, shadowState, parentResult); + repositoryShadow = shadowManager.updateShadow(shadowCtx, resourceObject, null, repositoryShadow, shadowState, parentResult); LOGGER.trace("Repository shadow after update:\n{}", repositoryShadow.debugDumpLazily(1)); // Complete the shadow by adding attributes from the resource object // This also completes the associations by adding shadowRefs - PrismObject assembledShadow = completeShadow(shadowCtx, resourceShadow, repositoryShadow, false, parentResult); + PrismObject assembledShadow = completeShadow(shadowCtx, resourceObject, repositoryShadow, false, parentResult); LOGGER.trace("Shadow when assembled:\n{}", assembledShadow.debugDumpLazily(1)); PrismObject resultShadow = futurizeShadow(ctx, repositoryShadow, assembledShadow, options, now); @@ -334,13 +334,8 @@ public PrismObject getShadow(String oid, PrismObject rep } } finally { // We need to record the fetch down here. Now it is certain that we - // are going to fetch from resource - // (we do not have raw/noFetch option) - // TODO: is this correct behaviour? don't we really want to record - // fetch for protected objects? - if (!ShadowUtil.isProtected(resourceShadow)) { - InternalMonitor.recordCount(InternalCounters.SHADOW_FETCH_OPERATION_COUNT); - } + // are going to fetch from resource (we do not have raw/noFetch option) + InternalMonitor.recordCount(InternalCounters.SHADOW_FETCH_OPERATION_COUNT); } } @@ -2017,26 +2012,25 @@ public SearchResultMetadata searchObjectsIterative(final ProvisioningContext ctx ObjectQuery attributeQuery = createAttributeQuery(query); - ResultHandler resultHandler = (PrismObject resourceShadow, OperationResult objResult) -> { - LOGGER.trace("Found resource object\n{}", resourceShadow.debugDumpLazily(1)); + ResultHandler resultHandler = (PrismObject resourceObject, OperationResult objResult) -> { + LOGGER.trace("Found resource object\n{}", resourceObject.debugDumpLazily(1)); PrismObject resultShadow; try { // The shadow does not have any kind or intent at this point. // But at least locate the definition using object classes. - ProvisioningContext estimatedShadowCtx = shadowCaretaker.reapplyDefinitions(ctx, resourceShadow); + ProvisioningContext estimatedShadowCtx = shadowCaretaker.reapplyDefinitions(ctx, resourceObject); // Try to find shadow that corresponds to the resource object. if (readFromRepository) { PrismObject repoShadow = acquireRepositoryShadow( - estimatedShadowCtx, resourceShadow, true, isDoDiscovery, parentResult); + estimatedShadowCtx, resourceObject, true, isDoDiscovery, objResult); // This determines the definitions exactly. How the repo // shadow should have proper kind/intent ProvisioningContext shadowCtx = shadowCaretaker.applyAttributesDefinition(ctx, repoShadow); // TODO: shadowState - repoShadow = shadowManager.updateShadow(shadowCtx, resourceShadow, null, repoShadow, - null, parentResult); + repoShadow = shadowManager.updateShadow(shadowCtx, resourceObject, null, repoShadow, null, objResult); - resultShadow = completeShadow(shadowCtx, resourceShadow, repoShadow, isDoDiscovery, objResult); + resultShadow = completeShadow(shadowCtx, resourceObject, repoShadow, isDoDiscovery, objResult); // TODO do we want also to futurize the shadow like in getObject? @@ -2050,7 +2044,7 @@ public SearchResultMetadata searchObjectsIterative(final ProvisioningContext ctx } } else { - resultShadow = resourceShadow; + resultShadow = resourceObject; } validateShadow(resultShadow, readFromRepository); @@ -2081,15 +2075,6 @@ public SearchResultMetadata searchObjectsIterative(final ProvisioningContext ctx } catch (RuntimeException | Error e) { objResult.recordFatalError(e); throw e; - } finally { - objResult.computeStatus(); - objResult.recordSuccessIfUnknown(); - // FIXME: hack. Hardcoded ugly summarization of successes. something like - // AbstractSummarizingResultHandler [lazyman] - if (objResult.isSuccess()) { - objResult.getSubresults().clear(); - } - parentResult.summarize(); } return doContinue; @@ -2137,19 +2122,17 @@ private PrismObject acquireRepositoryShadow(ProvisioningContext ctx, throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException, EncryptionException { - PrismObject repoShadow = shadowManager.lookupLiveShadowInRepository(ctx, resourceShadow, parentResult); + PrismObject existingRepoShadow = shadowManager.lookupLiveShadowInRepository(ctx, resourceShadow, parentResult); - if (repoShadow != null) { + if (existingRepoShadow != null) { if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Found shadow object in the repository {}", ShadowUtil.shortDumpShadow(repoShadow)); + LOGGER.trace("Found shadow object in the repository {}", ShadowUtil.shortDumpShadow(existingRepoShadow)); } - return repoShadow; + return existingRepoShadow; } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Shadow object (in repo) corresponding to the resource object (on the resource) was not found. " - + "The repo shadow will be created. The resource object:\n{}", resourceShadow); - } + LOGGER.trace("Shadow object (in repo) corresponding to the resource object (on the resource) was not found. " + + "The repo shadow will be created. The resource object:\n{}", resourceShadow); // TODO: do something about shadows with mathcing secondary identifiers? We do not need to care about these any longer, do we? //MID-5844 @@ -2189,9 +2172,10 @@ private PrismObject acquireRepositoryShadow(ProvisioningContext ctx, // not exist in the repository we need to create the shadow to align repo state to the // reality (resource) + PrismObject createdRepoShadow; try { - repoShadow = shadowManager.addDiscoveredRepositoryShadow(ctx, resourceShadow, parentResult); + createdRepoShadow = shadowManager.addDiscoveredRepositoryShadow(ctx, resourceShadow, parentResult); } catch (ObjectAlreadyExistsException e) { // Conflict! But we haven't supplied an OID and we have checked for existing shadow before, @@ -2225,15 +2209,12 @@ private PrismObject acquireRepositoryShadow(ProvisioningContext ctx, return conflictingShadow; } - resourceShadow.setOid(repoShadow.getOid()); - ObjectReferenceType resourceRef = resourceShadow.asObjectable().getResourceRef(); - if (resourceRef == null) { - resourceRef = new ObjectReferenceType(); - resourceRef.asReferenceValue().setObject(ctx.getResource().asPrismObject()); - resourceShadow.asObjectable().setResourceRef(resourceRef); - } else { - resourceRef.asReferenceValue().setObject(ctx.getResource().asPrismObject()); + resourceShadow.setOid(createdRepoShadow.getOid()); + ShadowType resourceShadowBean = resourceShadow.asObjectable(); + if (resourceShadowBean.getResourceRef() == null) { + resourceShadowBean.setResourceRef(new ObjectReferenceType()); } + resourceShadowBean.getResourceRef().asReferenceValue().setObject(ctx.getResource().asPrismObject()); if (isDoDiscovery) { // We have object for which there was no shadow. Which means that midPoint haven't known about this shadow before. @@ -2242,17 +2223,17 @@ private PrismObject acquireRepositoryShadow(ProvisioningContext ctx, notifyResourceObjectChangeListeners(resourceShadow, ctx.getResource().asPrismObject(), true); } + PrismObject finalRepoShadow; if (unknownIntent) { // Intent may have been changed during the notifyChange processing. // Re-read the shadow if necessary. - repoShadow = shadowManager.fixShadow(ctx, repoShadow, parentResult); - } - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Final repo shadow (created):\n{}", repoShadow.debugDump(1)); + finalRepoShadow = shadowManager.fixShadow(ctx, createdRepoShadow, parentResult); + } else { + finalRepoShadow = createdRepoShadow; } - return repoShadow; + LOGGER.trace("Final repo shadow (created and possibly re-read):\n{}", finalRepoShadow.debugDumpLazily(1)); + return finalRepoShadow; } private ObjectQuery createAttributeQuery(ObjectQuery query) throws SchemaException { diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowDeltaComputer.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowDeltaComputer.java index 43835d7fe2e..34547735257 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowDeltaComputer.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowDeltaComputer.java @@ -57,15 +57,15 @@ public class ShadowDeltaComputer { @NotNull ObjectDelta computeShadowDelta(@NotNull ProvisioningContext ctx, - @NotNull PrismObject repoShadowOld, PrismObject resourceShadowNew, + @NotNull PrismObject repoShadowOld, PrismObject currentResourceObject, ObjectDelta resourceObjectDelta, ShadowState shadowState) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException { ObjectDelta computedShadowDelta = repoShadowOld.createModifyDelta(); - RefinedObjectClassDefinition ocDef = ctx.computeCompositeObjectClassDefinition(resourceShadowNew); - PrismContainer currentResourceAttributes = resourceShadowNew.findContainer(ShadowType.F_ATTRIBUTES); + RefinedObjectClassDefinition ocDef = ctx.computeCompositeObjectClassDefinition(currentResourceObject); + PrismContainer currentResourceAttributes = currentResourceObject.findContainer(ShadowType.F_ATTRIBUTES); PrismContainer oldRepoAttributes = repoShadowOld.findContainer(ShadowType.F_ATTRIBUTES); ShadowType oldRepoShadowType = repoShadowOld.asObjectable(); @@ -75,17 +75,17 @@ ObjectDelta computeShadowDelta(@NotNull ProvisioningContext ctx, processAttributes(computedShadowDelta, incompleteCacheableItems, oldRepoAttributes, currentResourceAttributes, resourceObjectDelta, ocDef, cachingStrategy); - PolyString currentShadowName = ShadowUtil.determineShadowName(resourceShadowNew); + PolyString currentShadowName = ShadowUtil.determineShadowName(currentResourceObject); PolyString oldRepoShadowName = repoShadowOld.getName(); - if (!currentShadowName.equalsOriginalValue(oldRepoShadowName)) { + if (currentShadowName != null && !currentShadowName.equalsOriginalValue(oldRepoShadowName)) { PropertyDelta shadowNameDelta = prismContext.deltaFactory().property().createModificationReplaceProperty(ShadowType.F_NAME, - repoShadowOld.getDefinition(),currentShadowName); + repoShadowOld.getDefinition(), currentShadowName); computedShadowDelta.addModification(shadowNameDelta); } PropertyDelta auxOcDelta = ItemUtil.diff( repoShadowOld.findProperty(ShadowType.F_AUXILIARY_OBJECT_CLASS), - resourceShadowNew.findProperty(ShadowType.F_AUXILIARY_OBJECT_CLASS)); + currentResourceObject.findProperty(ShadowType.F_AUXILIARY_OBJECT_CLASS)); if (auxOcDelta != null) { computedShadowDelta.addModification(auxOcDelta); } @@ -105,10 +105,10 @@ ObjectDelta computeShadowDelta(@NotNull ProvisioningContext ctx, } else if (cachingStrategy == CachingStategyType.PASSIVE) { - compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, resourceShadowNew, repoShadowOld); - compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_VALID_FROM, resourceShadowNew, repoShadowOld); - compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_VALID_TO, resourceShadowNew, repoShadowOld); - compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, resourceShadowNew, repoShadowOld); + compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, currentResourceObject, repoShadowOld); + compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_VALID_FROM, currentResourceObject, repoShadowOld); + compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_VALID_TO, currentResourceObject, repoShadowOld); + compareUpdateProperty(computedShadowDelta, SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, currentResourceObject, repoShadowOld); if (incompleteCacheableItems.isEmpty()) { CachingMetadataType cachingMetadata = new CachingMetadataType(); @@ -210,19 +210,20 @@ private void processResourceAttribute(ObjectDelta computedShadowDelt PrismProperty oldRepoAttributeProperty = oldRepoAttributes.findProperty(attrDef.getItemName()); if (oldRepoAttributeProperty == null) { PropertyDelta attrAddDelta = currentResourceAttrProperty.createDelta(); - List> currentValues = currentResourceAttrProperty.getValues(); - // This is a brutal hack: For extension attributes the ADD operation is slow when using large # of - // values to add. So let's do REPLACE instead (this is OK if there are no existing values). - // TODO Move this logic to repository. Here it is only for PoC purposes. - if (currentValues.size() >= 100) { - Object[] currentValuesNormalized = new Object[currentValues.size()]; - for (int i = 0; i < currentValues.size(); i++) { - currentValuesNormalized[i] = matchingRule.normalize(currentValues.get(i).getValue()); - } - attrAddDelta.setRealValuesToReplace(currentValuesNormalized); + List> valuesOnResource = currentResourceAttrProperty.getValues(); + if (attrDef.isIndexOnly()) { + // We don't know what is in the repository. We simply want to replace everything with the current values. + setNormalizedValuesToReplace(attrAddDelta, valuesOnResource, matchingRule); } else { - for (PrismPropertyValue pval : currentValues) { - attrAddDelta.addRealValuesToAdd(matchingRule.normalize(pval.getValue())); + // This is a brutal hack: For extension attributes the ADD operation is slow when using large # of + // values to add. So let's do REPLACE instead (this is OK if there are no existing values). + // TODO Move this logic to repository. Here it is only for PoC purposes. + if (valuesOnResource.size() >= 100) { + setNormalizedValuesToReplace(attrAddDelta, valuesOnResource, matchingRule); + } else { + for (PrismPropertyValue pval : valuesOnResource) { + attrAddDelta.addRealValuesToAdd(matchingRule.normalize(pval.getValue())); + } } } if (attrAddDelta.getDefinition().getTypeName() == null) { @@ -270,6 +271,15 @@ private void processResourceAttribute(ObjectDelta computedShadowDelt } } + private void setNormalizedValuesToReplace(PropertyDelta attrAddDelta, List> currentValues, + MatchingRule matchingRule) throws SchemaException { + Object[] currentValuesNormalized = new Object[currentValues.size()]; + for (int i = 0; i < currentValues.size(); i++) { + currentValuesNormalized[i] = matchingRule.normalize(currentValues.get(i).getValue()); + } + attrAddDelta.setRealValuesToReplace(currentValuesNormalized); + } + private void compareUpdateProperty(ObjectDelta shadowDelta, ItemPath itemPath, PrismObject currentResourceShadow, PrismObject oldRepoShadow) { PrismProperty currentProperty = currentResourceShadow.findProperty(itemPath); diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowManager.java index a923d05b525..027d75003b5 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/shadowmanager/ShadowManager.java @@ -691,17 +691,13 @@ private void processQueryMatchingRuleFilter(ObjectFilter filter, RefinedObje // Used when new resource object is discovered public PrismObject addDiscoveredRepositoryShadow(ProvisioningContext ctx, PrismObject resourceShadow, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException, EncryptionException { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Adding new shadow from resource object:\n{}", resourceShadow.debugDump(1)); - } + LOGGER.trace("Adding new shadow from resource object:\n{}", resourceShadow.debugDumpLazily(1)); PrismObject repoShadow = createRepositoryShadow(ctx, resourceShadow); ConstraintsChecker.onShadowAddOperation(repoShadow.asObjectable()); String oid = repositoryService.addObject(repoShadow, null, parentResult); repoShadow.setOid(oid); LOGGER.debug("Added new shadow (from resource object): {}", repoShadow); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Added new shadow (from resource object):\n{}", repoShadow.debugDump(1)); - } + LOGGER.trace("Added new shadow (from resource object):\n{}", repoShadow.debugDumpLazily(1)); return repoShadow; } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessor.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessor.java index 0c28110f2c4..d71327c60c2 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessor.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessor.java @@ -279,10 +279,10 @@ private void preProcessChange(ProvisioningContext ctx, Change change, OperationR assert change.getCurrentResourceObject() != null || change.isDelete(); if (change.getCurrentResourceObject() != null) { // TODO do we need to complete the shadow now? Why? MID-5834 - PrismObject currentShadow = shadowCache.completeShadow(ctx, change.getCurrentResourceObject(), oldShadow, false, parentResult); - change.setCurrentResourceObject(currentShadow); + PrismObject currentResourceObjectShadowized = shadowCache.completeShadow(ctx, change.getCurrentResourceObject(), oldShadow, false, parentResult); + change.setCurrentResourceObject(currentResourceObjectShadowized); // TODO: shadowState MID-5834 - shadowManager.updateShadow(ctx, currentShadow, change.getObjectDelta(), oldShadow, null, parentResult); + shadowManager.updateShadow(ctx, currentResourceObjectShadowized, change.getObjectDelta(), oldShadow, null, parentResult); } if (change.getObjectDelta() != null && change.getObjectDelta().getOid() == null) { diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java index b61d3b2d52b..f31d72e2ebd 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeResultHandler.java @@ -422,7 +422,7 @@ private void processRequest(ProcessingRequest request, RunningTask workerTask, O TracingAppender.terminateCollecting(); // todo reconsider LevelOverrideTurboFilter.cancelLoggingOverride(); // todo reconsider } - if (result.isSuccess()) { + if (result.isSuccess() && !tracingRequested && !result.isTraced()) { // FIXME: hack. Hardcoded ugly summarization of successes. something like // AbstractSummarizingResultHandler [lazyman] result.getSubresults().clear(); diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/RAnyConverterStaticTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/RAnyConverterStaticTest.java index 1d165e2052b..74c5ea77246 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/RAnyConverterStaticTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/RAnyConverterStaticTest.java @@ -194,7 +194,9 @@ public void testExtensionEnum() throws Exception { try { values = converter.convertToRValue(item, false, RObjectExtensionType.EXTENSION); AssertJUnit.fail("Should have throw serialization related exception after creating ext item"); - } catch (DtoTranslationException ex) { + } catch (RestartOperationRequestedException ex) { // this is a new way + System.out.println("Got expected exception: " + ex); + } catch (DtoTranslationException ex) { // this was an old way AssertJUnit.assertEquals("Wrong exception class", RestartOperationRequestedException.class, ex.getCause().getClass()); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAnyConverter.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAnyConverter.java index fcefc7996dd..3b39bed5df9 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAnyConverter.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/any/RAnyConverter.java @@ -123,24 +123,22 @@ public RAnyConverter(PrismContext prismContext, ExtItemDictionary extItemDiction } @NotNull - private RAnyValue extractAndCreateValue(ItemDefinition def, PrismPropertyValue propertyValue, boolean assignment) + private RAnyValue extractAndCreateValue(PrismPropertyValue propertyValue, boolean assignment, ValueType type) throws SchemaException { - ValueType type = getValueType(def.getTypeName()); Object extractedValue = extractValue(propertyValue, type.getValueType()); return assignment ? type.createNewAExtValue(extractedValue) : type.createNewOExtValue(extractedValue); } @NotNull - public RAnyValue convertToRValue(PrismValue value, boolean isAssignment) throws SchemaException { + public RAnyValue convertToRValue(PrismValue value, boolean isAssignment, Integer itemId) throws SchemaException { RAnyValue rValue; ItemDefinition definition = value.getParent().getDefinition(); if (value instanceof PrismPropertyValue) { PrismPropertyValue propertyValue = (PrismPropertyValue) value; - - rValue = extractAndCreateValue(definition, propertyValue, isAssignment); + rValue = extractAndCreateValue(propertyValue, isAssignment, getValueType(definition.getTypeName())); } else if (value instanceof PrismReferenceValue) { if (isAssignment) { PrismReferenceValue referenceValue = (PrismReferenceValue) value; @@ -154,13 +152,13 @@ public RAnyValue convertToRValue(PrismValue value, boolean isAssignment) thro throw new AssertionError("Wrong value type: " + value); } - rValue.setItemId(extItemDictionary.createOrFindItemDefinition(definition).getId()); + rValue.setItemId(itemId); return rValue; } //todo assignment parameter really messed up this method, proper interfaces must be introduced later [lazyman] - public Set> convertToRValue(Item item, boolean assignment, + public Set> convertToRValue(Item item, boolean assignment, RObjectExtensionType ownerType) throws SchemaException, DtoTranslationException { Validate.notNull(item, "Object for converting must not be null."); Validate.notNull(item.getDefinition(), "Item '" + item.getElementName() + "' without definition can't be saved."); @@ -171,15 +169,13 @@ public Set> convertToRValue(Item item, boolean assignment, return rValues; } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Converting any values of item {}; definition: {}", item, definition); - } + LOGGER.trace("Converting any values of item {}; definition: {}", item, definition); + + Integer itemId = extItemDictionary.createOrFindItemDefinition(definition).getId(); try { - RAnyValue rValue; - List values = item.getValues(); - for (PrismValue value : values) { - rValue = convertToRValue(value, assignment); + for (PrismValue value : item.getValues()) { + RAnyValue rValue = convertToRValue(value, assignment, itemId); rValues.add(rValue); } } catch (Exception ex) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectDeltaUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectDeltaUpdater.java index f73b9a729f7..b2de44be0b2 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectDeltaUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectDeltaUpdater.java @@ -448,7 +448,7 @@ private void handleAssignmentExtensionItemDelta(RAssignment assignment, ItemDelt } private void processExtensionDeltaValueSet(Collection prismValuesFromDelta, - RAnyConverter.ValueType valueType, RObject object, + Integer itemId, RAnyConverter.ValueType valueType, RObject object, RObjectExtensionType objectOwnerType, RAssignmentExtension assignmentExtension, RAssignmentExtensionType assignmentExtensionType, BiConsumer>, Collection>>> deltaValuesProcessor) { @@ -462,7 +462,7 @@ private void processExtensionDeltaValueSet(Collection pris try { Collection>> rValuesFromDelta = new ArrayList<>(); for (PrismValue prismValueFromDelta : prismValuesFromDelta) { - RAnyValue rValueFromDelta = converter.convertToRValue(prismValueFromDelta, object == null); + RAnyValue rValueFromDelta = converter.convertToRValue(prismValueFromDelta, object == null, itemId); rValuesFromDelta.add(new PrismEntityPair<>(prismValueFromDelta, rValueFromDelta)); } @@ -527,17 +527,19 @@ private void handleExtensionDelta(ItemDelta delta, return; } + Integer itemId = extItemDictionary.createOrFindItemDefinition(definition).getId(); + if (delta.getValuesToReplace() != null) { - processExtensionDeltaValueSet(delta.getValuesToReplace(), valueType, object, objectExtensionType, + processExtensionDeltaValueSet(delta.getValuesToReplace(), itemId, valueType, object, objectExtensionType, assignmentExtension, assignmentExtensionType, (dbCollection, pairsFromDelta) -> replaceExtensionValues(objectExtensionType, assignmentExtensionType, definition, dbCollection, pairsFromDelta, ctx)); } else { - processExtensionDeltaValueSet(delta.getValuesToDelete(), valueType, object, objectExtensionType, assignmentExtension, + processExtensionDeltaValueSet(delta.getValuesToDelete(), itemId, valueType, object, objectExtensionType, assignmentExtension, assignmentExtensionType, (dbCollection, pairsFromDelta) -> deleteExtensionValues(dbCollection, pairsFromDelta, ctx)); - processExtensionDeltaValueSet(delta.getValuesToAdd(), valueType, object, objectExtensionType, assignmentExtension, + processExtensionDeltaValueSet(delta.getValuesToAdd(), itemId, valueType, object, objectExtensionType, assignmentExtension, assignmentExtensionType, (dbCollection, pairsFromDelta) -> addExtensionValues(dbCollection, pairsFromDelta, ctx)); } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/schemacheck/SchemaActionComputer.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/schemacheck/SchemaActionComputer.java index 851b401ca20..2b7d9de53f0 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/schemacheck/SchemaActionComputer.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/schemacheck/SchemaActionComputer.java @@ -55,9 +55,9 @@ class SchemaActionComputer { @Autowired private LocalizationService localizationService; @Autowired private BaseHelper baseHelper; - @SuppressWarnings("ArraysAsListWithZeroOrOneArgument") private static final Set> AUTOMATICALLY_UPGRADEABLE = new HashSet<>( - Arrays.asList(new ImmutablePair<>("3.8", "3.9")) + Arrays.asList(new ImmutablePair<>("3.8", "3.9"), + new ImmutablePair<>("3.9", "4.0")) ); enum State { @@ -275,7 +275,8 @@ private MissingSchemaAction getMissingSchemaAction() { @NotNull private String getRequiredDatabaseSchemaVersion() { // TODO adapt if major mp version != database schema version - return getMajorMidPointVersion(); + //return getMajorMidPointVersion(); + return "4.0"; // Temporary measure, until better mechanism is devised (MID-5884) } @NotNull 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 9bc16a59819..69edbeaa8cb 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 @@ -262,7 +262,7 @@ public void setTaskAndResult(ITestContext ctx, Method testMethod) throws SchemaE ctx.setAttribute(ATTR_TASK, task); ctx.setAttribute(ATTR_RESULT, result); - MidpointTestMethodContext.setup(task, result); + MidpointTestMethodContext.setup(testMethod.getName(), task, result); } protected TracingProfileType getTestMethodTracingProfile() { @@ -313,6 +313,15 @@ protected Task getTask(IAttributes attrs) { return (Task) attrs.getAttribute(ATTR_TASK); } + protected String getTestNameShort() { + MidpointTestMethodContext ctx = MidpointTestMethodContext.get(); + if (ctx != null) { + return ctx.getMethodName(); + } else { + return createAdHocTestContext().getMethodName(); + } + } + protected Task getTask() { MidpointTestMethodContext ctx = MidpointTestMethodContext.get(); if (ctx != null) { @@ -357,7 +366,7 @@ private MidpointTestMethodContext createAdHocTestContext() { LOGGER.warn("No test context for current thread: creating new"); System.out.println("No test context for current thread: creating new"); Task task = taskManager.createTaskInstance(this.getClass().getName() + ".unknownMethod"); - return MidpointTestMethodContext.setup(task, task.getResult()); + return MidpointTestMethodContext.setup("unknownMethod", task, task.getResult()); } abstract public void initSystem(Task initTask, OperationResult initResult) throws Exception; @@ -1769,6 +1778,10 @@ protected void displayTestTitle(String testName) { TestUtil.displayTestTitle(this, testName); } + protected void displayWhen() { + displayWhen(getTestNameShort()); + } + protected void displayWhen(String testName) { TestUtil.displayWhen(testName); } @@ -1777,6 +1790,10 @@ protected void displayWhen(String testName, String stage) { TestUtil.displayWhen(testName + " ("+stage+")"); } + protected void displayThen() { + displayThen(getTestNameShort()); + } + protected void displayThen(String testName) { TestUtil.displayThen(testName); } @@ -2018,6 +2035,14 @@ protected TracingProfileType createDefaultTracingProfile() { .fileNamePattern(DEFAULT_TRACING_FILENAME_PATTERN); } + protected TracingProfileType createPerformanceTracingProfile() { + return new TracingProfileType() + .beginTracingTypeProfile() + .level(TracingLevelType.MINIMAL) + .end() + .fileNamePattern(DEFAULT_TRACING_FILENAME_PATTERN); + } + protected Task createTracedTask(String operationName) { Task task = createTask(operationName); task.addTracingRequest(TracingRootType.CLOCKWORK_RUN); @@ -2862,6 +2887,18 @@ protected void clearLogFile() { } protected void setGlobalTracingOverride(@NotNull TracingProfileType profile) { + List roots = Arrays.asList( + TracingRootType.CLOCKWORK_RUN, + TracingRootType.ITERATIVE_TASK_OBJECT_PROCESSING, + TracingRootType.ASYNCHRONOUS_MESSAGE_PROCESSING, + TracingRootType.LIVE_SYNC_CHANGE_PROCESSING, + TracingRootType.WORKFLOW_OPERATION + // RETRIEVED_RESOURCE_OBJECT_PROCESSING is invoked too frequently to be universally enabled + ); + taskManager.setGlobalTracingOverride(roots, profile); + } + + protected void setGlobalTracingOverrideAll(@NotNull TracingProfileType profile) { taskManager.setGlobalTracingOverride(Arrays.asList(TracingRootType.values()), profile); } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java index 376497b662b..6dd864dcbe2 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/MidpointTestMethodContext.java @@ -17,6 +17,11 @@ public final class MidpointTestMethodContext { private static final ThreadLocal TEST_CONTEXT_THREAD_LOCAL = new ThreadLocal<>(); + /** + * Test method name. + */ + private final String methodName; + /** * Task used to execute the test. */ @@ -27,11 +32,16 @@ public final class MidpointTestMethodContext { */ private final OperationResult result; - private MidpointTestMethodContext(Task task, OperationResult result) { + private MidpointTestMethodContext(String methodName, Task task, OperationResult result) { + this.methodName = methodName; this.task = task; this.result = result; } + public String getMethodName() { + return methodName; + } + public Task getTask() { return task; } @@ -44,8 +54,8 @@ public static MidpointTestMethodContext get() { return TEST_CONTEXT_THREAD_LOCAL.get(); } - public static MidpointTestMethodContext setup(Task task, OperationResult result) { - MidpointTestMethodContext ctx = new MidpointTestMethodContext(task, result); + public static MidpointTestMethodContext setup(String methodName, Task task, OperationResult result) { + MidpointTestMethodContext ctx = new MidpointTestMethodContext(methodName, task, result); TEST_CONTEXT_THREAD_LOCAL.set(ctx); return ctx; } diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java index d6ca94668dd..9b165501483 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java @@ -112,8 +112,7 @@ public void storeTrace(Task task, OperationResult result, @Nullable OperationRes if (!Boolean.FALSE.equals(tracingProfile.isCreateTraceFile())) { boolean zip = !Boolean.FALSE.equals(tracingProfile.isCompressOutput()); - Map templateParameters = createTemplateParameters(task, - result); // todo evaluate lazily if needed + Map templateParameters = createTemplateParameters(task, result); // todo evaluate lazily if needed File file = createFileName(zip, tracingProfile, templateParameters); try { long start = System.currentTimeMillis(); @@ -479,6 +478,7 @@ private TracingProfileType resolveProfile(TracingProfileType tracingProfile, Tra merge(rv, getResolvedProfile(ref, tracingConfiguration, resolutionPath)); } merge(rv, tracingProfile); + rv.getRef().clear(); return rv; } } diff --git a/testing/pom.xml b/testing/pom.xml index b3e99aba6d8..4b8c530041b 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -50,6 +50,7 @@ longtest story rest + samples-test diff --git a/testing/samples-test/pom.xml b/testing/samples-test/pom.xml index 77eec43e1a6..777d258d080 100644 --- a/testing/samples-test/pom.xml +++ b/testing/samples-test/pom.xml @@ -14,7 +14,7 @@ parent com.evolveum.midpoint - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT ../../build-system/pom.xml @@ -39,6 +39,30 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-samples + compile + + unpack + + + + + com.evolveum.midpoint + midpoint-samples + ** + + + ${project.build.directory}/samples + ** + + + + maven-surefire-plugin @@ -69,54 +93,60 @@ com.evolveum.midpoint.infra util - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.infra prism-api - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT com.evolveum.midpoint.infra prism-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.infra schema - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.infra common - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo repo-api - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo task-api - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.model model-api - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.model model-test - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT + test + + + com.evolveum.midpoint + midpoint-samples + 4.1-SNAPSHOT test @@ -127,7 +157,7 @@ com.evolveum.midpoint.tools test-ng - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test @@ -154,67 +184,67 @@ com.evolveum.midpoint.infra test-util - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.provisioning provisioning-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo task-quartz-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo audit-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo security-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo security-enforcer-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.model model-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo repo-test-util - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint midpoint-localization - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test com.evolveum.midpoint.repo repo-sql-impl-test - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test @@ -225,7 +255,7 @@ com.evolveum.midpoint.repo system-init - 4.0.1-SNAPSHOT + 4.1-SNAPSHOT test diff --git a/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/AbstractSampleTest.java b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/AbstractSampleTest.java new file mode 100644 index 00000000000..649b41cc086 --- /dev/null +++ b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/AbstractSampleTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2013 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.samples.test; + +import com.evolveum.midpoint.model.api.ModelService; +import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.task.api.Task; +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.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import javax.xml.bind.JAXBException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.List; + +import static org.testng.AssertJUnit.assertEquals; + +/** + * Try to import selected samples to a real repository in an initialized system. + * + * We cannot import all the samples as some of them are mutually exclusive. + * + * @author Radovan Semancik + * + */ +@ContextConfiguration(locations = {"classpath:ctx-samples-test-main.xml"}) +@DirtiesContext(classMode=ClassMode.AFTER_CLASS) +public abstract class AbstractSampleTest extends AbstractModelIntegrationTest { + + protected static final File SAMPLES_DIRECTORY = new File("target/samples"); + protected static final File SCHEMA_DIRECTORY = new File ("src/test/resources/schema"); + protected static final File USER_ADMINISTRATOR_FILE = new File("src/test/resources/user-administrator.xml"); + + private static final Trace LOGGER = TraceManager.getTrace(AbstractSampleTest.class); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + // This should discover the connectors + LOGGER.trace("initSystem: trying modelService.postInit()"); + modelService.postInit(initResult); + LOGGER.trace("initSystem: modelService.postInit() done"); + + PrismObject userAdministrator = repoAddObjectFromFile(USER_ADMINISTRATOR_FILE, initResult); + loginSuperUser(userAdministrator); + } + +} diff --git a/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSampleImport.java b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSampleImport.java index ffb32467354..b6262e49772 100644 --- a/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSampleImport.java +++ b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSampleImport.java @@ -6,8 +6,6 @@ */ package com.evolveum.midpoint.samples.test; -import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectQuery; @@ -17,20 +15,14 @@ import com.evolveum.midpoint.task.api.Task; 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.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; -import javax.xml.bind.JAXBException; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -48,45 +40,21 @@ */ @ContextConfiguration(locations = {"classpath:ctx-samples-test-main.xml"}) @DirtiesContext(classMode=ClassMode.AFTER_CLASS) -public class TestSampleImport extends AbstractModelIntegrationTest { - - private static final String SAMPLE_DIRECTORY_NAME = "../"; - private static final String SCHEMA_DIRECTORY_NAME = SAMPLE_DIRECTORY_NAME + "schema/"; - private static final String USER_ADMINISTRATOR_FILENAME = "src/test/resources/user-administrator.xml"; - - private static final Trace LOGGER = TraceManager.getTrace(TestSampleImport.class); - - @Autowired(required = true) - private ModelService modelService; - - @Autowired(required = true) - private PrismContext prismContext; - - public TestSampleImport() throws JAXBException { - super(); - } +public class TestSampleImport extends AbstractSampleTest { @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); - - // This should discover the connectors - LOGGER.trace("initSystem: trying modelService.postInit()"); - modelService.postInit(initResult); - LOGGER.trace("initSystem: modelService.postInit() done"); - - PrismObject userAdministrator = repoAddObjectFromFile(USER_ADMINISTRATOR_FILENAME, initResult); - loginSuperUser(userAdministrator); } @Test public void importOpenDJBasic() throws FileNotFoundException, SchemaException { - importSample(new File(SAMPLE_DIRECTORY_NAME + "resources/opendj/opendj-localhost-basic.xml"), ResourceType.class, "Basic Localhost OpenDJ"); + importSample(new File(SAMPLES_DIRECTORY, "resources/opendj/opendj-localhost-basic.xml"), ResourceType.class, "Basic Localhost OpenDJ"); } @Test public void importOpenDJAdvanced() throws FileNotFoundException, SchemaException { - importSample(new File(SAMPLE_DIRECTORY_NAME + "resources/opendj/opendj-localhost-resource-sync-advanced.xml"), ResourceType.class, "Localhost OpenDJ"); + importSample(new File(SAMPLES_DIRECTORY, "resources/opendj/opendj-localhost-resource-sync-advanced.xml"), ResourceType.class, "Localhost OpenDJ"); } // Connector not part of the build, therefore this fails @@ -98,22 +66,19 @@ public void importOpenDJAdvanced() throws FileNotFoundException, SchemaException public void importSample(File sampleFile, Class type, String objectName) throws FileNotFoundException, SchemaException { TestUtil.displayTestTitle(this, "Import sample "+sampleFile.getPath()); // GIVEN - Task task = taskManager.createTaskInstance(); - OperationResult result = new OperationResult(TestSampleImport.class.getName() + ".importSample"); + Task task = createTask(sampleFile.getName()); + OperationResult result = task.getResult(); result.addParam("file", sampleFile.getPath()); FileInputStream stream = new FileInputStream(sampleFile); // WHEN - modelService.importObjectsFromStream(stream, MiscSchemaUtil.getDefaultImportOptions(), task, result); + modelService.importObjectsFromStream(stream, PrismContext.LANG_XML, MiscSchemaUtil.getDefaultImportOptions(), task, result); // THEN result.computeStatus(); display("Result after good import", result); TestUtil.assertSuccessOrWarning("Import has failed (result)", result,1); -// ObjectQuery query = ObjectQuery.createObjectQuery(EqualsFilter.createEqual(type, prismContext, -// ObjectType.F_NAME, PrismTestUtil.createPolyString(objectName))); -// QueryType query = QueryUtil.createNameQuery(objectName); ObjectQuery query = ObjectQueryUtil.createNameQuery(objectName, prismContext); List> objects = repositoryService.searchObjects(type, query, null, result); diff --git a/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSamples.java b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSamples.java index 444190ff902..2dcac8320fc 100644 --- a/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSamples.java +++ b/testing/samples-test/src/test/java/com/evolveum/midpoint/samples/test/TestSamples.java @@ -39,12 +39,11 @@ * @author Radovan Semancik * */ -public class TestSamples { +public class TestSamples extends AbstractSampleTest { - public static final String SAMPLES_DIRECTORY_NAME = ".."; - public static final String[] IGNORE_PATTERNS = new String[]{ "\\.svn", "pom.xml", "old", - "experimental", "json", "misc", "rest", "samples-test", "model-.*", "bulk-actions", "bulk", - "testng.*\\.xml", "target"}; + public static final String[] IGNORE_PATTERNS = new String[] { + "experimental", "json", "misc", "rest", "samples-test", "model-.*", "bulk-actions", "bulk", "legacy", + }; public static final String[] CHECK_PATTERNS = new String[]{ ".*.xml" }; public static final String OBJECT_RESULT_OPERATION_NAME = TestSamples.class.getName()+".validateObject"; private static final String RESULT_OPERATION_NAME = TestSamples.class.getName()+".validateFile"; @@ -55,12 +54,11 @@ public void setup() throws SchemaException, SAXException, IOException { PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); } - @Test(enabled = false) + @Test(enabled=false) // MID-5475 public void testSamples() throws FileNotFoundException { - testSamplesDirectory(new File(SAMPLES_DIRECTORY_NAME)); + testSamplesDirectory(SAMPLES_DIRECTORY); } - @Test(enabled = false) private void testSamplesDirectory(File directory) throws FileNotFoundException { String[] fileNames = directory.list(); for (int i = 0; i < fileNames.length; i++) { diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/AbstractGrouperTest.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/AbstractGrouperTest.java new file mode 100644 index 00000000000..8e65e88d633 --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/AbstractGrouperTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.story.grouper; + +import com.evolveum.icf.dummy.resource.ConflictException; +import com.evolveum.icf.dummy.resource.DummyGroup; +import com.evolveum.icf.dummy.resource.DummyResource; +import com.evolveum.icf.dummy.resource.SchemaViolationException; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.DummyResourceContoller; +import com.evolveum.midpoint.test.TestResource; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.testing.story.AbstractStoryTest; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.AfterClass; + +import javax.xml.namespace.QName; +import java.io.File; +import java.io.FileNotFoundException; +import java.net.ConnectException; + +import static org.testng.AssertJUnit.assertNotNull; + +/** + * Superclass for all Grouper-like test scenarios. + */ +@ContextConfiguration(locations = {"classpath:ctx-story-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public abstract class AbstractGrouperTest extends AbstractStoryTest { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "grouper"); + + protected static final File LDIF_INITIAL_OBJECTS_FILE = new File(TEST_DIR, "ldif-initial-objects.ldif"); + + protected static final File SYSTEM_CONFIGURATION_FILE = new File(TEST_DIR, "system-configuration.xml"); + + protected static final TestResource LIB_GROUPER = new TestResource(TEST_DIR, "function-library-grouper.xml", "2eef4181-25fa-420f-909d-846a36ca90f3"); + + protected static final TestResource RESOURCE_LDAP = new TestResource(TEST_DIR, "resource-ldap.xml", "0a37121f-d515-4a23-9b6d-554c5ef61272"); + protected static final TestResource RESOURCE_GROUPER = new TestResource(TEST_DIR, "resource-grouper.xml", "1eff65de-5bb6-483d-9edf-8cc2c2ee0233"); + + protected static final TestResource METAROLE_GROUPER_PROVIDED_GROUP = new TestResource(TEST_DIR, "metarole-grouper-provided-group.xml", "bcaec940-50c8-44bb-aa37-b2b5bb2d5b90"); + protected static final TestResource METAROLE_LDAP_GROUP = new TestResource(TEST_DIR, "metarole-ldap-group.xml", "8da46694-bd71-4e1e-bfd7-73865ae2ea9a"); + + protected static final TestResource ARCHETYPE_AFFILIATION = new TestResource(TEST_DIR, "archetype-affiliation.xml", "56f53812-047d-4b69-83e8-519a73d161e1"); + protected static final TestResource ORG_AFFILIATIONS = new TestResource(TEST_DIR, "org-affiliations.xml", "1d7c0e3a-4456-409c-9f50-95407b2eb785"); + + protected static final TestResource ROLE_LDAP_BASIC = new TestResource(TEST_DIR, "role-ldap-basic.xml", "c89f31dd-8d4f-4e0a-82cb-58ff9d8c1b2f"); + + protected static final TestResource TEMPLATE_USER = new TestResource(TEST_DIR, "template-user.xml", "8098b124-c20c-4965-8adf-e528abedf7a4"); + + protected static final TestResource USER_BANDERSON = new TestResource(TEST_DIR, "user-banderson.xml", "4f439db5-181e-4297-9f7d-b3115524dbe8"); + protected static final TestResource USER_JLEWIS685 = new TestResource(TEST_DIR, "user-jlewis685.xml", "8b7bd936-b863-45d0-aabe-734fa3e22081"); + + protected static final TestResource TASK_GROUP_SCAVENGER = new TestResource(TEST_DIR, "task-group-scavenger.xml", "1d7bef40-953e-443e-8e9a-ec6e313668c4"); + + protected static final String NS_EXT = "http://grouper-demo.tier.internet2.edu"; + protected static final QName EXT_GROUPER_NAME = new QName(NS_EXT, "grouperName"); + protected static final QName EXT_LDAP_DN = new QName(NS_EXT, "ldapDn"); + + protected static final String BANDERSON_USERNAME = "banderson"; + protected static final String JLEWIS685_USERNAME = "jlewis685"; + protected static final String NOBODY_USERNAME = "nobody"; + + protected static final String ALUMNI_NAME = "ref:affiliation:alumni"; + protected static final String STAFF_NAME = "ref:affiliation:staff"; + protected static final String MEMBER_NAME = "ref:affiliation:member"; + + protected static final ItemName ATTR_MEMBER = new ItemName(MidPointConstants.NS_RI, "members"); + + protected static final String DN_BANDERSON = "uid=banderson,ou=people,dc=example,dc=com"; + protected static final String DN_JLEWIS685 = "uid=jlewis685,ou=people,dc=example,dc=com"; + protected static final String DN_ALUMNI = "cn=alumni,ou=Affiliations,ou=Groups,dc=example,dc=com"; + protected static final String DN_STAFF = "cn=staff,ou=Affiliations,ou=Groups,dc=example,dc=com"; + + protected static final QName GROUPER_GROUP_OBJECT_CLASS_NAME = new QName(MidPointConstants.NS_RI, "GroupObjectClass"); + + protected static final String GROUPER_DUMMY_RESOURCE_ID = "grouper"; + public static final String USERNAME_FORMAT = "user-%08d"; + protected PrismObject resourceGrouper; + protected DummyResourceContoller grouperResourceCtl; + protected DummyResource grouperDummyResource; + + protected PrismObject resourceLdap; + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + //TracerImpl.checkHashCodeEqualsRelation = true; + + // These are experimental features, so they need to be explicitly enabled. This will be eliminated later, + // when we make them enabled by default. + sqlRepositoryService.getConfiguration().setEnableIndexOnlyItems(true); + sqlRepositoryService.getConfiguration().setEnableNoFetchExtensionValuesInsertion(true); + sqlRepositoryService.getConfiguration().setEnableNoFetchExtensionValuesDeletion(true); + + openDJController.addEntriesFromLdifFile(LDIF_INITIAL_OBJECTS_FILE); + + repoAddObject(LIB_GROUPER, initResult); + + grouperResourceCtl = DummyResourceContoller.create(GROUPER_DUMMY_RESOURCE_ID); + grouperResourceCtl.populateWithDefaultSchema(); + grouperDummyResource = grouperResourceCtl.getDummyResource(); + resourceGrouper = importAndGetObjectFromFile(ResourceType.class, RESOURCE_GROUPER.file, RESOURCE_GROUPER.oid, initTask, initResult); + grouperResourceCtl.setResource(resourceGrouper); + + resourceLdap = importAndGetObjectFromFile(ResourceType.class, RESOURCE_LDAP.file, RESOURCE_LDAP.oid, initTask, initResult); + openDJController.setResource(resourceLdap); + + addObject(METAROLE_GROUPER_PROVIDED_GROUP, initTask, initResult); + addObject(METAROLE_LDAP_GROUP, initTask, initResult); + + addObject(ARCHETYPE_AFFILIATION, initTask, initResult); + addObject(ORG_AFFILIATIONS, initTask, initResult); + + addObject(ROLE_LDAP_BASIC, initTask, initResult); + addObject(TEMPLATE_USER, initTask, initResult); + + addObject(TASK_GROUP_SCAVENGER, initTask, initResult); + } + + @Override + protected boolean isAutoTaskManagementEnabled() { + return true; + } + + @Override + protected File getSystemConfigurationFile() { + return SYSTEM_CONFIGURATION_FILE; + } + + @Override + protected boolean isAvoidLoggingChange() { + return false; + } + + @Override + protected void startResources() throws Exception { + openDJController.startCleanServerRI(); + } + + @AfterClass + public static void stopResources() throws Exception { + openDJController.stop(); + } + + void createGroup(String groupName, int users) throws Exception { + long start = System.currentTimeMillis(); + System.out.println("Creating the group"); + DummyGroup group = new DummyGroup(groupName); + for (int i = 0; i < users; i++) { + group.addMember(String.format(USERNAME_FORMAT, i)); + } + grouperDummyResource.addGroup(group); + System.out.println("Group created in " + (System.currentTimeMillis() - start) + " ms"); + } + + void addGroupMember(String groupName, int number) + throws InterruptedException, FileNotFoundException, ConnectException, SchemaViolationException, ConflictException { + DummyGroup group = grouperDummyResource.getGroupByName(groupName); + assertNotNull("No group " + groupName, group); + group.addMember(String.format(USERNAME_FORMAT, number)); + } + + void deleteGroupMember(String groupName, int number) + throws InterruptedException, FileNotFoundException, ConnectException, SchemaViolationException, ConflictException { + DummyGroup group = grouperDummyResource.getGroupByName(groupName); + assertNotNull("No group " + groupName, group); + group.removeMember(String.format(USERNAME_FORMAT, number)); + } +} diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperAsyncUpdate.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperAsyncUpdate.java index cafd660eeae..601cadc0740 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperAsyncUpdate.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperAsyncUpdate.java @@ -47,44 +47,7 @@ */ @ContextConfiguration(locations = {"classpath:ctx-story-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestGrouperAsyncUpdate extends AbstractStoryTest { - - private static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "grouper"); - - private static final File LDIF_INITIAL_OBJECTS_FILE = new File(TEST_DIR, "ldif-initial-objects.ldif"); - - private static final File SYSTEM_CONFIGURATION_FILE = new File(TEST_DIR, "system-configuration.xml"); - - private static final TestResource LIB_GROUPER = new TestResource(TEST_DIR, "function-library-grouper.xml", "2eef4181-25fa-420f-909d-846a36ca90f3"); - - private static final TestResource RESOURCE_LDAP = new TestResource(TEST_DIR, "resource-ldap.xml", "0a37121f-d515-4a23-9b6d-554c5ef61272"); - private static final TestResource RESOURCE_GROUPER = new TestResource(TEST_DIR, "resource-grouper.xml", "1eff65de-5bb6-483d-9edf-8cc2c2ee0233"); - - private static final TestResource METAROLE_GROUPER_PROVIDED_GROUP = new TestResource(TEST_DIR, "metarole-grouper-provided-group.xml", "bcaec940-50c8-44bb-aa37-b2b5bb2d5b90"); - private static final TestResource METAROLE_LDAP_GROUP = new TestResource(TEST_DIR, "metarole-ldap-group.xml", "8da46694-bd71-4e1e-bfd7-73865ae2ea9a"); - - private static final TestResource ARCHETYPE_AFFILIATION = new TestResource(TEST_DIR, "archetype-affiliation.xml", "56f53812-047d-4b69-83e8-519a73d161e1"); - private static final TestResource ORG_AFFILIATIONS = new TestResource(TEST_DIR, "org-affiliations.xml", "1d7c0e3a-4456-409c-9f50-95407b2eb785"); - - private static final TestResource ROLE_LDAP_BASIC = new TestResource(TEST_DIR, "role-ldap-basic.xml", "c89f31dd-8d4f-4e0a-82cb-58ff9d8c1b2f"); - - private static final TestResource TEMPLATE_USER = new TestResource(TEST_DIR, "template-user.xml", "8098b124-c20c-4965-8adf-e528abedf7a4"); - - private static final TestResource USER_BANDERSON = new TestResource(TEST_DIR, "user-banderson.xml", "4f439db5-181e-4297-9f7d-b3115524dbe8"); - private static final TestResource USER_JLEWIS685 = new TestResource(TEST_DIR, "user-jlewis685.xml", "8b7bd936-b863-45d0-aabe-734fa3e22081"); - - private static final TestResource TASK_GROUP_SCAVENGER = new TestResource(TEST_DIR, "task-group-scavenger.xml", "1d7bef40-953e-443e-8e9a-ec6e313668c4"); - - private static final String NS_EXT = "http://grouper-demo.tier.internet2.edu"; - public static final QName EXT_GROUPER_NAME = new QName(NS_EXT, "grouperName"); - public static final QName EXT_LDAP_DN = new QName(NS_EXT, "ldapDn"); - - private static final String BANDERSON_USERNAME = "banderson"; - private static final String JLEWIS685_USERNAME = "jlewis685"; - private static final String NOBODY_USERNAME = "nobody"; - - private static final String ALUMNI_NAME = "ref:affiliation:alumni"; - private static final String STAFF_NAME = "ref:affiliation:staff"; +public class TestGrouperAsyncUpdate extends AbstractGrouperTest { private static final File CHANGE_110 = new File(TEST_DIR, "change-110-alumni-add.json"); private static final File CHANGE_115 = new File(TEST_DIR, "change-115-staff-add.json"); @@ -96,20 +59,6 @@ public class TestGrouperAsyncUpdate extends AbstractStoryTest { private static final File CHANGE_250 = new File(TEST_DIR, "change-250-banderson-delete-alumni.json"); private static final File CHANGE_310 = new File(TEST_DIR, "change-310-staff-delete.json"); - private static final ItemName ATTR_MEMBER = new ItemName(MidPointConstants.NS_RI, "members"); - - private static final String DN_BANDERSON = "uid=banderson,ou=people,dc=example,dc=com"; - private static final String DN_JLEWIS685 = "uid=jlewis685,ou=people,dc=example,dc=com"; - private static final String DN_ALUMNI = "cn=alumni,ou=Affiliations,ou=Groups,dc=example,dc=com"; - private static final String DN_STAFF = "cn=staff,ou=Affiliations,ou=Groups,dc=example,dc=com"; - - private static final String GROUPER_DUMMY_RESOURCE_ID = "grouper"; - private PrismObject resourceGrouper; - private DummyResourceContoller grouperResourceCtl; - private DummyResource grouperDummyResource; - - private PrismObject resourceLdap; - private String orgAlumniOid; private String orgStaffOid; @@ -117,67 +66,15 @@ public class TestGrouperAsyncUpdate extends AbstractStoryTest { public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); - TracerImpl.checkHashCodeEqualsRelation = true; // temporary - - // These are experimental features, so they need to be explicitly enabled. This will be eliminated later, - // when we make them enabled by default. - sqlRepositoryService.getConfiguration().setEnableIndexOnlyItems(true); - sqlRepositoryService.getConfiguration().setEnableNoFetchExtensionValuesInsertion(true); - sqlRepositoryService.getConfiguration().setEnableNoFetchExtensionValuesDeletion(true); - - openDJController.addEntriesFromLdifFile(LDIF_INITIAL_OBJECTS_FILE); - - repoAddObject(LIB_GROUPER, initResult); - - grouperResourceCtl = DummyResourceContoller.create(GROUPER_DUMMY_RESOURCE_ID); - grouperResourceCtl.populateWithDefaultSchema(); - grouperDummyResource = grouperResourceCtl.getDummyResource(); - resourceGrouper = importAndGetObjectFromFile(ResourceType.class, RESOURCE_GROUPER.file, RESOURCE_GROUPER.oid, initTask, initResult); - grouperResourceCtl.setResource(resourceGrouper); - - resourceLdap = importAndGetObjectFromFile(ResourceType.class, RESOURCE_LDAP.file, RESOURCE_LDAP.oid, initTask, initResult); - openDJController.setResource(resourceLdap); - - addObject(METAROLE_GROUPER_PROVIDED_GROUP, initTask, initResult); - addObject(METAROLE_LDAP_GROUP, initTask, initResult); - - addObject(ARCHETYPE_AFFILIATION, initTask, initResult); - addObject(ORG_AFFILIATIONS, initTask, initResult); - - addObject(ROLE_LDAP_BASIC, initTask, initResult); - addObject(TEMPLATE_USER, initTask, initResult); - - addObject(TASK_GROUP_SCAVENGER, initTask, initResult); - setGlobalTracingOverride(createModelAndProvisioningLoggingTracingProfile()); } - @Override - protected boolean isAutoTaskManagementEnabled() { - return true; - } - @Override protected TracingProfileType getTestMethodTracingProfile() { return createModelAndProvisioningLoggingTracingProfile() .fileNamePattern(TEST_METHOD_TRACING_FILENAME_PATTERN); } - @Override - protected File getSystemConfigurationFile() { - return SYSTEM_CONFIGURATION_FILE; - } - - @Override - protected void startResources() throws Exception { - openDJController.startCleanServerRI(); - } - - @AfterClass - public static void stopResources() throws Exception { - openDJController.stop(); - } - @Test public void test000Sanity() throws Exception { Task task = getTask(); diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupImport.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupImport.java new file mode 100644 index 00000000000..3fe47623e48 --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupImport.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.story.grouper; + +import com.evolveum.icf.dummy.resource.DummyGroup; +import com.evolveum.midpoint.schema.internals.InternalsConfig; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.TestResource; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +/** + * Test import of large groups. + */ +@ContextConfiguration(locations = {"classpath:ctx-story-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestGrouperLargeGroupImport extends AbstractGrouperTest { + + private static final int ALUMNI_USERS = 10; + private static final int STAFF_USERS = 100000; + + private static final TestResource TASK_IMPORT_GROUPS = new TestResource(TEST_DIR, "task-import-groups.xml", "e2edaa90-7624-4a82-8a7c-92e00c78d8d3"); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + InternalsConfig.setConsistencyChecks(false); + createGroup(ALUMNI_NAME, ALUMNI_USERS); + createGroup(STAFF_NAME, STAFF_USERS); + //setGlobalTracingOverride(createPerformanceTracingProfile()); + //setGlobalTracingOverride(createDefaultTracingProfile()); + } + + @Override + protected void importSystemTasks(OperationResult initResult) { + // we don't need these here + } + + @Test + public void test000Sanity() throws Exception { + Task task = getTask(); + + assertSuccess(modelService.testResource(RESOURCE_LDAP.oid, task)); + assertSuccess(modelService.testResource(RESOURCE_GROUPER.oid, task)); + } + + @Test + public void test100ImportGroups() throws Exception { + Task task = getTask(); + OperationResult result = getResult(); + task.setOwner(userAdministrator); + + addObject(TASK_IMPORT_GROUPS, task, result); + + Thread.sleep(60000L); // leave the import task alone ... at least for a minute + + Task importTaskAfter = waitForTaskFinish(TASK_IMPORT_GROUPS.oid, false, 120000); + assertSuccess(importTaskAfter.getResult()); + } +} diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupReconciliation.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupReconciliation.java new file mode 100644 index 00000000000..6c75ffdced2 --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/grouper/TestGrouperLargeGroupReconciliation.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.story.grouper; + +import com.evolveum.icf.dummy.resource.DummyGroup; +import com.evolveum.midpoint.schema.internals.InternalsConfig; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.TestResource; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +/** + * Test reconciliation of large groups. + */ +@ContextConfiguration(locations = {"classpath:ctx-story-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestGrouperLargeGroupReconciliation extends AbstractGrouperTest { + + private static final int ALUMNI_USERS = 10; + private static final int STAFF_USERS = 100000; + + private static final TestResource TASK_RECONCILE_GROUPS = new TestResource(TEST_DIR, "task-reconcile-groups.xml", "1fde833d-7105-40fb-b59a-c863a1f53609"); + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + InternalsConfig.setConsistencyChecks(false); + createGroup(ALUMNI_NAME, ALUMNI_USERS); + createGroup(STAFF_NAME, STAFF_USERS); + //setGlobalTracingOverride(createPerformanceTracingProfile()); + //setGlobalTracingOverride(createDefaultTracingProfile()); + } + + @Override + protected void importSystemTasks(OperationResult initResult) { + // we don't need these here + } + + @Test + public void test000Sanity() throws Exception { + Task task = getTask(); + + assertSuccess(modelService.testResource(RESOURCE_LDAP.oid, task)); + assertSuccess(modelService.testResource(RESOURCE_GROUPER.oid, task)); + } + + @Test + public void test100ReconcileGroups() throws Exception { + Task task = getTask(); + OperationResult result = getResult(); + task.setOwner(userAdministrator); + + addObject(TASK_RECONCILE_GROUPS, task, result); + + Thread.sleep(60000L); // leave the reconciliation task alone ... at least for a minute + + Task taskAfter = waitForTaskFinish(TASK_RECONCILE_GROUPS.oid, false, 120000); + assertSuccess(taskAfter.getResult()); + } + + @Test + public void test110ReconcileGroupsAgain() throws Exception { + Task task = getTask(); + OperationResult result = getResult(); + task.setOwner(userAdministrator); + + deleteGroupMember(ALUMNI_NAME, 3); + addGroupMember(ALUMNI_NAME, 13); + deleteGroupMember(STAFF_NAME, 4); + addGroupMember(STAFF_NAME, STAFF_USERS + 4); + + restartTask(TASK_RECONCILE_GROUPS.oid); + + Thread.sleep(60000L); // leave the reconciliation task alone ... at least for a minute + + Task taskAfter = waitForTaskFinish(TASK_RECONCILE_GROUPS.oid, false, 120000); + assertSuccess(taskAfter.getResult()); + } +} diff --git a/testing/story/src/test/resources/grouper/system-configuration.xml b/testing/story/src/test/resources/grouper/system-configuration.xml index d251136d579..e19c35a8f26 100644 --- a/testing/story/src/test/resources/grouper/system-configuration.xml +++ b/testing/story/src/test/resources/grouper/system-configuration.xml @@ -13,20 +13,36 @@ File Appender INFO - - TRACE - com.evolveum.midpoint.common.LoggingConfigurationManager - - - TRACE - com.evolveum.midpoint.notifications - + + + + + + + + %date [%thread] %-5level \(%logger{46}\): %message%n target/test.log true + + + + functional + Functional tracing + true + functional-trace %{timestamp} %{focusName} + true + true + true + + normal + + + + UserType @@ -40,29 +56,6 @@ - - - - workItemLifecycleEvent - dummy:workItemLifecycle - - - workItemAllocationEvent - dummy:workItemAllocation - - - workItemCustomEvent - dummy:workItemCustom - - - workflowProcessEvent - dummy:process - - - - target/mail-notifications.log - - never never diff --git a/testing/story/src/test/resources/grouper/task-import-groups.xml b/testing/story/src/test/resources/grouper/task-import-groups.xml new file mode 100644 index 00000000000..cb2547afc99 --- /dev/null +++ b/testing/story/src/test/resources/grouper/task-import-groups.xml @@ -0,0 +1,37 @@ + + + + + + Import groups + + + ri:GroupObjectClass + + + + + + + + + e2edaa90-7624-4a82-8a7c-92e00c78d8d3 + + runnable + + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/import/handler-3 + + + single + diff --git a/testing/story/src/test/resources/grouper/task-reconcile-groups.xml b/testing/story/src/test/resources/grouper/task-reconcile-groups.xml new file mode 100644 index 00000000000..ed138723b91 --- /dev/null +++ b/testing/story/src/test/resources/grouper/task-reconcile-groups.xml @@ -0,0 +1,37 @@ + + + + + + Reconcile groups + + + ri:GroupObjectClass + + + + + + + + + 1fde833d-7105-40fb-b59a-c863a1f53609 + + runnable + + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 + + + single +