Skip to content

Commit

Permalink
Consistency update: fixes related to manual connectors (MID-3891)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Aug 1, 2018
1 parent d29a2bf commit 9fb5ef1
Show file tree
Hide file tree
Showing 18 changed files with 601 additions and 535 deletions.
Expand Up @@ -158,15 +158,10 @@ public <F extends FocusType> void processActivationUserCurrent(LensContext<F> co
}

if (projCtx.isThombstone()) {
if (shouldKeepThombstone(projCtx)) {
// Let's keep thombstones linked until they expire. So we do not have shadows without owners.
// This is also needed for async delete operations.
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.KEEP);
} else {
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.UNLINK);
LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.UNLINK);
}
// Let's keep thombstones linked until they expire. So we do not have shadows without owners.
// This is also needed for async delete operations.
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.KEEP);
return;
}

Expand Down Expand Up @@ -334,18 +329,6 @@ public <F extends FocusType> void processActivationUserCurrent(LensContext<F> co

}

private boolean shouldKeepThombstone(LensProjectionContext projCtx) {
PrismObject<ShadowType> objectCurrent = projCtx.getObjectCurrent();
if (objectCurrent != null) {
ShadowType objectCurrentType = objectCurrent.asObjectable();
if (!objectCurrentType.getPendingOperation().isEmpty()) {
return true;
}
}
// TODO: thombstone expiration
return false;
}

