/* * Copyright (c) 2010-2017 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.provisioning.impl.csv; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static com.evolveum.midpoint.test.IntegrationTestTools.getAttributeValue; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import java.io.File; import java.util.List; import javax.xml.namespace.QName; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; import org.testng.annotations.Test; import org.w3c.dom.Element; import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.provisioning.impl.AbstractProvisioningIntegrationTest; import com.evolveum.midpoint.provisioning.impl.opendj.TestOpenDj; import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.processor.ResourceSchemaImpl; import com.evolveum.midpoint.schema.result.OperationResult; 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.IntegrationTestTools; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; 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.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilityCollectionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ProvisioningScriptHostType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType.Host; /** * The test of Provisioning service on the API level. The test is using CSV resource. * * @author Radovan Semancik * */ @ContextConfiguration(locations = "classpath:ctx-provisioning-test-main.xml") @DirtiesContext public abstract class AbstractCsvTest extends AbstractProvisioningIntegrationTest { protected static final File TEST_DIR = new File("src/test/resources/csv/"); protected static final String RESOURCE_NS = MidPointConstants.NS_RI; public static final QName RESOURCE_CSV_ACCOUNT_OBJECTCLASS = new QName(RESOURCE_NS, "AccountObjectClass"); protected static final String CSV_CONNECTOR_TYPE = "com.evolveum.polygon.connector.csv.CsvConnector"; private static final File CSV_TARGET_FILE = new File("target/midpoint.csv"); protected static final String ACCOUNT_JACK_FIRSTNAME = "Jack"; protected static final String ACCOUNT_JACK_LASTNAME = "Sparrow"; private static final Trace LOGGER = TraceManager.getTrace(AbstractCsvTest.class); protected static final String ATTR_FIRSTNAME = "firstname"; protected static final QName ATTR_FIRSTNAME_QNAME = new QName(RESOURCE_NS, ATTR_FIRSTNAME); protected static final String ATTR_LASTNAME = "lastname"; protected static final QName ATTR_LASTNAME_QNAME = new QName(RESOURCE_NS, ATTR_LASTNAME); protected PrismObject<ResourceType> resource; protected ResourceType resourceType; @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); resource = addResourceFromFile(getResourceFile(), CSV_CONNECTOR_TYPE, initResult); resourceType = resource.asObjectable(); FileUtils.copyFile(getSourceCsvFile(), CSV_TARGET_FILE); } protected abstract File getResourceFile(); protected abstract String getResourceOid(); protected abstract File getSourceCsvFile(); protected abstract File getAccountJackFile(); protected abstract String getAccountJackOid(); @Test public void test000Integrity() throws Exception { final String TEST_NAME = "test000Integrity"; TestUtil.displayTestTile(TEST_NAME); assertNotNull("Resource is null", resource); assertNotNull("ResourceType is null", resourceType); OperationResult result = new OperationResult(AbstractCsvTest.class.getName() + "." + TEST_NAME); ResourceType resource = repositoryService.getObject(ResourceType.class, getResourceOid(), null, result).asObjectable(); String connectorOid = resource.getConnectorRef().getOid(); ConnectorType connector = repositoryService .getObject(ConnectorType.class, connectorOid, null, result).asObjectable(); assertNotNull(connector); display("CSVFile Connector", connector); // Check connector schema IntegrationTestTools.assertConnectorSchemaSanity(connector, prismContext); } /** * This should be the very first test that works with the resource. * * The original repository object does not have resource schema. The schema * should be generated from the resource on the first use. This is the test * that executes testResource and checks whether the schema was generated. */ @Test public void test003Connection() throws Exception { final String TEST_NAME = "test003Connection"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractCsvTest.class.getName() + "." + TEST_NAME); // Check that there is no schema before test (pre-condition) ResourceType resourceBefore = repositoryService.getObject(ResourceType.class, getResourceOid(), null, result).asObjectable(); assertNotNull("No connector ref", resourceBefore.getConnectorRef()); assertNotNull("No connector ref OID", resourceBefore.getConnectorRef().getOid()); ConnectorType connector = repositoryService.getObject(ConnectorType.class, resourceBefore .getConnectorRef().getOid(), null, result).asObjectable(); assertNotNull(connector); XmlSchemaType xmlSchemaTypeBefore = resourceBefore.getSchema(); Element resourceXsdSchemaElementBefore = ResourceTypeUtil.getResourceXsdSchema(resourceBefore); AssertJUnit.assertNull("Found schema before test connection. Bad test setup?", resourceXsdSchemaElementBefore); // WHEN OperationResult testResult = provisioningService.testResource(getResourceOid()); // THEN display("Test result", testResult); TestUtil.assertSuccess("Test resource failed (result)", testResult); PrismObject<ResourceType> resourceRepoAfter = repositoryService.getObject(ResourceType.class, getResourceOid(), null, result); ResourceType resourceTypeRepoAfter = resourceRepoAfter.asObjectable(); display("Resource after test", resourceTypeRepoAfter); XmlSchemaType xmlSchemaTypeAfter = resourceTypeRepoAfter.getSchema(); assertNotNull("No schema after test connection", xmlSchemaTypeAfter); Element resourceXsdSchemaElementAfter = ResourceTypeUtil.getResourceXsdSchema(resourceTypeRepoAfter); assertNotNull("No schema after test connection", resourceXsdSchemaElementAfter); String resourceXml = prismContext.serializeObjectToString(resourceRepoAfter, PrismContext.LANG_XML); display("Resource XML", resourceXml); CachingMetadataType cachingMetadata = xmlSchemaTypeAfter.getCachingMetadata(); assertNotNull("No caching metadata", cachingMetadata); assertNotNull("No retrievalTimestamp", cachingMetadata.getRetrievalTimestamp()); assertNotNull("No serialNumber", cachingMetadata.getSerialNumber()); Element xsdElement = ObjectTypeUtil.findXsdElement(xmlSchemaTypeAfter); ResourceSchema parsedSchema = ResourceSchemaImpl.parse(xsdElement, resourceBefore.toString(), prismContext); assertNotNull("No schema after parsing", parsedSchema); // schema will be checked in next test } @Test public void test004Configuration() throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException { TestUtil.displayTestTile("test004Configuration"); // GIVEN OperationResult result = new OperationResult(AbstractCsvTest.class.getName() + ".test004Configuration"); // WHEN resource = provisioningService.getObject(ResourceType.class, getResourceOid(), null, null, result); resourceType = resource.asObjectable(); PrismContainer<Containerable> configurationContainer = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); assertNotNull("No configuration container", configurationContainer); PrismContainerDefinition confContDef = configurationContainer.getDefinition(); assertNotNull("No configuration container definition", confContDef); PrismContainer confingurationPropertiesContainer = configurationContainer.findContainer(SchemaConstants.CONNECTOR_SCHEMA_CONFIGURATION_PROPERTIES_ELEMENT_QNAME); assertNotNull("No configuration properties container", confingurationPropertiesContainer); PrismContainerDefinition confPropDef = confingurationPropertiesContainer.getDefinition(); assertNotNull("No configuration properties container definition", confPropDef); } @Test public void test005ParsedSchema() throws Exception { final String TEST_NAME = "test005ParsedSchema"; TestUtil.displayTestTile(TEST_NAME); // THEN // The returned type should have the schema pre-parsed assertNotNull(RefinedResourceSchemaImpl.hasParsedSchema(resourceType)); // Also test if the utility method returns the same thing ResourceSchema resourceSchema = RefinedResourceSchemaImpl.getResourceSchema(resourceType, prismContext); display("Parsed resource schema", resourceSchema); assertNotNull("No resource schema", resourceSchema); ObjectClassComplexTypeDefinition accountDef = resourceSchema.findObjectClassDefinition(RESOURCE_CSV_ACCOUNT_OBJECTCLASS); assertNotNull("Account definition is missing", accountDef); assertNotNull("Null identifiers in account", accountDef.getPrimaryIdentifiers()); assertFalse("Empty identifiers in account", accountDef.getPrimaryIdentifiers().isEmpty()); assertNotNull("No naming attribute in account", accountDef.getNamingAttribute()); assertFalse("No nativeObjectClass in account", StringUtils.isEmpty(accountDef.getNativeObjectClass())); assertAccountDefinition(accountDef); ResourceAttributeDefinition<String> icfsNameDef = accountDef.findAttributeDefinition(SchemaConstants.ICFS_NAME); assertNull("ICFS NAME definition sneaked in", icfsNameDef); ResourceAttributeDefinition<String> icfsUidDef = accountDef.findAttributeDefinition(SchemaConstants.ICFS_UID); assertNull("ICFS UID definition sneaked in", icfsUidDef); // Check whether it is reusing the existing schema and not parsing it all over again // Not equals() but == ... we want to really know if exactly the same // object instance is returned assertTrue("Broken caching", resourceSchema == RefinedResourceSchemaImpl.getResourceSchema(resourceType, prismContext)); } protected abstract void assertAccountDefinition(ObjectClassComplexTypeDefinition accountDef); @Test public void test006Capabilities() throws Exception { final String TEST_NAME = "test006Capabilities"; TestUtil.displayTestTile(TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestOpenDj.class.getName()+"."+TEST_NAME); // WHEN ResourceType resource = provisioningService.getObject(ResourceType.class, getResourceOid(), null, null, result).asObjectable(); // THEN display("Resource from provisioninig", resource); display("Resource from provisioninig (XML)", PrismTestUtil.serializeObjectToString(resource.asPrismObject(), PrismContext.LANG_XML)); CapabilityCollectionType nativeCapabilities = resource.getCapabilities().getNative(); List<Object> nativeCapabilitiesList = nativeCapabilities.getAny(); assertFalse("Empty capabilities returned",nativeCapabilitiesList.isEmpty()); // Connector cannot do activation, this should be null ActivationCapabilityType capAct = CapabilityUtil.getCapability(nativeCapabilitiesList, ActivationCapabilityType.class); assertNull("Found activation capability while not expecting it" ,capAct); ScriptCapabilityType capScript = CapabilityUtil.getCapability(nativeCapabilitiesList, ScriptCapabilityType.class); assertNotNull("No script capability", capScript); List<Host> scriptHosts = capScript.getHost(); assertEquals("Wrong number of script hosts", 1, scriptHosts.size()); assertScriptHost(capScript, ProvisioningScriptHostType.CONNECTOR); List<Object> effectiveCapabilities = ResourceTypeUtil.getEffectiveCapabilities(resource); for (Object capability : effectiveCapabilities) { System.out.println("Capability: "+CapabilityUtil.getCapabilityDisplayName(capability)+" : "+capability); } } private void assertScriptHost(ScriptCapabilityType capScript, ProvisioningScriptHostType expectedHostType) { for (Host host: capScript.getHost()) { if (host.getType() == expectedHostType) { return; } } AssertJUnit.fail("No script capability with host type "+expectedHostType); } @Test public void test100AddAccountJack() throws Exception { final String TEST_NAME = "test100AddAccountJack"; TestUtil.displayTestTile(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); PrismObject<ShadowType> shadowBefore = parseObject(getAccountJackFile()); // WHEN TestUtil.displayWhen(TEST_NAME); provisioningService.addObject(shadowBefore, null, null, task, result); // THEN TestUtil.displayThen(TEST_NAME); assertSuccess(result); } @Test public void test110GetAccountJack() throws Exception { final String TEST_NAME = "test110GetAccountJack"; TestUtil.displayTestTile(TEST_NAME); Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // WHEN TestUtil.displayWhen(TEST_NAME); PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class, getAccountJackOid(), null, task, result); // THEN TestUtil.displayThen(TEST_NAME); assertSuccess(result); assertNotNull(shadow); display("Shadow after", shadow); ShadowType shadowType = shadow.asObjectable(); PrismAsserts.assertEqualsPolyString("Wrong name", "jack", shadow.getName()); assertNotNull(shadow.getOid()); assertEquals(RESOURCE_CSV_ACCOUNT_OBJECTCLASS, shadowType.getObjectClass()); assertEquals(getResourceOid(), shadowType.getResourceRef().getOid()); assertAccountJackAttributes(shadowType); assertNotNull("Missing activation", shadowType.getActivation()); assertNotNull("Missing activation status", shadowType.getActivation().getAdministrativeStatus()); assertEquals("Not enabled", ActivationStatusType.ENABLED, shadowType.getActivation().getAdministrativeStatus()); PrismObject<ShadowType> repoShadow = repositoryService.getObject(ShadowType.class, shadow.getOid(), null, result); ShadowType repoShadowType = repoShadow.asObjectable(); assertEquals(RESOURCE_CSV_ACCOUNT_OBJECTCLASS, repoShadowType.getObjectClass()); assertEquals(getResourceOid(), repoShadowType.getResourceRef().getOid()); assertAccountJackAttributesRepo(shadowType); } protected abstract void assertAccountJackAttributes(ShadowType shadowType); protected abstract void assertAccountJackAttributesRepo(ShadowType shadowType); }