From 6be4a2fc32c20c453f20e4b877da3eb84e01ef1a Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Fri, 23 Feb 2018 14:55:31 +0100 Subject: [PATCH] Tests for resource caching --- .../AbstractDirectManualResourceTest.java | 3 + .../manual/AbstractManualResourceTest.java | 162 +++++++- .../intest/manual/TestManualCapabilities.java | 54 +++ .../manual/resource-manual-capabilities.xml | 171 ++++++++ model/model-intest/testng-integration.xml | 1 + .../AbstractProvisioningIntegrationTest.java | 184 ++++++++- .../impl/dummy/AbstractBasicDummyTest.java | 15 +- .../impl/dummy/AbstractDummyTest.java | 151 +------ .../impl/dummy/TestDummySchemaless.java | 388 +++++++++++++++++- ...esource-dummy-schemaless-static-schema.xml | 32 +- 10 files changed, 964 insertions(+), 197 deletions(-) create mode 100644 model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestManualCapabilities.java create mode 100644 model/model-intest/src/test/resources/manual/resource-manual-capabilities.xml diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractDirectManualResourceTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractDirectManualResourceTest.java index 7e5472bc27b..898be60b94d 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractDirectManualResourceTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractDirectManualResourceTest.java @@ -115,6 +115,9 @@ public abstract class AbstractDirectManualResourceTest extends AbstractManualRes protected static final File RESOURCE_MANUAL_FILE = new File(TEST_DIR, "resource-manual.xml"); protected static final String RESOURCE_MANUAL_OID = "0ef80ab8-2906-11e7-b81a-3f343e28c264"; + + protected static final File RESOURCE_MANUAL_CAPABILITIES_FILE = new File(TEST_DIR, "resource-manual-capabilities.xml"); + protected static final String RESOURCE_MANUAL_CAPABILITIES_OID = "0ef80ab8-2906-11e7-b81a-3f343e28c264"; protected static final File RESOURCE_SEMI_MANUAL_FILE = new File(TEST_DIR, "resource-semi-manual.xml"); protected static final String RESOURCE_SEMI_MANUAL_OID = "aea5a57c-2904-11e7-8020-7b121a9e3595"; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java index 41ae45fc191..4ae5fd88e55 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/AbstractManualResourceTest.java @@ -77,6 +77,7 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ImportOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; @@ -289,8 +290,12 @@ public void test000Sanity() throws Exception { } @Test - public void test003Connection() throws Exception { - final String TEST_NAME = "test003Connection"; + public void test012TestConnection() throws Exception { + final String TEST_NAME = "test012TestConnection"; + testConnection(TEST_NAME); + } + + public void testConnection(final String TEST_NAME) throws Exception { displayTestTitle(TEST_NAME); // GIVEN Task task = createTask(TEST_NAME); @@ -303,15 +308,22 @@ public void test003Connection() throws Exception { Element resourceXsdSchemaElementBefore = ResourceTypeUtil.getResourceXsdSchema(resourceBefore); assertResourceSchemaBeforeTest(resourceXsdSchemaElementBefore); - CapabilitiesType capabilities = resourceBefore.getCapabilities(); - if (capabilities != null) { - AssertJUnit.assertNull("Native capabilities present before test connection. Bad test setup?", capabilities.getNative()); + CapabilitiesType capabilitiesBefore = resourceBefore.getCapabilities(); + if (nativeCapabilitiesEntered()) { + AssertJUnit.assertNotNull("Native capabilities missing before test connection. Bad test setup?", capabilitiesBefore); + AssertJUnit.assertNotNull("Native capabilities missing before test connection. Bad test setup?", capabilitiesBefore.getNative()); + } else { + if (capabilitiesBefore != null) { + AssertJUnit.assertNull("Native capabilities present before test connection. Bad test setup?", capabilitiesBefore.getNative()); + } } // WHEN + displayWhen(TEST_NAME); OperationResult testResult = modelService.testResource(getResourceOid(), task); // THEN + displayThen(TEST_NAME); display("Test result", testResult); TestUtil.assertSuccess("Test resource failed (result)", testResult); @@ -325,30 +337,46 @@ public void test003Connection() throws Exception { assertNotNull("No schema after test connection", resourceXsdSchemaElementAfter); String resourceXml = prismContext.serializeObjectToString(resourceRepoAfter, PrismContext.LANG_XML); - display("Resource XML", resourceXml); + display("Resource XML after test connection", resourceXml); - CachingMetadataType cachingMetadata = xmlSchemaTypeAfter.getCachingMetadata(); - assertNotNull("No caching metadata", cachingMetadata); - assertNotNull("No retrievalTimestamp", cachingMetadata.getRetrievalTimestamp()); - assertNotNull("No serialNumber", cachingMetadata.getSerialNumber()); + CachingMetadataType schemaCachingMetadata = xmlSchemaTypeAfter.getCachingMetadata(); + assertNotNull("No caching metadata", schemaCachingMetadata); + assertNotNull("No retrievalTimestamp", schemaCachingMetadata.getRetrievalTimestamp()); + assertNotNull("No serialNumber", schemaCachingMetadata.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 + CapabilitiesType capabilitiesRepoAfter = resourceTypeRepoAfter.getCapabilities(); + AssertJUnit.assertNotNull("Capabilities missing after test connection.", capabilitiesRepoAfter); + AssertJUnit.assertNotNull("Native capabilities missing after test connection.", capabilitiesRepoAfter.getNative()); + AssertJUnit.assertNotNull("Capabilities caching metadata missing after test connection.", capabilitiesRepoAfter.getCachingMetadata()); + + ResourceType resourceModelAfter = modelService.getObject(ResourceType.class, getResourceOid(), null, null, result).asObjectable(); + + rememberSteadyResources(); + + CapabilitiesType capabilitiesModelAfter = resourceModelAfter.getCapabilities(); + AssertJUnit.assertNotNull("Capabilities missing after test connection (model)", capabilitiesModelAfter); + AssertJUnit.assertNotNull("Native capabilities missing after test connection (model)", capabilitiesModelAfter.getNative()); + AssertJUnit.assertNotNull("Capabilities caching metadata missing after test connection (model)", capabilitiesModelAfter.getCachingMetadata()); } + protected boolean nativeCapabilitiesEntered() { + return false; + } + protected abstract void assertResourceSchemaBeforeTest(Element resourceXsdSchemaElementBefore); @Test - public void test004Configuration() throws Exception { - final String TEST_NAME = "test004Configuration"; + public void test014Configuration() throws Exception { + final String TEST_NAME = "test014Configuration"; displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractManualResourceTest.class.getName() + "." + TEST_NAME); - + // WHEN resource = modelService.getObject(ResourceType.class, getResourceOid(), null, null, result); resourceType = resource.asObjectable(); @@ -364,15 +392,16 @@ public void test004Configuration() throws Exception { // PrismContainerDefinition confPropDef = confingurationPropertiesContainer.getDefinition(); // assertNotNull("No configuration properties container definition", confPropDef); + assertSteadyResources(); } @Test - public void test005ParsedSchema() throws Exception { - final String TEST_NAME = "test005ParsedSchema"; + public void test016ParsedSchema() throws Exception { + final String TEST_NAME = "test016ParsedSchema"; displayTestTitle(TEST_NAME); // GIVEN OperationResult result = new OperationResult(AbstractManualResourceTest.class.getName() + "." + TEST_NAME); - + // THEN // The returned type should have the schema pre-parsed assertNotNull(RefinedResourceSchemaImpl.hasParsedSchema(resourceType)); @@ -410,11 +439,17 @@ public void test005ParsedSchema() throws Exception { assertTrue("No fullname create", fullnameDef.canAdd()); assertTrue("No fullname update", fullnameDef.canModify()); assertTrue("No fullname read", fullnameDef.canRead()); + + assertSteadyResources(); } @Test - public void test006Capabilities() throws Exception { - final String TEST_NAME = "test006Capabilities"; + public void test017Capabilities() throws Exception { + final String TEST_NAME = "test017Capabilities"; + testCapabilities(TEST_NAME); + } + + public void testCapabilities(final String TEST_NAME) throws Exception { displayTestTitle(TEST_NAME); // GIVEN @@ -424,10 +459,15 @@ public void test006Capabilities() throws Exception { ResourceType resource = modelService.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)); + display("Resource from model", resource); + display("Resource from model (XML)", PrismTestUtil.serializeObjectToString(resource.asPrismObject(), PrismContext.LANG_XML)); - CapabilityCollectionType nativeCapabilities = resource.getCapabilities().getNative(); + assertSteadyResources(); + + CapabilitiesType capabilities = resource.getCapabilities(); + assertNotNull("Missing capability caching metadata", capabilities.getCachingMetadata()); + + CapabilityCollectionType nativeCapabilities = capabilities.getNative(); List nativeCapabilitiesList = nativeCapabilities.getAny(); assertFalse("Empty capabilities returned",nativeCapabilitiesList.isEmpty()); @@ -446,9 +486,87 @@ public void test006Capabilities() throws Exception { for (Object capability : effectiveCapabilities) { System.out.println("Capability: "+CapabilityUtil.getCapabilityDisplayName(capability)+" : "+capability); } + + assertSteadyResources(); + } + + @Test + public void test018ResourceCaching() throws Exception { + final String TEST_NAME = "test018ResourceCaching"; + testResourceCaching(TEST_NAME); + } + + public void testResourceCaching(final String TEST_NAME) throws Exception { + displayTestTitle(TEST_NAME); + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + PrismObject resourceReadonlyBefore = modelService.getObject( + ResourceType.class, getResourceOid(), GetOperationOptions.createReadOnlyCollection(), task, result); + + assertSteadyResources(); + + // WHEN + displayWhen(TEST_NAME); + PrismObject resourceReadOnlyAgain = modelService.getObject( + ResourceType.class, getResourceOid(), GetOperationOptions.createReadOnlyCollection(), task, result); + + assertSteadyResources(); + + // WHEN + displayWhen(TEST_NAME); + PrismObject resourceAgain = modelService.getObject( + ResourceType.class, getResourceOid(), null, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + +// assertTrue("Resource instance changed", resourceBefore == resourceReadOnlyAgain); + + assertSteadyResources(); + } + + @Test + public void test020ReimportResource() throws Exception { + final String TEST_NAME = "test020ReimportResource"; + displayTestTitle(TEST_NAME); + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + ImportOptionsType options = new ImportOptionsType(); + options.setOverwrite(true); + + // WHEN + displayWhen(TEST_NAME); + modelService.importObjectsFromFile(getResourceFile(), options, task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); } + @Test + public void test022TestConnection() throws Exception { + final String TEST_NAME = "test022TestConnection"; + testConnection(TEST_NAME); + } + + @Test + public void test027Capabilities() throws Exception { + final String TEST_NAME = "test027Capabilities"; + testCapabilities(TEST_NAME); + } + + @Test + public void test028ResourceCaching() throws Exception { + final String TEST_NAME = "test028ResourceCaching"; + testResourceCaching(TEST_NAME); + } + + @Test public void test100AssignWillRoleOne() throws Exception { // The count will be checked only after propagation was run, so we can address both direct and grouping cases diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestManualCapabilities.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestManualCapabilities.java new file mode 100644 index 00000000000..45a067fe413 --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/manual/TestManualCapabilities.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2018 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.model.intest.manual; + +import java.io.File; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.w3c.dom.Element; + +/** + * @author Radovan Semancik + */ +@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public class TestManualCapabilities extends TestManual { + + @Override + protected File getResourceFile() { + return RESOURCE_MANUAL_CAPABILITIES_FILE; + } + + @Override + protected boolean nativeCapabilitiesEntered() { + return true; + } + + @Override + protected int getNumberOfAccountAttributeDefinitions() { + return 5; + } + +} \ No newline at end of file diff --git a/model/model-intest/src/test/resources/manual/resource-manual-capabilities.xml b/model/model-intest/src/test/resources/manual/resource-manual-capabilities.xml new file mode 100644 index 00000000000..88bb13be3ce --- /dev/null +++ b/model/model-intest/src/test/resources/manual/resource-manual-capabilities.xml @@ -0,0 +1,171 @@ + + + + + + Manual Resource + + + + + c:connectorType + ManualConnector + + + + + + administrator + + + + + + + + + + + + + + tns:username + tns:username + tns:username + + + + + + + + + Username + 110 + + + + + + + 200 + + + + + + + + + + + + + + + account + default + true + ri:AccountObjectClass + + ri:username + + strong + + name + + + + + ri:fullname + + + fullName + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + + true + + + + + + + + + + + + ri:status + 1 + 0 + + + + + + + light + PT15M + + + diff --git a/model/model-intest/testng-integration.xml b/model/model-intest/testng-integration.xml index 48058754832..653db2ff587 100644 --- a/model/model-intest/testng-integration.xml +++ b/model/model-intest/testng-integration.xml @@ -126,6 +126,7 @@ + diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/AbstractProvisioningIntegrationTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/AbstractProvisioningIntegrationTest.java index e5fd4be46a0..5bcf862dab4 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/AbstractProvisioningIntegrationTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/AbstractProvisioningIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,20 +19,46 @@ */ package com.evolveum.midpoint.provisioning.impl; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; + import java.io.File; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.w3c.dom.Element; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.provisioning.impl.dummy.TestDummyResourceAndSchemaCaching; import com.evolveum.midpoint.provisioning.impl.mock.SynchornizationServiceMock; +import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.internals.InternalMonitor; import com.evolveum.midpoint.schema.internals.InternalsConfig; +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.AbstractIntegrationTest; +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.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType; /** * @author Radovan Semancik @@ -47,16 +73,164 @@ public abstract class AbstractProvisioningIntegrationTest extends AbstractIntegr private static final Trace LOGGER = TraceManager.getTrace(AbstractProvisioningIntegrationTest.class); - @Autowired(required=true) - protected ProvisioningService provisioningService; + @Autowired protected ProvisioningService provisioningService; + @Autowired protected SynchornizationServiceMock syncServiceMock; + + // Testing connector discovery + @Autowired protected ConnectorManager connectorManager; + + // Used to make sure that the connector is cached + @Autowired protected ResourceManager resourceManager; + + // Values used to check if something is unchanged or changed properly + private Long lastResourceVersion = null; + private ConnectorInstance lastConfiguredConnectorInstance; + private CachingMetadataType lastCachingMetadata; + private ResourceSchema lastResourceSchema = null; + private RefinedResourceSchema lastRefinedResourceSchema; - @Autowired(required = true) - protected SynchornizationServiceMock syncServiceMock; @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { InternalsConfig.encryptionChecks = false; provisioningService.postInit(initResult); } + + protected void assertVersion(PrismObject object, String expectedVersion) { + assertEquals("Wrong version of "+object, expectedVersion, object.asObjectable().getVersion()); + } + + protected void rememberResourceVersion(String version) { + lastResourceVersion = parseVersion(version); + } + + protected void assertResourceVersionIncrement(PrismObject resource, int expectedIncrement) { + assertResourceVersionIncrement(resource.getVersion(), expectedIncrement); + } + + protected void assertResourceVersionIncrement(String currentVersion, int expectedIncrement) { + long currentVersionLong = parseVersion(currentVersion); + long actualIncrement = currentVersionLong - lastResourceVersion; + assertEquals("Unexpected increment in resource version", (long)expectedIncrement, actualIncrement); + lastResourceVersion = currentVersionLong; + } + + private long parseVersion(String stringVersion) { + if (stringVersion == null) { + AssertJUnit.fail("Version is null"); + } + if (stringVersion.isEmpty()) { + AssertJUnit.fail("Version is empty"); + } + return Long.parseLong(stringVersion); + } + + protected CachingMetadataType getSchemaCachingMetadata(PrismObject resource) { + ResourceType resourceType = resource.asObjectable(); + XmlSchemaType xmlSchemaType = resourceType.getSchema(); + assertNotNull("No schema", xmlSchemaType); + Element resourceXsdSchemaElementAfter = ResourceTypeUtil.getResourceXsdSchema(resourceType); + assertNotNull("No schema XSD element", resourceXsdSchemaElementAfter); + return xmlSchemaType.getCachingMetadata(); + } + + protected void rememberSchemaMetadata(PrismObject resource) { + lastCachingMetadata = getSchemaCachingMetadata(resource); + } + + protected void assertSchemaMetadataUnchanged(PrismObject resource) { + CachingMetadataType current = getSchemaCachingMetadata(resource); + assertEquals("Schema caching metadata changed", lastCachingMetadata, current); + } + protected void rememberResourceSchema(ResourceSchema resourceSchema) { + lastResourceSchema = resourceSchema; + } + + protected void assertResourceSchemaUnchanged(ResourceSchema currentResourceSchema) { + // We really want == there. We want to make sure that this is actually the same instance and that + // it was properly cached + assertTrue("Resource schema has changed", lastResourceSchema == currentResourceSchema); + } + + protected void rememberRefinedResourceSchema(RefinedResourceSchema rResourceSchema) { + lastRefinedResourceSchema = rResourceSchema; + } + + protected void assertRefinedResourceSchemaUnchanged(RefinedResourceSchema currentRefinedResourceSchema) { + // We really want == there. We want to make sure that this is actually the same instance and that + // it was properly cached + assertTrue("Refined resource schema has changed", lastRefinedResourceSchema == currentRefinedResourceSchema); + } + + protected void assertHasSchema(PrismObject resource, String desc) throws SchemaException { + ResourceType resourceType = resource.asObjectable(); + display("Resource "+desc, resourceType); + + XmlSchemaType xmlSchemaTypeAfter = resourceType.getSchema(); + assertNotNull("No schema in "+desc, xmlSchemaTypeAfter); + Element resourceXsdSchemaElementAfter = ResourceTypeUtil.getResourceXsdSchema(resourceType); + assertNotNull("No schema XSD element in "+desc, resourceXsdSchemaElementAfter); + + String resourceXml = prismContext.serializeObjectToString(resource, PrismContext.LANG_XML); +// display("Resource XML", resourceXml); + + CachingMetadataType cachingMetadata = xmlSchemaTypeAfter.getCachingMetadata(); + assertNotNull("No caching metadata in "+desc, cachingMetadata); + assertNotNull("No retrievalTimestamp in "+desc, cachingMetadata.getRetrievalTimestamp()); + assertNotNull("No serialNumber in "+desc, cachingMetadata.getSerialNumber()); + + Element xsdElement = ObjectTypeUtil.findXsdElement(xmlSchemaTypeAfter); + ResourceSchema parsedSchema = ResourceSchemaImpl.parse(xsdElement, resource.toString(), prismContext); + assertNotNull("No schema after parsing in "+desc, parsedSchema); + } + + protected void rememberConnectorInstance(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() + + ".rememberConnectorInstance"); + rememberConnectorInstance(resourceManager.getConfiguredConnectorInstance(resource, ReadCapabilityType.class, false, result)); + } + + protected void rememberConnectorInstance(ConnectorInstance currentConnectorInstance) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + lastConfiguredConnectorInstance = currentConnectorInstance; + } + + protected void assertConnectorInstanceUnchanged(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() + + ".assertConnectorInstanceUnchanged"); + ConnectorInstance currentConfiguredConnectorInstance = resourceManager.getConfiguredConnectorInstance( + resource, ReadCapabilityType.class, false, result); + assertTrue("Connector instance has changed", lastConfiguredConnectorInstance == currentConfiguredConnectorInstance); + } + + protected void assertConnectorInstanceChanged(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() + + ".rememberConnectorInstance"); + ConnectorInstance currentConfiguredConnectorInstance = resourceManager.getConfiguredConnectorInstance( + resource, ReadCapabilityType.class, false, result); + assertTrue("Connector instance has NOT changed", lastConfiguredConnectorInstance != currentConfiguredConnectorInstance); + lastConfiguredConnectorInstance = currentConfiguredConnectorInstance; + } + + protected void assertSteadyResource() throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT, 0); + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT, 0); + PrismObject resource = getResource(); + if (resource != null) { + assertResourceVersionIncrement(resource, 0); + assertSchemaMetadataUnchanged(resource); + assertConnectorInstanceUnchanged(resource); + } + + display("Resource cache", InternalMonitor.getResourceCacheStats()); + // We do not assert hits, there may be a lot of them + assertResourceCacheMissesIncrement(0); + } + + protected PrismObject getResource() { + return null; + } } diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java index 7a039dc3835..aff048e8d10 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractBasicDummyTest.java @@ -716,11 +716,11 @@ public void test029CapabilitiesRepo() throws Exception { @Test public void test030ResourceAndConnectorCaching() throws Exception { - TestUtil.displayTestTitle("test030ResourceAndConnectorCaching"); + final String TEST_NAME = "test030ResourceAndConnectorCaching"; + displayTestTitle(TEST_NAME); // GIVEN - OperationResult result = new OperationResult(TestOpenDj.class.getName() - + ".test010ResourceAndConnectorCaching"); + OperationResult result = new OperationResult(TestOpenDj.class.getName() + "." + TEST_NAME); ConnectorInstance configuredConnectorInstance = resourceManager.getConfiguredConnectorInstance( resource, ReadCapabilityType.class, false, result); assertNotNull("No configuredConnectorInstance", configuredConnectorInstance); @@ -728,13 +728,13 @@ public void test030ResourceAndConnectorCaching() throws Exception { assertNotNull("No resource schema", resourceSchema); // WHEN + displayWhen(TEST_NAME); PrismObject resourceAgain = provisioningService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, null, result); // THEN - result.computeStatus(); - display("getObject result", result); - TestUtil.assertSuccess(result); + displayThen(TEST_NAME); + assertSuccess(result); ResourceType resourceTypeAgain = resourceAgain.asObjectable(); assertNotNull("No connector ref", resourceTypeAgain.getConnectorRef()); @@ -778,8 +778,7 @@ public void test030ResourceAndConnectorCaching() throws Exception { assertTrue("Connector instance was not cached", configuredConnectorInstance == configuredConnectorInstanceAgain); // Check if the connector still works. - OperationResult testResult = new OperationResult(TestOpenDj.class.getName() - + ".test010ResourceAndConnectorCaching.test"); + OperationResult testResult = new OperationResult(TestOpenDj.class.getName() + "."+TEST_NAME+".test"); configuredConnectorInstanceAgain.test(testResult); testResult.computeStatus(); TestUtil.assertSuccess("Connector test failed", testResult); diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java index e7b8e2a5631..3a96cfa1e32 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/AbstractDummyTest.java @@ -164,25 +164,15 @@ public abstract class AbstractDummyTest extends AbstractProvisioningIntegrationT protected String accountWillCurrentPassword = ACCOUNT_WILL_PASSWORD; - // Testing connector discovery - @Autowired(required = true) - protected ConnectorManager connectorManager; - - // Used to make sure that the connector is cached - @Autowired(required = true) - protected ResourceManager resourceManager; - @Autowired(required = true) protected ProvisioningContextFactory provisioningContextFactory; - // Values used to check if something is unchanged or changed properly - private Long lastResourceVersion = null; - private ConnectorInstance lastConfiguredConnectorInstance; - private CachingMetadataType lastCachingMetadata; - private ResourceSchema lastResourceSchema = null; - private RefinedResourceSchema lastRefinedResourceSchema; - protected String daemonIcfUid; + + @Override + protected PrismObject getResource() { + return resource; + } @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { @@ -425,135 +415,4 @@ protected void assertEntitlementPriv(PrismObject account, String ent assertAssociation(account, ASSOCIATION_PRIV_NAME, entitlementOid); } - protected void assertVersion(PrismObject object, String expectedVersion) { - assertEquals("Wrong version of "+object, expectedVersion, object.asObjectable().getVersion()); - } - - protected void rememberResourceVersion(String version) { - lastResourceVersion = parseVersion(version); - } - - protected void assertResourceVersionIncrement(PrismObject resource, int expectedIncrement) { - assertResourceVersionIncrement(resource.getVersion(), expectedIncrement); - } - - protected void assertResourceVersionIncrement(String currentVersion, int expectedIncrement) { - long currentVersionLong = parseVersion(currentVersion); - long actualIncrement = currentVersionLong - lastResourceVersion; - assertEquals("Unexpected increment in resource version", (long)expectedIncrement, actualIncrement); - lastResourceVersion = currentVersionLong; - } - - private long parseVersion(String stringVersion) { - if (stringVersion == null) { - AssertJUnit.fail("Version is null"); - } - if (stringVersion.isEmpty()) { - AssertJUnit.fail("Version is empty"); - } - return Long.parseLong(stringVersion); - } - - protected CachingMetadataType getSchemaCachingMetadata(PrismObject resource) { - ResourceType resourceType = resource.asObjectable(); - XmlSchemaType xmlSchemaTypeAfter = resourceType.getSchema(); - assertNotNull("No schema", xmlSchemaTypeAfter); - Element resourceXsdSchemaElementAfter = ResourceTypeUtil.getResourceXsdSchema(resourceType); - assertNotNull("No schema XSD element", resourceXsdSchemaElementAfter); - return xmlSchemaTypeAfter.getCachingMetadata(); - } - - protected void rememberSchemaMetadata(PrismObject resource) { - lastCachingMetadata = getSchemaCachingMetadata(resource); - } - - protected void assertSchemaMetadataUnchanged(PrismObject resource) { - CachingMetadataType current = getSchemaCachingMetadata(resource); - assertEquals("Schema caching metadata changed", lastCachingMetadata, current); - } - - protected void rememberResourceSchema(ResourceSchema resourceSchema) { - lastResourceSchema = resourceSchema; - } - - protected void assertResourceSchemaUnchanged(ResourceSchema currentResourceSchema) { - // We really want == there. We want to make sure that this is actually the same instance and that - // it was properly cached - assertTrue("Resource schema has changed", lastResourceSchema == currentResourceSchema); - } - - protected void rememberRefinedResourceSchema(RefinedResourceSchema rResourceSchema) { - lastRefinedResourceSchema = rResourceSchema; - } - - protected void assertRefinedResourceSchemaUnchanged(RefinedResourceSchema currentRefinedResourceSchema) { - // We really want == there. We want to make sure that this is actually the same instance and that - // it was properly cached - assertTrue("Refined resource schema has changed", lastRefinedResourceSchema == currentRefinedResourceSchema); - } - - protected void assertHasSchema(PrismObject resource, String desc) throws SchemaException { - ResourceType resourceType = resource.asObjectable(); - display("Resource "+desc, resourceType); - - XmlSchemaType xmlSchemaTypeAfter = resourceType.getSchema(); - assertNotNull("No schema in "+desc, xmlSchemaTypeAfter); - Element resourceXsdSchemaElementAfter = ResourceTypeUtil.getResourceXsdSchema(resourceType); - assertNotNull("No schema XSD element in "+desc, resourceXsdSchemaElementAfter); - - String resourceXml = prismContext.serializeObjectToString(resource, PrismContext.LANG_XML); -// display("Resource XML", resourceXml); - - CachingMetadataType cachingMetadata = xmlSchemaTypeAfter.getCachingMetadata(); - assertNotNull("No caching metadata in "+desc, cachingMetadata); - assertNotNull("No retrievalTimestamp in "+desc, cachingMetadata.getRetrievalTimestamp()); - assertNotNull("No serialNumber in "+desc, cachingMetadata.getSerialNumber()); - - Element xsdElement = ObjectTypeUtil.findXsdElement(xmlSchemaTypeAfter); - ResourceSchema parsedSchema = ResourceSchemaImpl.parse(xsdElement, resource.toString(), prismContext); - assertNotNull("No schema after parsing in "+desc, parsedSchema); - } - - protected void rememberConnectorInstance(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() - + ".rememberConnectorInstance"); - rememberConnectorInstance(resourceManager.getConfiguredConnectorInstance(resource, ReadCapabilityType.class, false, result)); - } - - protected void rememberConnectorInstance(ConnectorInstance currentConnectorInstance) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - lastConfiguredConnectorInstance = currentConnectorInstance; - } - - protected void assertConnectorInstanceUnchanged(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() - + ".rememberConnectorInstance"); - ConnectorInstance currentConfiguredConnectorInstance = resourceManager.getConfiguredConnectorInstance( - resource, ReadCapabilityType.class, false, result); - assertTrue("Connector instance has changed", lastConfiguredConnectorInstance == currentConfiguredConnectorInstance); - } - - protected void assertConnectorInstanceChanged(PrismObject resource) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - OperationResult result = new OperationResult(TestDummyResourceAndSchemaCaching.class.getName() - + ".rememberConnectorInstance"); - ConnectorInstance currentConfiguredConnectorInstance = resourceManager.getConfiguredConnectorInstance( - resource, ReadCapabilityType.class, false, result); - assertTrue("Connector instance has NOT changed", lastConfiguredConnectorInstance != currentConfiguredConnectorInstance); - lastConfiguredConnectorInstance = currentConfiguredConnectorInstance; - } - - protected void assertSteadyResource() throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT, 0); - assertCounterIncrement(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT, 0); - assertCounterIncrement(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT, 0); - assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT, 0); - assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT, 0); - assertResourceVersionIncrement(resource, 0); - assertSchemaMetadataUnchanged(resource); - assertConnectorInstanceUnchanged(resource); - - display("Resource cache", InternalMonitor.getResourceCacheStats()); - // We do not assert hits, there may be a lot of them - assertResourceCacheMissesIncrement(0); - } - } diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummySchemaless.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummySchemaless.java index 97d9db81292..32c65673f6f 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummySchemaless.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/dummy/TestDummySchemaless.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2018 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ */ package com.evolveum.midpoint.provisioning.impl.dummy; -import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNotNull; @@ -27,10 +26,12 @@ import static org.testng.AssertJUnit.assertTrue; import java.io.File; +import java.util.Collection; import java.util.List; import javax.xml.namespace.QName; +import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -40,19 +41,36 @@ import com.evolveum.icf.dummy.resource.DummyAccount; import com.evolveum.icf.dummy.resource.DummyResource; +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Definition; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.DiffUtil; +import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.util.PrismAsserts; import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions; import com.evolveum.midpoint.provisioning.api.ProvisioningService; +import com.evolveum.midpoint.provisioning.impl.AbstractProvisioningIntegrationTest; import com.evolveum.midpoint.provisioning.impl.ProvisioningTestUtil; +import com.evolveum.midpoint.provisioning.impl.opendj.TestOpenDj; +import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance; import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.schema.constants.ConnectorTestOperation; import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; import com.evolveum.midpoint.schema.internals.InternalsConfig; +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.schema.util.SchemaTestConstants; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.AbstractIntegrationTest; @@ -61,13 +79,17 @@ import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CapabilitiesType; 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.ResourceType; +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.XmlSchemaType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType; import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.TestConnectionCapabilityType; @@ -81,7 +103,7 @@ */ @ContextConfiguration(locations = "classpath:ctx-provisioning-test-main.xml") @DirtiesContext -public class TestDummySchemaless extends AbstractIntegrationTest { +public class TestDummySchemaless extends AbstractProvisioningIntegrationTest { private static final File TEST_DIR = new File(AbstractDummyTest.TEST_DIR_DUMMY, "dummy-schemaless"); @@ -104,7 +126,6 @@ public class TestDummySchemaless extends AbstractIntegrationTest { private static DummyResource dummyResourceSchemaless; private PrismObject resourceStaticSchema; - private ResourceType resourceTypeStaticSchema; private static DummyResource dummyResourceStaticSchema; private static DummyResourceContoller dummyResourceSchemalessCtl; @@ -135,13 +156,17 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti dummyResourceSchemaless = dummyResourceSchemalessCtl.getDummyResource(); resourceStaticSchema = addResourceFromFile(RESOURCE_DUMMY_STATIC_SCHEMA_FILE, IntegrationTestTools.DUMMY_CONNECTOR_TYPE, initResult); - resourceTypeStaticSchema = resourceStaticSchema.asObjectable(); dummyResourceStaticSchema = DummyResource.getInstance(RESOURCE_DUMMY_STATIC_SCHEMA_INSTANCE_ID); dummyResourceStaticSchema.reset(); dummyResourceStaticSchema.populateWithDefaultSchema(); } + + @Override + protected PrismObject getResource() { + return resourceStaticSchema; + } @Test public void test000Integrity() throws Exception { @@ -250,7 +275,242 @@ public void test006GetObjectSchemaless() throws Exception { assertNotNull("No connector ref", resourceType.getConnectorRef()); assertNotNull("No connector ref OID", resourceType.getConnectorRef().getOid()); } + + @Test + public void test020ResourceStaticSchemaTest() throws Exception { + resourceStaticSchemaTest("test020ResourceStaticSchemaTest"); + } + + public void resourceStaticSchemaTest(final String TEST_NAME) throws Exception { + displayTestTitle(TEST_NAME); + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + // Some connector initialization and other things might happen in previous tests. + // The monitor is static, not part of spring context, it will not be cleared + + rememberCounter(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT); + rememberCounter(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); + rememberCounter(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT); + rememberCounter(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT); + rememberResourceCacheStats(); + + // Check that there is no schema before test (pre-condition) + PrismObject resourceBefore = repositoryService.getObject(ResourceType.class, RESOURCE_DUMMY_STATIC_SCHEMA_OID, null, result); + ResourceType resourceTypeBefore = resourceBefore.asObjectable(); + rememberResourceVersion(resourceBefore.getVersion()); + assertNotNull("No connector ref", resourceTypeBefore.getConnectorRef()); + assertNotNull("No connector ref OID", resourceTypeBefore.getConnectorRef().getOid()); + ConnectorType connector = repositoryService.getObject(ConnectorType.class, + resourceTypeBefore.getConnectorRef().getOid(), null, result).asObjectable(); + assertNotNull(connector); + XmlSchemaType xmlSchemaTypeBefore = resourceTypeBefore.getSchema(); + assertNotNull("No schema in static resource before", xmlSchemaTypeBefore); + Element resourceXsdSchemaElementBefore = ResourceTypeUtil.getResourceXsdSchema(resourceTypeBefore); + assertNotNull("No schema XSD element in static resource before", resourceXsdSchemaElementBefore); + + // WHEN + OperationResult testResult = provisioningService.testResource(RESOURCE_DUMMY_STATIC_SCHEMA_OID, task); + + // THEN + display("Test result", testResult); + OperationResult connectorResult = assertSingleConnectorTestResult(testResult); + assertTestResourceSuccess(connectorResult, ConnectorTestOperation.CONNECTOR_INITIALIZATION); + assertTestResourceSuccess(connectorResult, ConnectorTestOperation.CONNECTOR_CONFIGURATION); + assertTestResourceSuccess(connectorResult, ConnectorTestOperation.CONNECTOR_CONNECTION); + assertTestResourceSuccess(connectorResult, ConnectorTestOperation.CONNECTOR_CAPABILITIES); + assertSuccess(connectorResult); + assertTestResourceSuccess(testResult, ConnectorTestOperation.RESOURCE_SCHEMA); + assertSuccess(testResult); + + PrismObject resourceRepoAfter = repositoryService.getObject(ResourceType.class, + RESOURCE_DUMMY_STATIC_SCHEMA_OID, 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); + + IntegrationTestTools.displayXml("Resource XML", resourceRepoAfter); + + 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, resourceTypeBefore.toString(), prismContext); + assertNotNull("No schema after parsing", parsedSchema); + + // schema will be checked in next test + + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT, 1); + + // Not sure why 2 instead 1, but this is a small difference, we can live with that + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT, 2); + + // One increment for availablity status, the other for schema + assertResourceVersionIncrement(resourceRepoAfter, 2); + + } + /** + * MID-4472, MID-4174 + */ + @Test + public void test030ResourceStatciSchemaResourceAndConnectorCaching() throws Exception { + resourceStatciSchemaResourceAndConnectorCaching("test030ResourceStatciSchemaResourceAndConnectorCaching"); + } + + public void resourceStatciSchemaResourceAndConnectorCaching(final String TEST_NAME) throws Exception { + displayTestTitle(TEST_NAME); + + // GIVEN + OperationResult result = new OperationResult(TestOpenDj.class.getName() + "." + TEST_NAME); + + // re-read the resource before tests so we have a clean slate, e.g. configuration properly parsed (no raw elements) + resourceStaticSchema = provisioningService.getObject(ResourceType.class, RESOURCE_DUMMY_STATIC_SCHEMA_OID, null, null, result); + ConnectorInstance currentConnectorInstance = resourceManager.getConfiguredConnectorInstance( + resourceStaticSchema, ReadCapabilityType.class, false, result); + + IntegrationTestTools.displayXml("Initialized static schema resource", resourceStaticSchema); + + rememberCounter(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT); + rememberCounter(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); + rememberCounter(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT); + rememberCounter(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT); + rememberSchemaMetadata(resourceStaticSchema); + rememberConnectorInstance(currentConnectorInstance); + rememberResourceCacheStats(); + + ConnectorInstance configuredConnectorInstance = resourceManager.getConfiguredConnectorInstance( + resourceStaticSchema, ReadCapabilityType.class, false, result); + assertNotNull("No configuredConnectorInstance", configuredConnectorInstance); + ResourceSchema resourceSchemaBefore = RefinedResourceSchemaImpl.getResourceSchema(resourceStaticSchema, prismContext); + assertNotNull("No resource schema", resourceSchemaBefore); + assertStaticSchemaSanity(resourceSchemaBefore); + + // WHEN + displayWhen(TEST_NAME); + PrismObject resourceAgain = provisioningService.getObject(ResourceType.class, RESOURCE_DUMMY_STATIC_SCHEMA_OID, + null, null, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + ResourceType resourceTypeAgain = resourceAgain.asObjectable(); + assertNotNull("No connector ref", resourceTypeAgain.getConnectorRef()); + assertNotNull("No connector ref OID", resourceTypeAgain.getConnectorRef().getOid()); + + PrismContainer configurationContainer = resourceStaticSchema.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); + PrismContainer configurationContainerAgain = resourceAgain + .findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); + assertTrue("Configurations not equivalent", configurationContainer.equivalent(configurationContainerAgain)); + + // Check resource schema caching + ResourceSchema resourceSchemaAgain = RefinedResourceSchemaImpl.getResourceSchema(resourceAgain, prismContext); + assertNotNull("No resource schema (again)", resourceSchemaAgain); + assertTrue("Resource schema was not cached", resourceSchemaBefore == resourceSchemaAgain); + + // Check capabilities caching + + CapabilitiesType capabilitiesType = resourceStaticSchema.asObjectable().getCapabilities(); + assertNotNull("No capabilities fetched from provisioning", capabilitiesType); + CachingMetadataType capCachingMetadataType = capabilitiesType.getCachingMetadata(); + assertNotNull("No capabilities caching metadata fetched from provisioning", capCachingMetadataType); + CachingMetadataType capCachingMetadataTypeAgain = resourceTypeAgain.getCapabilities().getCachingMetadata(); + assertEquals("Capabilities caching metadata serial number has changed", capCachingMetadataType.getSerialNumber(), + capCachingMetadataTypeAgain.getSerialNumber()); + assertEquals("Capabilities caching metadata timestamp has changed", capCachingMetadataType.getRetrievalTimestamp(), + capCachingMetadataTypeAgain.getRetrievalTimestamp()); + + // Rough test if everything is fine + resourceStaticSchema.asObjectable().setFetchResult(null); + resourceAgain.asObjectable().setFetchResult(null); + ObjectDelta dummyResourceDiff = DiffUtil.diff(resourceStaticSchema, resourceAgain); + display("Dummy resource diff", dummyResourceDiff); + assertTrue("The resource read again is not the same as the original. diff:"+dummyResourceDiff, dummyResourceDiff.isEmpty()); + + // Now we stick our nose deep inside the provisioning impl. But we need + // to make sure that the + // configured connector is properly cached + ConnectorInstance configuredConnectorInstanceAgain = resourceManager.getConfiguredConnectorInstance( + resourceAgain, ReadCapabilityType.class, false, result); + assertNotNull("No configuredConnectorInstance (again)", configuredConnectorInstanceAgain); + assertTrue("Connector instance was not cached", configuredConnectorInstance == configuredConnectorInstanceAgain); + + // Check if the connector still works. + OperationResult testResult = new OperationResult(TestOpenDj.class.getName() + + ".test010ResourceAndConnectorCaching.test"); + configuredConnectorInstanceAgain.test(testResult); + testResult.computeStatus(); + TestUtil.assertSuccess("Connector test failed", testResult); + + // Test connection should also refresh the connector by itself. So check if it has been refreshed + + ConnectorInstance configuredConnectorInstanceAfterTest = resourceManager.getConfiguredConnectorInstance( + resourceAgain, ReadCapabilityType.class, false, result); + assertNotNull("No configuredConnectorInstance (again)", configuredConnectorInstanceAfterTest); + assertTrue("Connector instance was not cached", configuredConnectorInstanceAgain == configuredConnectorInstanceAfterTest); + + assertSteadyResource(); + } + + @Test + public void test040ReAddResourceStaticSchema() throws Exception { + final String TEST_NAME = "test040ReAddResourceStaticSchema"; + displayTestTitle(TEST_NAME); + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject resourceNew = prismContext.parseObject(RESOURCE_DUMMY_STATIC_SCHEMA_FILE); + fillInConnectorRef(resourceNew, IntegrationTestTools.DUMMY_CONNECTOR_TYPE, result); + + // WHEN + displayWhen(TEST_NAME); + provisioningService.addObject(resourceNew, null, ProvisioningOperationOptions.createOverwrite(true), task, result); + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_SCHEMA_PARSE_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT, 0); + assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT, 0); + assertCounterIncrement(InternalCounters.RESOURCE_SCHEMA_PARSE_COUNT, 0); + + PrismObject resourceRepoAfter = repositoryService.getObject(ResourceType.class, + RESOURCE_DUMMY_STATIC_SCHEMA_OID, null, result); + + // One increment for availablity status, the other for schema + assertResourceVersionIncrement(resourceRepoAfter, 1); + } + + @Test + public void test042ResourceStaticSchemaTestAgain() throws Exception { + resourceStaticSchemaTest("test042ResourceStaticSchemaTestAgain"); + } + + /** + * MID-4472, MID-4174 + */ + @Test + public void test044ResourceStatciSchemaResourceAndConnectorCachingAgain() throws Exception { + resourceStatciSchemaResourceAndConnectorCaching("test044ResourceStatciSchemaResourceAndConnectorCachingAgain"); + } + + /** * This should be the very first test that works with the resource. * @@ -308,15 +568,15 @@ public void test105ParsedSchemaStaticSchema() throws Exception { // THEN // The returned type should have the schema pre-parsed - assertNotNull(RefinedResourceSchemaImpl.hasParsedSchema(resourceTypeStaticSchema)); + assertNotNull(RefinedResourceSchemaImpl.hasParsedSchema(resourceStaticSchema.asObjectable())); // Also test if the utility method returns the same thing - ResourceSchema returnedSchema = RefinedResourceSchemaImpl.getResourceSchema(resourceTypeStaticSchema, prismContext); + ResourceSchema returnedSchema = RefinedResourceSchemaImpl.getResourceSchema(resourceStaticSchema.asObjectable(), prismContext); display("Parsed resource schema", returnedSchema); assertNotNull("Null resource schema", returnedSchema); - dummyResourceSchemalessCtl.assertDummyResourceSchemaSanity(returnedSchema, resourceTypeStaticSchema, true); + assertStaticSchemaSanity(returnedSchema); } @Test @@ -337,7 +597,113 @@ public void test106GetObjectStaticSchema() throws Exception { display("Parsed resource schema", returnedSchema); assertNotNull("Null resource schema", returnedSchema); - dummyResourceSchemalessCtl.assertDummyResourceSchemaSanity(returnedSchema, resource.asObjectable(), true); + assertStaticSchemaSanity(returnedSchema); + } + + private void assertStaticSchemaSanity(ResourceSchema resorceSchema) { + ResourceType resourceType = resourceStaticSchema.asObjectable(); + assertNotNull("No resource schema in "+resourceType, resorceSchema); + QName objectClassQname = new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "AccountObjectClass"); + ObjectClassComplexTypeDefinition accountDefinition = resorceSchema.findObjectClassDefinition(objectClassQname); + assertNotNull("No object class definition for "+objectClassQname+" in resource schema", accountDefinition); + ObjectClassComplexTypeDefinition accountDef1 = resorceSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT); + assertTrue("Mismatched account definition: "+accountDefinition+" <-> "+accountDef1, accountDefinition == accountDef1); + + assertNotNull("No object class definition " + objectClassQname, accountDefinition); + assertEquals("Object class " + objectClassQname + " is not account", ShadowKindType.ACCOUNT, accountDefinition.getKind()); + assertTrue("Object class " + objectClassQname + " is not default account", accountDefinition.isDefaultInAKind()); + assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isEmpty()); + assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isIgnored()); + + Collection identifiers = accountDefinition.getPrimaryIdentifiers(); + assertNotNull("Null identifiers for " + objectClassQname, identifiers); + assertFalse("Empty identifiers for " + objectClassQname, identifiers.isEmpty()); + + + ResourceAttributeDefinition uidAttributeDefinition = accountDefinition.findAttributeDefinition(SchemaTestConstants.ICFS_UID); + assertNotNull("No definition for attribute "+SchemaTestConstants.ICFS_UID, uidAttributeDefinition); + assertTrue("Attribute "+SchemaTestConstants.ICFS_UID+" in not an identifier",uidAttributeDefinition.isIdentifier(accountDefinition)); + assertTrue("Attribute "+SchemaTestConstants.ICFS_UID+" in not in identifiers list",identifiers.contains(uidAttributeDefinition)); + assertEquals("Wrong displayName for attribute "+SchemaTestConstants.ICFS_UID, "Modified ConnId UID", uidAttributeDefinition.getDisplayName()); + assertEquals("Wrong displayOrder for attribute "+SchemaTestConstants.ICFS_UID, (Integer)100, uidAttributeDefinition.getDisplayOrder()); + + Collection secondaryIdentifiers = accountDefinition.getSecondaryIdentifiers(); + assertNotNull("Null secondary identifiers for " + objectClassQname, secondaryIdentifiers); + assertFalse("Empty secondary identifiers for " + objectClassQname, secondaryIdentifiers.isEmpty()); + + ResourceAttributeDefinition nameAttributeDefinition = accountDefinition.findAttributeDefinition(SchemaTestConstants.ICFS_NAME); + assertNotNull("No definition for attribute "+SchemaTestConstants.ICFS_NAME, nameAttributeDefinition); + assertTrue("Attribute "+SchemaTestConstants.ICFS_NAME+" in not an identifier",nameAttributeDefinition.isSecondaryIdentifier(accountDefinition)); + assertTrue("Attribute "+SchemaTestConstants.ICFS_NAME+" in not in identifiers list",secondaryIdentifiers.contains(nameAttributeDefinition)); + assertEquals("Wrong displayName for attribute "+SchemaTestConstants.ICFS_NAME, "Modified ConnId Name", nameAttributeDefinition.getDisplayName()); + assertEquals("Wrong displayOrder for attribute "+SchemaTestConstants.ICFS_NAME, (Integer)110, nameAttributeDefinition.getDisplayOrder()); + + assertNotNull("Null identifiers in account", accountDef1.getPrimaryIdentifiers()); + assertFalse("Empty identifiers in account", accountDef1.getPrimaryIdentifiers().isEmpty()); + assertNotNull("Null secondary identifiers in account", accountDef1.getSecondaryIdentifiers()); + assertFalse("Empty secondary identifiers in account", accountDef1.getSecondaryIdentifiers().isEmpty()); + assertNotNull("No naming attribute in account", accountDef1.getNamingAttribute()); + assertFalse("No nativeObjectClass in account", StringUtils.isEmpty(accountDef1.getNativeObjectClass())); + + ResourceAttributeDefinition uidDef = accountDef1 + .findAttributeDefinition(SchemaTestConstants.ICFS_UID); + assertEquals(1, uidDef.getMaxOccurs()); + assertEquals(0, uidDef.getMinOccurs()); + assertFalse("No UID display name", StringUtils.isBlank(uidDef.getDisplayName())); + assertFalse("UID has create", uidDef.canAdd()); + assertFalse("UID has update",uidDef.canModify()); + assertTrue("No UID read",uidDef.canRead()); + assertTrue("UID definition not in identifiers", accountDef1.getPrimaryIdentifiers().contains(uidDef)); + assertEquals("Wrong refined displayName for attribute "+SchemaTestConstants.ICFS_UID, "Modified ConnId UID", uidDef.getDisplayName()); + assertEquals("Wrong refined displayOrder for attribute "+SchemaTestConstants.ICFS_UID, (Integer)100, uidDef.getDisplayOrder()); + + ResourceAttributeDefinition nameDef = accountDef1 + .findAttributeDefinition(SchemaTestConstants.ICFS_NAME); + assertEquals(1, nameDef.getMaxOccurs()); + assertEquals(1, nameDef.getMinOccurs()); + assertFalse("No NAME displayName", StringUtils.isBlank(nameDef.getDisplayName())); + assertTrue("No NAME create", nameDef.canAdd()); + assertTrue("No NAME update",nameDef.canModify()); + assertTrue("No NAME read",nameDef.canRead()); + assertTrue("NAME definition not in identifiers", accountDef1.getSecondaryIdentifiers().contains(nameDef)); + assertEquals("Wrong refined displayName for attribute "+SchemaTestConstants.ICFS_NAME, "Modified ConnId Name", nameDef.getDisplayName()); + assertEquals("Wrong refined displayOrder for attribute "+SchemaTestConstants.ICFS_NAME, (Integer)110, nameDef.getDisplayOrder()); + + assertNull("The _PASSSWORD_ attribute sneaked into schema", accountDef1.findAttributeDefinition(new QName(SchemaTestConstants.NS_ICFS,"password"))); + + // ACCOUNT + ObjectClassComplexTypeDefinition accountDef = resorceSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT); + assertNotNull("No ACCOUNT kind definition", accountDef); + + ResourceAttributeDefinition fullnameDef = accountDef.findAttributeDefinition("fullname"); + assertNotNull("No definition for fullname", fullnameDef); + assertEquals(1, fullnameDef.getMaxOccurs()); + assertEquals(1, fullnameDef.getMinOccurs()); + assertTrue("No fullname create", fullnameDef.canAdd()); + assertTrue("No fullname update", fullnameDef.canModify()); + assertTrue("No fullname read", fullnameDef.canRead()); + assertTrue("Wrong displayOrder for attribute fullName: "+fullnameDef.getDisplayOrder(), + fullnameDef.getDisplayOrder() == 200 || fullnameDef.getDisplayOrder() == 250 || fullnameDef.getDisplayOrder() == 260); + + // GROUP + ObjectClassComplexTypeDefinition groupObjectClass = resorceSchema.findObjectClassDefinition(SchemaTestConstants.GROUP_OBJECT_CLASS_LOCAL_NAME); + assertNotNull("No group objectClass", groupObjectClass); + + ResourceAttributeDefinition membersDef = groupObjectClass.findAttributeDefinition(DummyResourceContoller.DUMMY_GROUP_MEMBERS_ATTRIBUTE_NAME); + assertNotNull("No definition for members", membersDef); + assertEquals("Wrong maxOccurs", -1, membersDef.getMaxOccurs()); + assertEquals("Wrong minOccurs", 0, membersDef.getMinOccurs()); + assertTrue("No members create", membersDef.canAdd()); + assertTrue("No members update", membersDef.canModify()); + assertTrue("No members read", membersDef.canRead()); + + assertEquals("Unexpected number of schema definitions in "+dummyResourceSchemalessCtl.getName()+" dummy resource", dummyResourceStaticSchema.getNumberOfObjectclasses(), resorceSchema.getDefinitions().size()); + + for (Definition def: resorceSchema.getDefinitions()) { + if (def instanceof RefinedObjectClassDefinition) { + AssertJUnit.fail("Refined definition sneaked into resource schema of "+dummyResourceSchemalessCtl.getName()+" dummy resource: "+def); + } + } } @Test @@ -413,9 +779,7 @@ public void test200AddAccount() throws Exception { String addedObjectOid = provisioningService.addObject(account.asPrismObject(), null, null, taskManager.createTaskInstance(), result); // THEN - result.computeStatus(); - display("add object result", result); - TestUtil.assertSuccess("addObject has failed (result)", result); + assertSuccess("addObject has failed (result)", result); assertEquals(ACCOUNT_WILL_OID, addedObjectOid); account.asPrismObject().checkConsistence(); diff --git a/provisioning/provisioning-impl/src/test/resources/dummy/dummy-schemaless/resource-dummy-schemaless-static-schema.xml b/provisioning/provisioning-impl/src/test/resources/dummy/dummy-schemaless/resource-dummy-schemaless-static-schema.xml index 6f1f8d655e9..32e2cef142d 100644 --- a/provisioning/provisioning-impl/src/test/resources/dummy/dummy-schemaless/resource-dummy-schemaless-static-schema.xml +++ b/provisioning/provisioning-impl/src/test/resources/dummy/dummy-schemaless/resource-dummy-schemaless-static-schema.xml @@ -1,6 +1,6 @@ + - ConnId UID + + Modified ConnId UID 100 read @@ -88,7 +91,8 @@ - ConnId Name + + Modified ConnId Name 110 @@ -192,9 +196,29 @@ + + + + + + + + + + + + + + resource + + + connector + + +