/*
* Copyright (c) 2013-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.model.intest.sync;
import static org.testng.AssertJUnit.assertTrue;
import static com.evolveum.midpoint.test.IntegrationTestTools.display;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import java.io.File;
import java.util.List;
import javax.xml.bind.JAXBElement;
import com.evolveum.midpoint.prism.util.ItemPathUtil;
import com.evolveum.midpoint.prism.xnode.PrimitiveXNode;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
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 com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.audit.api.AuditEventStage;
import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.IdItemPathSegment;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.DummyResourceContoller;
import com.evolveum.midpoint.test.IntegrationTestTools;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingStrengthType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceAttributeDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
/**
* @author semancik
*
*/
@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class TestRecomputeTask extends AbstractInitializedModelIntegrationTest {
private static final File TEST_DIR = new File("src/test/resources/sync");
private static final File TASK_USER_RECOMPUTE_FILE = new File(TEST_DIR, "task-user-recompute.xml");
private static final String TASK_USER_RECOMPUTE_OID = "91919191-76e0-59e2-86d6-3d4f02d3aaaa";
private static final File TASK_USER_RECOMPUTE_LIGHT_FILE = new File(TEST_DIR, "task-user-recompute-light.xml");
private static final String TASK_USER_RECOMPUTE_LIGHT_OID = "b7b6af78-fffe-11e6-ac04-2fdd62641ce2";
private static final File TASK_USER_RECOMPUTE_CAPTAIN_FILE = new File(TEST_DIR, "task-user-recompute-captain.xml");
private static final String TASK_USER_RECOMPUTE_CAPTAIN_OID = "91919191-76e0-59e2-86d6-3d4f02d3aaac";
private static final File TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_FILE = new File(TEST_DIR, "task-user-recompute-herman-by-expression.xml");
private static final String TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID = "91919191-76e0-59e2-86d6-3d4f02d3aadd";
@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
super.initSystem(initTask, initResult);
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL);
// DebugUtil.setDetailedDebugDump(true);
}
@Test
public void test100RecomputeAll() throws Exception {
final String TEST_NAME = "test100RecomputeAll";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();
// Preconditions
assertUsers(5);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME);
// Do some ordinary operations
assignRole(USER_GUYBRUSH_OID, ROLE_PIRATE_OID, task, result);
assignRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result);
addObject(USER_HERMAN_FILE);
assignRole(USER_HERMAN_OID, ROLE_JUDGE_OID, task, result);
result.computeStatus();
TestUtil.assertSuccess(result);
// Now do something evil
// change definition of role "pirate". midPoint will not recompute automatically
// the recompute task should do it
// One simple change
modifyRoleAddConstruction(ROLE_JUDGE_OID, 1111L, RESOURCE_DUMMY_RED_OID);
// More complicated change
PrismObject<RoleType> rolePirate = modelService.getObject(RoleType.class, ROLE_PIRATE_OID, null, task, result);
ItemPath attrItemPath = new ItemPath(
new NameItemPathSegment(RoleType.F_INDUCEMENT),
new IdItemPathSegment(1111L),
new NameItemPathSegment(AssignmentType.F_CONSTRUCTION),
new IdItemPathSegment(60004L),
new NameItemPathSegment(ConstructionType.F_ATTRIBUTE));
PrismProperty<ResourceAttributeDefinitionType> attributeProperty = rolePirate.findProperty(attrItemPath);
assertNotNull("No attribute property in "+rolePirate);
PrismPropertyValue<ResourceAttributeDefinitionType> oldAttrPVal = null;
for (PrismPropertyValue<ResourceAttributeDefinitionType> pval: attributeProperty.getValues()) {
ResourceAttributeDefinitionType attrType = pval.getValue();
if (ItemPathUtil.getOnlySegmentQName(attrType.getRef()).getLocalPart().equals(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME)) {
oldAttrPVal = pval;
}
}
assertNotNull("Definition for weapon attribute not found in "+rolePirate);
PrismPropertyValue<ResourceAttributeDefinitionType> newAttrPVal = oldAttrPVal.clone();
JAXBElement<?> cutlassExpressionEvalJaxbElement = newAttrPVal.getValue().getOutbound().getExpression().getExpressionEvaluator().get(0);
RawType cutlassValueEvaluator = (RawType) cutlassExpressionEvalJaxbElement.getValue();
RawType daggerValueEvaluator = new RawType(new PrimitiveXNode<String>("dagger"), prismContext);
JAXBElement<?> daggerExpressionEvalJaxbElement = new JAXBElement<Object>(SchemaConstants.C_VALUE, Object.class, daggerValueEvaluator);
newAttrPVal.getValue().getOutbound().getExpression().getExpressionEvaluator().add(daggerExpressionEvalJaxbElement);
newAttrPVal.getValue().getOutbound().setStrength(MappingStrengthType.STRONG);
ObjectDelta<RoleType> rolePirateDelta = ObjectDelta.createModificationDeleteProperty(RoleType.class, ROLE_PIRATE_OID,
attrItemPath, prismContext, oldAttrPVal.getValue());
IntegrationTestTools.displayJaxb("AAAAAAAAAAA", newAttrPVal.getValue(), ConstructionType.F_ATTRIBUTE);
display("BBBBBB", newAttrPVal.getValue().toString());
rolePirateDelta.addModificationAddProperty(attrItemPath, newAttrPVal.getValue());
display("Role pirate delta", rolePirateDelta);
modelService.executeChanges(MiscSchemaUtil.createCollection(rolePirateDelta), null, task, result);
displayRoles(task, result);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
PrismObject<UserType> userJack = getUser(USER_JACK_OID);
display("User jack (before)", userJack);
assertDummyAccount(null, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME);
result.computeStatus();
TestUtil.assertSuccess(result);
// WHEN
TestUtil.displayWhen(TEST_NAME);
addObject(TASK_USER_RECOMPUTE_FILE);
dummyAuditService.clear();
waitForTaskStart(TASK_USER_RECOMPUTE_OID, false);
// WHEN
TestUtil.displayWhen(TEST_NAME);
waitForTaskFinish(TASK_USER_RECOMPUTE_OID, true, 40000);
// THEN
TestUtil.displayThen(TEST_NAME);
List<PrismObject<UserType>> users = modelService.searchObjects(UserType.class, null, null, task, result);
display("Users after recompute", users);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger");
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
userJack = getUser(USER_JACK_OID);
display("User jack (after)", userJack);
assertNoDummyAccount(null, ACCOUNT_JACK_DUMMY_USERNAME);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true);
assertUsers(6);
// Check audit
display("Audit", dummyAuditService);
List<AuditEventRecord> auditRecords = dummyAuditService.getRecords();
int i=0;
int modifications = 0;
for (; i < (auditRecords.size() - 1); i+=2) {
AuditEventRecord requestRecord = auditRecords.get(i);
assertNotNull("No request audit record ("+i+")", requestRecord);
assertEquals("Got this instead of request audit record ("+i+"): "+requestRecord, AuditEventStage.REQUEST, requestRecord.getEventStage());
assertTrue("Unexpected delta in request audit record "+requestRecord, requestRecord.getDeltas() == null || requestRecord.getDeltas().isEmpty());
AuditEventRecord executionRecord = auditRecords.get(i+1);
assertNotNull("No execution audit record ("+i+")", executionRecord);
assertEquals("Got this instead of execution audit record ("+i+"): "+executionRecord, AuditEventStage.EXECUTION, executionRecord.getEventStage());
assertTrue("Empty deltas in execution audit record "+executionRecord, executionRecord.getDeltas() != null && ! executionRecord.getDeltas().isEmpty());
modifications++;
// check next records
while (i < (auditRecords.size() - 2)) {
AuditEventRecord nextRecord = auditRecords.get(i+2);
if (nextRecord.getEventStage() == AuditEventStage.EXECUTION) {
// more than one execution record is OK
i++;
} else {
break;
}
}
}
assertEquals("Unexpected number of audit modifications", 6, modifications);
deleteObject(TaskType.class, TASK_USER_RECOMPUTE_OID, task, result);
}
private void displayRoles(Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException {
PrismObject<RoleType> rolePirate = modelService.getObject(RoleType.class, ROLE_PIRATE_OID, null, task, result);
display("Role pirate after modify", rolePirate);
IntegrationTestTools.displayXml("Role pirate after modify", rolePirate);
PrismObject<RoleType> roleJudge = modelService.getObject(RoleType.class, ROLE_JUDGE_OID, null, task, result);
display("Role judge after modify", roleJudge);
IntegrationTestTools.displayXml("Role judge after modify", roleJudge);
}
@Test
public void test110RecomputeSome() throws Exception {
final String TEST_NAME = "test110RecomputeSome";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();
// Preconditions
assertUsers(6);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", true);
result.computeStatus();
TestUtil.assertSuccess(result);
// Now do something evil, remove "red" construction from judge role
modifyRoleDeleteInducement(ROLE_JUDGE_OID, 1111L, false, null);
displayRoles(task, result);
// WHEN
TestUtil.displayWhen(TEST_NAME);
addObject(TASK_USER_RECOMPUTE_CAPTAIN_FILE);
dummyAuditService.clear();
waitForTaskStart(TASK_USER_RECOMPUTE_CAPTAIN_OID, false);
// WHEN
TestUtil.displayWhen(TEST_NAME);
waitForTaskFinish(TASK_USER_RECOMPUTE_CAPTAIN_OID, true, 40000);
// THEN
TestUtil.displayThen(TEST_NAME);
List<PrismObject<UserType>> users = modelService.searchObjects(UserType.class, null, null, task, result);
display("Users after recompute", users);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger");
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
// Red resource does not delete accounts on deprovision, it disables them
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false);
// Only captains are recomputed. Therefore herman stays unrecomputed
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", true);
assertUsers(6);
}
/**
* Here we recompute herman as well.
*/
@Test
public void test120RecomputeByExpression() throws Exception {
final String TEST_NAME = "test120RecomputeByExpression";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();
// Preconditions
assertUsers(6);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", true);
result.computeStatus();
TestUtil.assertSuccess(result);
// WHEN
TestUtil.displayWhen(TEST_NAME);
addObject(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_FILE);
dummyAuditService.clear();
waitForTaskStart(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID, false);
// WHEN
TestUtil.displayWhen(TEST_NAME);
waitForTaskFinish(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID, true, 40000);
// THEN
TestUtil.displayThen(TEST_NAME);
List<PrismObject<UserType>> users = modelService.searchObjects(UserType.class, null, null, task, result);
display("Users after recompute", users);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger");
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
// Red resource does not delete accounts on deprovision, it disables them
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false);
// Herman should be recomputed now
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", false);
TaskType recomputeTask = getTask(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID).asObjectable();
assertEquals("Wrong success count", 1, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalSuccessCount());
assertEquals("Wrong failure count", 0, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalFailureCount());
assertUsers(6);
}
/**
* Light recompute. Very efficient, no resource operations, just fix the focus.
* MID-3384
*/
@Test
public void test130RecomputeLight() throws Exception {
final String TEST_NAME = "test130RecomputeLight";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();
// Preconditions
assertUsers(6);
PrismObject<UserType> usetJackBefore = getUser(USER_JACK_OID);
display("User jack before", usetJackBefore);
assertAssignedRole(usetJackBefore, ROLE_JUDGE_OID);
assertRoleMembershipRef(usetJackBefore, ROLE_JUDGE_OID);
assignOrg(USER_GUYBRUSH_OID, ORG_MINISTRY_OF_OFFENSE_OID, null);
PrismObject<UserType> usetGuybrushBefore = getUser(USER_GUYBRUSH_OID);
display("User guybrush before", usetGuybrushBefore);
assertAssignedRole(usetGuybrushBefore, ROLE_PIRATE_OID);
assertRoleMembershipRef(usetGuybrushBefore, ROLE_PIRATE_OID, ORG_MINISTRY_OF_OFFENSE_OID);
assertAssignedOrgs(usetGuybrushBefore, ORG_MINISTRY_OF_OFFENSE_OID);
assertHasOrgs(usetGuybrushBefore, ORG_MINISTRY_OF_OFFENSE_OID);
clearUserOrgAndRoleRefs(USER_JACK_OID);
clearUserOrgAndRoleRefs(USER_GUYBRUSH_OID);
rememberShadowFetchOperationCount();
rememberConnectorOperationCount();
// WHEN
TestUtil.displayWhen(TEST_NAME);
addObject(TASK_USER_RECOMPUTE_LIGHT_FILE);
dummyAuditService.clear();
waitForTaskStart(TASK_USER_RECOMPUTE_LIGHT_OID, false);
// WHEN
TestUtil.displayWhen(TEST_NAME);
waitForTaskFinish(TASK_USER_RECOMPUTE_LIGHT_OID, true, 40000);
// THEN
TestUtil.displayThen(TEST_NAME);
List<PrismObject<UserType>> users = modelService.searchObjects(UserType.class, null, null, task, result);
display("Users after recompute", users);
assertShadowFetchOperationCountIncrement(0);
assertConnectorOperationIncrement(0);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger");
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
// Red resource does not delete accounts on deprovision, it disables them
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false);
// Herman should be recomputed now
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", false);
TaskType recomputeTask = getTask(TASK_USER_RECOMPUTE_LIGHT_OID).asObjectable();
assertEquals("Wrong success count", 6, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalSuccessCount());
assertEquals("Wrong failure count", 0, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalFailureCount());
PrismObject<UserType> usetJackAfter = getUser(USER_JACK_OID);
display("User jack after", usetJackAfter);
assertAssignedRole(usetJackAfter, ROLE_JUDGE_OID);
assertRoleMembershipRef(usetJackAfter, ROLE_JUDGE_OID);
PrismObject<UserType> usetGuybrushAfter = getUser(USER_GUYBRUSH_OID);
display("User guybrush after", usetGuybrushAfter);
assertAssignedRole(usetGuybrushAfter, ROLE_PIRATE_OID);
assertRoleMembershipRef(usetGuybrushAfter, ROLE_PIRATE_OID, ORG_MINISTRY_OF_OFFENSE_OID);
assertAssignedOrgs(usetGuybrushAfter, ORG_MINISTRY_OF_OFFENSE_OID);
assertHasOrgs(usetGuybrushAfter, ORG_MINISTRY_OF_OFFENSE_OID);
assertUsers(6);
}
}