Skip to content

Commit

Permalink
Add a test for correlator failure
Browse files Browse the repository at this point in the history
Also created convenience method
AbstractModelIntegrationTest#initAndTestDummyResource (on
DummyTestResource).
  • Loading branch information
mederly committed Feb 24, 2022
1 parent bc09c7d commit 05a6cfc
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,19 @@ private static double getProcessingTime(Collection<ActivityItemProcessingStatist
*/
public static String getLastProcessedObjectName(ActivityItemProcessingStatisticsType info,
Predicate<ProcessedItemSetType> itemSetFilter) {
ProcessedItemType lastSuccess = getLastProcessedObject(info, itemSetFilter);
return lastSuccess != null ? lastSuccess.getName() : null;
ProcessedItemType last = getLastProcessedObject(info, itemSetFilter);
return last != null ? last.getName() : null;
}

/**
* Returns message about the item that was last processed by given task in item set defined by the filter.
*
* TODO this should operate on a tree!
*/
public static String getLastProcessedItemMessage(ActivityItemProcessingStatisticsType info,
Predicate<ProcessedItemSetType> itemSetFilter) {
ProcessedItemType last = getLastProcessedObject(info, itemSetFilter);
return last != null ? last.getMessage() : null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

import java.io.File;

import com.evolveum.midpoint.test.DummyTestResource;

import com.evolveum.midpoint.test.TestTask;

import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
Expand Down Expand Up @@ -41,12 +47,6 @@
import com.evolveum.midpoint.test.asserter.ShadowAsserter;
import com.evolveum.midpoint.test.asserter.UserAsserter;
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;

@ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
Expand All @@ -63,6 +63,12 @@ public class TestSynchronizationService extends AbstractInternalModelIntegration

private static final String INTENT_GROUP = "group";

private static final DummyTestResource RESOURCE_DUMMY_BROKEN =
new DummyTestResource(TEST_DIR, "resource-dummy-broken.xml", "ba2099e5-7c6b-4742-a13a-0cbc476aeb01", "broken");

private static final TestTask TASK_IMPORT_DUMMY_BROKEN =
new TestTask(TEST_DIR, "task-import-dummy-broken.xml", "826071d1-5f8b-4d44-af0a-f0e7970f01a4");

@Autowired SynchronizationService synchronizationService;
@Autowired Clockwork clockwork;
@Autowired ClockworkMedic clockworkMedic;
Expand All @@ -81,6 +87,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti

initDummyResourcePirate(RESOURCE_DUMMY_LIMITED_NAME,
RESOURCE_DUMMY_LIMITED_FILE, RESOURCE_DUMMY_LIMITED_OID, initTask, initResult);

initAndTestDummyResource(RESOURCE_DUMMY_BROKEN, initTask, initResult);
}

@Test
Expand Down Expand Up @@ -995,6 +1003,40 @@ public void test300AddedGroupPirates() throws Exception {

}

@Test
public void test400BrokenCorrelator() throws Exception {
given("dummy account exists on a resource with broken correlator");
Task task = getTestTask();
OperationResult result = task.getResult();

String accountName = "test400";
RESOURCE_DUMMY_BROKEN.controller.addAccount(accountName);

when("import task is run");
TASK_IMPORT_DUMMY_BROKEN.initialize(this, task, result);
waitForTaskCloseOrSuspend(TASK_IMPORT_DUMMY_BROKEN.oid, 20000);

then("error is correctly recorded both in task and in shadow");

// Adapt this if the details of error handling in synchronization service are changed.
String expectedMessage = "Error occurred during resource object shadow owner lookup, reason: Circuit is broken";

TASK_IMPORT_DUMMY_BROKEN.assertAfter()
.rootActivityState()
.progress()
.assertCommitted(0, 1, 0)
.end()
.itemProcessingStatistics()
.assertTotalCounts(0, 1, 0)
.assertLastFailureObjectName(accountName)
.assertLastFailureMessage(expectedMessage);

PrismObject<ShadowType> shadow = findShadowByPrismName(accountName, RESOURCE_DUMMY_BROKEN.getResource(), result);
assertShadowAfter(shadow)
.assertCorrelationSituation(CorrelationSituationType.ERROR)
.assertHasComplexOperationExecutionFailureWithMessage(TASK_IMPORT_DUMMY_BROKEN.oid, expectedMessage);
}

private void setDebugListener() {
mockListener = new MockLensDebugListener();
DiagnosticContextManager manager = new DiagnosticContextManager() {
Expand Down
95 changes: 95 additions & 0 deletions model/model-impl/src/test/resources/sync/resource-dummy-broken.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2018 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<resource oid="ba2099e5-7c6b-4742-a13a-0cbc476aeb01"
xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3">

<name>resource-dummy-broken</name>
<description>Dummy resource with broken correlation</description>
<connectorRef type="c:ConnectorType">
<filter>
<q:and>
<q:equal>
<q:path>connectorType</q:path>
<q:value>com.evolveum.icf.dummy.connector.DummyConnector</q:value>
</q:equal>
<q:equal>
<q:path>connectorVersion</q:path>
<q:value>2.0</q:value>
</q:equal>
</q:and>
</filter>
</connectorRef>
<connectorConfiguration xmlns:icfi="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.icf.dummy/com.evolveum.icf.dummy.connector.DummyConnector"
xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">

<icfc:configurationProperties>
<icfi:instanceId>broken</icfi:instanceId>
</icfc:configurationProperties>

</connectorConfiguration>

<schemaHandling>
<objectType>
<kind>account</kind>
<intent>default</intent>
<displayName>Default Account</displayName>
<default>true</default>
<objectClass>ri:AccountObjectClass</objectClass>
</objectType>
</schemaHandling>

<synchronization>
<objectSynchronization>
<objectClass>ri:AccountObjectClass</objectClass>
<kind>account</kind>
<intent>default</intent>
<correlationDefinition>
<correlators>
<expression>
<documentation>All requests are rejected because the network service is down.</documentation>
<owner>
<script>
<code>
import com.evolveum.midpoint.util.exception.CommunicationException

throw new CommunicationException('Circuit is broken')
</code>
</script>
</owner>
</expression>
</correlators>
</correlationDefinition>
<reaction>
<situation>linked</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>deleted</situation>
<synchronize>true</synchronize>
</reaction>
<reaction>
<situation>unlinked</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#link</handlerUri>
</action>
</reaction>
<reaction>
<situation>unmatched</situation>
<synchronize>true</synchronize>
<action>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus</handlerUri>
</action>
</reaction>
</objectSynchronization>
</synchronization>
</resource>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!--
~ Copyright (C) 2010-2022 Evolveum and contributors
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
-->

<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="826071d1-5f8b-4d44-af0a-f0e7970f01a4">
<name>import-dummy-broken</name>
<ownerRef oid="00000000-0000-0000-0000-000000000002" type="UserType" />
<executionState>runnable</executionState>
<activity>
<work>
<import>
<resourceObjects>
<resourceRef oid="ba2099e5-7c6b-4742-a13a-0cbc476aeb01"/>
<kind>account</kind>
<intent>default</intent>
</resourceObjects>
</import>
</work>
</activity>
</task>
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,15 @@ public DummyResourceContoller initDummyResource(DummyTestResource resource, Task
return resource.controller;
}

public DummyResourceContoller initAndTestDummyResource(DummyTestResource resource, Task task, OperationResult result)
throws Exception {
resource.controller = dummyResourceCollection.initDummyResource(
resource.name, resource.file, resource.oid, resource.controllerInitLambda, task, result);
modelService.testResource(resource.controller.getResource().getOid(), task);
resource.reload(result); // To have schema, etc
return resource.controller;
}

protected DummyResourceContoller initDummyResource(String name, File resourceFile, String resourceOid,
Task task, OperationResult result) throws Exception {
return dummyResourceCollection.initDummyResource(name, resourceFile, resourceOid, null, task, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@

package com.evolveum.midpoint.test;

import java.io.File;
import java.io.IOException;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.FailableProcessor;
import com.evolveum.midpoint.util.annotation.Experimental;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;

import java.io.File;

/**
* Representation of Dummy Resource in tests.
*/
Expand All @@ -34,6 +38,12 @@ public DummyTestResource(File dir, String fileName, String oid, String name, Fai
this.controllerInitLambda = controllerInitLambda;
}

@Override
public void reload(OperationResult result) throws SchemaException, IOException, ObjectNotFoundException {
super.reload(result);
controller.setResource(getObject());
}

public PrismObject<ResourceType> getResource() {
return controller.getResource();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public TestTask(@NotNull File dir, @NotNull String fileName, @NotNull String oid
}

/**
* Initializes the task.
* Initializes the task - i.e. imports it into repository (via model).
* This may or may not start the task, depending on the execution state in the file.
*
* @param test To provide access to necessary functionality. Temporary!
*/
Expand All @@ -71,6 +72,7 @@ public void rerun(OperationResult result) throws CommonException {
}

public TaskAsserter<Void> assertAfter() throws SchemaException, ObjectNotFoundException {
return test.assertTask(oid, "after");
return test.assertTask(oid, "after")
.display();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public ActivityItemProcessingStatisticsAsserter<RA> assertLastFailureObjectName(
return this;
}

public ActivityItemProcessingStatisticsAsserter<RA> assertLastFailureMessage(String expected) {
assertEquals("Wrong 'last failure' message", expected, getLastFailedItemMessage());
return this;
}

@Override
protected String desc() {
return getDetails();
Expand Down Expand Up @@ -128,4 +133,9 @@ private String getLastSuccessObjectOid() {
private String getLastFailedObjectName() {
return ActivityItemProcessingStatisticsUtil.getLastProcessedObjectName(information, OutcomeKeyedCounterTypeUtil::isFailure);
}

private String getLastFailedItemMessage() {
return ActivityItemProcessingStatisticsUtil.getLastProcessedItemMessage(
information, OutcomeKeyedCounterTypeUtil::isFailure);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,17 @@ public ShadowAsserter<RA> assertHasMatchRequestId() throws SchemaException {
return MiscUtil.castSafely(
getCorrelatorStateRequired(), IdMatchCorrelatorStateType.class);
}

/**
* Temporary: until correlation state asserter is implemented.
*/
public ShadowAsserter<RA> assertCorrelationSituation(CorrelationSituationType expected) {
assertThat(getCorrelationSituation()).as("correlation situation").isEqualTo(expected);
return this;
}

private CorrelationSituationType getCorrelationSituation() {
ShadowCorrelationStateType correlation = getObjectable().getCorrelation();
return correlation != null ? correlation.getSituation() : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,21 @@ public PrismObjectAsserter<O, RA> assertHasComplexOperationExecution(String task
throw new AssertionError("No complex operation execution record for task OID " + taskOid + " and status " + status);
}

/**
* Preliminary test method (until full operation execution asserter is created).
*/
public PrismObjectAsserter<O, RA> assertHasComplexOperationExecutionFailureWithMessage(String taskOid, String message) {
for (OperationExecutionType record : getObjectable().getOperationExecution()) {
if (matches(record, OperationExecutionRecordTypeType.COMPLEX, taskOid, OperationResultStatusType.FATAL_ERROR)
&& message.equals(record.getMessage())) {
assertRecordSanity(record);
return this;
}
}
throw new AssertionError("No complex operation execution record for task OID "
+ taskOid + " and status FATAL_ERROR with message " + message);
}

// TEMPORARY! TODO Create OperationExecutionAsserter
private void assertRecordSanity(OperationExecutionType record) {
if (isError(record.getStatus())) {
Expand Down

0 comments on commit 05a6cfc

Please sign in to comment.