/*
* 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.prism;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.assertEquals;
import static com.evolveum.midpoint.prism.PrismInternalTestUtil.*;
import java.io.File;
import java.io.IOException;
import javax.xml.namespace.QName;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.foo.AssignmentType;
import com.evolveum.midpoint.prism.foo.UserType;
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.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.SchemaException;
/**
* @author semancik
*
*/
public abstract class TestCompare {
private static final QName REF_QNAME = new QName(NS_FOO, "ref");
private static final QName REF_TYPE_QNAME = new QName(NS_FOO, "RefType");;
protected abstract String getSubdirName();
protected abstract String getFilenameSuffix();
protected File getCommonSubdir() {
return new File(COMMON_DIR_PATH, getSubdirName());
}
protected File getFile(String baseName) {
return new File(getCommonSubdir(), baseName+"."+getFilenameSuffix());
}
@BeforeSuite
public void setupDebug() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(DEFAULT_NAMESPACE_PREFIX);
PrismTestUtil.resetPrismContext(new PrismInternalTestUtil());
}
/**
* Parse the same files twice, compare the results.
*/
@Test
public void testCompareJack() throws SchemaException, SAXException, IOException {
System.out.println("===[ testCompareJack ]===");
// GIVEN
PrismContext prismContext = constructInitializedPrismContext();
// Document document = DOMUtil.parseFile(USER_JACK_FILE_XML);
// Element userElement = DOMUtil.getFirstChildElement(document);
PrismObject<UserType> user1 = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
PrismObject<UserType> user2 = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
// WHEN, THEN
assertTrue("Users not the same (PrismObject)(1)", user1.equals(user2));
assertTrue("Users not the same (PrismObject)(2)", user2.equals(user1));
// Following line won't work here. We don't have proper generated classes here.
// It is tested in the "schema" project that has a proper code generation
// assertTrue("Users not the same (Objectable)", user1.asObjectable().equals(user2.asObjectable()));
assertTrue("Users not equivalent (1)", user1.equivalent(user2));
assertTrue("Users not equivalent (2)", user2.equivalent(user1));
}
/**
* Parse original jack and modified Jack. Diff and assert if the resulting
* delta is OK.
*/
@Test
public void testDiffJack() throws Exception {
System.out.println("===[ testDiffJack ]===");
// GIVEN
PrismContext prismContext = constructInitializedPrismContext();
PrismObject<UserType> jackOriginal = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
PrismObject<UserType> jackModified = prismContext.parseObject(getFile(USER_JACK_MODIFIED_FILE_BASENAME));
// WHEN
ObjectDelta<UserType> jackDelta = jackOriginal.diff (jackModified);
// THEN
System.out.println("Jack delta:");
System.out.println(jackDelta.debugDump());
jackDelta.assertDefinitions();
jackDelta.checkConsistence(true, true, true);
assertEquals("Wrong delta type", ChangeType.MODIFY, jackDelta.getChangeType());
assertEquals("Wrong delta OID", USER_JACK_OID, jackDelta.getOid());
assertEquals("Wrong number of modificaitions", 8, jackDelta.getModifications().size());
PrismAsserts.assertPropertyReplace(jackDelta, USER_FULLNAME_QNAME, "Jack Sparrow");
PrismAsserts.assertPropertyDelete(jackDelta, new ItemPath(USER_EXTENSION_QNAME, EXTENSION_MULTI_ELEMENT), "dva");
PrismAsserts.assertPropertyAdd(jackDelta, new ItemPath(USER_EXTENSION_QNAME, EXTENSION_MULTI_ELEMENT), "osem");
// TODO: assert BAR
PrismAsserts.assertPropertyDelete(jackDelta, USER_ADDITIONALNAMES_QNAME, "Captain");
PrismAsserts.assertPropertyAdd(jackDelta, USER_LOCALITY_QNAME, "World's End");
// There won't be any activation deltas. Activation is operational.
PrismAsserts.assertNoItemDelta(jackDelta, USER_ENABLED_PATH);
PrismAsserts.assertNoItemDelta(jackDelta, USER_VALID_FROM_PATH);
PrismAsserts.assertPropertyReplace(jackDelta,
new ItemPath(
new NameItemPathSegment(USER_ASSIGNMENT_QNAME),
new IdItemPathSegment(USER_ASSIGNMENT_2_ID),
new NameItemPathSegment(USER_DESCRIPTION_QNAME)),
"Assignment II");
ContainerDelta<?> assignment3Delta = PrismAsserts.assertContainerAddGetContainerDelta(jackDelta, new ItemPath(USER_ASSIGNMENT_QNAME));
PrismContainerValue<?> assignment3DeltaAddValue = assignment3Delta.getValuesToAdd().iterator().next();
assertEquals("Assignment 3 wrong ID", USER_ASSIGNMENT_3_ID, assignment3DeltaAddValue.getId());
// TODO assert assignment[i1112]/accountConstruction
}
/**
* Parse original jack and modified Jack. Diff and assert if the resulting
* delta is OK.
* This is literal diff. All the changes should be part of the resulting delta.
*/
@Test
public void testDiffJackLiteral() throws Exception {
System.out.println("===[ testDiffJackLiteral ]===");
// GIVEN
PrismContext prismContext = constructInitializedPrismContext();
PrismObject<UserType> jackOriginal = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
PrismObject<UserType> jackModified = prismContext.parseObject(getFile(USER_JACK_MODIFIED_FILE_BASENAME));
// WHEN
ObjectDelta<UserType> jackDelta = jackOriginal.diff(jackModified, true, true);
// THEN
System.out.println("Jack delta:");
System.out.println(jackDelta.debugDump());
jackDelta.assertDefinitions();
jackDelta.checkConsistence(true, true, true);
assertEquals("Wrong delta type", ChangeType.MODIFY, jackDelta.getChangeType());
assertEquals("Wrong delta OID", USER_JACK_OID, jackDelta.getOid());
assertEquals("Wrong number of modificaitions", 10, jackDelta.getModifications().size());
PrismAsserts.assertPropertyReplace(jackDelta, USER_FULLNAME_QNAME, "Jack Sparrow");
PrismAsserts.assertPropertyDelete(jackDelta, new ItemPath(USER_EXTENSION_QNAME, EXTENSION_MULTI_ELEMENT), "dva");
PrismAsserts.assertPropertyAdd(jackDelta, new ItemPath(USER_EXTENSION_QNAME, EXTENSION_MULTI_ELEMENT), "osem");
// TODO: assert BAR
PrismAsserts.assertPropertyDelete(jackDelta, USER_ADDITIONALNAMES_QNAME, "Captain");
PrismAsserts.assertPropertyAdd(jackDelta, USER_LOCALITY_QNAME, "World's End");
PrismAsserts.assertPropertyReplace(jackDelta, USER_ENABLED_PATH, false);
PrismAsserts.assertPropertyDelete(jackDelta, USER_VALID_FROM_PATH, USER_JACK_VALID_FROM);
PrismAsserts.assertPropertyReplace(jackDelta,
new ItemPath(
new NameItemPathSegment(USER_ASSIGNMENT_QNAME),
new IdItemPathSegment(USER_ASSIGNMENT_2_ID),
new NameItemPathSegment(USER_DESCRIPTION_QNAME)),
"Assignment II");
ContainerDelta<?> assignment3Delta = PrismAsserts.assertContainerAddGetContainerDelta(jackDelta, new ItemPath(USER_ASSIGNMENT_QNAME));
PrismContainerValue<?> assignment3DeltaAddValue = assignment3Delta.getValuesToAdd().iterator().next();
assertEquals("Assignment 3 wrong ID", USER_ASSIGNMENT_3_ID, assignment3DeltaAddValue.getId());
// TODO assert assignment[i1112]/accountConstruction
}
@Test
public void testDiffPatchRoundTrip() throws SchemaException, SAXException, IOException {
System.out.println("===[ testDiffPatchRoundTrip ]===");
// GIVEN
PrismContext prismContext = constructInitializedPrismContext();
PrismObject<UserType> jackOriginal = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
PrismObject<UserType> jackModified = prismContext.parseObject(getFile(USER_JACK_MODIFIED_FILE_BASENAME));
ObjectDelta<UserType> jackDelta = jackOriginal.diff(jackModified);
// System.out.println("jackOriginal:\n" + prismContext.getXnodeProcessor().serializeObject(jackOriginal).debugDump(1));
// System.out.println("jackModified:\n" + prismContext.getXnodeProcessor().serializeObject(jackModified).debugDump(1));
// System.out.println("jackDelta:\n" + jackDelta.debugDump());
jackDelta.assertDefinitions();
jackDelta.checkConsistence(true, true, true);
// WHEN
jackDelta.applyTo(jackOriginal);
// System.out.println("jackOriginal after applying delta:\n" + prismContext.getXnodeProcessor().serializeObject(jackOriginal).debugDump(1));
// THEN
assertTrue("Roundtrip failed", jackOriginal.equivalent(jackModified));
}
@Test
public void testEqualsReferenceValues() throws Exception {
System.out.println("===[ testEqualsReferenceValues ]===");
PrismContext prismContext = constructInitializedPrismContext();
PrismReferenceValue val11 = new PrismReferenceValue("oid1");
val11.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val12 = new PrismReferenceValue("oid1");
val12.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val13 = new PrismReferenceValue("oid1");
// No type
PrismReferenceValue val21 = new PrismReferenceValue();
val21.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val22 = new PrismReferenceValue();
val22.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val23 = new PrismReferenceValue();
// No type
PrismObject<UserType> user = prismContext.parseObject(getFile(USER_JACK_FILE_BASENAME));
PrismReferenceValue val31 = new PrismReferenceValue();
val31.setObject(user);
PrismReferenceValue val32 = new PrismReferenceValue();
val32.setObject(user.clone());
PrismReferenceValue val33 = new PrismReferenceValue();
// No type, no object
PrismReferenceValue val34 = new PrismReferenceValue();
PrismObject<UserType> differentUser = user.clone();
differentUser.setOid(null);
differentUser.setPropertyRealValue(UserType.F_FULL_NAME, "Jack Different");
val34.setObject(differentUser);
PrismReferenceValue val35 = new PrismReferenceValue();
PrismObject<UserType> yetAnotherDifferentUser = user.clone();
yetAnotherDifferentUser.setOid(null);
yetAnotherDifferentUser.setPropertyRealValue(UserType.F_FULL_NAME, "John J Random");
val35.setObject(yetAnotherDifferentUser);
assertTrue("val11 - val11", val11.equals(val11));
assertTrue("val11 - val12", val11.equals(val12));
assertTrue("val12 - val11", val12.equals(val11));
assertFalse("val11 - val13", val11.equals(val13));
assertFalse("val13 - val11", val13.equals(val11));
assertTrue("val21 - val21", val21.equals(val21));
assertTrue("val21 - val22", val21.equals(val22));
assertTrue("val22 - val21", val22.equals(val21));
assertFalse("val21 - val23", val21.equals(val23));
assertFalse("val23 - val21", val23.equals(val21));
assertTrue("val31 - val31", val31.equals(val31));
assertTrue("val31 - val32", val31.equals(val32));
assertTrue("val32 - val31", val32.equals(val31));
assertFalse("val31 - val33", val31.equals(val33));
assertFalse("val33 - val31", val33.equals(val31));
assertFalse("val31 - val34", val31.equals(val34));
assertFalse("val34 - val31", val34.equals(val31));
assertFalse("val31 - val35", val31.equals(val35));
assertFalse("val35 - val31", val35.equals(val31));
assertFalse("val34 - val35", val34.equals(val35));
assertFalse("val35 - val34", val35.equals(val34));
}
@Test
public void testEqualsReferenceValuesSchema() throws Exception {
System.out.println("===[ testEqualsReferenceValuesSchema ]===");
PrismContext prismContext = constructInitializedPrismContext();
PrismReferenceDefinitionImpl ref1Def = new PrismReferenceDefinitionImpl(REF_QNAME, REF_TYPE_QNAME, prismContext);
ref1Def.setTargetTypeName(ACCOUNT_TYPE_QNAME);
PrismReference ref1 = new PrismReference(REF_QNAME, ref1Def, prismContext);
PrismReferenceValue val11 = new PrismReferenceValue("oid1");
val11.setTargetType(ACCOUNT_TYPE_QNAME);
ref1.add(val11);
PrismReferenceValue val12 = new PrismReferenceValue("oid1");
val12.setTargetType(ACCOUNT_TYPE_QNAME);
ref1.add(val12);
PrismReferenceValue val13 = new PrismReferenceValue("oid1");
// No type
ref1.add(val13);
PrismReferenceValue val14 = new PrismReferenceValue("oid1");
// No type
ref1.add(val14);
PrismReferenceDefinition ref2Def = new PrismReferenceDefinitionImpl(REF_QNAME, REF_TYPE_QNAME, prismContext);
// no target type def
PrismReference ref2 = new PrismReference(REF_QNAME, ref2Def, prismContext);
PrismReferenceValue val21 = new PrismReferenceValue("oid1");
val21.setTargetType(ACCOUNT_TYPE_QNAME);
ref2.add(val21);
PrismReferenceValue val22 = new PrismReferenceValue("oid1");
val22.setTargetType(ACCOUNT_TYPE_QNAME);
ref2.add(val22);
PrismReferenceValue val23 = new PrismReferenceValue("oid1");
// No type
ref2.add(val23);
// No def in val4x
PrismReferenceValue val41 = new PrismReferenceValue("oid1");
val41.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val42 = new PrismReferenceValue("oid1");
val42.setTargetType(ACCOUNT_TYPE_QNAME);
PrismReferenceValue val43 = new PrismReferenceValue("oid1");
// No type
assertTrue("val11 - val11", val11.equals(val11));
assertTrue("val11 - val12", val11.equals(val12));
assertTrue("val12 - val11", val12.equals(val11));
assertTrue("val11 - val13", val11.equals(val13));
assertTrue("val13 - val11", val13.equals(val11));
assertTrue("val13 - val14", val13.equals(val14));
assertTrue("val21 - val21", val21.equals(val21));
assertTrue("val21 - val22", val21.equals(val22));
assertTrue("val22 - val21", val22.equals(val21));
assertFalse("val21 - val23", val21.equals(val23));
assertFalse("val23 - val21", val23.equals(val21));
assertTrue("val41 - val41", val41.equals(val41));
assertTrue("val41 - val42", val41.equals(val42));
assertTrue("val42 - val41", val42.equals(val41));
assertFalse("val41 - val43", val41.equals(val43));
assertFalse("val43 - val41", val43.equals(val41));
assertTrue("val11 - val21", val11.equals(val21));
assertTrue("val11 - val41", val11.equals(val41));
assertTrue("val41 - val11", val41.equals(val11));
assertTrue("val41 - val21", val41.equals(val12));
assertTrue("val13 - val21", val13.equals(val21));
assertTrue("val13 - val41", val13.equals(val41));
assertFalse("val43 - val11", val43.equals(val11));
assertFalse("val43 - val12", val43.equals(val12));
assertFalse("val43 - val13", val43.equals(val13));
assertFalse("val43 - val21", val43.equals(val21));
assertFalse("val43 - val22", val43.equals(val22));
assertTrue("val43 - val23", val43.equals(val23));
// assertTrue("val11 - val11", val11.equals(val11));
// assertTrue("val11 - val11", val11.equals(val11));
// assertTrue("val11 - val11", val11.equals(val11));
// assertTrue("val11 - val11", val11.equals(val11));
}
@Test(enabled = false) // normalization no longer removes empty values
public void testEqualsBrokenAssignmentActivation() throws Exception {
System.out.println("===[ testEqualsReferenceValues ]===");
// GIVEN
PrismObjectDefinition<UserType> userDef = PrismInternalTestUtil.getUserTypeDefinition();
PrismContainerDefinition<AssignmentType> assignmentDef = userDef.findContainerDefinition(UserType.F_ASSIGNMENT);
PrismContainer<AssignmentType> goodAssignment = assignmentDef.instantiate(UserType.F_ASSIGNMENT);
PrismContainer<AssignmentType> brokenAssignment = goodAssignment.clone();
assertEquals("Not equals after clone", goodAssignment, brokenAssignment);
// lets break one of these ...
PrismContainerValue<AssignmentType> emptyValue = new PrismContainerValue<AssignmentType>(PrismTestUtil.getPrismContext());
brokenAssignment.add(emptyValue);
// WHEN
assertFalse("Unexpected equals", goodAssignment.equals(brokenAssignment));
brokenAssignment.normalize();
assertEquals("Not equals after normalize(bad)", goodAssignment, brokenAssignment);
goodAssignment.normalize();
assertEquals("Not equals after normalize(good)", goodAssignment, brokenAssignment);
}
}