Skip to content

Commit

Permalink
referenceSearch: added more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Jan 18, 2023
1 parent d3ae1a4 commit a0b844e
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,7 @@ public SearchResultList<ObjectReferenceType> searchReferences(
throw new UnsupportedOperationException("Invalid filter for reference search: " + filter);
}

System.out.println("query = " + query);
// OwnedByFilter ownedByFilter = (OwnedByFilter) filter;

// TODO later this should be resolved from the ownedBy filter, starting with its type
SqaleQueryContext<ObjectReferenceType, QObjectReference<MObject>, MReference> queryContext =
SqaleQueryContext.from(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2022 Evolveum and contributors
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
Expand Down Expand Up @@ -54,10 +54,7 @@
import com.evolveum.midpoint.util.CheckedRunnable;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAttributesType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.query_3.QueryType;

@ContextConfiguration(locations = { "../../../../../ctx-test.xml" })
Expand Down Expand Up @@ -559,6 +556,32 @@ boolean record = !queryRecorder.isRecording();
}
}

@NotNull
protected final SearchResultList<ObjectReferenceType> searchReferences(
ObjectQuery query,
OperationResult operationResult,
Collection<SelectorOptions<GetOperationOptions>> selectorOptions)
throws SchemaException {
try {
displayQuery(query);
} catch (SchemaException e) {
// TODO fix problem with parsing . path and remove this catch
display("Cannot parse query? " + e);
}
boolean record = !queryRecorder.isRecording();
if (record) {
queryRecorder.clearBufferAndStartRecording();
}
try {
return repositoryService.searchReferences(query, selectorOptions, operationResult);
} finally {
if (record) {
queryRecorder.stopRecording();
display(queryRecorder.dumpQueryBuffer());
}
}
}

/** Displays the query in XML and Axiom form and checks its XML reparsability. */
protected void displayQuery(@Nullable ObjectQuery query) throws SchemaException {
display("QUERY: " + query);
Expand All @@ -567,10 +590,10 @@ protected void displayQuery(@Nullable ObjectQuery query) throws SchemaException
}
String serializedQuery = null;
try {
QueryType queryType = prismContext.getQueryConverter().createQueryType(query);
serializedQuery = prismContext.xmlSerializer().serializeAnyData(
queryType, SchemaConstants.MODEL_EXTENSION_OBJECT_QUERY);
display("Serialized QUERY: " + serializedQuery);
QueryType queryType = prismContext.getQueryConverter().createQueryType(query);
serializedQuery = prismContext.xmlSerializer().serializeAnyData(
queryType, SchemaConstants.MODEL_EXTENSION_OBJECT_QUERY);
display("Serialized QUERY: " + serializedQuery);
} catch (Exception e) {
display("Can not serialize query");
}
Expand All @@ -584,9 +607,9 @@ protected void displayQuery(@Nullable ObjectQuery query) throws SchemaException
}

