/* * 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.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 static org.testng.AssertJUnit.assertNull; import java.io.FileNotFoundException; import java.net.ConnectException; import java.util.Collection; import java.util.Date; import java.util.List; import javax.xml.namespace.QName; 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.DummyAccount; import com.evolveum.icf.dummy.resource.DummyResource; import com.evolveum.icf.dummy.resource.SchemaViolationException; import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.schema.util.ResourceTypeUtil; 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.MiscUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; 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.ObjectSynchronizationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; 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.SynchronizationSituationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationType; 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 abstract class AbstractSynchronizationStoryTest extends AbstractInitializedModelIntegrationTest { protected static final String ACCOUNT_WALLY_DUMMY_USERNAME = "wally"; protected static final String ACCOUNT_MANCOMB_DUMMY_USERNAME = "mancomb"; private static final Date ACCOUNT_MANCOMB_VALID_FROM_DATE = MiscUtil.asDate(2011, 2, 3, 4, 5, 6); private static final Date ACCOUNT_MANCOMB_VALID_TO_DATE = MiscUtil.asDate(2066, 5, 4, 3, 2, 1); protected static String userWallyOid; protected boolean allwaysCheckTimestamp = false; protected long timeBeforeSync; @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.NONE); // DebugUtil.setDetailedDebugDump(true); } protected abstract void importSyncTask(PrismObject<ResourceType> resource) throws FileNotFoundException; protected abstract String getSyncTaskOid(PrismObject<ResourceType> resource); protected int getWaitTimeout() { return DEFAULT_TASK_WAIT_TIMEOUT; } protected int getNumberOfExtraDummyUsers() { return 0; } protected boolean isReconciliation() { return false; } @Test public void test100ImportLiveSyncTaskDummyGreen() throws Exception { final String TEST_NAME = "test100ImportLiveSyncTaskDummyGreen"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); /// WHEN TestUtil.displayWhen(TEST_NAME); importSyncTask(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); waitForSyncTaskStart(resourceDummyGreen); } @Test public void test110AddDummyGreenAccountMancomb() throws Exception { final String TEST_NAME = "test110AddDummyGreenAccountMancomb"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); // Preconditions assertUsers(5); DummyAccount account = new DummyAccount(ACCOUNT_MANCOMB_DUMMY_USERNAME); account.setEnabled(true); account.setValidFrom(ACCOUNT_MANCOMB_VALID_FROM_DATE); account.setValidTo(ACCOUNT_MANCOMB_VALID_TO_DATE); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepgood"); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Melee Island"); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceGreen.addAccount(account); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyGreen); display("Account mancomb", accountMancomb); assertNotNull("No mancomb account shadow", accountMancomb); assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_GREEN_OID, accountMancomb.asObjectable().getResourceRef().getOid()); assertShadowOperationalData(accountMancomb, SynchronizationSituationType.LINKED); assertValidFrom(accountMancomb, ACCOUNT_MANCOMB_VALID_FROM_DATE); assertValidTo(accountMancomb, ACCOUNT_MANCOMB_VALID_TO_DATE); PrismObject<UserType> userMancomb = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); display("User mancomb", userMancomb); assertNotNull("User mancomb was not created", userMancomb); assertLinks(userMancomb, 1); assertAdministrativeStatusEnabled(userMancomb); assertValidFrom(userMancomb, ACCOUNT_MANCOMB_VALID_FROM_DATE); assertValidTo(userMancomb, ACCOUNT_MANCOMB_VALID_TO_DATE); assertLinked(userMancomb, accountMancomb); assertUsers(6); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("userPasswordNotifier", 1); // password is generated by mapping (if there's none) // checkDummyTransportMessages("accountPasswordNotifier", 1); // account password is then set // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 1); // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // account itself is not added (only the shadow is!) // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 1); } @Test public void test200ImportLiveSyncTaskDummyBlue() throws Exception { final String TEST_NAME = "test200ImportLiveSyncTaskDummyBlue"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); /// WHEN TestUtil.displayWhen(TEST_NAME); importSyncTask(resourceDummyBlue); // THEN TestUtil.displayThen(TEST_NAME); waitForSyncTaskStart(resourceDummyBlue); } /** * Add wally to the green dummy resource. User should be created and linked. */ @Test public void test210AddDummyGreenAccountWally() throws Exception { final String TEST_NAME = "test210AddDummyGreenAccountWally"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceCtlGreen.addAccount(ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", "Scabb Island"); // Wait for sync task to pick up the change waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally Feed"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally was not created", userWally); userWallyOid = userWally.getOid(); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", null, null); assertLinks(userWally, 1); assertUsers(7); assertLinked(userWally, accountWallyGreen); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("userPasswordNotifier", 1); // previously non-existing password is generated // checkDummyTransportMessages("accountPasswordNotifier", 1); // password is then set on the account // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 2); // changes on green & blue (induced) // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // account itself is not added (only the shadow is!) // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 0); } /** * Add wally also to the blue dummy resource. User should be linked to this account. */ @Test public void test220AddDummyBlueAccountWally() throws Exception { final String TEST_NAME = "test220AddDummyBlueAccountWally"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceCtlBlue.addAccount(ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", "Scabb Island"); // Wait for sync task to pick up the change // However, blue is not authoritative regarding creating new users, so wally will not be created at this time waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); // Make sure that the "kickback" sync cycle of the other resource runs to completion // We want to check the state after it gets stable // and it could spoil the next test waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally Feed"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally was not created", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", null, null); assertLinks(userWally, 2); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertUsers(7); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("accountPasswordNotifier", 0); // checkDummyTransportMessages("userPasswordNotifier", 0); // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 0); // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // account itself is not added (only the shadow is!) // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 1); } /** * Add mancomb also to the blue dummy resource. This account should be linked to the existing user. * Similar to the previous test but blue resource has a slightly different correlation expression. */ @Test public void test315AddDummyBlueAccountMancomb() throws Exception { final String TEST_NAME = "test315AddDummyBlueAccountMancomb"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceCtlBlue.addAccount(ACCOUNT_MANCOMB_DUMMY_USERNAME, "Mancomb Seepgood", "Melee Island"); // Wait for sync task to pick up the change waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); // Make sure that the "kickback" sync cycle of the other resource runs to completion // We want to check the state after it gets stable // and it could spoil the next test waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); // THEN TestUtil.displayThen(TEST_NAME); // The ckecks are simplified here because the developer has a lazy mood :-) assertDummyAccount(RESOURCE_DUMMY_BLUE_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, "Mancomb Seepgood", true); assertDummyAccount(RESOURCE_DUMMY_GREEN_NAME, ACCOUNT_MANCOMB_DUMMY_USERNAME, "Mancomb Seepgood", true); PrismObject<UserType> userMancomb = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); display("User mancomb", userMancomb); assertNotNull("User mancomb disappeared", userMancomb); assertUser(userMancomb, userMancomb.getOid(), ACCOUNT_MANCOMB_DUMMY_USERNAME, "Mancomb Seepgood", null, null); assertLinks(userMancomb, 2); assertAccount(userMancomb, RESOURCE_DUMMY_BLUE_OID); assertAccount(userMancomb, RESOURCE_DUMMY_GREEN_OID); assertUsers(7); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("userPasswordNotifier", 1); // previously non-existing password is generated // checkDummyTransportMessages("accountPasswordNotifier", 1); // password is then set on the account // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 2); // changes on green & blue (induced) // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // account itself is not added (only the shadow is!) // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 0); } /** * Import sync task for default dummy resource as well. This does not do much as we will no be manipulating * the default dummy account directly. Just make sure that it does not do anything bad. */ @Test public void test350ImportLiveSyncTaskDummyDefault() throws Exception { final String TEST_NAME = "test350ImportLiveSyncTaskDummyDefault"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); /// WHEN TestUtil.displayWhen(TEST_NAME); importSyncTask(getDummyResourceObject()); // THEN TestUtil.displayThen(TEST_NAME); waitForSyncTaskStart(getDummyResourceObject()); // Dummy resource has some extra users that may be created in recon, so let's give it a chance to do it now waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); assertUsers(7 + getNumberOfExtraDummyUsers()); } /** * Import sync task for default dummy resource as well. This does not do much as we will no be manipulating * the default dummy account directly. Just make sure that it does not do anything bad. */ @Test public void test360ModifyUserAddDummyDefaultAccount() throws Exception { final String TEST_NAME = "test360ModifyUserAddDummyDefaultAccount"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); assertEquals("OID of user wally have changed", userWallyOid, userWally.getOid()); ObjectDelta<UserType> userDelta = createModifyUserAddAccount(userWally.getOid(), getDummyResourceObject()); Collection<ObjectDelta<? extends ObjectType>> deltas = (Collection)MiscUtil.createCollection(userDelta); /// WHEN TestUtil.displayWhen(TEST_NAME); modelService.executeChanges(deltas, null, task, result); // THEN TestUtil.displayThen(TEST_NAME); // Make sure we have steady state waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); PrismObject<ShadowType> accountWallyDefault = checkWallyAccount(getDummyResourceObject(), getDummyResource(), "default", "Wally Feed"); assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally disappeared", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", null, null); assertLinks(userWally, 3); assertLinked(userWally, accountWallyDefault); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertUsers(7 + getNumberOfExtraDummyUsers()); } // @Test // public void test365ModifyDummyGreenAccountWallyUserTemplate() throws Exception { // final String TEST_NAME = "test390ModifyDummyGreenAccountWallyUserTemplate"; // displayTestTile(this, TEST_NAME); // // // GIVEN // Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); // OperationResult result = task.getResult(); // rememberTimeBeforeSync(); // // addObjectFromFile(USER_TEMPLATE_SYNC_FILENAME, UserTemplateType.class, result); // assumeUserTemplate(USER_TEMPLATE_SYNC_OID, resourceDummyGreen.asObjectable(), result); // // DummyAccount wallyDummyAccount = dummyResourceGreen.getAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); // // /// WHEN // displayWhen(TEST_NAME); // wallyDummyAccount.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Wally Bloodnose"); //// wallyDummyAccount.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_QUOTE_NAME, "Cola"); // // // Wait for sync task to pick up the change // waitForSyncTaskNextRun(resourceDummyGreen); // //// // Make sure that the "kickback" sync cycle of the other resource runs to completion //// // We want to check the state after it gets stable //// // and it could spoil the next test // waitForSyncTaskNextRun(resourceDummyBlue); // waitForSyncTaskNextRun(resourceDummyGreen); //// // Make sure we have steady state // waitForSyncTaskNextRun(resourceDummy); // // // THEN // displayThen(TEST_NAME); // // PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); // display("User wally", userWally); // assertNotNull("User wally disappeared", userWally); // assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Bloodnose", null, "Wally Bloodnose from Sync"); // // PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "blue", "Wally Bloodnose"); // if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); // //// PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally B. Feed"); //// assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); // PrismObject<ShadowType> accountWallyDefault = checkWallyAccount(resourceDummy, dummyResource, "default", "Wally Bloodnose"); // assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); // //// assertAccounts(userWally, 3); // //// assertLinked(userWally, accountWallyGreen); // assertLinked(userWally, accountWallyGreen); // assertLinked(userWally, accountWallyDefault); // // assertUsers(7 + getNumberOfExtraDummyUsers()); // } /** * Change fullname on the green account. There is an inbound mapping to the user so it should propagate. * There is also outbound mapping from the user to dummy account, therefore it should propagate there as well. */ @Test public void test370ModifyDummyGreenAccountWally() throws Exception { final String TEST_NAME = "test370ModifyDummyGreenAccountWally"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); repoAddObjectFromFile(USER_TEMPLATE_SYNC_FILENAME, result); assumeUserTemplate(USER_TEMPLATE_SYNC_OID, resourceDummyGreen.asObjectable(), "default account type", result); rememberTimeBeforeSync(); prepareNotifications(); DummyAccount wallyDummyAccount = dummyResourceGreen.getAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); /// WHEN TestUtil.displayWhen(TEST_NAME); wallyDummyAccount.replaceAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Wally B. Feed"); // Wait for sync task to pick up the change waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // Make sure that the "kickback" sync cycle of the other resource runs to completion // We want to check the state after it gets stable // and it could spoil the next test waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // Make sure we have steady state waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally disappeared", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally B. Feed", null, "Wally B. Feed from Sync"); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally B. Feed"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyDefault; // See MID-2518 if (isReconciliation()) { // Can be iether "Wally Feed" or "Wally B. Feed". Both are correct. Depends on he order of recon // task execution. accountWallyDefault = checkWallyAccount(getDummyResourceObject(), getDummyResource(), "default", null); } else { accountWallyDefault = checkWallyAccount(getDummyResourceObject(), getDummyResource(), "default", "Wally B. Feed"); } assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); assertLinks(userWally, 3); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertLinked(userWally, accountWallyDefault); assertUsers(7 + getNumberOfExtraDummyUsers()); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("accountPasswordNotifier", 0); // checkDummyTransportMessages("userPasswordNotifier", 0); // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 1); // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // checkDummyTransportMessagesAtLeast("simpleUserNotifier", 1); // actually I dont understand why sometimes is here 1, sometimes 2 messages (has to do something with mapping username->familyname) // checkDummyTransportMessages("simpleUserNotifier-ADD", 0); } /** * Change user fullname. Fullname has normal mapping on default dummy. * See if the change propagates correctly. Also see that there are no side-effects. */ @Test public void test380ModifyUserWallyFullName() throws Exception { final String TEST_NAME = "test380ModifyUserWallyFullName"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); DummyAccount wallyDummyAccount = dummyResourceGreen.getAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); /// WHEN TestUtil.displayWhen(TEST_NAME); modifyUserReplace(userWallyOid, UserType.F_FULL_NAME, task, result, PrismTestUtil.createPolyString("Bloodnose")); // Wait for sync tasks to pick up the change and have some chance to screw things waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // Run green recon twice here. If the recon already searched for current state of the // wally account, the old value ("Wally B. Feed") is stored in the memory. Even if we rewrite // the account state by this operation the value already read into memory will be used instead // and it will be propagated to other resources. The next recon run should fix it in the user. // But as the mapping to default dummy is normal, the recon will not fix it on the resource. waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally disappeared", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Bloodnose", null, "Bloodnose from Sync"); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Bloodnose"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyDefault = findAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME, getDummyResourceObject()); String fullNameDummyAttribute = IntegrationTestTools.getAttributeValue(accountWallyDefault.asObjectable(), new QName(ResourceTypeUtil.getResourceNamespace(getDummyResourceObject()), DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME)); if (!"Bloodnose".equals(fullNameDummyAttribute) && !"Wally B. Feed".equals(fullNameDummyAttribute)) { AssertJUnit.fail("Wrong full name on default dummy resource: "+fullNameDummyAttribute); } assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); assertLinks(userWally, 3); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertLinked(userWally, accountWallyDefault); assertUsers(7 + getNumberOfExtraDummyUsers()); notificationManager.setDisabled(true); } /** * Change user locality. Locality has strong mapping on default dummy. * See if the change propagates correctly. Also see that there are no side-effects. */ @Test public void test382ModifyUserWallyLocality() throws Exception { final String TEST_NAME = "test382ModifyUserWallyLocality"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); DummyAccount wallyDummyAccount = dummyResourceGreen.getAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); /// WHEN TestUtil.displayWhen(TEST_NAME); modifyUserReplace(userWallyOid, UserType.F_LOCALITY, task, result, PrismTestUtil.createPolyString("Plunder island")); // Wait for sync tasks to pick up the change and have some chance to screw things waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // Run green recon twice here. If the recon already searched for current state of the // wally account, the old value is stored in the memory. Even if we rewrite // the account state by this operation the value already read into memory will be used instead // and it will be propagated to other resources. The next recon run should fix it. // Both in user and on the resource. waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally disappeared", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Bloodnose", null, "Bloodnose from Sync"); PrismAsserts.assertPropertyValue(userWally, UserType.F_LOCALITY, PrismTestUtil.createPolyString("Plunder island")); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Bloodnose"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyDefault = findAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME, getDummyResourceObject()); String fullNameDummyAttribute = IntegrationTestTools.getAttributeValue(accountWallyDefault.asObjectable(), new QName(ResourceTypeUtil.getResourceNamespace(getDummyResourceObject()), DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME)); if (!"Bloodnose".equals(fullNameDummyAttribute) && !"Wally B. Feed".equals(fullNameDummyAttribute)) { AssertJUnit.fail("Wrong full name on default dummy resource: "+fullNameDummyAttribute); } assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); assertShadowOperationalData(accountWallyDefault, SynchronizationSituationType.LINKED); assertDummyAccountAttribute(RESOURCE_DUMMY_GREEN_NAME, ACCOUNT_WALLY_DUMMY_USERNAME, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Plunder island"); assertDummyAccountAttribute(RESOURCE_DUMMY_BLUE_NAME, ACCOUNT_WALLY_DUMMY_USERNAME, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Scabb Island"); assertDummyAccountAttribute(null, ACCOUNT_WALLY_DUMMY_USERNAME, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Plunder island"); assertLinks(userWally, 3); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertLinked(userWally, accountWallyDefault); assertUsers(7 + getNumberOfExtraDummyUsers()); notificationManager.setDisabled(true); } /** * Delete default dummy account. * Dummy resource has unlinkAccount sync reaction for deleted situation. The account should be unlinked * but the user and other accounts should remain as they were. */ @Test public void test400DeleteDummyDefaultAccount() throws Exception { final String TEST_NAME = "test400DeleteDummyDefaultAccount"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); /// WHEN TestUtil.displayWhen(TEST_NAME); getDummyResource().deleteAccountByName(ACCOUNT_WALLY_DUMMY_USERNAME); display("Dummy (default) resource", getDummyResource().debugDump()); // Make sure we have steady state waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); waitForSyncTaskNextRunAssertSuccess(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); assertNoDummyAccount(ACCOUNT_WALLY_DUMMY_USERNAME); assertNoShadow(ACCOUNT_WALLY_DUMMY_USERNAME, getDummyResourceObject(), task, result); PrismObject<ShadowType> accountWallyBlue = checkWallyAccount(resourceDummyBlue, dummyResourceBlue, "blue", "Wally Feed"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyBlue, SynchronizationSituationType.LINKED); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Bloodnose"); if (allwaysCheckTimestamp) assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally disappeared", userWally); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Bloodnose", null, "Bloodnose from Sync"); assertLinks(userWally, 2); assertLinked(userWally, accountWallyGreen); assertLinked(userWally, accountWallyBlue); assertUsers(7 + getNumberOfExtraDummyUsers()); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("accountPasswordNotifier", 0); // checkDummyTransportMessages("userPasswordNotifier", 0); // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 0); // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // checkDummyTransportMessages("simpleUserNotifier", 0); // checkDummyTransportMessages("simpleUserNotifier-ADD", 0); } /** * Delete green dummy account. * Green dummy resource has deleteUser sync reaction for deleted situation. This should delete the user * and all other accounts. */ @Test public void test410DeleteDummyGreenAccount() throws Exception { final String TEST_NAME = "test410DeleteDummyGreenAccount"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); prepareNotifications(); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceGreen.deleteAccountByName(ACCOUNT_WALLY_DUMMY_USERNAME); // Make sure we have steady state waitForSyncTaskNextRunAssertSuccess(getDummyResourceObject()); OperationResult takResultBlue = waitForSyncTaskNextRun(resourceDummyBlue); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); assertNoDummyAccount(ACCOUNT_WALLY_DUMMY_USERNAME); assertNoShadow(ACCOUNT_WALLY_DUMMY_USERNAME, getDummyResourceObject(), task, result); assertNoDummyAccount(RESOURCE_DUMMY_GREEN_NAME, ACCOUNT_WALLY_DUMMY_USERNAME); assertNoShadow(ACCOUNT_WALLY_DUMMY_USERNAME, resourceDummyGreen, task, result); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNull("User wally is not gone", userWally); assertNoDummyAccount(RESOURCE_DUMMY_BLUE_NAME, ACCOUNT_WALLY_DUMMY_USERNAME); // Interesting things can happen here. Like this: // // Recon blue: Search on resource, remeber results in connector, sending them one // by one to midpoint. But recon task is slow, it will not send wally // account yet. // Recon green: Search on resource, got wally as the first result, sending to model, // model deletes user and blue account. // Recon blue: It finally gets to send wally account to the model. But the original // shadow is gone. So, provisioning creates a new shadow. And it is right. // the object just came from the connector and therefore provisioning // thinks that it is fresh and it has been re-created. // // We have nothing simple to do about this. And really, we do not care much because // it is not really a problem. It is rare and the next recon run should fix it anyway. // It will not cause any real harm on target resource. It may do some (even quite nasty) // churn on source+target resource. But source+target is a dangerous lifestyle anyway. // // So, if that happens we will just wait for the next recon run and check that it // sorts it out. ObjectQuery wallyBlueAccountsQuery = createAccountShadowQuery(ACCOUNT_WALLY_DUMMY_USERNAME, resourceDummyBlue); List<PrismObject<ShadowType>> wallyBlueAccounts = repositoryService.searchObjects(ShadowType.class, wallyBlueAccountsQuery, null, result); if (!wallyBlueAccounts.isEmpty()) { waitForSyncTaskNextRun(resourceDummyBlue); } assertNoShadow(ACCOUNT_WALLY_DUMMY_USERNAME, resourceDummyBlue, task, result); assertUsers(6 + getNumberOfExtraDummyUsers()); if (isReconciliation()) { if (takResultBlue.getStatus() == OperationResultStatus.PARTIAL_ERROR) { // Blue resource recon may fail. The user may be deleted before the blue // recon task finishes. If the result (user, accounts) is OK then tolerate this error. } else { TestUtil.assertSuccess("Blue resource syncronization has failed", takResultBlue); } } else { TestUtil.assertSuccess("Blue resource syncronization has failed", takResultBlue); } // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("accountPasswordNotifier", 0); // checkDummyTransportMessages("userPasswordNotifier", 0); // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 1); // default is already deleted, green is deleted manually // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 0); } @Test public void test510AddDummyGreenAccountWallyUserTemplate() throws Exception { final String TEST_NAME = "test510AddDummyGreenAccountWallyUserTemplate"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); assumeUserTemplate(USER_TEMPLATE_SYNC_OID, resourceDummyGreen.asObjectable(), null, result); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceCtlGreen.addAccount(ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", "Scabb Island"); // Wait for sync task to pick up the change waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountWallyGreen = checkWallyAccount(resourceDummyGreen, dummyResourceGreen, "green", "Wally Feed"); assertShadowOperationalData(accountWallyGreen, SynchronizationSituationType.LINKED); PrismObject<UserType> userWally = findUserByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("User wally", userWally); assertNotNull("User wally was not created", userWally); userWallyOid = userWally.getOid(); assertUser(userWally, userWallyOid, ACCOUNT_WALLY_DUMMY_USERNAME, "Wally Feed", null, "Wally Feed from Sync"); assertLinks(userWally, 1); assertLinked(userWally, accountWallyGreen); assertUsers(7 + getNumberOfExtraDummyUsers()); // sync = ResourceTypeUtil.determineSynchronization(resourceDummyBlue.asObjectable(), UserType.class); // if (sync != null){ // sync.setObjectTemplateRef(null); // } } /** * Calypso is a protected account. It should not be touched by the sync. */ @Test public void test600AddDummyGreenAccountCalypso() throws Exception { final String TEST_NAME = "test600AddDummyGreenAccountCalypso"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); // Preconditions assertUsers(7 + getNumberOfExtraDummyUsers()); DummyAccount account = new DummyAccount(ACCOUNT_CALYPSO_DUMMY_USERNAME); account.setEnabled(true); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Calypso"); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "The Seven Seas"); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceGreen.addAccount(account); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountShadow = findAccountByUsername(ACCOUNT_CALYPSO_DUMMY_USERNAME, resourceDummyGreen); display("Account calypso", accountShadow); assertNotNull("No calypso account shadow", accountShadow); assertEquals("Wrong resourceRef in calypso account", RESOURCE_DUMMY_GREEN_OID, accountShadow.asObjectable().getResourceRef().getOid()); assertTrue("Calypso shadow is NOT protected", accountShadow.asObjectable().isProtectedObject()); PrismObject<UserType> userCalypso = findUserByUsername(ACCOUNT_CALYPSO_DUMMY_USERNAME); display("User calypso", userCalypso); assertNull("User calypso was created, it should not", userCalypso); assertUsers(7 + getNumberOfExtraDummyUsers()); } /** * Accounts starting with X are admin accounts (intent "admin"). Check if synchronization gets this right. */ @Test public void test700AddDummyGreenAccountXjojo() throws Exception { final String TEST_NAME = "test700AddDummyGreenAccountXjojo"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME); OperationResult result = task.getResult(); rememberTimeBeforeSync(); prepareNotifications(); // Preconditions assertUsers(7 + getNumberOfExtraDummyUsers()); DummyAccount account = new DummyAccount("Xjojo"); account.setEnabled(true); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Jojo the Monkey"); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Scabb Island"); /// WHEN TestUtil.displayWhen(TEST_NAME); dummyResourceGreen.addAccount(account); waitForSyncTaskNextRunAssertSuccess(resourceDummyGreen); // THEN TestUtil.displayThen(TEST_NAME); PrismObject<ShadowType> accountAfter = findAccountByUsername("Xjojo", resourceDummyGreen); display("Account after", accountAfter); assertNotNull("No account shadow", accountAfter); assertEquals("Wrong resourceRef in account shadow", RESOURCE_DUMMY_GREEN_OID, accountAfter.asObjectable().getResourceRef().getOid()); assertShadowOperationalData(accountAfter, SynchronizationSituationType.LINKED); assertShadowKindIntent(accountAfter, ShadowKindType.ACCOUNT, "admin"); PrismObject<UserType> userAfter = findUserByUsername("jojo"); display("User after", userAfter); assertNotNull("User jojo was not created", userAfter); assertLinks(userAfter, 1); assertAdministrativeStatusEnabled(userAfter); assertLinked(userAfter, accountAfter); assertUsers(8 + getNumberOfExtraDummyUsers()); // notifications notificationManager.setDisabled(true); // checkDummyTransportMessages("userPasswordNotifier", 1); // password is generated by mapping (if there's none) // checkDummyTransportMessages("accountPasswordNotifier", 1); // account password is then set // checkDummyTransportMessages("simpleAccountNotifier-SUCCESS", 1); // checkDummyTransportMessages("simpleAccountNotifier-FAILURE", 0); // checkDummyTransportMessages("simpleAccountNotifier-ADD-SUCCESS", 0); // account itself is not added (only the shadow is!) // checkDummyTransportMessages("simpleUserNotifier", 1); // checkDummyTransportMessages("simpleUserNotifier-ADD", 1); } private void assumeUserTemplate(String templateOid, ResourceType resource, String syncConfigName, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { SynchronizationType resourceSync = resource.getSynchronization(); resourceSync.getObjectSynchronization().get(0).setObjectTemplateRef(ObjectTypeUtil.createObjectRef(templateOid, ObjectTypes.OBJECT_TEMPLATE)); Collection<? extends ItemDelta> refDelta = PropertyDelta.createModificationReplacePropertyCollection(ResourceType.F_SYNCHRONIZATION, resource.asPrismObject().getDefinition(), resourceSync); repositoryService.modifyObject(ResourceType.class, resource.getOid(), refDelta, result); ResourceType res = repositoryService.getObject(ResourceType.class, resource.getOid(), null, result).asObjectable(); assertNotNull(res); assertNotNull("Synchronization is not specified", res.getSynchronization()); ObjectSynchronizationType ost = determineSynchronization(res, UserType.class, syncConfigName); assertNotNull("object sync type is not specified", ost); assertNotNull("user template not specified", ost.getObjectTemplateRef()); assertEquals("Wrong user template in resource", templateOid, ost.getObjectTemplateRef().getOid()); } protected void waitForSyncTaskStart(PrismObject<ResourceType> resource) throws Exception { waitForTaskStart(getSyncTaskOid(resource), false, getWaitTimeout()); } protected OperationResult waitForSyncTaskNextRunAssertSuccess(PrismObject<ResourceType> resource) throws Exception { return waitForTaskNextRunAssertSuccess(getSyncTaskOid(resource), false, getWaitTimeout()); } protected OperationResult waitForSyncTaskNextRun(PrismObject<ResourceType> resource) throws Exception { return waitForTaskNextRun(getSyncTaskOid(resource), false, getWaitTimeout()); } private PrismObject<ShadowType> checkWallyAccount(PrismObject<ResourceType> resource, DummyResource dummy, String resourceDesc, String expectedFullName) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException { return checkWallyAccount(resource, dummy, resourceDesc, expectedFullName, null, null); } private PrismObject<ShadowType> checkWallyAccount(PrismObject<ResourceType> resource, DummyResource dummy, String resourceDesc, String expectedFullName, String shipName, String quote) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ConnectException, FileNotFoundException, SchemaViolationException, ConflictException { PrismObject<ShadowType> accountShadowWally = findAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME, resource); display("Account shadow wally ("+resourceDesc+")", accountShadowWally); assertEquals("Wrong resourceRef in wally account ("+resourceDesc+")", resource.getOid(), accountShadowWally.asObjectable().getResourceRef().getOid()); if (expectedFullName != null) { IntegrationTestTools.assertAttribute(accountShadowWally.asObjectable(), resource.asObjectable(), DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, expectedFullName); } DummyAccount dummyAccount = dummy.getAccountByUsername(ACCOUNT_WALLY_DUMMY_USERNAME); display("Account wally ("+resourceDesc+")", dummyAccount); assertNotNull("No dummy account ("+resourceDesc+")", dummyAccount); if (expectedFullName != null) { assertEquals("Wrong dummy account fullname ("+resourceDesc+")", expectedFullName, dummyAccount.getAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME)); } if (shipName != null){ assertEquals("Wrong dummy account shipName ("+resourceDesc+")", shipName, dummyAccount.getAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_SHIP_NAME)); } if (quote != null){ assertEquals("Wrong dummy account quote ("+resourceDesc+")", quote, dummyAccount.getAttributeValue(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_QUOTE_NAME)); } return accountShadowWally; } protected void rememberTimeBeforeSync() { timeBeforeSync = System.currentTimeMillis(); } protected void assertShadowOperationalData(PrismObject<ShadowType> shadow, SynchronizationSituationType expectedSituation) { super.assertShadowOperationalData(shadow, expectedSituation, timeBeforeSync); } }