/* * Copyright (c) 2010-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.impl.sync; import static org.testng.AssertJUnit.assertEquals; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertFalse; import java.io.File; 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 com.evolveum.icf.dummy.resource.DummyAccount; import com.evolveum.icf.dummy.resource.DummyGroup; import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest; import com.evolveum.midpoint.model.impl.lens.Clockwork; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.model.impl.lens.LensProjectionContext; import com.evolveum.midpoint.model.impl.util.mock.MockLensDebugListener; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; import com.evolveum.midpoint.schema.constants.SchemaConstants; 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.util.TestUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; 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.SynchronizationSituationType; 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 TestSynchronizationService extends AbstractInternalModelIntegrationTest { public static final File TEST_DIR = new File("src/test/resources/sync"); public static final File SHADOW_PIRATES_DUMMY_FILE = new File(TEST_DIR, "shadow-pirates-dummy.xml"); public static final String GROUP_PIRATES_DUMMY_NAME = "pirates"; private static final String INTENT_GROUP = "group"; @Autowired SynchronizationService synchronizationService; @Autowired Clockwork clockwork; private String accountShadowJackDummyOid = null; private String accountShadowCalypsoDummyOid = null; @Test public void test010AddedAccountJack() throws Exception { final String TEST_NAME = "test010AddedAccountJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); PrismObject<ShadowType> accountShadowJack = repoAddObjectFromFile(ACCOUNT_SHADOW_JACK_DUMMY_FILE, result); accountShadowJackDummyOid = accountShadowJack.getOid(); provisioningService.applyDefinition(accountShadowJack, result); assertNotNull("No oid in shadow", accountShadowJack.getOid()); DummyAccount dummyAccount = new DummyAccount(); dummyAccount.setName(ACCOUNT_JACK_DUMMY_USERNAME); dummyAccount.setPassword("deadMenTellNoTales"); dummyAccount.setEnabled(true); dummyAccount.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Jack Sparrow"); getDummyResource().addAccount(dummyAccount); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(accountShadowJack); change.setResource(getDummyResourceObject()); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertSideEffectiveDeltasOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta", ActivationStatusType.ENABLED); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); assertEquals("Wrong detected situation in context", SynchronizationSituationType.UNLINKED, accCtx.getSynchronizationSituationDetected()); assertEquals("Wrong resolved situation in context", SynchronizationSituationType.LINKED, accCtx.getSynchronizationSituationResolved()); PrismAsserts.assertNoDelta("Unexpected account primary delta", accCtx.getPrimaryDelta()); //it this really expected?? delta was already executed, should we expect it in the secondary delta? // assertNotNull("Missing account secondary delta", accCtx.getSecondaryDelta()); // assertIterationDelta(accCtx.getSecondaryDelta(), 0, ""); assertLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJack.getOid()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); result.computeStatus(); TestUtil.assertSuccess(result); } @Test public void test020ModifyLootAbsolute() throws Exception { final String TEST_NAME = "test020ModifyLootAbsolute"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); DummyAccount dummyAccount = getDummyResource().getAccountByUsername(ACCOUNT_JACK_DUMMY_USERNAME); dummyAccount.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOOT_NAME, "999"); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); PrismObject<ShadowType> accountShadowJack = provisioningService.getObject(ShadowType.class, accountShadowJackDummyOid, null, task, result); change.setCurrentShadow(accountShadowJack); change.setResource(getDummyResourceObject()); change.setSourceChannel(SchemaConstants.CHANGE_CHANNEL_LIVE_SYNC_URI); // WHEN TestUtil.displayWhen(TEST_NAME); synchronizationService.notifyChange(change, task, result); // THEN TestUtil.displayThen(TEST_NAME); LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertEquals("Unexpected number of executed deltas", 1, context.getFocusContext().getExecutedDeltas().size()); ObjectDelta<UserType> userSecondaryDelta = context.getFocusContext().getExecutedDeltas().iterator().next().getObjectDelta(); assertNotNull("No user secondary delta", userSecondaryDelta); assertEquals("Unexpected number of modifications in user secondary delta", 3, userSecondaryDelta.getModifications().size()); PrismAsserts.assertPropertyAdd(userSecondaryDelta, UserType.F_COST_CENTER, "999"); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); PrismAsserts.assertNoDelta("account primary delta", accCtx.getPrimaryDelta()); PrismAsserts.assertNoDelta("account secondary delta", accCtx.getSecondaryDelta()); assertEquals("Wrong detected situation in context", SynchronizationSituationType.LINKED, accCtx.getSynchronizationSituationDetected()); assertLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJack.getOid()); PrismObject<UserType> user = getUser(USER_JACK_OID); assertEquals("Unexpected used constCenter", "999", user.asObjectable().getCostCenter()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); result.computeStatus(); TestUtil.assertSuccess(result); } @Test public void test021ModifyLootAbsoluteEmpty() throws Exception { final String TEST_NAME = "test021ModifyLootAbsoluteEmpty"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); DummyAccount dummyAccount = getDummyResource().getAccountByUsername(ACCOUNT_JACK_DUMMY_USERNAME); dummyAccount.replaceAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOOT_NAME); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); PrismObject<ShadowType> accountShadowJack = provisioningService.getObject(ShadowType.class, accountShadowJackDummyOid, null, task, result); change.setCurrentShadow(accountShadowJack); change.setResource(getDummyResourceObject()); change.setSourceChannel(SchemaConstants.CHANGE_CHANNEL_LIVE_SYNC_URI); display("SENDING CHANGE NOTIFICATION", change); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertEquals("Unexpected number of executed deltas", 1, context.getFocusContext().getExecutedDeltas().size()); ObjectDelta<UserType> userSecondaryDelta = context.getFocusContext().getExecutedDeltas().iterator().next().getObjectDelta(); // ObjectDelta<UserType> userSecondaryDelta = context.getFocusContext().getSecondaryDelta(); assertNotNull("No user secondary delta", userSecondaryDelta); assertEquals("Unexpected number of modifications in user secondary delta", 3, userSecondaryDelta.getModifications().size()); PrismAsserts.assertPropertyReplace(userSecondaryDelta, UserType.F_COST_CENTER); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); PrismAsserts.assertNoDelta("Unexpected account primary delta", accCtx.getPrimaryDelta()); PrismAsserts.assertNoDelta("Unexpected account secondary delta", accCtx.getSecondaryDelta()); assertEquals("Wrong detected situation in context", SynchronizationSituationType.LINKED, accCtx.getSynchronizationSituationDetected()); assertLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJack.getOid()); PrismObject<UserType> user = getUser(USER_JACK_OID); assertEquals("Unexpected used constCenter", null, user.asObjectable().getCostCenter()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); result.computeStatus(); TestUtil.assertSuccess(result); } /** * Sending empty delta, this is what reconciliation does. */ @Test public void test030Reconcile() throws Exception { final String TEST_NAME = "test030Reconcile"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); PrismObject<ShadowType> accountShadowJack = provisioningService.getObject(ShadowType.class, accountShadowJackDummyOid, null, task, result); change.setCurrentShadow(accountShadowJack); change.setResource(getDummyResourceObject()); change.setSourceChannel(SchemaConstants.CHANGE_CHANNEL_DISCOVERY_URI); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertSideEffectiveDeltasOnly("user secondary delta", context.getFocusContext().getSecondaryDelta()); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); PrismAsserts.assertNoDelta("account primary delta", accCtx.getPrimaryDelta()); PrismAsserts.assertNoDelta("account secondary delta", accCtx.getSecondaryDelta()); assertEquals("Wrong detected situation in context", SynchronizationSituationType.LINKED, accCtx.getSynchronizationSituationDetected()); assertLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJack.getOid()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); result.computeStatus(); TestUtil.assertSuccess(result); } @Test public void test039DeletedAccountJack() throws Exception { final String TEST_NAME = "test039DeletedAccountJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); PrismObject<ShadowType> shadowRepo = repositoryService.getObject(ShadowType.class, accountShadowJackDummyOid, null, result); assertIteration(shadowRepo, 0, ""); assertSituation(shadowRepo, SynchronizationSituationType.LINKED); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); getDummyResource().deleteAccountByName(ACCOUNT_JACK_DUMMY_USERNAME); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); shadowRepo = repositoryService.getObject(ShadowType.class, accountShadowJackDummyOid, null, result); assertIteration(shadowRepo, 0, ""); assertSituation(shadowRepo, SynchronizationSituationType.LINKED); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(shadow); change.setResource(getDummyResourceObject()); ObjectDelta<ShadowType> syncDelta = ObjectDelta.createDeleteDelta(ShadowType.class, accountShadowJackDummyOid, prismContext); change.setObjectDelta(syncDelta); // WHEN TestUtil.displayWhen(TEST_NAME); synchronizationService.notifyChange(change, task, result); // THEN TestUtil.displayThen(TEST_NAME); LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertSideEffectiveDeltasOnly("user secondary delta", context.getFocusContext().getSecondaryDelta()); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null, true); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); assertEquals("Wrong detected situation in context", SynchronizationSituationType.DELETED, accCtx.getSynchronizationSituationDetected()); PrismAsserts.assertNoDelta("Unexpected account primary delta", accCtx.getPrimaryDelta()); assertNotLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJackDummyOid); shadowRepo = repositoryService.getObject(ShadowType.class, accountShadowJackDummyOid, null, result); assertIteration(shadowRepo, 0, ""); assertSituation(shadowRepo, SynchronizationSituationType.DELETED); result.computeStatus(); TestUtil.assertSuccess(result); PrismObject<UserType> userAfter = getUser(USER_JACK_OID); assertLinks(userAfter, 0); repositoryService.deleteObject(ShadowType.class, accountShadowJackDummyOid, result); } /** * Calypso is protected, no reaction should be applied. */ @Test public void test050AddedAccountCalypso() throws Exception { final String TEST_NAME = "test050AddedAccountCalypso"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); PrismObject<ShadowType> accountShadowCalypso = repoAddObjectFromFile(ACCOUNT_SHADOW_CALYPSO_DUMMY_FILE, result); accountShadowCalypsoDummyOid = accountShadowCalypso.getOid(); provisioningService.applyDefinition(accountShadowCalypso, result); assertNotNull("No oid in shadow", accountShadowCalypso.getOid()); // Make sure that it is properly marked as protected. This is what provisioning would normally do accountShadowCalypso.asObjectable().setProtectedObject(true); DummyAccount dummyAccount = new DummyAccount(); dummyAccount.setName(ACCOUNT_CALYPSO_DUMMY_USERNAME); dummyAccount.setPassword("h1ghS3AS"); dummyAccount.setEnabled(true); dummyAccount.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Calypso"); getDummyResource().addAccount(dummyAccount); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(accountShadowCalypso); change.setResource(getDummyResourceObject()); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNull("Unexpected lens context", context); PrismObject<UserType> userCalypso = findUserByUsername(ACCOUNT_CALYPSO_DUMMY_USERNAME); assertNull("Unexpected user "+userCalypso, userCalypso); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowCalypsoDummyOid); assertSituation(shadow, null); result.computeStatus(); TestUtil.assertSuccess(result); } /** * Calypso is protected, no reaction should be applied. */ @Test public void test051CalypsoRecon() throws Exception { final String TEST_NAME = "test051CalypsoRecon"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); // Lets make this a bit more interesting by setting up a fake situation in the shadow ObjectDelta<ShadowType> objectDelta = createModifyAccountShadowReplaceDelta(accountShadowCalypsoDummyOid, getDummyResourceObject(), new ItemPath(ShadowType.F_SYNCHRONIZATION_SITUATION), SynchronizationSituationType.DISPUTED); repositoryService.modifyObject(ShadowType.class, accountShadowCalypsoDummyOid, objectDelta.getModifications(), result); PrismObject<ShadowType> accountShadowCalypso = getShadowModelNoFetch(accountShadowCalypsoDummyOid); // Make sure that it is properly marked as protected. This is what provisioning would normally do accountShadowCalypso.asObjectable().setProtectedObject(true); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(accountShadowCalypso); change.setResource(getDummyResourceObject()); display("Change notification", change); // WHEN TestUtil.displayWhen(TEST_NAME); synchronizationService.notifyChange(change, task, result); // THEN TestUtil.displayThen(TEST_NAME); LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNull("Unexpected lens context", context); PrismObject<UserType> userCalypso = findUserByUsername(ACCOUNT_CALYPSO_DUMMY_USERNAME); assertNull("Unexpected user "+userCalypso, userCalypso); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowCalypsoDummyOid); assertSituation(shadow, SynchronizationSituationType.DISPUTED); result.computeStatus(); TestUtil.assertSuccess(result); } @Test public void test100AddedAccountJack() throws Exception { final String TEST_NAME = "test100AddedAccountJack"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); PrismObject<UserType> userBefore = getUser(USER_JACK_OID); assertLinks(userBefore, 0); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); PrismObject<ShadowType> accountShadowJack = repoAddObjectFromFile(ACCOUNT_SHADOW_JACK_DUMMY_FILE, result); accountShadowJackDummyOid = accountShadowJack.getOid(); provisioningService.applyDefinition(accountShadowJack, result); assertNotNull("No oid in shadow", accountShadowJack.getOid()); DummyAccount dummyAccount = new DummyAccount(); dummyAccount.setName(ACCOUNT_JACK_DUMMY_USERNAME); dummyAccount.setPassword("deadMenTellNoTales"); dummyAccount.setEnabled(true); dummyAccount.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Jack Sparrow"); getDummyResource().addAccount(dummyAccount); display("Dummy resource before", getDummyResource()); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(accountShadowJack); change.setResource(getDummyResourceObject()); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertSideEffectiveDeltasOnly(context.getFocusContext().getSecondaryDelta(), "user secondary delta", ActivationStatusType.ENABLED); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); assertEquals("Wrong detected situation in context", SynchronizationSituationType.UNLINKED, accCtx.getSynchronizationSituationDetected()); assertEquals("Wrong resolved situation in context", SynchronizationSituationType.LINKED, accCtx.getSynchronizationSituationResolved()); PrismAsserts.assertNoDelta("Unexpected account primary delta", accCtx.getPrimaryDelta()); //it this really expected?? delta was already executed, should we expect it in the secondary delta? // assertNotNull("Missing account secondary delta", accCtx.getSecondaryDelta()); // assertIterationDelta(accCtx.getSecondaryDelta(), 0, ""); assertLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJack.getOid()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); result.computeStatus(); TestUtil.assertSuccess(result); PrismObject<UserType> userAfter = getUser(USER_JACK_OID); assertLinks(userAfter, 1); assertLinked(userAfter, shadow); } /** * Delete the account but also the shadow in the repo. The system should work well. */ @Test public void test199DeletedAccountJackTotal() throws Exception { final String TEST_NAME = "test199DeletedAccountJackTotal"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); getDummyResource().deleteAccountByName(ACCOUNT_JACK_DUMMY_USERNAME); PrismObject<ShadowType> shadow = getShadowModelNoFetch(accountShadowJackDummyOid); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(shadow); change.setResource(getDummyResourceObject()); ObjectDelta<ShadowType> syncDelta = ObjectDelta.createDeleteDelta(ShadowType.class, accountShadowJackDummyOid, prismContext); change.setObjectDelta(syncDelta); repositoryService.deleteObject(ShadowType.class, accountShadowJackDummyOid, result); // WHEN synchronizationService.notifyChange(change, task, result); // THEN LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNotNull("No focus context", context.getFocusContext()); assertNull("Unexpected user primary delta", context.getFocusContext().getPrimaryDelta()); assertSideEffectiveDeltasOnly("user secondary delta", context.getFocusContext().getSecondaryDelta()); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ACCOUNT, null, true); LensProjectionContext accCtx = context.findProjectionContext(rat); assertNotNull("No account sync context for "+rat, accCtx); assertEquals("Wrong detected situation in context", SynchronizationSituationType.DELETED, accCtx.getSynchronizationSituationDetected()); PrismAsserts.assertNoDelta("Unexpected account primary delta", accCtx.getPrimaryDelta()); assertNotLinked(context.getFocusContext().getObjectOld().getOid(), accountShadowJackDummyOid); PrismObject<UserType> userAfter = getUser(USER_JACK_OID); assertLinks(userAfter, 0); result.computeStatus(); display("Final result", result); TestUtil.assertSuccess(result,1); assertNoObject(ShadowType.class, accountShadowJackDummyOid, task, result); } @Test public void test210AddedGroupPirates() throws Exception { final String TEST_NAME = "test210AddedGroupPirates"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = taskManager.createTaskInstance(TestSynchronizationService.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); MockLensDebugListener mockListener = new MockLensDebugListener(); clockwork.setDebugListener(mockListener); PrismObject<ShadowType> shadowPirates = repoAddObjectFromFile(SHADOW_PIRATES_DUMMY_FILE, result); provisioningService.applyDefinition(shadowPirates, result); assertNotNull("No oid in shadow", shadowPirates.getOid()); DummyGroup dummyGroup = new DummyGroup(); dummyGroup.setName(GROUP_PIRATES_DUMMY_NAME); dummyGroup.setEnabled(true); dummyGroup.addAttributeValues(DummyResourceContoller.DUMMY_GROUP_ATTRIBUTE_DESCRIPTION, "Scurvy Pirates"); getDummyResource().addGroup(dummyGroup); ResourceObjectShadowChangeDescription change = new ResourceObjectShadowChangeDescription(); change.setCurrentShadow(shadowPirates); change.setResource(getDummyResourceObject()); // WHEN TestUtil.displayWhen(TEST_NAME); synchronizationService.notifyChange(change, task, result); // THEN TestUtil.displayWhen(TEST_NAME); result.computeStatus(); TestUtil.assertSuccess(result); LensContext<UserType> context = mockListener.getLastSyncContext(); display("Resulting context (as seen by debug listener)", context); assertNotNull("No resulting context (as seen by debug listener)", context); assertNotNull("No focus primary delta", context.getFocusContext().getPrimaryDelta()); // assertNotNull("No focus secondary delta", context.getFocusContext().getSecondaryDelta()); assertFalse("No executed focus deltas", context.getFocusContext().getExecutedDeltas().isEmpty()); ObjectDelta<UserType> userSecondaryDelta = (ObjectDelta<UserType>) context.getFocusContext().getExecutedDeltas().iterator().next().getObjectDelta(); ResourceShadowDiscriminator rat = new ResourceShadowDiscriminator(getDummyResourceObject().getOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); LensProjectionContext projCtx = context.findProjectionContext(rat); assertNotNull("No projection sync context for "+rat, projCtx); assertEquals("Wrong detected situation in context", SynchronizationSituationType.UNMATCHED, projCtx.getSynchronizationSituationDetected()); assertEquals("Wrong resolved situation in context", SynchronizationSituationType.LINKED, projCtx.getSynchronizationSituationResolved()); PrismAsserts.assertNoDelta("Unexpected projection primary delta", projCtx.getPrimaryDelta()); //it this really expected?? delta was already executed, should we expect it in the secondary delta? // assertNotNull("Missing account secondary delta", accCtx.getSecondaryDelta()); // assertIterationDelta(accCtx.getSecondaryDelta(), 0, ""); assertLinked(RoleType.class, context.getFocusContext().getOid(), shadowPirates.getOid()); PrismObject<ShadowType> shadow = getShadowModelNoFetch(shadowPirates.getOid()); assertIteration(shadow, 0, ""); assertSituation(shadow, SynchronizationSituationType.LINKED); } }