// sanity check if it's re-parsable
if (serializedQuery != null) {
if (serializedQuery != null) {
assertThat(prismContext.parserFor(serializedQuery).parseRealValue(QueryType.class))
.isNotNull();
.isNotNull();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;

import org.jetbrains.annotations.Nullable;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
Expand All @@ -57,6 +55,7 @@
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
Expand Down Expand Up @@ -88,6 +87,8 @@ public class SqaleRepoSearchTest extends SqaleRepoBaseTest {
private String connector1Oid;
private String connector2Oid;
private String roleAvIOid; // role for assignment-vs-inducement tests
private String roleOtherOid;
private String roleOneMoreOid;

// other info used in queries
private final QName relation1 = QName.valueOf("{https://random.org/ns}rel-1");
Expand All @@ -110,10 +111,10 @@ public void initObjects() throws Exception {
.lifecycleState("role-ind-lc"))
.asPrismObject(), null, result);

String roleOtherOid = repositoryService.addObject(
roleOtherOid = repositoryService.addObject(
new RoleType().name("role-other")
.asPrismObject(), null, result);
String roleOneMoreOid = repositoryService.addObject(
roleOneMoreOid = repositoryService.addObject(
new RoleType().name("role-one-more")
.asPrismObject(), null, result);

Expand Down Expand Up @@ -243,7 +244,7 @@ public void initObjects() throws Exception {
.taskRef(task1Oid, TaskType.COMPLEX_TYPE)
.status(OperationResultStatusType.SUCCESS)
.timestamp("2021-10-01T00:00:00Z"))
.roleMembershipRef(testRefWithMetadata(roleOtherOid, RoleType.COMPLEX_TYPE, relation2))
.roleMembershipRef(createTestRefWithMetadata(roleOtherOid, RoleType.COMPLEX_TYPE, relation2))
.extension(new ExtensionType());
ExtensionType user1Extension = user1.getExtension();
addExtensionValue(user1Extension, "string", "string-value");
Expand Down Expand Up @@ -371,7 +372,7 @@ public void initObjects() throws Exception {
.organization("org-2")
.organizationalUnit("ou-1")
.organizationalUnit("ou-2")
.roleMembershipRef(testRefWithMetadata(
.roleMembershipRef(createTestRefWithMetadata(
roleOneMoreOid, RoleType.COMPLEX_TYPE, ORG_DEFAULT))
.asPrismObject(),
null, result);
Expand Down Expand Up @@ -480,7 +481,8 @@ public void initObjects() throws Exception {
assertThatOperationResult(result).isSuccess();
}

private ObjectReferenceType testRefWithMetadata(String targetOid, QName targetType, QName relation) throws SchemaException {
private ObjectReferenceType createTestRefWithMetadata(
String targetOid, QName targetType, QName relation) throws SchemaException {
ObjectReferenceType ref = new ObjectReferenceType()
.oid(targetOid)
.type(targetType)
Expand Down Expand Up @@ -2454,51 +2456,61 @@ public void test760SearchUsersWithRightHandReferencedPath() {
// endregion

// region reference search
@Test // TODO disable if not finished before merging
public void test800SearchReference() {
@Test
public void test800SearchReference() throws SchemaException {
when("searching role membership references to roles with specified relation");
OperationResult operationResult = createOperationResult();
queryRecorder.clearBufferAndStartRecording();

try {
ObjectQuery refQuery = prismContext.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
.and()
.item(ItemPath.SELF_PATH).ref(null, RoleType.COMPLEX_TYPE, relation2)
.build();
// orgXOid, org11Oid have user2 as a member
SearchResultList<ObjectReferenceType> result =
repositoryService.searchReferences(refQuery, null, operationResult);
// TODO asserts incl. metadata check
System.out.println("result = " + result);
} finally {
queryRecorder.stopRecording();
display(queryRecorder.dumpQueryBuffer());
}
}

@Test // TODO disable if not finished before merging
public void test801SearchReferenceWithImpliedDefaultRelation() {
ObjectQuery refQuery = prismContext.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
.and()
.item(ItemPath.SELF_PATH).ref(null, RoleType.COMPLEX_TYPE, relation2)
.build();
SearchResultList<ObjectReferenceType> result = searchReferences(refQuery, operationResult, null);

then("operation is success and expected refs are returned");
assertThatOperationResult(operationResult).isSuccess();
assertThat(result)
.hasSize(2)
.anyMatch(r -> refMatches(r, user1Oid, roleOtherOid, relation2))
.anyMatch(r -> refMatches(r, user3Oid, roleAvIOid, relation2));
// TODO metadata check
}

@Test
public void test801SearchReferenceWithImpliedDefaultRelation() throws SchemaException {
when("searching role membership references to roles with default relation");
OperationResult operationResult = createOperationResult();
queryRecorder.clearBufferAndStartRecording();
ObjectQuery refQuery = prismContext.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
.and()
.item(ItemPath.SELF_PATH).ref(null, RoleType.COMPLEX_TYPE) // no relation => default
.build();
SearchResultList<ObjectReferenceType> result = searchReferences(refQuery, operationResult, null);

try {
ObjectQuery refQuery = prismContext.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
.and()
.item(ItemPath.SELF_PATH).ref(null, RoleType.COMPLEX_TYPE) // no relation => default
.build();
// orgXOid, org11Oid have user2 as a member
SearchResultList<ObjectReferenceType> result =
repositoryService.searchReferences(refQuery, null, operationResult);
// TODO asserts
} finally {
queryRecorder.stopRecording();
display(queryRecorder.dumpQueryBuffer());
}
then("expected ref is returned");
assertThat(result)
.hasSize(1)
.anyMatch(r -> refMatches(r, user4Oid, roleOneMoreOid, ORG_DEFAULT));
}

// TODO test with relation is null behavior
@Test
public void test802SearchReferenceWithAnyRelation() throws SchemaException {
when("searching role membership references to roles with any relation");
OperationResult operationResult = createOperationResult();
ObjectQuery refQuery = prismContext.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
.and()
.item(ItemPath.SELF_PATH).ref(null, RoleType.COMPLEX_TYPE, Q_ANY) // any relation
.build();
SearchResultList<ObjectReferenceType> result = searchReferences(refQuery, operationResult, null);

then("expected refs are returned");
assertThat(result)
.hasSize(3)
.anyMatch(r -> refMatches(r, user1Oid, roleOtherOid, relation2))
.anyMatch(r -> refMatches(r, user3Oid, roleAvIOid, relation2))
.anyMatch(r -> refMatches(r, user4Oid, roleOneMoreOid, ORG_DEFAULT));
}

@Test
public void test819SearchReferenceFailsOnWrongTopLevelPath() {
public void test819ReferenceQueryFailsOnWrongTopLevelPath() {
assertThatThrownBy(
() -> prismContext
.queryForReferenceOwnedBy(UserType.class, UserType.F_ROLE_MEMBERSHIP_REF)
Expand Down Expand Up @@ -2982,4 +2994,12 @@ public void test999MultipleOrdersAreSupportedByFluentApiAndRepository() throws S
.containsExactly(user2Oid, user3Oid, user1Oid, creatorOid, modifierOid, user4Oid);
}
// endregion

private boolean refMatches(ObjectReferenceType ref,
@Nullable String ownerOid, String targetOid, QName relation) {
PrismObject<?> parentObject = PrismValueUtil.getParentObject(ref.asReferenceValue());
return (ownerOid == null || parentObject != null && parentObject.getOid().equals(ownerOid))
&& ref.getOid().equals(targetOid)
&& QNameUtil.match(ref.getRelation(), relation);
}
}

0 comments on commit a0b844e

Please sign in to comment.