![JAR search and dependency download from the Maven repository](/logo.png)
org.identityconnectors.contract.test.SchemaApiOpTests Maven / Gradle / Ivy
The newest version!
/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
* ====================
* Portions Copyrighted 2018 ConnId
*/
package org.identityconnectors.contract.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.identityconnectors.common.CollectionUtil;
import org.identityconnectors.contract.exceptions.ObjectNotFoundException;
import org.identityconnectors.framework.api.operations.APIOperation;
import org.identityconnectors.framework.api.operations.SchemaApiOp;
import org.identityconnectors.framework.api.operations.ScriptOnConnectorApiOp;
import org.identityconnectors.framework.api.operations.ScriptOnResourceApiOp;
import org.identityconnectors.framework.api.operations.TestApiOp;
import org.identityconnectors.framework.api.operations.ValidateApiOp;
import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeInfoUtil;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.common.objects.ObjectClassInfo;
import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.Uid;
import org.junit.jupiter.api.Test;
/**
* Contract test of {@link SchemaApiOp} operation.
*
* @author Zdenek Louzensky
*/
public class SchemaApiOpTests extends ContractTestBase {
public static final String TEST_NAME = "Schema";
/*
* Properties prefixes:
* it's added .testsuite.${type.name} after the prefix
*/
private static final String SUPPORTED_OBJECT_CLASSES_PROPERTY_PREFIX = "oclasses";
private static final String SUPPORTED_OPERATIONS_PROPERTY_PREFIX = "operations";
private static final String STRICT_CHECK_PROPERTY_PREFIX = "strictCheck";
/*
* AttributeInfo field names used in property configuration:
*/
private static final String ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT = "returnedByDefault";
private static final String ATTRIBUTE_FIELD_MULTI_VALUE = "multiValue";
private static final String ATTRIBUTE_FIELD_REQUIRED = "required";
private static final String ATTRIBUTE_FIELD_CREATEABLE = "createable";
private static final String ATTRIBUTE_FIELD_UPDATEABLE = "updateable";
private static final String ATTRIBUTE_FILED_READABLE = "readable";
private static final String ATTRIBUTE_FIELD_TYPE = "type";
/**
* {@inheritDoc}
*/
@Override
public Set> getAPIOperations() {
Set> s = new HashSet<>();
// list of required operations by this test:
s.add(SchemaApiOp.class);
return s;
}
/**
* Tests that the schema doesn't contain {@link Uid}
*/
@Test
public void testUidNotPresent() {
final Schema schema = getConnectorFacade().schema();
Set ocInfos = schema.getObjectClassInfo();
ocInfos.stream().map((ocInfo) -> ocInfo.getAttributeInfo()).
forEachOrdered(attInfos -> {
attInfos.forEach((attInfo) -> {
//ensure there is not Uid present
assertTrue(!attInfo.is(Uid.NAME), "Uid can't be present in connector Schema!");
});
});
}
/**
* Tests that every object class contains {@link Name} among its attributes.
*/
@Test
public void testNamePresent() {
final Schema schema = getConnectorFacade().schema();
Set ocInfos = schema.getObjectClassInfo();
ocInfos.forEach((ocInfo) -> {
Set attInfos = ocInfo.getAttributeInfo();
// ensure there is NAME present
boolean found = attInfos.stream().anyMatch(attInfo -> attInfo.is(Name.NAME));
final String msg = "Name is not present among attributes of object class '%s'.";
assertTrue(found, String.format(msg, ocInfo.getType()));
});
}
/**
* List of all operations which must be supported by all object classes when
* supported at all.
*/
private static final List> OP_SUPPORTED_BY_ALL_OCLASSES =
new LinkedList>();
static {
OP_SUPPORTED_BY_ALL_OCLASSES.add(ScriptOnConnectorApiOp.class);
OP_SUPPORTED_BY_ALL_OCLASSES.add(ScriptOnResourceApiOp.class);
OP_SUPPORTED_BY_ALL_OCLASSES.add(TestApiOp.class);
OP_SUPPORTED_BY_ALL_OCLASSES.add(ValidateApiOp.class);
}
/**
* Test ensures that following operations are supported by all object
* classes when supported at all: ScriptOnConnectorApiOp, ScriptOnResourceApiOp,
* TestApiOp, ValidateApiOp.
*/
@Test
public void testOpSupportedByAllOClasses() {
final Schema schema = getConnectorFacade().schema();
Set ocInfos = schema.getObjectClassInfo();
OP_SUPPORTED_BY_ALL_OCLASSES.forEach((apiOp) -> {
Set suppOClasses = schema.getSupportedObjectClassesByOperation(apiOp);
if (!suppOClasses.isEmpty()) {
// operation is supported for at least one object class
// then it must be supported for all object classes
final String MSG =
"Operation %s must be in the schema supported by all object classes which supports connector.";
assertTrue(CollectionUtil.equals(suppOClasses, ocInfos), String.format(MSG, apiOp));
}
});
}
/**
* Tests that returned schema by connector is the same as expected schema to
* be returned.
*/
@Test
public void testSchemaExpected() {
final Schema schema = getConnectorFacade().schema();
String msg = null;
Boolean strictCheck = getStrictCheckProperty();
// list of expected object classes
@SuppressWarnings("unchecked")
List expOClasses = (List) getTestPropertyOrFail(List.class.getName(),
SUPPORTED_OBJECT_CLASSES_PROPERTY_PREFIX, true);
List testedOClasses = new ArrayList<>();
// iterate over object classes and check that were expected and check
// their attributes
for (ObjectClassInfo ocInfo : schema.getObjectClassInfo()) {
boolean expected = expOClasses.contains(ocInfo.getType());
if (strictCheck) {
msg = "Schema returned object class %s that is not expected to be suported.";
assertTrue(expected, String.format(msg, ocInfo.getType()));
} else if (!expected) {
// this object class was not expected, and we are not checking strictly,
// so skip this object class
continue;
}
testedOClasses.add(ocInfo.getType());
// list of expected attributes for the object class
@SuppressWarnings("unchecked")
List expAttrs = (List) getTestPropertyOrFail(List.class.getName(),
"attributes." + ocInfo.getType() + "."
+ SUPPORTED_OBJECT_CLASSES_PROPERTY_PREFIX, strictCheck);
// check object class attributes
for (AttributeInfo attr : ocInfo.getAttributeInfo()) {
if (strictCheck) {
msg = "Object class %s contains unexpected attribute: %s.";
assertTrue(expAttrs.contains(attr.getName()), String.format(
msg, ocInfo.getType(), attr.getName()));
}
// expected attribute values
@SuppressWarnings("unchecked")
Map expAttrValues = (Map) getTestPropertyOrFail(
Map.class.getName(), attr.getName() + ".attribute." + ocInfo.getType()
+ "." + SUPPORTED_OBJECT_CLASSES_PROPERTY_PREFIX, strictCheck);
// check attribute's values in case the test is strict or property is provided
if (strictCheck || expAttrValues != null) {
// check all attribute's fields
checkAttributeValues(ocInfo, attr, expAttrValues);
}
}
// check that all expected attributes are in schema
for (String expAttr : expAttrs) {
msg = "Schema doesn't contain expected attribute '%s' in object class '%s'.";
assertNotNull(AttributeInfoUtil.find(expAttr, ocInfo.getAttributeInfo()),
String.format(msg, expAttr, ocInfo.getType()));
}
}
Set notFoundOClasses = new HashSet<>(expOClasses);
notFoundOClasses.removeAll(testedOClasses);
if (!notFoundOClasses.isEmpty()) {
msg = "Schema did not contain expected object class %s.";
fail(String.format(msg, notFoundOClasses.iterator().next()));
}
// expected object classes supported by operations
@SuppressWarnings("unchecked")
Map> expOperations = (Map>) getTestPropertyOrFail(
Map.class.getName(), SUPPORTED_OPERATIONS_PROPERTY_PREFIX, true);
Map, Set> supportedOperations = schema
.getSupportedObjectClassesByOperation();
List testedOps = new ArrayList<>();
// iterate over operations
for (Class extends APIOperation> operation : supportedOperations.keySet()) {
boolean expectedOp = expOperations.containsKey(operation.getSimpleName());
if (strictCheck) {
msg = "Schema returned unexpected operation: %s.";
assertTrue(expectedOp, String.format(msg, operation.getSimpleName()));
} else if (!expectedOp) {
// this operation was not expected, and we are not checking strictly,
// so skip this operation
continue;
}
testedOps.add(operation.getSimpleName());
// expected object classes supported by the operation
List expOClassesForOp = expOperations.get(operation.getSimpleName());
assertNotNull(expOClassesForOp);
List testedOClassesForOp = new ArrayList<>();
for (ObjectClassInfo ocInfo : supportedOperations.get(operation)) {
boolean expectedOClassForOp = expOClassesForOp.contains(ocInfo.getType());
if (strictCheck) {
msg = "Operation %s supports unexpected object class: %s.";
assertTrue(expectedOClassForOp, String.format(msg, operation.getSimpleName(), ocInfo.getType()));
} else if (!expectedOClassForOp) {
// this object class was not expected for this operation, and we are not checking strictly,
// so skip this object class
continue;
}
testedOClassesForOp.add(ocInfo.getType());
}
Set notFoundOClassesForOp = new HashSet<>(expOClassesForOp);
notFoundOClassesForOp.removeAll(testedOClassesForOp);
if (!notFoundOClassesForOp.isEmpty()) {
msg = "Operation %s is not supported by object class %s.";
fail(String.format(msg, operation.getSimpleName(), notFoundOClassesForOp.iterator().next()));
}
}
Set notFoundOps = new HashSet<>(expOperations.keySet());
notFoundOps.removeAll(testedOps);
if (!notFoundOps.isEmpty()) {
msg = "Schema did not contain expected operation %s.";
fail(String.format(msg, notFoundOps.iterator().next()));
}
}
/**
* Checks that attribute values are the same as expectedValues.
*/
private void checkAttributeValues(ObjectClassInfo ocInfo, AttributeInfo attribute,
Map expectedValues) {
// check that all attributes are provided
String msg = "Missing property definition for field '%s' of attribute '" + attribute.getName()
+ "' in object class " + ocInfo.getType();
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_TYPE), String.format(msg, ATTRIBUTE_FIELD_TYPE));
assertNotNull(expectedValues.get(ATTRIBUTE_FILED_READABLE), String.format(msg, ATTRIBUTE_FILED_READABLE));
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_CREATEABLE), String.format(msg, ATTRIBUTE_FIELD_CREATEABLE));
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_UPDATEABLE), String.format(msg, ATTRIBUTE_FIELD_UPDATEABLE));
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_REQUIRED), String.format(msg, ATTRIBUTE_FIELD_REQUIRED));
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_MULTI_VALUE), String.format(msg, ATTRIBUTE_FIELD_MULTI_VALUE));
assertNotNull(expectedValues.get(ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT), String.format(msg,
ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT));
msg = "Object class '" + ocInfo.getType() + "', attribute '" + attribute.getName()
+ "': field '%s' expected value is '%s', but returned '%s'.";
assertEquals(attribute.getType(), expectedValues.get(ATTRIBUTE_FIELD_TYPE), String.format(msg,
ATTRIBUTE_FIELD_TYPE, expectedValues
.get(ATTRIBUTE_FIELD_TYPE), attribute.getType().getName()));
assertEquals(attribute.isReadable(), expectedValues.get(ATTRIBUTE_FILED_READABLE), String.format(msg,
ATTRIBUTE_FILED_READABLE, expectedValues
.get(ATTRIBUTE_FILED_READABLE), attribute.isReadable()));
assertEquals(attribute.isCreateable(), expectedValues.get(ATTRIBUTE_FIELD_CREATEABLE), String.format(msg,
ATTRIBUTE_FIELD_CREATEABLE, expectedValues
.get(ATTRIBUTE_FIELD_CREATEABLE), attribute.isCreateable()));
assertEquals(attribute.isUpdateable(), expectedValues.get(ATTRIBUTE_FIELD_UPDATEABLE), String.format(msg,
ATTRIBUTE_FIELD_UPDATEABLE, expectedValues
.get(ATTRIBUTE_FIELD_UPDATEABLE), attribute.isUpdateable()));
assertEquals(attribute.isRequired(), expectedValues.get(ATTRIBUTE_FIELD_REQUIRED), String.format(msg,
ATTRIBUTE_FIELD_REQUIRED, expectedValues
.get(ATTRIBUTE_FIELD_REQUIRED), attribute.isRequired()));
assertEquals(attribute.isMultiValued(), expectedValues.get(ATTRIBUTE_FIELD_MULTI_VALUE), String.format(msg,
ATTRIBUTE_FIELD_MULTI_VALUE, expectedValues
.get(ATTRIBUTE_FIELD_MULTI_VALUE), attribute.isMultiValued()));
assertEquals(attribute.isReturnedByDefault(), expectedValues.get(ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT), String.
format(msg, ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT,
expectedValues.get(ATTRIBUTE_FIELD_RETURNED_BY_DEFAULT), attribute.isReturnedByDefault()));
}
/**
* Returns strictCheck property value.
* When property is not defined true is assumed.
*/
private Boolean getStrictCheckProperty() {
Boolean strict = true;
try {
strict = (Boolean) getDataProvider().getTestSuiteAttribute(STRICT_CHECK_PROPERTY_PREFIX, TEST_NAME);
} catch (ObjectNotFoundException ex) {
// ok - property not defined
}
return strict;
}
/**
* Returns property value or fails test if property is not defined.
*/
private Object getTestPropertyOrFail(String typeName, String propName, boolean failOnError) {
Object propValue = null;
try {
propValue = getDataProvider().getTestSuiteAttribute(propName, TEST_NAME);
} catch (ObjectNotFoundException ex) {
if (failOnError) {
fail("Property definition not found: " + ex.getMessage());
}
}
if (failOnError) {
assertNotNull(propValue);
}
return propValue;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy