Skip to content

Commit

Permalink
Fixing delta with empty containers
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Nov 28, 2016
1 parent 5b9a623 commit 63314d4
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 21 deletions.
Expand Up @@ -1068,6 +1068,10 @@ void diffItems(PrismContainerValue<C> thisValue, PrismContainerValue<C> other,
if (other.getItems() != null) {
for (Item otherItem: other.getItems()) {
Item thisItem = thisValue.findItem(otherItem.getElementName());
if (thisItem != null) {
// Already processed in previous loop
continue;
}
if (!isLiteral) {
ItemDefinition itemDef = otherItem.getDefinition();
if (itemDef == null && thisValue.getDefinition() != null) {
Expand All @@ -1077,13 +1081,12 @@ void diffItems(PrismContainerValue<C> thisValue, PrismContainerValue<C> other,
continue;
}
}
if (thisItem == null) {
// Other has an item that we don't have, this must be an add
ItemDelta itemDelta = otherItem.createDelta();
itemDelta.addValuesToAdd(otherItem.getClonedValues());
if (!itemDelta.isEmpty()) {
((Collection)deltas).add(itemDelta);
}

// Other has an item that we don't have, this must be an add
ItemDelta itemDelta = otherItem.createDelta();
itemDelta.addValuesToAdd(otherItem.getClonedValues());
if (!itemDelta.isEmpty()) {
((Collection)deltas).add(itemDelta);
}
}
}
Expand All @@ -1093,6 +1096,9 @@ private boolean isOperationalOnly(Item item, ItemDefinition itemDef) {
if (itemDef != null && itemDef.isOperational()) {
return true;
}
if (item.isEmpty()) {
return false;
}
if (!(item instanceof PrismContainer)) {
return false;
}
Expand Down
Expand Up @@ -16,26 +16,40 @@

package com.evolveum.midpoint.schema;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyDefinitionImpl;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FailedOperationTypeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;

import java.io.IOException;

import javax.xml.namespace.QName;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
Expand All @@ -47,14 +61,17 @@
*/
public class TestDiffEquals {

@BeforeSuite
private static final String NS_TEST_RI = "http://midpoint.evolveum.com/xml/ns/test/ri-1";

@BeforeSuite
public void setup() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX);
PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY);
}

@Test
public void testUserSimplePropertyDiff() throws SchemaException {
System.out.println("\n\n===[ testUserSimplePropertyDiff ]===\n");
UserType userType1 = new UserType();
userType1.setName(PrismTestUtil.createPolyStringType("test name"));
UserType userType2 = new UserType();
Expand All @@ -75,6 +92,7 @@ public void testUserSimplePropertyDiff() throws SchemaException {

@Test
public void testUserListSimpleDiff() throws SchemaException {
System.out.println("\n\n===[ testUserListSimpleDiff ]===\n");
UserType u1 = new UserType();
u1.setName(PrismTestUtil.createPolyStringType("test name"));
UserType u2 = new UserType();
Expand All @@ -95,6 +113,7 @@ public void testUserListSimpleDiff() throws SchemaException {

@Test
public void testAssignmentEquals() throws Exception {
System.out.println("\n\n===[ testAssignmentEquals ]===\n");
PrismContext prismContext = PrismTestUtil.getPrismContext();

AssignmentType a1a = new AssignmentType();
Expand Down Expand Up @@ -155,6 +174,7 @@ public void testAssignmentEquals() throws Exception {

@Test
public void testContextlessAssignmentEquals() throws Exception {
System.out.println("\n\n===[ testContextlessAssignmentEquals ]===\n");
AssignmentType a1 = new AssignmentType(); // no prismContext here
a1.setDescription("descr1");

Expand All @@ -177,6 +197,7 @@ public void testContextlessAssignmentEquals() throws Exception {

@Test
public void testContextlessAssignmentEquals2() throws Exception {
System.out.println("\n\n===[ testContextlessAssignmentEquals2 ]===\n");

// (1) user without prismContext - the functionality is reduced

Expand Down Expand Up @@ -220,4 +241,60 @@ public void testContextlessAssignmentEquals2() throws Exception {
assertNotNull(delta2.getPrismContext());
}

@Test
public void testDiffShadow() throws Exception {
System.out.println("\n\n===[ testDiffShadow ]===\n");
PrismContext prismContext = PrismTestUtil.getPrismContext();

PrismObject<ShadowType> shadow1 = prismContext.getSchemaRegistry()
.findObjectDefinitionByCompileTimeClass(ShadowType.class).instantiate();
ShadowType shadow1Type = shadow1.asObjectable();
shadow1Type.setName(new PolyStringType("Whatever"));
shadow1Type.setFailedOperationType(FailedOperationTypeType.ADD);
shadow1Type.getAuxiliaryObjectClass().add(new QName(NS_TEST_RI, "foo"));
PrismContainer<Containerable> shadow1Attrs = shadow1.findOrCreateContainer(ShadowType.F_ATTRIBUTES);

ShadowType shadow2Type = new ShadowType();
PrismObject<ShadowType> shadow2 = shadow2Type.asPrismObject();
prismContext.adopt(shadow2Type);
shadow2Type.setName(new PolyStringType("Whatever"));
shadow2Type.getAuxiliaryObjectClass().add(new QName(NS_TEST_RI, "foo"));
shadow2Type.getAuxiliaryObjectClass().add(new QName(NS_TEST_RI, "bar"));
PrismContainer<Containerable> shadow2Attrs = shadow2.findOrCreateContainer(ShadowType.F_ATTRIBUTES);

PrismProperty<String> attrEntryUuid = new PrismProperty<>(new QName(NS_TEST_RI, "entryUuid"), prismContext);
PrismPropertyDefinition<String> attrEntryUuidDef = new PrismPropertyDefinitionImpl<>(new QName(NS_TEST_RI, "entryUuid"),
DOMUtil.XSD_STRING, prismContext);
attrEntryUuid.setDefinition(attrEntryUuidDef);
shadow2Attrs.add(attrEntryUuid);
attrEntryUuid.addRealValue("1234-5678-8765-4321");

PrismProperty<String> attrDn = new PrismProperty<>(new QName(NS_TEST_RI, "dn"), prismContext);
PrismPropertyDefinition<String> attrDnDef = new PrismPropertyDefinitionImpl<>(new QName(NS_TEST_RI, "dn"),
DOMUtil.XSD_STRING, prismContext);
attrDn.setDefinition(attrDnDef);
shadow2Attrs.add(attrDn);
attrDn.addRealValue("uid=foo,o=bar");

System.out.println("Shadow 1");
System.out.println(shadow1.debugDump(1));
System.out.println("Shadow 2");
System.out.println(shadow2.debugDump(1));

// WHEN
ObjectDelta<ShadowType> delta = shadow1.diff(shadow2);

// THEN
assertNotNull("No delta", delta);
System.out.println("Delta");
System.out.println(delta.debugDump(1));

PrismAsserts.assertIsModify(delta);
PrismAsserts.assertPropertyDelete(delta, ShadowType.F_FAILED_OPERATION_TYPE, FailedOperationTypeType.ADD);
PrismAsserts.assertPropertyAdd(delta, ShadowType.F_AUXILIARY_OBJECT_CLASS, new QName(NS_TEST_RI, "bar"));
PrismAsserts.assertContainerAdd(delta, ShadowType.F_ATTRIBUTES, shadow2Attrs.getValue().clone());
PrismAsserts.assertModifications(delta, 3);
}


}
Expand Up @@ -193,6 +193,11 @@ public static void displayThen(String testName) {
System.out.println(TEST_OUT_SECTION_PREFIX + " THEN " + testName + TEST_OUT_SECTION_SUFFIX);
LOGGER.info(TEST_LOG_SECTION_PREFIX + " THEN " + testName + TEST_LOG_SECTION_SUFFIX);
}

public static void info(String message) {
System.out.println(TEST_OUT_SECTION_PREFIX + message + TEST_OUT_SECTION_SUFFIX);
LOGGER.info(TEST_LOG_SECTION_PREFIX + message + TEST_LOG_SECTION_SUFFIX);
}

public static void assertSuccess(String message, OperationResult result, OperationResult originalResult, int stopLevel, int currentLevel, boolean warningOk) {
if (!checkResults) {
Expand Down
Expand Up @@ -1003,12 +1003,14 @@ public <T extends ShadowType> void finishOperation(PrismObject<T> object, Provis
PrismObject<ShadowType> shadow = (PrismObject<ShadowType>)object;
ShadowType shadowType = shadow.asObjectable();

try{
if (FailedOperationTypeType.ADD == shadowType.getFailedOperationType()){
LOGGER.debug("Finishing operation {} on {}", shadowType.getFailedOperationType(), object);

try {
if (FailedOperationTypeType.ADD == shadowType.getFailedOperationType()) {
getShadowCache(Mode.RECON).addShadow(shadow, null, null, options, task, result);
} else if (FailedOperationTypeType.MODIFY == shadowType.getFailedOperationType()){
} else if (FailedOperationTypeType.MODIFY == shadowType.getFailedOperationType()) {
getShadowCache(Mode.RECON).modifyShadow(shadow, shadow.getOid(), new ArrayList<ItemDelta>(), null, options, task, result);
} else if (FailedOperationTypeType.DELETE == shadowType.getFailedOperationType()){
} else if (FailedOperationTypeType.DELETE == shadowType.getFailedOperationType()) {
getShadowCache(Mode.RECON).deleteShadow(shadow, options, null, task, result);
} else {
result.recordWarning("Missing or unknown type of operation to finish: " + shadowType.getFailedOperationType());
Expand Down Expand Up @@ -1040,6 +1042,7 @@ public <T extends ShadowType> void finishOperation(PrismObject<T> object, Provis
throw e;
}
result.cleanupResult();
LOGGER.debug("Finished operation {} on {}: ", shadowType.getFailedOperationType(), object, result);
}

private <T extends ObjectType> boolean handleRepoObject(final Class<T> type, PrismObject<T> object,
Expand Down
Expand Up @@ -377,9 +377,9 @@ public String addShadow(PrismObject<ShadowType> shadow, OperationProvisioningScr
return null;
}

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Definition:\n{}", ctx.getObjectClassDefinition().debugDump());
}
// if (LOGGER.isTraceEnabled()) {
// LOGGER.trace("Definition:\n{}", ctx.getObjectClassDefinition().debugDump());
// }

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
if (attributesContainer == null || attributesContainer.isEmpty()) {
Expand Down
Expand Up @@ -75,7 +75,9 @@ private void cleanShadowInRepository(PrismObject<ShadowType> shadow, OperationRe

ProvisioningUtil.normalizeShadow(normalizedShadow.asObjectable(), parentResult);

LOGGER.trace("normalized shadow {}", normalizedShadow.debugDump());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("normalized shadow {}", normalizedShadow.debugDump(1));
}
// FIXME: ugly hack, need to be fixed (problem with comparing operation
// result, because it was changed and in this call it is different as
// one in repo, therefore the following if)
Expand All @@ -91,7 +93,9 @@ private void cleanShadowInRepository(PrismObject<ShadowType> shadow, OperationRe
}
// ShadowUtil.getAttributesContainer(repoShadow).clear();

LOGGER.trace("origin shadow with failure description {}", oldShadow.debugDump());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("origin shadow with failure description {}", oldShadow.debugDump(1));
}

ObjectDelta delta = oldShadow.diff(normalizedShadow);

Expand All @@ -101,8 +105,10 @@ private void cleanShadowInRepository(PrismObject<ShadowType> shadow, OperationRe
delta.removePropertyModification(ShadowType.F_OBJECT_CHANGE);
delta.addModification(clearObjectChange);

LOGGER.trace("Normalizing shadow: change description: {}", delta.debugDump());
// prismContext.adopt(shadow);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Normalizing shadow: change description: {}", delta.debugDump());
}

try {
ConstraintsChecker.onShadowModifyOperation(delta.getModifications());
getRepositoryService().modifyObject(ShadowType.class, oldShadow.getOid(), delta.getModifications(),
Expand Down
Expand Up @@ -1308,6 +1308,7 @@ public void test260GetDiscoveryAddCommunicationProblem() throws Exception {

// GIVEN
openDJController.assumeStopped();
display("OpenDJ stopped");
OperationResult parentResult = new OperationResult(TEST_NAME);

repoAddObjectFromFile(USER_ANGELIKA_FILENAME, parentResult);
Expand All @@ -1316,9 +1317,13 @@ public void test260GetDiscoveryAddCommunicationProblem() throws Exception {

Task task = taskManager.createTaskInstance();

// WHEN
TestUtil.displayWhen(TEST_NAME);
//REQUEST_USER_MODIFY_ADD_ACCOUNT_COMMUNICATION_PROBLEM
requestToExecuteChanges(REQUEST_USER_MODIFY_ASSIGN_ACCOUNT, USER_ANGELIKA_OID, UserType.class, task, null, parentResult);

// THEN
TestUtil.displayThen(TEST_NAME);
parentResult.computeStatus();
display("add object communication problem result: ", parentResult);
assertEquals("Expected handled error but got: " + parentResult.getStatus(), OperationResultStatus.HANDLED_ERROR, parentResult.getStatus());
Expand All @@ -1332,6 +1337,7 @@ public void test260GetDiscoveryAddCommunicationProblem() throws Exception {
openDJController.start();
//and set the resource availability status to UP
modifyResourceAvailabilityStatus(AvailabilityStatusType.UP, parentResult);
TestUtil.info("OpenDJ started, resource UP");

checkNormalizedShadowWithAttributes(accountOid, "angelika", "angelika", "angelika", "angelika", false, task, parentResult);
}
Expand Down Expand Up @@ -2532,10 +2538,12 @@ private ShadowType checkPostponedAccountWithAttributes(String accountOid, String
}

private ShadowType checkPostponedAccountBasic(PrismObject<ShadowType> failedAccount, FailedOperationTypeType failedOperation, boolean modify, OperationResult parentResult) throws Exception{
display("Repository shadow (postponed operation expected)", failedAccount);
assertNotNull("Shadow must not be null", failedAccount);
ShadowType failedAccountType = failedAccount.asObjectable();
assertNotNull(failedAccountType);
displayJaxb("shadow from the repository: ", failedAccountType, ShadowType.COMPLEX_TYPE);
// Too much noise
// displayJaxb("shadow from the repository: ", failedAccountType, ShadowType.COMPLEX_TYPE);
assertEquals("Failed operation saved with account differt from the expected value.",
failedOperation, failedAccountType.getFailedOperationType());
assertNotNull("Result of failed shadow must not be null.", failedAccountType.getResult());
Expand All @@ -2544,7 +2552,6 @@ private ShadowType checkPostponedAccountBasic(PrismObject<ShadowType> failedAcco
if (modify){
assertNotNull("Null object change in shadow", failedAccountType.getObjectChange());
}
display("Shadow with postponed operation", failedAccount);
return failedAccountType;
}

Expand Down

0 comments on commit 63314d4

Please sign in to comment.