public <F extends FocusType> void processActivationMetadata(LensContext<F> context, LensProjectionContext accCtx,
XMLGregorianCalendar now, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException {
ObjectDelta<ShadowType> projDelta = accCtx.getDelta();
Expand Down

Large diffs are not rendered by default.

Expand Up @@ -997,28 +997,30 @@ public void test120RecomputeWillAfter5min() throws Exception {
displayThen(TEST_NAME);
assertSuccess(result);

PrismObject<ShadowType> shadowRepo = repositoryService.getObject(ShadowType.class, accountWillOid, null, result);
display("Repo shadow", shadowRepo);
assertSinglePendingOperation(shadowRepo,
accountWillReqestTimestampStart, accountWillReqestTimestampEnd,
OperationResultStatusType.SUCCESS,
accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);

PrismObject<ShadowType> shadowModel = modelService.getObject(ShadowType.class,
accountWillOid, null, task, result);

PendingOperationType pendingOperation = assertSinglePendingOperation(shadowModel,
accountWillReqestTimestampStart, accountWillReqestTimestampEnd,
OperationResultStatusType.SUCCESS,
accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);
assertRepoShadow(accountWillOid)
.pendingOperations()
.singleOperation()
.assertRequestTimestamp(accountWillReqestTimestampStart, accountWillReqestTimestampEnd)
.assertExecutionStatus(PendingOperationExecutionStatusType.COMPLETED)
.assertResultStatus(OperationResultStatusType.SUCCESS)
.assertCompletionTimestamp(accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);

assertModelShadow(accountWillOid)
.pendingOperations()
.singleOperation()
.assertRequestTimestamp(accountWillReqestTimestampStart, accountWillReqestTimestampEnd)
.assertExecutionStatus(PendingOperationExecutionStatusType.COMPLETED)
.assertResultStatus(OperationResultStatusType.SUCCESS)
.assertCompletionTimestamp(accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);

assertCase(willLastCaseOid, SchemaConstants.CASE_STATE_CLOSED);

assertSteadyResources();
}

/**
* ff 20min, grace should expire
* ff 20min, grace should expire. But operation is still kept in the shadow.
* Retention period is longer.
*/
@Test
public void test130RecomputeWillAfter25min() throws Exception {
Expand All @@ -1038,13 +1040,56 @@ public void test130RecomputeWillAfter25min() throws Exception {
displayThen(TEST_NAME);
assertSuccess(result);

PrismObject<ShadowType> shadowRepo = repositoryService.getObject(ShadowType.class, accountWillOid, null, result);
display("Repo shadow", shadowRepo);
assertNoPendingOperation(shadowRepo);
assertRepoShadow(accountWillOid)
.pendingOperations()
.singleOperation()
.assertRequestTimestamp(accountWillReqestTimestampStart, accountWillReqestTimestampEnd)
.assertExecutionStatus(PendingOperationExecutionStatusType.COMPLETED)
.assertResultStatus(OperationResultStatusType.SUCCESS)
.assertCompletionTimestamp(accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);

assertModelShadow(accountWillOid)
.pendingOperations()
.singleOperation()
.assertRequestTimestamp(accountWillReqestTimestampStart, accountWillReqestTimestampEnd)
.assertExecutionStatus(PendingOperationExecutionStatusType.COMPLETED)
.assertResultStatus(OperationResultStatusType.SUCCESS)
.assertCompletionTimestamp(accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);

PrismObject<ShadowType> shadowModel = modelService.getObject(ShadowType.class,
accountWillOid, null, task, result);
assertNoPendingOperation(shadowModel);
assertCase(willLastCaseOid, SchemaConstants.CASE_STATE_CLOSED);

assertSteadyResources();
}

/**
* ff 7min, pending operation retention period is over.
* Pending operations should be gone.
*/
@Test
public void test132RecomputeWillAfter32min() throws Exception {
final String TEST_NAME = "test132RecomputeWillAfter32min";
displayTestTitle(TEST_NAME);
// GIVEN
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

clockForward("PT7M");

// WHEN
displayWhen(TEST_NAME);
recomputeUser(userWillOid, task, result);

// THEN
displayThen(TEST_NAME);
assertSuccess(result);

assertRepoShadow(accountWillOid)
.pendingOperations()
.assertNone();

assertModelShadow(accountWillOid)
.pendingOperations()
.assertNone();

assertCase(willLastCaseOid, SchemaConstants.CASE_STATE_CLOSED);

Expand Down
Expand Up @@ -129,6 +129,7 @@
<consistency>
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<reshreshOnRead>true</reshreshOnRead>
<connectorErrorCriticality>
<network>false</network>
<schema>false</schema>
Expand Down
Expand Up @@ -166,6 +166,7 @@
<consistency>
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

</resource>
Expand Up @@ -130,6 +130,7 @@
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<operationGroupingInterval>PT2M</operationGroupingInterval>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

</resource>
Expand Up @@ -129,6 +129,9 @@
<consistency>
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<pendingOperationRetentionPeriod>PT30M</pendingOperationRetentionPeriod>
<deadShadowRetentionPeriod>PT2H</deadShadowRetentionPeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

</resource>
Expand Up @@ -177,6 +177,7 @@
<recordPendingOperations>all</recordPendingOperations>
<avoidDuplicateOperations>true</avoidDuplicateOperations>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -200,6 +200,7 @@
<avoidDuplicateValues>true</avoidDuplicateValues>
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -158,6 +158,7 @@
<avoidDuplicateValues>true</avoidDuplicateValues>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<operationGroupingInterval>PT2M</operationGroupingInterval>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -152,6 +152,7 @@
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<operationGroupingInterval>PT2M</operationGroupingInterval>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -149,6 +149,7 @@
<recordPendingOperations>all</recordPendingOperations>
<avoidDuplicateOperations>true</avoidDuplicateOperations>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -146,6 +146,9 @@
<consistency>
<shadowConstraintsCheck>light</shadowConstraintsCheck>
<pendingOperationGracePeriod>PT15M</pendingOperationGracePeriod>
<pendingOperationRetentionPeriod>PT30M</pendingOperationRetentionPeriod>
<deadShadowRetentionPeriod>PT2H</deadShadowRetentionPeriod>
<reshreshOnRead>true</reshreshOnRead>
</consistency>

<synchronization>
Expand Down
Expand Up @@ -124,6 +124,7 @@
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ObjectDeltaOperation;
import com.evolveum.midpoint.schema.PointInTimeType;
import com.evolveum.midpoint.schema.RepositoryDiag;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.SearchResultList;
Expand Down Expand Up @@ -162,6 +163,7 @@
import com.evolveum.midpoint.test.IntegrationTestTools;
import com.evolveum.midpoint.test.asserter.DummyAccountAsserter;
import com.evolveum.midpoint.test.asserter.FocusAsserter;
import com.evolveum.midpoint.test.asserter.ShadowAsserter;
import com.evolveum.midpoint.test.asserter.UserAsserter;
import com.evolveum.midpoint.test.util.MidPointAsserts;
import com.evolveum.midpoint.test.util.TestUtil;
Expand Down Expand Up @@ -1558,26 +1560,28 @@ protected Collection<PrismObject<ShadowType>> listAccounts(PrismObject<ResourceT
}

protected PrismObject<ShadowType> getShadowModel(String accountOid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
return getShadowModel(accountOid, false, true);
return getShadowModel(accountOid, null, true);
}

protected PrismObject<ShadowType> getShadowModelNoFetch(String accountOid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
return getShadowModel(accountOid, true, true);
return getShadowModel(accountOid, GetOperationOptions.createNoFetch(), true);
}

protected PrismObject<ShadowType> getShadowModel(String accountOid, boolean noFetch, boolean assertSuccess) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
Task task = taskManager.createTaskInstance(AbstractModelIntegrationTest.class.getName() + ".getAccount");

protected PrismObject<ShadowType> getShadowModelFuture(String accountOid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
return getShadowModel(accountOid, GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE), true);
}

protected PrismObject<ShadowType> getShadowModel(String accountOid, GetOperationOptions rootOptions, boolean assertSuccess) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
Task task = taskManager.createTaskInstance(AbstractModelIntegrationTest.class.getName() + ".getShadowModel");
OperationResult result = task.getResult();
Collection<SelectorOptions<GetOperationOptions>> opts = null;
if (noFetch) {
GetOperationOptions rootOpts = new GetOperationOptions();
rootOpts.setNoFetch(true);
opts = SelectorOptions.createCollection(rootOpts);
if (rootOptions != null) {
opts = SelectorOptions.createCollection(rootOptions);
}
PrismObject<ShadowType> account = modelService.getObject(ShadowType.class, accountOid, opts , task, result);
result.computeStatus();
if (assertSuccess) {
TestUtil.assertSuccess("getObject(Account) result not success", result);
TestUtil.assertSuccess("getObject(shadow) result not success", result);
}
return account;
}
Expand Down Expand Up @@ -1668,7 +1672,7 @@ protected <F extends FocusType> PrismReferenceValue getLinkRef(PrismObject<F> fo
for (ObjectReferenceType linkRefType: focusType.getLinkRef()) {
String linkTargetOid = linkRefType.getOid();
assertFalse("No linkRef oid", StringUtils.isBlank(linkTargetOid));
PrismObject<ShadowType> account = getShadowModel(linkTargetOid, true, false);
PrismObject<ShadowType> account = getShadowModel(linkTargetOid, GetOperationOptions.createNoFetch(), false);
if (resourceOid.equals(account.asObjectable().getResourceRef().getOid())) {
// This is noFetch. Therefore there is no fetchResult
return linkRefType.asReferenceValue();
Expand All @@ -1683,7 +1687,7 @@ protected <F extends FocusType> String getLinkRefOid(PrismObject<F> focus, Strin
for (ObjectReferenceType linkRefType: focusType.getLinkRef()) {
String linkTargetOid = linkRefType.getOid();
assertFalse("No linkRef oid", StringUtils.isBlank(linkTargetOid));
PrismObject<ShadowType> account = getShadowModel(linkTargetOid, true, false);
PrismObject<ShadowType> account = getShadowModel(linkTargetOid, GetOperationOptions.createNoFetch(), false);
ShadowType shadowType = account.asObjectable();
if (kind != null && !kind.equals(shadowType.getKind())) {
continue;
Expand Down Expand Up @@ -5236,6 +5240,11 @@ protected PendingOperationType findPendingOperation(PrismObject<ShadowType> shad
}
return null;
}

protected void initializeAsserter(UserAsserter<Void> asserter) {
asserter.setPrismContext(prismContext);
asserter.setObjectResolver(repoObjectResolver);
}

protected UserAsserter<Void> assertUserAfter(String oid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
UserAsserter<Void> asserter = assertUser(oid, "after");
Expand All @@ -5261,15 +5270,43 @@ protected UserAsserter<Void> assertUserBeforeByUsername(String username) throws
protected UserAsserter<Void> assertUser(String oid, String message) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
PrismObject<UserType> user = getUser(oid);
UserAsserter<Void> asserter = UserAsserter.forUser(user, message);
asserter.setObjectResolver(repoObjectResolver);
initializeAsserter(asserter);
return asserter;
}

protected UserAsserter<Void> assertUserByUsername(String username, String message) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
PrismObject<UserType> user = findUserByUsername(username);
UserAsserter<Void> asserter = UserAsserter.forUser(user, message);
asserter.setObjectResolver(repoObjectResolver);
initializeAsserter(asserter);
return asserter;
}

protected ShadowAsserter<Void> assertModelShadow(String oid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
PrismObject<ShadowType> repoShadow = getShadowModel(oid);
ShadowAsserter<Void> asserter = ShadowAsserter.forShadow(repoShadow, "model");
asserter
.display();
return asserter;
}

protected ShadowAsserter<Void> assertModelShadowFuture(String oid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
PrismObject<ShadowType> repoShadow = getShadowModelFuture(oid);
ShadowAsserter<Void> asserter = ShadowAsserter.forShadow(repoShadow, "model(future)");
asserter
.display();
return asserter;
}

protected void assertNoModelShadow(String oid) throws SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
Task task = createTask("assertNoModelShadow");
OperationResult result = task.getResult();
try {
PrismObject<ShadowType> shadow = modelService.getObject(ShadowType.class, oid, null, task, result);
fail("Expected that shadow "+oid+" will not be in the model. But it was: "+shadow);
} catch (ObjectNotFoundException e) {
// Expected
assertFailure(result);
}
}

}

0 comments on commit 9fb5ef1

Please sign in to comment.