/* * 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.model.impl.expr; import static com.evolveum.midpoint.test.IntegrationTestTools.display; import static org.testng.AssertJUnit.assertEquals; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.xml.sax.SAXException; import com.evolveum.midpoint.model.common.expression.ExpressionVariables; import com.evolveum.midpoint.model.common.expression.script.ScriptExpression; import com.evolveum.midpoint.model.common.expression.script.ScriptExpressionFactory; import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest; import com.evolveum.midpoint.model.impl.controller.ModelController; import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.MidPointPrismContextFactory; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.PrettyPrinter; 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.ScriptExpressionEvaluatorType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; /** * * @author lazyman * @author mederly * @author semancik * */ @ContextConfiguration(locations = { "classpath:ctx-model-test-main.xml" }) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public class TestModelExpressions extends AbstractInternalModelIntegrationTest { private static final File TEST_DIR = new File("src/test/resources/expr"); private static final QName PROPERTY_NAME = new QName(SchemaConstants.NS_C, "foo"); private static final Trace LOGGER = TraceManager.getTrace(TestModelExpressions.class); private static final String CHEF_OID = "00000003-0000-0000-0000-000000000000"; private static final String CHEESE_OID = "00000002-0000-0000-0000-000000000000"; private static final String CHEESE_JR_OID = "00000002-0000-0000-0000-000000000001"; private static final String ELAINE_OID = "00000001-0000-0000-0000-000000000000"; private static final String LECHUCK_OID = "00000007-0000-0000-0000-000000000000"; private static final String F0006_OID = "00000000-8888-6666-0000-100000000006"; @Autowired(required=true) private ScriptExpressionFactory scriptExpressionFactory; @Autowired(required = true) private TaskManager taskManager; private static final File TEST_EXPRESSIONS_OBJECTS_FILE = new File(TEST_DIR, "orgstruct.xml"); @BeforeSuite public void setup() throws SchemaException, SAXException, IOException { PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); } @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); importObjectFromFile(TEST_EXPRESSIONS_OBJECTS_FILE); } @Test public void testHello() throws Exception { final String TEST_NAME = "testHello"; TestUtil.displayTestTile(this, TEST_NAME); assertExecuteScriptExpressionString(TEST_NAME, null, "Hello swashbuckler"); } private ScriptExpressionEvaluatorType parseScriptType(String fileName) throws SchemaException, IOException, JAXBException { ScriptExpressionEvaluatorType expressionType = PrismTestUtil.parseAtomicValue( new File(TEST_DIR, fileName), ScriptExpressionEvaluatorType.COMPLEX_TYPE); return expressionType; } @Test public void testGetUserByOid() throws Exception { final String TEST_NAME = "testGetUserByOid"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestModelExpressions.class.getName() + "." + TEST_NAME); PrismObject<UserType> chef = repositoryService.getObject(UserType.class, CHEF_OID, null, result); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, chef); // WHEN, THEN assertExecuteScriptExpressionString(TEST_NAME, variables, chef.asObjectable().getName().getOrig()); } @Test public void testGetManagersOids() throws Exception { final String TEST_NAME = "testGetManagersOids"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestModelExpressions.class.getName() + "." + TEST_NAME); PrismObject<UserType> chef = repositoryService.getObject(UserType.class, CHEF_OID, null, result); ScriptExpressionEvaluatorType scriptType = parseScriptType("expression-" + TEST_NAME + ".xml"); PrismPropertyDefinition<String> outputDefinition = new PrismPropertyDefinitionImpl<>(PROPERTY_NAME, DOMUtil.XSD_STRING, PrismTestUtil.getPrismContext()); ScriptExpression scriptExpression = scriptExpressionFactory.createScriptExpression(scriptType, outputDefinition, TEST_NAME); ExpressionVariables variables = new ExpressionVariables(); variables.addVariableDefinition(new QName(SchemaConstants.NS_C, "user"), chef); // WHEN List<PrismPropertyValue<String>> scriptOutputs = evaluate(scriptExpression, variables, false, TEST_NAME, null, result); // THEN display("Script output", scriptOutputs); assertEquals("Unexpected number of script outputs", 3, scriptOutputs.size()); Set<String> oids = new HashSet<String>(); oids.add(scriptOutputs.get(0).getValue()); oids.add(scriptOutputs.get(1).getValue()); oids.add(scriptOutputs.get(2).getValue()); Set<String> expectedOids = new HashSet<String>(Arrays.asList(new String[] { CHEESE_OID, CHEESE_JR_OID, LECHUCK_OID })); assertEquals("Unexpected script output", expectedOids, oids); } /** * MID-2887 */ @Test public void testIsUniquePropertyValue() throws Exception { final String TEST_NAME = "testIsUniquePropertyValue"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TestModelExpressions.class.getName() + "." + TEST_NAME); PrismObject<UserType> chef = repositoryService.getObject(UserType.class, CHEF_OID, null, result); ScriptExpressionEvaluatorType scriptType = parseScriptType("expression-" + TEST_NAME + ".xml"); PrismPropertyDefinition<Boolean> outputDefinition = new PrismPropertyDefinitionImpl<>(PROPERTY_NAME, DOMUtil.XSD_BOOLEAN, PrismTestUtil.getPrismContext()); ScriptExpression scriptExpression = scriptExpressionFactory.createScriptExpression(scriptType, outputDefinition, TEST_NAME); ExpressionVariables variables = new ExpressionVariables(); variables.addVariableDefinition(new QName(SchemaConstants.NS_C, "user"), chef); variables.addVariableDefinition(new QName(SchemaConstants.NS_C, "value"), "Scumm Bar Chef"); // WHEN List<PrismPropertyValue<Boolean>> scriptOutputs = evaluate(scriptExpression, variables, false, TEST_NAME, null, result); // THEN display("Script output", scriptOutputs); assertEquals("Unexpected number of script outputs", 1, scriptOutputs.size()); Boolean scriptOutput = scriptOutputs.get(0).getValue(); assertEquals("Unexpected script output", Boolean.TRUE, scriptOutput); } @Test public void testGetOrgByName() throws Exception { final String TEST_NAME = "testGetOrgByName"; TestUtil.displayTestTile(this, TEST_NAME); assertExecuteScriptExpressionString(TEST_NAME, null, F0006_OID); } @Test public void testGetLinkedShadowName() throws Exception { final String TEST_NAME = "testGetLinkedShadowName"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, ACCOUNT_GUYBRUSH_DUMMY_USERNAME); assertShadowFetchOperationCountIncrement(1); } @Test public void testGetLinkedShadowKindIntentUsername() throws Exception { final String TEST_NAME = "testGetLinkedShadowKindIntentUsername"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, ACCOUNT_GUYBRUSH_DUMMY_USERNAME); assertShadowFetchOperationCountIncrement(1); } @Test public void testGetLinkedShadowKindIntentFullname() throws Exception { final String TEST_NAME = "testGetLinkedShadowKindIntentFullname"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, ACCOUNT_GUYBRUSH_DUMMY_FULLNAME); assertShadowFetchOperationCountIncrement(1); } @Test public void testGetLinkedShadowNameRepo() throws Exception { final String TEST_NAME = "testGetLinkedShadowNameRepo"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, ACCOUNT_GUYBRUSH_DUMMY_USERNAME); assertShadowFetchOperationCountIncrement(0); } @Test public void testGetLinkedShadowKindIntentUsernameRepo() throws Exception { final String TEST_NAME = "testGetLinkedShadowKindIntentUsernameRepo"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, ACCOUNT_GUYBRUSH_DUMMY_USERNAME); assertShadowFetchOperationCountIncrement(0); } @Test public void testGetLinkedShadowKindIntentFullnameRepo() throws Exception { final String TEST_NAME = "testGetLinkedShadowKindIntentFullnameRepo"; TestUtil.displayTestTile(this, TEST_NAME); rememberShadowFetchOperationCount(); ExpressionVariables variables = ExpressionVariables.create(ExpressionConstants.VAR_USER, getUser(USER_GUYBRUSH_OID)); assertExecuteScriptExpressionString(TEST_NAME, variables, null); assertShadowFetchOperationCountIncrement(0); } private void assertExecuteScriptExpressionString(final String TEST_NAME, ExpressionVariables variables, String expectedOutput) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, IOException, JAXBException { String output = executeScriptExpressionString(TEST_NAME, variables); assertEquals("Unexpected script output", expectedOutput, output); } private String executeScriptExpressionString(final String TEST_NAME, ExpressionVariables variables) throws SchemaException, IOException, JAXBException, ExpressionEvaluationException, ObjectNotFoundException { // GIVEN OperationResult result = new OperationResult(TestModelExpressions.class.getName() + "." + TEST_NAME); ScriptExpressionEvaluatorType scriptType = parseScriptType("expression-" + TEST_NAME + ".xml"); ItemDefinition outputDefinition = new PrismPropertyDefinitionImpl(PROPERTY_NAME, DOMUtil.XSD_STRING, PrismTestUtil.getPrismContext()); ScriptExpression scriptExpression = scriptExpressionFactory.createScriptExpression(scriptType, outputDefinition, TEST_NAME); if (variables == null) { variables = new ExpressionVariables(); } // WHEN TestUtil.displayWhen(TEST_NAME); List<PrismPropertyValue<String>> scriptOutputs = evaluate(scriptExpression, variables, false, TEST_NAME, null, result); // THEN TestUtil.displayThen(TEST_NAME); display("Script output", scriptOutputs); result.computeStatus(); TestUtil.assertSuccess(result); if (scriptOutputs.size() == 0) { return null; } assertEquals("Unexpected number of script outputs", 1, scriptOutputs.size()); return scriptOutputs.get(0).getValue(); } private <T> List<PrismPropertyValue<T>> evaluate(ScriptExpression scriptExpression, ExpressionVariables variables, boolean useNew, String contextDescription, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException { if (task == null) { task = taskManager.createTaskInstance(); } try { ModelExpressionThreadLocalHolder.pushExpressionEnvironment(new ExpressionEnvironment<>(task, result)); return scriptExpression.evaluate(variables, null, useNew, contextDescription, task, result); } finally { ModelExpressionThreadLocalHolder.popExpressionEnvironment(); } } }