/*
* Copyright (c) 2010-2016 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.impl.lens;
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.io.FileNotFoundException;
import java.io.IOException;
import java.net.ConnectException;
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.AssertJUnit;
import org.testng.annotations.Test;
import com.evolveum.icf.dummy.resource.ConflictException;
import com.evolveum.icf.dummy.resource.SchemaViolationException;
import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.model.impl.lens.projector.DependencyProcessor;
import com.evolveum.midpoint.model.impl.lens.projector.Projector;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.ResourceShadowDiscriminator;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.test.DummyResourceContoller;
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.PolicyViolationException;
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.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
/**
* @author semancik
*
*/
@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class TestDependencies extends AbstractInternalModelIntegrationTest {
public static final File TEST_DIR = new File("src/test/resources/lens/dependencies");
private static final File ACCOUNT_ELAINE_TEMPLATE_FILE = new File(TEST_DIR, "account-elaine-template.xml");
@Autowired(required = true)
private Projector projector;
@Autowired(required = true)
private DependencyProcessor dependencyProcessor;
@Autowired(required = true)
private TaskManager taskManager;
@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
super.initSystem(initTask, initResult);
initDummy("a", initTask, initResult);
initDummy("b", initTask, initResult); // depends on A
initDummy("c", initTask, initResult); // depends on B
initDummy("d", initTask, initResult); // depends on B
initDummy("p", initTask, initResult); // depends on R (order 5)
initDummy("r", initTask, initResult); // depends on P (order 0)
initDummy("x", initTask, initResult); // depends on Y (circular)
initDummy("y", initTask, initResult); // depends on Z (circular)
initDummy("z", initTask, initResult); // depends on X (circular)
}
private void initDummy(String name, Task initTask, OperationResult initResult) throws FileNotFoundException, ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ConnectException, SchemaViolationException, ConflictException {
String resourceOid = getDummyOid(name);
DummyResourceContoller resourceCtl = DummyResourceContoller.create(name.toUpperCase());
resourceCtl.extendSchemaPirate();
PrismObject<ResourceType> resource = importAndGetObjectFromFile(ResourceType.class,
getDummFile(name), resourceOid, initTask, initResult);
resourceCtl.setResource(resource);
}
private File getDummFile(String name) {
return new File(TEST_DIR, "resource-dummy-"+name+".xml");
}
private String getDummyOid(String name) {
return "14440000-0000-0000-000"+name+"-000000000000";
}
private String getDummuAccountOid(String dummyName, String accountName) {
return "14440000-0000-0000-000"+dummyName+"-10000000000"+accountName;
}
@Test
public void test100SortToWavesIdependent() throws Exception {
final String TEST_NAME = "test100SortToWavesIdependent";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
fillContextWithDummyElaineAccount(context, "a", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 0);
}
@Test
public void test101SortToWavesAB() throws Exception {
final String TEST_NAME = "test101SortToWavesAB";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
fillContextWithDummyElaineAccount(context, "a", result);
fillContextWithDummyElaineAccount(context, "b", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 0);
assertWave(context, getDummyOid("b"), 0, 1);
}
@Test
public void test102SortToWavesABCD() throws Exception {
final String TEST_NAME = "test102SortToWavesABCD";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
fillContextWithDummyElaineAccount(context, "a", result);
fillContextWithDummyElaineAccount(context, "b", result);
fillContextWithDummyElaineAccount(context, "c", result);
fillContextWithDummyElaineAccount(context, "d", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 0);
assertWave(context, getDummyOid("b"), 0, 1);
assertWave(context, getDummyOid("c"), 0, 2);
assertWave(context, getDummyOid("d"), 0, 2);
}
@Test
public void test120SortToWavesBCUnsatisfied() throws Exception {
final String TEST_NAME = "test120SortToWavesBCUnsatisfied";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
fillContextWithDummyElaineAccount(context, "b", result);
fillContextWithDummyElaineAccount(context, "c", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
try {
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
display("Context after", context);
AssertJUnit.fail("Unexpected success");
} catch (PolicyViolationException e) {
// this is expected
}
}
@Test
public void test151SortToWavesPR() throws Exception {
final String TEST_NAME = "test151SortToWavesPR";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
fillContextWithUser(context, USER_ELAINE_OID, result);
fillContextWithDummyElaineAccount(context, "p", result);
fillContextWithDummyElaineAccount(context, "r", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, getDummyOid("p"), 0, 0);
assertWave(context, getDummyOid("r"), 0, 1);
assertWave(context, getDummyOid("p"), 5, 2);
}
/**
* Different ordering of contexts as compared to previous tests. This results
* in different order of computation.
*/
@Test
public void test152SortToWavesRP() throws Exception {
final String TEST_NAME = "test152SortToWavesRP";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
fillContextWithUser(context, USER_ELAINE_OID, result);
fillContextWithDummyElaineAccount(context, "r", result);
fillContextWithDummyElaineAccount(context, "p", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, getDummyOid("p"), 0, 0);
assertWave(context, getDummyOid("r"), 0, 1);
assertWave(context, getDummyOid("p"), 5, 2);
}
@Test
public void test200SortToWavesIdependentDeprovision() throws Exception {
final String TEST_NAME = "test200SortToWavesIdependentDeprovision";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
setDelete(accountContext);
setDelete(fillContextWithDummyElaineAccount(context, "a", result));
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 0);
}
@Test
public void test201SortToWavesABDeprovision() throws Exception {
final String TEST_NAME = "test201SortToWavesABDeprovision";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
setDelete(accountContext);
setDelete(fillContextWithDummyElaineAccount(context, "a", result));
setDelete(fillContextWithDummyElaineAccount(context, "b", result));
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 1);
assertWave(context, getDummyOid("b"), 0, 0);
}
@Test
public void test202SortToWavesABCDDeprovision() throws Exception {
final String TEST_NAME = "test202SortToWavesABCDDeprovision";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
LensFocusContext<UserType> focusContext = fillContextWithUser(context, USER_ELAINE_OID, result);
LensProjectionContext accountContext = fillContextWithAccount(context, ACCOUNT_SHADOW_ELAINE_DUMMY_OID, result);
setDelete(accountContext);
setDelete(fillContextWithDummyElaineAccount(context, "a", result));
setDelete(fillContextWithDummyElaineAccount(context, "b", result));
setDelete(fillContextWithDummyElaineAccount(context, "c", result));
setDelete(fillContextWithDummyElaineAccount(context, "d", result));
context.recompute();
display("Context before", context);
context.checkConsistence();
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
// THEN
display("Context after", context);
assertWave(context, RESOURCE_DUMMY_OID, 0, 0);
assertWave(context, getDummyOid("a"), 0, 2);
assertWave(context, getDummyOid("b"), 0, 1);
assertWave(context, getDummyOid("c"), 0, 0);
assertWave(context, getDummyOid("d"), 0, 0);
}
private void setDelete(LensProjectionContext accountContext) {
accountContext.setPrimaryDelta(ObjectDelta.createDeleteDelta(ShadowType.class, accountContext.getOid(), prismContext));
}
@Test
public void test300SortToWavesXYZCircular() throws Exception {
final String TEST_NAME = "test300SortToWavesXYZCircular";
TestUtil.displayTestTile(this, TEST_NAME);
// GIVEN
Task task = taskManager.createTaskInstance(TestDependencies.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();
assumeAssignmentPolicy(AssignmentPolicyEnforcementType.RELATIVE);
LensContext<UserType> context = createUserLensContext();
fillContextWithUser(context, USER_ELAINE_OID, result);
fillContextWithDummyElaineAccount(context, "x", result);
fillContextWithDummyElaineAccount(context, "y", result);
fillContextWithDummyElaineAccount(context, "z", result);
context.recompute();
display("Context before", context);
context.checkConsistence();
try {
// WHEN
dependencyProcessor.sortProjectionsToWaves(context);
AssertJUnit.fail("Unexpected success");
} catch (PolicyViolationException e) {
// This is expected
display("Expected exception", e);
}
}
private LensProjectionContext fillContextWithDummyElaineAccount(
LensContext<UserType> context, String dummyName, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, IOException {
String resourceOid = getDummyOid(dummyName);
String accountOid = getDummuAccountOid(dummyName,"e");
PrismObject<ShadowType> account = PrismTestUtil.parseObject(ACCOUNT_ELAINE_TEMPLATE_FILE);
ShadowType accountType = account.asObjectable();
accountType.setOid(accountOid);
accountType.getResourceRef().setOid(resourceOid);
provisioningService.applyDefinition(account, result);
return fillContextWithAccount(context, account, result);
}
private void assertWave(LensContext<UserType> context,
String resourceOid, int order, int expectedWave) {
LensProjectionContext ctxAccDummy = findAccountContext(context, resourceOid, order);
assertNotNull("No context for "+resourceOid+", order="+order, ctxAccDummy);
assertWave(ctxAccDummy, expectedWave);
}
private void assertWave(LensProjectionContext projCtx, int expectedWave) {
assertEquals("Wrong wave in "+projCtx, expectedWave, projCtx.getWave());
}
private LensProjectionContext findAccountContext(LensContext<UserType> context,
String resourceOid, int order) {
ResourceShadowDiscriminator discr = new ResourceShadowDiscriminator(resourceOid, ShadowKindType.ACCOUNT, null);
discr.setOrder(order);
return context.findProjectionContext(discr);
}
}